[WIN32K]
[reactos.git] / dll / win32 / oleaut32 / typelib.c
1 /*
2 * TYPELIB
3 *
4 * Copyright 1997 Marcus Meissner
5 * 1999 Rein Klazes
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 *
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
26 *
27 * - Tested using OLEVIEW (Platform SDK tool) only.
28 *
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
32 *
33 * - locale stuff is partially implemented but hasn't been tested.
34 *
35 * - typelib file is still read in its entirety, but it is released now.
36 *
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
39 *
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
43 * behaviour.
44 * -. lousy fatal error handling
45 *
46 */
47
48 #include "config.h"
49 #include "wine/port.h"
50
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
56
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
60
61 #include "winerror.h"
62 #include "windef.h"
63 #include "winbase.h"
64 #include "winnls.h"
65 #include "winreg.h"
66 #include "winuser.h"
67 #include "lzexpand.h"
68
69 #include "wine/unicode.h"
70 #include "objbase.h"
71 #include "typelib.h"
72 #include "wine/debug.h"
73 #include "variant.h"
74 #include "wine/list.h"
75
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78
79 typedef struct
80 {
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
88
89 typedef struct
90 {
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
94 /*
95 * Name info array.
96 */
97 } NE_TYPEINFO;
98
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
101
102 /****************************************************************************
103 * FromLExxx
104 *
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
107 */
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
110 {
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
113 }
114
115
116 static DWORD FromLEDWord(DWORD p_iVal)
117 {
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
122 }
123 #else
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
126 #endif
127
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
130
131 /****************************************************************************
132 * FromLExxx
133 *
134 * Fix byte order in any structure if necessary
135 */
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
138 {
139 WORD *Val = p_Val;
140
141 p_iSize /= sizeof(WORD);
142
143 while (p_iSize) {
144 *Val = FromLEWord(*Val);
145 Val++;
146 p_iSize--;
147 }
148 }
149
150
151 static void FromLEDWords(void *p_Val, int p_iSize)
152 {
153 DWORD *Val = p_Val;
154
155 p_iSize /= sizeof(DWORD);
156
157 while (p_iSize) {
158 *Val = FromLEDWord(*Val);
159 Val++;
160 p_iSize--;
161 }
162 }
163 #else
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
166 #endif
167
168 /*
169 * Find a typelib key which matches a requested maj.min version.
170 */
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
172 {
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
174 WCHAR buffer[60];
175 char key_name[16];
176 DWORD len, i;
177 INT best_maj = -1, best_min = -1;
178 HKEY hkey;
179
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
182
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
185
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
189 {
190 INT v_maj, v_min;
191
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
193 {
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
195
196 if (*wMaj == 0xffff && *wMin == 0xffff)
197 {
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
200 }
201 else if (*wMaj == v_maj)
202 {
203 best_maj = v_maj;
204
205 if (*wMin == v_min)
206 {
207 best_min = v_min;
208 break; /* exact match */
209 }
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
211 }
212 }
213 len = sizeof(key_name);
214 }
215 RegCloseKey( hkey );
216
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
218
219 if (*wMaj == 0xffff && *wMin == 0xffff)
220 {
221 if (best_maj >= 0 && best_min >= 0)
222 {
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
226 }
227 }
228
229 if (*wMaj == best_maj && best_min >= 0)
230 {
231 *wMin = best_min;
232 return TRUE;
233 }
234 return FALSE;
235 }
236
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
240 {
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
243
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
247 return buffer;
248 }
249
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
253 {
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
255
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
258 return buffer;
259 }
260
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
264 {
265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
266 static const WCHAR win16W[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W[] = {'w','i','n','3','2',0};
268 static const WCHAR win64W[] = {'w','i','n','6','4',0};
269
270 sprintfW( buffer, LcidFormatW, lcid );
271 switch(syskind)
272 {
273 case SYS_WIN16: strcatW( buffer, win16W ); break;
274 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 case SYS_WIN64: strcatW( buffer, win64W ); break;
276 default:
277 TRACE("Typelib is for unsupported syskind %i\n", syskind);
278 return NULL;
279 }
280 return buffer;
281 }
282
283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
284
285
286 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
287 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
288 SYSKIND syskind, LCID lcid, LPBSTR path )
289 {
290 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
291 LCID myLCID = lcid;
292 HKEY hkey;
293 WCHAR buffer[60];
294 WCHAR Path[MAX_PATH];
295 LONG res;
296
297 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
298
299 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
300 get_typelib_key( guid, wMaj, wMin, buffer );
301
302 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
303 if (res == ERROR_FILE_NOT_FOUND)
304 {
305 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
306 return TYPE_E_LIBNOTREGISTERED;
307 }
308 else if (res != ERROR_SUCCESS)
309 {
310 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
311 return TYPE_E_REGISTRYACCESS;
312 }
313
314 while (hr != S_OK)
315 {
316 LONG dwPathLen = sizeof(Path);
317
318 get_lcid_subkey( myLCID, syskind, buffer );
319
320 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
321 {
322 if (!lcid)
323 break;
324 else if (myLCID == lcid)
325 {
326 /* try with sub-langid */
327 myLCID = SUBLANGID(lcid);
328 }
329 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
330 {
331 /* try with system langid */
332 myLCID = 0;
333 }
334 else
335 {
336 break;
337 }
338 }
339 else
340 {
341 *path = SysAllocString( Path );
342 hr = S_OK;
343 }
344 }
345 RegCloseKey( hkey );
346 TRACE_(typelib)("-- 0x%08x\n", hr);
347 return hr;
348 }
349
350 /****************************************************************************
351 * QueryPathOfRegTypeLib [OLEAUT32.164]
352 *
353 * Gets the path to a registered type library.
354 *
355 * PARAMS
356 * guid [I] referenced guid
357 * wMaj [I] major version
358 * wMin [I] minor version
359 * lcid [I] locale id
360 * path [O] path of typelib
361 *
362 * RETURNS
363 * Success: S_OK.
364 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
365 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
366 * opened.
367 */
368 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
369 {
370 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
371 }
372
373 /******************************************************************************
374 * CreateTypeLib [OLEAUT32.160] creates a typelib
375 *
376 * RETURNS
377 * Success: S_OK
378 * Failure: Status
379 */
380 HRESULT WINAPI CreateTypeLib(
381 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
382 ) {
383 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
384 return E_FAIL;
385 }
386
387 /******************************************************************************
388 * LoadTypeLib [OLEAUT32.161]
389 *
390 * Loads a type library
391 *
392 * PARAMS
393 * szFile [I] Name of file to load from.
394 * pptLib [O] Pointer that receives ITypeLib object on success.
395 *
396 * RETURNS
397 * Success: S_OK
398 * Failure: Status
399 *
400 * SEE
401 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
402 */
403 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
404 {
405 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
406 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
407 }
408
409 /******************************************************************************
410 * LoadTypeLibEx [OLEAUT32.183]
411 *
412 * Loads and optionally registers a type library
413 *
414 * RETURNS
415 * Success: S_OK
416 * Failure: Status
417 */
418 HRESULT WINAPI LoadTypeLibEx(
419 LPCOLESTR szFile, /* [in] Name of file to load from */
420 REGKIND regkind, /* [in] Specify kind of registration */
421 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
422 {
423 WCHAR szPath[MAX_PATH+1];
424 HRESULT res;
425
426 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
427
428 *pptLib = NULL;
429
430 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
431
432 if (SUCCEEDED(res))
433 switch(regkind)
434 {
435 case REGKIND_DEFAULT:
436 /* don't register typelibs supplied with full path. Experimentation confirms the following */
437 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
438 (szFile[0] && (szFile[1] == ':'))) break;
439 /* else fall-through */
440
441 case REGKIND_REGISTER:
442 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
443 {
444 IUnknown_Release(*pptLib);
445 *pptLib = 0;
446 }
447 break;
448 case REGKIND_NONE:
449 break;
450 }
451
452 TRACE(" returns %08x\n",res);
453 return res;
454 }
455
456 /******************************************************************************
457 * LoadRegTypeLib [OLEAUT32.162]
458 *
459 * Loads a registered type library.
460 *
461 * PARAMS
462 * rguid [I] GUID of the registered type library.
463 * wVerMajor [I] major version.
464 * wVerMinor [I] minor version.
465 * lcid [I] locale ID.
466 * ppTLib [O] pointer that receives an ITypeLib object on success.
467 *
468 * RETURNS
469 * Success: S_OK.
470 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
471 * LoadTypeLib.
472 */
473 HRESULT WINAPI LoadRegTypeLib(
474 REFGUID rguid,
475 WORD wVerMajor,
476 WORD wVerMinor,
477 LCID lcid,
478 ITypeLib **ppTLib)
479 {
480 BSTR bstr=NULL;
481 HRESULT res;
482
483 *ppTLib = NULL;
484
485 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
486
487 if(SUCCEEDED(res))
488 {
489 res= LoadTypeLib(bstr, ppTLib);
490 SysFreeString(bstr);
491 }
492
493 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
494
495 return res;
496 }
497
498
499 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
500 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
501 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
502 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
503 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
504 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
505
506 /******************************************************************************
507 * RegisterTypeLib [OLEAUT32.163]
508 * Adds information about a type library to the System Registry
509 * NOTES
510 * Docs: ITypeLib FAR * ptlib
511 * Docs: OLECHAR FAR* szFullPath
512 * Docs: OLECHAR FAR* szHelpDir
513 *
514 * RETURNS
515 * Success: S_OK
516 * Failure: Status
517 */
518 HRESULT WINAPI RegisterTypeLib(
519 ITypeLib * ptlib, /* [in] Pointer to the library*/
520 OLECHAR * szFullPath, /* [in] full Path of the library*/
521 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
522 may be NULL*/
523 {
524 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
525 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
526 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
527 HRESULT res;
528 TLIBATTR *attr;
529 WCHAR keyName[60];
530 WCHAR tmp[16];
531 HKEY key, subKey;
532 UINT types, tidx;
533 TYPEKIND kind;
534 DWORD disposition;
535
536 if (ptlib == NULL || szFullPath == NULL)
537 return E_INVALIDARG;
538
539 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
540 return E_FAIL;
541
542 #ifdef _WIN64
543 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
544 #else
545 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
546 #endif
547
548 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
549
550 res = S_OK;
551 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
552 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
553 {
554 LPOLESTR doc;
555
556 /* Set the human-readable name of the typelib */
557 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
558 res = E_FAIL;
559 else if (doc)
560 {
561 if (RegSetValueExW(key, NULL, 0, REG_SZ,
562 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
563 res = E_FAIL;
564
565 SysFreeString(doc);
566 }
567
568 /* Make up the name of the typelib path subkey */
569 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
570
571 /* Create the typelib path subkey */
572 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
573 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
574 {
575 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
576 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
577 res = E_FAIL;
578
579 RegCloseKey(subKey);
580 }
581 else
582 res = E_FAIL;
583
584 /* Create the flags subkey */
585 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
586 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
587 {
588 /* FIXME: is %u correct? */
589 static const WCHAR formatW[] = {'%','u',0};
590 WCHAR buf[20];
591 sprintfW(buf, formatW, attr->wLibFlags);
592 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
593 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
594 res = E_FAIL;
595
596 RegCloseKey(subKey);
597 }
598 else
599 res = E_FAIL;
600
601 /* create the helpdir subkey */
602 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
603 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
604 {
605 BOOL freeHelpDir = FALSE;
606 OLECHAR* pIndexStr;
607
608 /* if we created a new key, and helpDir was null, set the helpdir
609 to the directory which contains the typelib. However,
610 if we just opened an existing key, we leave the helpdir alone */
611 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
612 szHelpDir = SysAllocString(szFullPath);
613 pIndexStr = strrchrW(szHelpDir, '\\');
614 if (pIndexStr) {
615 *pIndexStr = 0;
616 }
617 freeHelpDir = TRUE;
618 }
619
620 /* if we have an szHelpDir, set it! */
621 if (szHelpDir != NULL) {
622 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
623 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
624 res = E_FAIL;
625 }
626 }
627
628 /* tidy up */
629 if (freeHelpDir) SysFreeString(szHelpDir);
630 RegCloseKey(subKey);
631
632 } else {
633 res = E_FAIL;
634 }
635
636 RegCloseKey(key);
637 }
638 else
639 res = E_FAIL;
640
641 /* register OLE Automation-compatible interfaces for this typelib */
642 types = ITypeLib_GetTypeInfoCount(ptlib);
643 for (tidx=0; tidx<types; tidx++) {
644 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
645 LPOLESTR name = NULL;
646 ITypeInfo *tinfo = NULL;
647
648 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
649
650 switch (kind) {
651 case TKIND_INTERFACE:
652 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
653 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
654 break;
655
656 case TKIND_DISPATCH:
657 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
658 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
659 break;
660
661 default:
662 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
663 break;
664 }
665
666 if (tinfo) {
667 TYPEATTR *tattr = NULL;
668 ITypeInfo_GetTypeAttr(tinfo, &tattr);
669
670 if (tattr) {
671 TRACE_(typelib)("guid=%s, flags=%04x (",
672 debugstr_guid(&tattr->guid),
673 tattr->wTypeFlags);
674
675 if (TRACE_ON(typelib)) {
676 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
677 XX(FAPPOBJECT);
678 XX(FCANCREATE);
679 XX(FLICENSED);
680 XX(FPREDECLID);
681 XX(FHIDDEN);
682 XX(FCONTROL);
683 XX(FDUAL);
684 XX(FNONEXTENSIBLE);
685 XX(FOLEAUTOMATION);
686 XX(FRESTRICTED);
687 XX(FAGGREGATABLE);
688 XX(FREPLACEABLE);
689 XX(FDISPATCHABLE);
690 XX(FREVERSEBIND);
691 XX(FPROXY);
692 #undef XX
693 MESSAGE("\n");
694 }
695
696 /* Register all dispinterfaces (which includes dual interfaces) and
697 oleautomation interfaces */
698 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
699 kind == TKIND_DISPATCH)
700 {
701 /* register interface<->typelib coupling */
702 get_interface_key( &tattr->guid, keyName );
703 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
704 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
705 {
706 if (name)
707 RegSetValueExW(key, NULL, 0, REG_SZ,
708 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
709
710 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
711 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
712 RegSetValueExW(subKey, NULL, 0, REG_SZ,
713 (const BYTE *)PSOA, sizeof PSOA);
714 RegCloseKey(subKey);
715 }
716
717 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
718 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
719 RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (const BYTE *)PSOA, sizeof PSOA);
721 RegCloseKey(subKey);
722 }
723
724 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
725 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
726 {
727 WCHAR buffer[40];
728 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
729 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
730
731 StringFromGUID2(&attr->guid, buffer, 40);
732 RegSetValueExW(subKey, NULL, 0, REG_SZ,
733 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
734 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
735 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
736 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
737 RegCloseKey(subKey);
738 }
739
740 RegCloseKey(key);
741 }
742 }
743
744 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
745 }
746
747 ITypeInfo_Release(tinfo);
748 }
749
750 SysFreeString(name);
751 }
752 }
753
754 ITypeLib_ReleaseTLibAttr(ptlib, attr);
755
756 return res;
757 }
758
759
760 /******************************************************************************
761 * UnRegisterTypeLib [OLEAUT32.186]
762 * Removes information about a type library from the System Registry
763 * NOTES
764 *
765 * RETURNS
766 * Success: S_OK
767 * Failure: Status
768 */
769 HRESULT WINAPI UnRegisterTypeLib(
770 REFGUID libid, /* [in] Guid of the library */
771 WORD wVerMajor, /* [in] major version */
772 WORD wVerMinor, /* [in] minor version */
773 LCID lcid, /* [in] locale id */
774 SYSKIND syskind)
775 {
776 BSTR tlibPath = NULL;
777 DWORD tmpLength;
778 WCHAR keyName[60];
779 WCHAR subKeyName[50];
780 int result = S_OK;
781 DWORD i = 0;
782 BOOL deleteOtherStuff;
783 HKEY key = NULL;
784 HKEY subKey = NULL;
785 TYPEATTR* typeAttr = NULL;
786 TYPEKIND kind;
787 ITypeInfo* typeInfo = NULL;
788 ITypeLib* typeLib = NULL;
789 int numTypes;
790
791 TRACE("(IID: %s)\n",debugstr_guid(libid));
792
793 /* Create the path to the key */
794 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
795
796 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
797 {
798 TRACE("Unsupported syskind %i\n", syskind);
799 result = E_INVALIDARG;
800 goto end;
801 }
802
803 /* get the path to the typelib on disk */
804 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
805 result = E_INVALIDARG;
806 goto end;
807 }
808
809 /* Try and open the key to the type library. */
810 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
811 result = E_INVALIDARG;
812 goto end;
813 }
814
815 /* Try and load the type library */
816 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
817 result = TYPE_E_INVALIDSTATE;
818 goto end;
819 }
820
821 /* remove any types registered with this typelib */
822 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
823 for (i=0; i<numTypes; i++) {
824 /* get the kind of type */
825 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
826 goto enddeleteloop;
827 }
828
829 /* skip non-interfaces, and get type info for the type */
830 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
831 goto enddeleteloop;
832 }
833 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
834 goto enddeleteloop;
835 }
836 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
837 goto enddeleteloop;
838 }
839
840 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
841 kind == TKIND_DISPATCH)
842 {
843 /* the path to the type */
844 get_interface_key( &typeAttr->guid, subKeyName );
845
846 /* Delete its bits */
847 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
848 goto enddeleteloop;
849
850 RegDeleteKeyW(subKey, ProxyStubClsidW);
851 RegDeleteKeyW(subKey, ProxyStubClsid32W);
852 RegDeleteKeyW(subKey, TypeLibW);
853 RegCloseKey(subKey);
854 subKey = NULL;
855 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
856 }
857
858 enddeleteloop:
859 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
860 typeAttr = NULL;
861 if (typeInfo) ITypeInfo_Release(typeInfo);
862 typeInfo = NULL;
863 }
864
865 /* Now, delete the type library path subkey */
866 get_lcid_subkey( lcid, syskind, subKeyName );
867 RegDeleteKeyW(key, subKeyName);
868 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
869 RegDeleteKeyW(key, subKeyName);
870
871 /* check if there is anything besides the FLAGS/HELPDIR keys.
872 If there is, we don't delete them */
873 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
874 deleteOtherStuff = TRUE;
875 i = 0;
876 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
877 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
878
879 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
880 if (!strcmpW(subKeyName, FLAGSW)) continue;
881 if (!strcmpW(subKeyName, HELPDIRW)) continue;
882 deleteOtherStuff = FALSE;
883 break;
884 }
885
886 /* only delete the other parts of the key if we're absolutely sure */
887 if (deleteOtherStuff) {
888 RegDeleteKeyW(key, FLAGSW);
889 RegDeleteKeyW(key, HELPDIRW);
890 RegCloseKey(key);
891 key = NULL;
892
893 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
894 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
895 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
896 }
897
898 end:
899 SysFreeString(tlibPath);
900 if (typeLib) ITypeLib_Release(typeLib);
901 if (subKey) RegCloseKey(subKey);
902 if (key) RegCloseKey(key);
903 return result;
904 }
905
906 /******************************************************************************
907 * RegisterTypeLibForUser [OLEAUT32.442]
908 * Adds information about a type library to the user registry
909 * NOTES
910 * Docs: ITypeLib FAR * ptlib
911 * Docs: OLECHAR FAR* szFullPath
912 * Docs: OLECHAR FAR* szHelpDir
913 *
914 * RETURNS
915 * Success: S_OK
916 * Failure: Status
917 */
918 HRESULT WINAPI RegisterTypeLibForUser(
919 ITypeLib * ptlib, /* [in] Pointer to the library*/
920 OLECHAR * szFullPath, /* [in] full Path of the library*/
921 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
922 may be NULL*/
923 {
924 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
925 debugstr_w(szFullPath), debugstr_w(szHelpDir));
926 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
927 }
928
929 /******************************************************************************
930 * UnRegisterTypeLibForUser [OLEAUT32.443]
931 * Removes information about a type library from the user registry
932 *
933 * RETURNS
934 * Success: S_OK
935 * Failure: Status
936 */
937 HRESULT WINAPI UnRegisterTypeLibForUser(
938 REFGUID libid, /* [in] GUID of the library */
939 WORD wVerMajor, /* [in] major version */
940 WORD wVerMinor, /* [in] minor version */
941 LCID lcid, /* [in] locale id */
942 SYSKIND syskind)
943 {
944 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
945 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
946 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
947 }
948
949 /*======================= ITypeLib implementation =======================*/
950
951 typedef struct tagTLBCustData
952 {
953 GUID guid;
954 VARIANT data;
955 struct tagTLBCustData* next;
956 } TLBCustData;
957
958 /* data structure for import typelibs */
959 typedef struct tagTLBImpLib
960 {
961 int offset; /* offset in the file (MSFT)
962 offset in nametable (SLTG)
963 just used to identify library while reading
964 data from file */
965 GUID guid; /* libid */
966 BSTR name; /* name */
967
968 LCID lcid; /* lcid of imported typelib */
969
970 WORD wVersionMajor; /* major version number */
971 WORD wVersionMinor; /* minor version number */
972
973 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
974 NULL if not yet loaded */
975 struct tagTLBImpLib * next;
976 } TLBImpLib;
977
978 /* internal ITypeLib data */
979 typedef struct tagITypeLibImpl
980 {
981 const ITypeLib2Vtbl *lpVtbl;
982 const ITypeCompVtbl *lpVtblTypeComp;
983 LONG ref;
984 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
985 LCID lcid;
986
987 /* strings can be stored in tlb as multibyte strings BUT they are *always*
988 * exported to the application as a UNICODE string.
989 */
990 BSTR Name;
991 BSTR DocString;
992 BSTR HelpFile;
993 BSTR HelpStringDll;
994 DWORD dwHelpContext;
995 int TypeInfoCount; /* nr of typeinfo's in librarry */
996 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
997 int ctCustData; /* number of items in cust data list */
998 TLBCustData * pCustData; /* linked list to cust data */
999 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
1000 int ctTypeDesc; /* number of items in type desc array */
1001 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1002 library. Only used while reading MSFT
1003 typelibs */
1004 struct list ref_list; /* list of ref types in this typelib */
1005 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1006
1007
1008 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1009 struct tagITypeLibImpl *next, *prev;
1010 WCHAR *path;
1011 INT index;
1012 } ITypeLibImpl;
1013
1014 static const ITypeLib2Vtbl tlbvt;
1015 static const ITypeCompVtbl tlbtcvt;
1016
1017 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1018 {
1019 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1020 }
1021
1022 /* ITypeLib methods */
1023 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1024 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1025
1026 /*======================= ITypeInfo implementation =======================*/
1027
1028 /* data for referenced types */
1029 typedef struct tagTLBRefType
1030 {
1031 INT index; /* Type index for internal ref or for external ref
1032 it the format is SLTG. -2 indicates to
1033 use guid */
1034
1035 GUID guid; /* guid of the referenced type */
1036 /* if index == TLB_REF_USE_GUID */
1037
1038 HREFTYPE reference; /* The href of this ref */
1039 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1040 TLB_REF_INTERNAL for internal refs
1041 TLB_REF_NOT_FOUND for broken refs */
1042
1043 struct list entry;
1044 } TLBRefType;
1045
1046 #define TLB_REF_USE_GUID -2
1047
1048 #define TLB_REF_INTERNAL (void*)-2
1049 #define TLB_REF_NOT_FOUND (void*)-1
1050
1051 /* internal Parameter data */
1052 typedef struct tagTLBParDesc
1053 {
1054 BSTR Name;
1055 int ctCustData;
1056 TLBCustData * pCustData; /* linked list to cust data */
1057 } TLBParDesc;
1058
1059 /* internal Function data */
1060 typedef struct tagTLBFuncDesc
1061 {
1062 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1063 BSTR Name; /* the name of this function */
1064 TLBParDesc *pParamDesc; /* array with param names and custom data */
1065 int helpcontext;
1066 int HelpStringContext;
1067 BSTR HelpString;
1068 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1069 int ctCustData;
1070 TLBCustData * pCustData; /* linked list to cust data; */
1071 struct tagTLBFuncDesc * next;
1072 } TLBFuncDesc;
1073
1074 /* internal Variable data */
1075 typedef struct tagTLBVarDesc
1076 {
1077 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1078 BSTR Name; /* the name of this variable */
1079 int HelpContext;
1080 int HelpStringContext; /* FIXME: where? */
1081 BSTR HelpString;
1082 int ctCustData;
1083 TLBCustData * pCustData;/* linked list to cust data; */
1084 struct tagTLBVarDesc * next;
1085 } TLBVarDesc;
1086
1087 /* internal implemented interface data */
1088 typedef struct tagTLBImplType
1089 {
1090 HREFTYPE hRef; /* hRef of interface */
1091 int implflags; /* IMPLFLAG_*s */
1092 int ctCustData;
1093 TLBCustData * pCustData;/* linked list to custom data; */
1094 struct tagTLBImplType *next;
1095 } TLBImplType;
1096
1097 /* internal TypeInfo data */
1098 typedef struct tagITypeInfoImpl
1099 {
1100 const ITypeInfo2Vtbl *lpVtbl;
1101 const ITypeCompVtbl *lpVtblTypeComp;
1102 LONG ref;
1103 BOOL not_attached_to_typelib;
1104 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1105 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1106 int index; /* index in this typelib; */
1107 HREFTYPE hreftype; /* hreftype for app object binding */
1108 /* type libs seem to store the doc strings in ascii
1109 * so why should we do it in unicode?
1110 */
1111 BSTR Name;
1112 BSTR DocString;
1113 BSTR DllName;
1114 DWORD dwHelpContext;
1115 DWORD dwHelpStringContext;
1116
1117 /* functions */
1118 TLBFuncDesc * funclist; /* linked list with function descriptions */
1119
1120 /* variables */
1121 TLBVarDesc * varlist; /* linked list with variable descriptions */
1122
1123 /* Implemented Interfaces */
1124 TLBImplType * impltypelist;
1125
1126 int ctCustData;
1127 TLBCustData * pCustData; /* linked list to cust data; */
1128 struct tagITypeInfoImpl * next;
1129 } ITypeInfoImpl;
1130
1131 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1132 {
1133 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1134 }
1135
1136 static const ITypeInfo2Vtbl tinfvt;
1137 static const ITypeCompVtbl tcompvt;
1138
1139 static ITypeInfo2 * ITypeInfo_Constructor(void);
1140 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This);
1141
1142 typedef struct tagTLBContext
1143 {
1144 unsigned int oStart; /* start of TLB in file */
1145 unsigned int pos; /* current pos */
1146 unsigned int length; /* total length */
1147 void *mapping; /* memory mapping */
1148 MSFT_SegDir * pTblDir;
1149 ITypeLibImpl* pLibInfo;
1150 } TLBContext;
1151
1152
1153 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1154
1155 /*
1156 debug
1157 */
1158 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1159 if (pTD->vt & VT_RESERVED)
1160 szVarType += strlen(strcpy(szVarType, "reserved | "));
1161 if (pTD->vt & VT_BYREF)
1162 szVarType += strlen(strcpy(szVarType, "ref to "));
1163 if (pTD->vt & VT_ARRAY)
1164 szVarType += strlen(strcpy(szVarType, "array of "));
1165 if (pTD->vt & VT_VECTOR)
1166 szVarType += strlen(strcpy(szVarType, "vector of "));
1167 switch(pTD->vt & VT_TYPEMASK) {
1168 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1169 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1170 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1171 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1172 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1173 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1174 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1175 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1176 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1177 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1178 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1179 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1180 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1181 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1182 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1183 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1184 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1185 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1186 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1187 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1188 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1189 pTD->u.hreftype); break;
1190 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1191 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1192 case VT_PTR: sprintf(szVarType, "ptr to ");
1193 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1194 break;
1195 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1196 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1197 break;
1198 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1199 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1200 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1201 break;
1202
1203 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1204 }
1205 }
1206
1207 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1208 char buf[200];
1209 USHORT flags = edesc->u.paramdesc.wParamFlags;
1210 dump_TypeDesc(&edesc->tdesc,buf);
1211 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1212 MESSAGE("\t\tu.paramdesc.wParamFlags");
1213 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1214 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1215 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1216 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1217 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1218 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1219 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1220 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1221 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1222 }
1223 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1224 int i;
1225 MESSAGE("memid is %08x\n",funcdesc->memid);
1226 for (i=0;i<funcdesc->cParams;i++) {
1227 MESSAGE("Param %d:\n",i);
1228 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1229 }
1230 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1231 switch (funcdesc->funckind) {
1232 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1233 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1234 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1235 case FUNC_STATIC: MESSAGE("static");break;
1236 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1237 default: MESSAGE("unknown");break;
1238 }
1239 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1240 switch (funcdesc->invkind) {
1241 case INVOKE_FUNC: MESSAGE("func");break;
1242 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1243 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1244 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1245 }
1246 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1247 switch (funcdesc->callconv) {
1248 case CC_CDECL: MESSAGE("cdecl");break;
1249 case CC_PASCAL: MESSAGE("pascal");break;
1250 case CC_STDCALL: MESSAGE("stdcall");break;
1251 case CC_SYSCALL: MESSAGE("syscall");break;
1252 default:break;
1253 }
1254 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1255 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1256 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1257
1258 MESSAGE("\telemdescFunc (return value type):\n");
1259 dump_ELEMDESC(&funcdesc->elemdescFunc);
1260 }
1261
1262 static const char * const typekind_desc[] =
1263 {
1264 "TKIND_ENUM",
1265 "TKIND_RECORD",
1266 "TKIND_MODULE",
1267 "TKIND_INTERFACE",
1268 "TKIND_DISPATCH",
1269 "TKIND_COCLASS",
1270 "TKIND_ALIAS",
1271 "TKIND_UNION",
1272 "TKIND_MAX"
1273 };
1274
1275 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1276 {
1277 int i;
1278 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1279 for (i=0;i<pfd->funcdesc.cParams;i++)
1280 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1281
1282
1283 dump_FUNCDESC(&(pfd->funcdesc));
1284
1285 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1286 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1287 }
1288 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1289 {
1290 while (pfd)
1291 {
1292 dump_TLBFuncDescOne(pfd);
1293 pfd = pfd->next;
1294 };
1295 }
1296 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1297 {
1298 while (pvd)
1299 {
1300 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1301 pvd = pvd->next;
1302 };
1303 }
1304
1305 static void dump_TLBImpLib(const TLBImpLib *import)
1306 {
1307 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1308 debugstr_w(import->name));
1309 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1310 import->wVersionMinor, import->lcid, import->offset);
1311 }
1312
1313 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1314 {
1315 TLBRefType *ref;
1316
1317 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1318 {
1319 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1320 if(ref->index == -1)
1321 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1322 else
1323 TRACE_(typelib)("type no: %d\n", ref->index);
1324
1325 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1326 {
1327 TRACE_(typelib)("in lib\n");
1328 dump_TLBImpLib(ref->pImpTLInfo);
1329 }
1330 }
1331 }
1332
1333 static void dump_TLBImplType(const TLBImplType * impl)
1334 {
1335 while (impl) {
1336 TRACE_(typelib)(
1337 "implementing/inheriting interface hRef = %x implflags %x\n",
1338 impl->hRef, impl->implflags);
1339 impl = impl->next;
1340 }
1341 }
1342
1343 static void dump_Variant(const VARIANT * pvar)
1344 {
1345 SYSTEMTIME st;
1346
1347 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1348
1349 if (pvar)
1350 {
1351 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1352 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1353 {
1354 TRACE(",%p", V_BYREF(pvar));
1355 }
1356 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1357 {
1358 TRACE(",%p", V_ARRAY(pvar));
1359 }
1360 else switch (V_TYPE(pvar))
1361 {
1362 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1363 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1364 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1365 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1366 case VT_INT:
1367 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1368 case VT_UINT:
1369 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1370 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1371 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1372 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1373 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1374 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1375 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1376 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1377 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1378 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1379 V_CY(pvar).s.Lo); break;
1380 case VT_DATE:
1381 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1382 TRACE(",<invalid>");
1383 else
1384 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1385 st.wHour, st.wMinute, st.wSecond);
1386 break;
1387 case VT_ERROR:
1388 case VT_VOID:
1389 case VT_USERDEFINED:
1390 case VT_EMPTY:
1391 case VT_NULL: break;
1392 default: TRACE(",?"); break;
1393 }
1394 }
1395 TRACE("}\n");
1396 }
1397
1398 static void dump_DispParms(const DISPPARAMS * pdp)
1399 {
1400 unsigned int index;
1401
1402 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1403
1404 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1405 {
1406 TRACE("named args:\n");
1407 for (index = 0; index < pdp->cNamedArgs; index++)
1408 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1409 }
1410
1411 if (pdp->cArgs && pdp->rgvarg)
1412 {
1413 TRACE("args:\n");
1414 for (index = 0; index < pdp->cArgs; index++)
1415 dump_Variant( &pdp->rgvarg[index] );
1416 }
1417 }
1418
1419 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1420 {
1421 TRACE("%p ref=%u\n", pty, pty->ref);
1422 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1423 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1424 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1425 TRACE("fct:%u var:%u impl:%u\n",
1426 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1427 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1428 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1429 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1430 if (TRACE_ON(ole))
1431 dump_TLBFuncDesc(pty->funclist);
1432 dump_TLBVarDesc(pty->varlist);
1433 dump_TLBImplType(pty->impltypelist);
1434 }
1435
1436 static void dump_VARDESC(const VARDESC *v)
1437 {
1438 MESSAGE("memid %d\n",v->memid);
1439 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1440 MESSAGE("oInst %d\n",v->u.oInst);
1441 dump_ELEMDESC(&(v->elemdescVar));
1442 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1443 MESSAGE("varkind %d\n",v->varkind);
1444 }
1445
1446 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1447 {
1448 /* VT_LPWSTR is largest type that */
1449 /* may appear in type description*/
1450 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1451 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1452 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1453 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1454 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1455 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1456 {{0},30},{{0},31}
1457 };
1458
1459 static void TLB_abort(void)
1460 {
1461 DebugBreak();
1462 }
1463
1464 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1465 static void * TLB_Alloc(unsigned size)
1466 {
1467 void * ret;
1468 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1469 /* FIXME */
1470 ERR("cannot allocate memory\n");
1471 }
1472 return ret;
1473 }
1474
1475 static void TLB_Free(void * ptr)
1476 {
1477 HeapFree(GetProcessHeap(), 0, ptr);
1478 }
1479
1480 /* returns the size required for a deep copy of a typedesc into a
1481 * flat buffer */
1482 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1483 {
1484 SIZE_T size = 0;
1485
1486 if (alloc_initial_space)
1487 size += sizeof(TYPEDESC);
1488
1489 switch (tdesc->vt)
1490 {
1491 case VT_PTR:
1492 case VT_SAFEARRAY:
1493 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1494 break;
1495 case VT_CARRAY:
1496 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1497 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1498 break;
1499 }
1500 return size;
1501 }
1502
1503 /* deep copy a typedesc into a flat buffer */
1504 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1505 {
1506 if (!dest)
1507 {
1508 dest = buffer;
1509 buffer = (char *)buffer + sizeof(TYPEDESC);
1510 }
1511
1512 *dest = *src;
1513
1514 switch (src->vt)
1515 {
1516 case VT_PTR:
1517 case VT_SAFEARRAY:
1518 dest->u.lptdesc = buffer;
1519 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1520 break;
1521 case VT_CARRAY:
1522 dest->u.lpadesc = buffer;
1523 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1524 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1525 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1526 break;
1527 }
1528 return buffer;
1529 }
1530
1531 /* free custom data allocated by MSFT_CustData */
1532 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1533 {
1534 TLBCustData *pCustDataNext;
1535 for (; pCustData; pCustData = pCustDataNext)
1536 {
1537 VariantClear(&pCustData->data);
1538
1539 pCustDataNext = pCustData->next;
1540 TLB_Free(pCustData);
1541 }
1542 }
1543
1544 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1545 {
1546 DWORD len;
1547 BSTR ret;
1548
1549 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1550 ret = SysAllocStringLen(NULL, len - 1);
1551 if (!ret) return ret;
1552 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1553 return ret;
1554 }
1555
1556 /**********************************************************************
1557 *
1558 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1559 */
1560 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1561 {
1562 return pcx->pos;
1563 }
1564
1565 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1566 {
1567 if (where != DO_NOT_SEEK)
1568 {
1569 where += pcx->oStart;
1570 if (where > pcx->length)
1571 {
1572 /* FIXME */
1573 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1574 TLB_abort();
1575 }
1576 pcx->pos = where;
1577 }
1578 }
1579
1580 /* read function */
1581 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1582 {
1583 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1584 pcx->pos, count, pcx->oStart, pcx->length, where);
1585
1586 MSFT_Seek(pcx, where);
1587 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1588 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1589 pcx->pos += count;
1590 return count;
1591 }
1592
1593 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1594 LONG where )
1595 {
1596 DWORD ret;
1597
1598 ret = MSFT_Read(buffer, count, pcx, where);
1599 FromLEDWords(buffer, ret);
1600
1601 return ret;
1602 }
1603
1604 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1605 LONG where )
1606 {
1607 DWORD ret;
1608
1609 ret = MSFT_Read(buffer, count, pcx, where);
1610 FromLEWords(buffer, ret);
1611
1612 return ret;
1613 }
1614
1615 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1616 {
1617 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1618 memset(pGuid,0, sizeof(GUID));
1619 return;
1620 }
1621 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1622 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1623 pGuid->Data2 = FromLEWord(pGuid->Data2);
1624 pGuid->Data3 = FromLEWord(pGuid->Data3);
1625 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1626 }
1627
1628 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1629 {
1630 MSFT_NameIntro niName;
1631
1632 if (offset < 0)
1633 {
1634 ERR_(typelib)("bad offset %d\n", offset);
1635 return -1;
1636 }
1637
1638 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1639 pcx->pTblDir->pNametab.offset+offset);
1640
1641 return niName.hreftype;
1642 }
1643
1644 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1645 {
1646 char * name;
1647 MSFT_NameIntro niName;
1648 int lengthInChars;
1649 BSTR bstrName = NULL;
1650
1651 if (offset < 0)
1652 {
1653 ERR_(typelib)("bad offset %d\n", offset);
1654 return NULL;
1655 }
1656 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1657 pcx->pTblDir->pNametab.offset+offset);
1658 niName.namelen &= 0xFF; /* FIXME: correct ? */
1659 name=TLB_Alloc((niName.namelen & 0xff) +1);
1660 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1661 name[niName.namelen & 0xff]='\0';
1662
1663 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1664 name, -1, NULL, 0);
1665
1666 /* no invalid characters in string */
1667 if (lengthInChars)
1668 {
1669 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1670
1671 /* don't check for invalid character since this has been done previously */
1672 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1673 }
1674 TLB_Free(name);
1675
1676 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1677 return bstrName;
1678 }
1679
1680 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1681 {
1682 char * string;
1683 INT16 length;
1684 int lengthInChars;
1685 BSTR bstr = NULL;
1686
1687 if(offset<0) return NULL;
1688 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1689 if(length <= 0) return 0;
1690 string=TLB_Alloc(length +1);
1691 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1692 string[length]='\0';
1693
1694 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1695 string, -1, NULL, 0);
1696
1697 /* no invalid characters in string */
1698 if (lengthInChars)
1699 {
1700 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1701
1702 /* don't check for invalid character since this has been done previously */
1703 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1704 }
1705 TLB_Free(string);
1706
1707 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1708 return bstr;
1709 }
1710 /*
1711 * read a value and fill a VARIANT structure
1712 */
1713 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1714 {
1715 int size;
1716
1717 TRACE_(typelib)("\n");
1718
1719 if(offset <0) { /* data are packed in here */
1720 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1721 V_I4(pVar) = offset & 0x3ffffff;
1722 return;
1723 }
1724 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1725 pcx->pTblDir->pCustData.offset + offset );
1726 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1727 switch (V_VT(pVar)){
1728 case VT_EMPTY: /* FIXME: is this right? */
1729 case VT_NULL: /* FIXME: is this right? */
1730 case VT_I2 : /* this should not happen */
1731 case VT_I4 :
1732 case VT_R4 :
1733 case VT_ERROR :
1734 case VT_BOOL :
1735 case VT_I1 :
1736 case VT_UI1 :
1737 case VT_UI2 :
1738 case VT_UI4 :
1739 case VT_INT :
1740 case VT_UINT :
1741 case VT_VOID : /* FIXME: is this right? */
1742 case VT_HRESULT :
1743 size=4; break;
1744 case VT_R8 :
1745 case VT_CY :
1746 case VT_DATE :
1747 case VT_I8 :
1748 case VT_UI8 :
1749 case VT_DECIMAL : /* FIXME: is this right? */
1750 case VT_FILETIME :
1751 size=8;break;
1752 /* pointer types with known behaviour */
1753 case VT_BSTR :{
1754 char * ptr;
1755 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1756 if(size < 0) {
1757 char next;
1758 DWORD origPos = MSFT_Tell(pcx), nullPos;
1759
1760 do {
1761 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1762 } while (next);
1763 nullPos = MSFT_Tell(pcx);
1764 size = nullPos - origPos;
1765 MSFT_Seek(pcx, origPos);
1766 }
1767 ptr=TLB_Alloc(size);/* allocate temp buffer */
1768 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1769 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1770 /* FIXME: do we need a AtoW conversion here? */
1771 V_UNION(pVar, bstrVal[size])='\0';
1772 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1773 TLB_Free(ptr);
1774 }
1775 size=-4; break;
1776 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1777 case VT_DISPATCH :
1778 case VT_VARIANT :
1779 case VT_UNKNOWN :
1780 case VT_PTR :
1781 case VT_SAFEARRAY :
1782 case VT_CARRAY :
1783 case VT_USERDEFINED :
1784 case VT_LPSTR :
1785 case VT_LPWSTR :
1786 case VT_BLOB :
1787 case VT_STREAM :
1788 case VT_STORAGE :
1789 case VT_STREAMED_OBJECT :
1790 case VT_STORED_OBJECT :
1791 case VT_BLOB_OBJECT :
1792 case VT_CF :
1793 case VT_CLSID :
1794 default:
1795 size=0;
1796 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1797 V_VT(pVar));
1798 }
1799
1800 if(size>0) /* (big|small) endian correct? */
1801 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1802 return;
1803 }
1804 /*
1805 * create a linked list with custom data
1806 */
1807 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1808 {
1809 MSFT_CDGuid entry;
1810 TLBCustData* pNew;
1811 int count=0;
1812
1813 TRACE_(typelib)("\n");
1814
1815 while(offset >=0){
1816 count++;
1817 pNew=TLB_Alloc(sizeof(TLBCustData));
1818 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1819 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1820 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1821 /* add new custom data at head of the list */
1822 pNew->next=*ppCustData;
1823 *ppCustData=pNew;
1824 offset = entry.next;
1825 }
1826 return count;
1827 }
1828
1829 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1830 ITypeInfoImpl *pTI)
1831 {
1832 if(type <0)
1833 pTd->vt=type & VT_TYPEMASK;
1834 else
1835 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1836
1837 if(pTd->vt == VT_USERDEFINED)
1838 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1839
1840 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1841 }
1842
1843 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1844 {
1845 /* resolve referenced type if any */
1846 while (lpTypeDesc)
1847 {
1848 switch (lpTypeDesc->vt)
1849 {
1850 case VT_PTR:
1851 lpTypeDesc = lpTypeDesc->u.lptdesc;
1852 break;
1853
1854 case VT_CARRAY:
1855 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1856 break;
1857
1858 case VT_USERDEFINED:
1859 MSFT_DoRefType(pcx, pTI->pTypeLib,
1860 lpTypeDesc->u.hreftype);
1861
1862 lpTypeDesc = NULL;
1863 break;
1864
1865 default:
1866 lpTypeDesc = NULL;
1867 }
1868 }
1869 }
1870
1871 static void
1872 MSFT_DoFuncs(TLBContext* pcx,
1873 ITypeInfoImpl* pTI,
1874 int cFuncs,
1875 int cVars,
1876 int offset,
1877 TLBFuncDesc** pptfd)
1878 {
1879 /*
1880 * member information is stored in a data structure at offset
1881 * indicated by the memoffset field of the typeinfo structure
1882 * There are several distinctive parts.
1883 * The first part starts with a field that holds the total length
1884 * of this (first) part excluding this field. Then follow the records,
1885 * for each member there is one record.
1886 *
1887 * The first entry is always the length of the record (including this
1888 * length word).
1889 * The rest of the record depends on the type of the member. If there is
1890 * a field indicating the member type (function, variable, interface, etc)
1891 * I have not found it yet. At this time we depend on the information
1892 * in the type info and the usual order how things are stored.
1893 *
1894 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1895 * for each member;
1896 *
1897 * Third is an equal sized array with file offsets to the name entry
1898 * of each member.
1899 *
1900 * The fourth and last (?) part is an array with offsets to the records
1901 * in the first part of this file segment.
1902 */
1903
1904 int infolen, nameoffset, reclength, nrattributes, i;
1905 int recoffset = offset + sizeof(INT);
1906
1907 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1908 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1909 TLBFuncDesc *ptfd_prev = NULL;
1910
1911 TRACE_(typelib)("\n");
1912
1913 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1914
1915 for ( i = 0; i < cFuncs ; i++ )
1916 {
1917 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1918
1919 /* name, eventually add to a hash table */
1920 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1921 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1922
1923 /* nameoffset is sometimes -1 on the second half of a propget/propput
1924 * pair of functions */
1925 if ((nameoffset == -1) && (i > 0))
1926 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1927 else
1928 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1929
1930 /* read the function information record */
1931 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1932
1933 reclength &= 0xffff;
1934
1935 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1936
1937 /* do the attributes */
1938 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1939 / sizeof(int);
1940
1941 if ( nrattributes > 0 )
1942 {
1943 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1944
1945 if ( nrattributes > 1 )
1946 {
1947 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1948 pFuncRec->OptAttr[1]) ;
1949
1950 if ( nrattributes > 2 )
1951 {
1952 if ( pFuncRec->FKCCIC & 0x2000 )
1953 {
1954 if (!IS_INTRESOURCE(pFuncRec->OptAttr[2]))
1955 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->OptAttr[2]);
1956 (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->OptAttr[2]);
1957 }
1958 else
1959 {
1960 (*pptfd)->Entry = MSFT_ReadString(pcx,
1961 pFuncRec->OptAttr[2]);
1962 }
1963 if( nrattributes > 5 )
1964 {
1965 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1966
1967 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1968 {
1969 MSFT_CustData(pcx,
1970 pFuncRec->OptAttr[6],
1971 &(*pptfd)->pCustData);
1972 }
1973 }
1974 }
1975 else
1976 {
1977 (*pptfd)->Entry = (BSTR)-1;
1978 }
1979 }
1980 }
1981
1982 /* fill the FuncDesc Structure */
1983 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1984 offset + infolen + ( i + 1) * sizeof(INT));
1985
1986 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1987 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1988 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1989 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1990 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1991 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1992 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1993
1994 MSFT_GetTdesc(pcx,
1995 pFuncRec->DataType,
1996 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1997 pTI);
1998 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1999
2000 /* do the parameters/arguments */
2001 if(pFuncRec->nrargs)
2002 {
2003 int j = 0;
2004 MSFT_ParameterInfo paraminfo;
2005
2006 (*pptfd)->funcdesc.lprgelemdescParam =
2007 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
2008
2009 (*pptfd)->pParamDesc =
2010 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
2011
2012 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2013 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2014
2015 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2016 {
2017 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
2018
2019 MSFT_GetTdesc(pcx,
2020 paraminfo.DataType,
2021 &elemdesc->tdesc,
2022 pTI);
2023
2024 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2025
2026 /* name */
2027 if (paraminfo.oName == -1)
2028 /* this occurs for [propput] or [propget] methods, so
2029 * we should just set the name of the parameter to the
2030 * name of the method. */
2031 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
2032 else
2033 (*pptfd)->pParamDesc[j].Name =
2034 MSFT_ReadName( pcx, paraminfo.oName );
2035 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
2036
2037 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2038
2039 /* default value */
2040 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2041 (pFuncRec->FKCCIC & 0x1000) )
2042 {
2043 INT* pInt = (INT *)((char *)pFuncRec +
2044 reclength -
2045 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
2046
2047 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2048
2049 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
2050 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2051
2052 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2053 pInt[j], pcx);
2054 }
2055 else
2056 elemdesc->u.paramdesc.pparamdescex = NULL;
2057 /* custom info */
2058 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2059 {
2060 MSFT_CustData(pcx,
2061 pFuncRec->OptAttr[7+j],
2062 &(*pptfd)->pParamDesc[j].pCustData);
2063 }
2064
2065 /* SEEK value = jump to offset,
2066 * from there jump to the end of record,
2067 * go back by (j-1) arguments
2068 */
2069 MSFT_ReadLEDWords( &paraminfo ,
2070 sizeof(MSFT_ParameterInfo), pcx,
2071 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2072 * sizeof(MSFT_ParameterInfo)));
2073 }
2074 }
2075
2076 /* scode is not used: archaic win16 stuff FIXME: right? */
2077 (*pptfd)->funcdesc.cScodes = 0 ;
2078 (*pptfd)->funcdesc.lprgscode = NULL ;
2079
2080 ptfd_prev = *pptfd;
2081 pptfd = & ((*pptfd)->next);
2082 recoffset += reclength;
2083 }
2084 HeapFree(GetProcessHeap(), 0, recbuf);
2085 }
2086
2087 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2088 int cVars, int offset, TLBVarDesc ** pptvd)
2089 {
2090 int infolen, nameoffset, reclength;
2091 char recbuf[256];
2092 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2093 int i;
2094 int recoffset;
2095
2096 TRACE_(typelib)("\n");
2097
2098 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2099 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2100 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2101 recoffset += offset+sizeof(INT);
2102 for(i=0;i<cVars;i++){
2103 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2104 /* name, eventually add to a hash table */
2105 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2106 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2107 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2108 /* read the variable information record */
2109 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2110 reclength &=0xff;
2111 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2112 /* Optional data */
2113 if(reclength >(6*sizeof(INT)) )
2114 (*pptvd)->HelpContext=pVarRec->HelpContext;
2115 if(reclength >(7*sizeof(INT)) )
2116 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2117 if(reclength >(8*sizeof(INT)) )
2118 if(reclength >(9*sizeof(INT)) )
2119 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2120 /* fill the VarDesc Structure */
2121 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2122 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2123 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2124 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2125 MSFT_GetTdesc(pcx, pVarRec->DataType,
2126 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2127 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2128 if(pVarRec->VarKind == VAR_CONST ){
2129 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2130 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2131 pVarRec->OffsValue, pcx);
2132 } else
2133 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2134 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2135 pptvd=&((*pptvd)->next);
2136 recoffset += reclength;
2137 }
2138 }
2139 /* fill in data for a hreftype (offset). When the referenced type is contained
2140 * in the typelib, it's just an (file) offset in the type info base dir.
2141 * If comes from import, it's an offset+1 in the ImpInfo table
2142 * */
2143 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2144 int offset)
2145 {
2146 TLBRefType *ref;
2147
2148 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2149
2150 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2151 {
2152 if(ref->reference == offset) return;
2153 }
2154
2155 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2156 list_add_tail(&pTL->ref_list, &ref->entry);
2157
2158 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2159 /* external typelib */
2160 MSFT_ImpInfo impinfo;
2161 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2162
2163 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2164
2165 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2166 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2167 while (pImpLib){ /* search the known offsets of all import libraries */
2168 if(pImpLib->offset==impinfo.oImpFile) break;
2169 pImpLib=pImpLib->next;
2170 }
2171 if(pImpLib){
2172 ref->reference = offset;
2173 ref->pImpTLInfo = pImpLib;
2174 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2175 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2176 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2177 ref->index = TLB_REF_USE_GUID;
2178 } else
2179 ref->index = impinfo.oGuid;
2180 }else{
2181 ERR("Cannot find a reference\n");
2182 ref->reference = -1;
2183 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2184 }
2185 }else{
2186 /* in this typelib */
2187 ref->index = MSFT_HREFTYPE_INDEX(offset);
2188 ref->reference = offset;
2189 ref->pImpTLInfo = TLB_REF_INTERNAL;
2190 }
2191 }
2192
2193 /* process Implemented Interfaces of a com class */
2194 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2195 int offset)
2196 {
2197 int i;
2198 MSFT_RefRecord refrec;
2199 TLBImplType **ppImpl = &pTI->impltypelist;
2200
2201 TRACE_(typelib)("\n");
2202
2203 for(i=0;i<count;i++){
2204 if(offset<0) break; /* paranoia */
2205 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2206 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2207 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2208 (*ppImpl)->hRef = refrec.reftype;
2209 (*ppImpl)->implflags=refrec.flags;
2210 (*ppImpl)->ctCustData=
2211 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2212 offset=refrec.onext;
2213 ppImpl=&((*ppImpl)->next);
2214 }
2215 }
2216 /*
2217 * process a typeinfo record
2218 */
2219 static ITypeInfoImpl * MSFT_DoTypeInfo(
2220 TLBContext *pcx,
2221 int count,
2222 ITypeLibImpl * pLibInfo)
2223 {
2224 MSFT_TypeInfoBase tiBase;
2225 ITypeInfoImpl *ptiRet;
2226
2227 TRACE_(typelib)("count=%u\n", count);
2228
2229 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2230 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2231 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2232
2233 /* this is where we are coming from */
2234 ptiRet->pTypeLib = pLibInfo;
2235 ptiRet->index=count;
2236 /* fill in the typeattr fields */
2237
2238 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2239 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2240 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2241 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2242 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2243 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2244 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2245 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2246 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2247 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2248 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2249 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2250 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2251 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2252 MSFT_GetTdesc(pcx, tiBase.datatype1,
2253 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2254
2255 /* FIXME: */
2256 /* IDLDESC idldescType; *//* never saw this one != zero */
2257
2258 /* name, eventually add to a hash table */
2259 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2260 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2261 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2262 /* help info */
2263 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2264 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2265 ptiRet->dwHelpContext=tiBase.helpcontext;
2266
2267 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2268 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2269
2270 /* note: InfoType's Help file and HelpStringDll come from the containing
2271 * library. Further HelpString and Docstring appear to be the same thing :(
2272 */
2273 /* functions */
2274 if(ptiRet->TypeAttr.cFuncs >0 )
2275 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2276 ptiRet->TypeAttr.cVars,
2277 tiBase.memoffset, & ptiRet->funclist);
2278 /* variables */
2279 if(ptiRet->TypeAttr.cVars >0 )
2280 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2281 ptiRet->TypeAttr.cVars,
2282 tiBase.memoffset, & ptiRet->varlist);
2283 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2284 switch(ptiRet->TypeAttr.typekind)
2285 {
2286 case TKIND_COCLASS:
2287 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2288 tiBase.datatype1);
2289 break;
2290 case TKIND_DISPATCH:
2291 /* This is not -1 when the interface is a non-base dual interface or
2292 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2293 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2294 not this interface.
2295 */
2296
2297 if (tiBase.datatype1 != -1)
2298 {
2299 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2300 ptiRet->impltypelist->hRef = tiBase.datatype1;
2301 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2302 }
2303 break;
2304 default:
2305 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2306 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2307 ptiRet->impltypelist->hRef = tiBase.datatype1;
2308 break;
2309 }
2310 }
2311 ptiRet->ctCustData=
2312 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2313
2314 TRACE_(typelib)("%s guid: %s kind:%s\n",
2315 debugstr_w(ptiRet->Name),
2316 debugstr_guid(&ptiRet->TypeAttr.guid),
2317 typekind_desc[ptiRet->TypeAttr.typekind]);
2318 if (TRACE_ON(typelib))
2319 dump_TypeInfo(ptiRet);
2320
2321 return ptiRet;
2322 }
2323
2324 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2325 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2326 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2327 * tradeoff here.
2328 */
2329 static ITypeLibImpl *tlb_cache_first;
2330 static CRITICAL_SECTION cache_section;
2331 static CRITICAL_SECTION_DEBUG cache_section_debug =
2332 {
2333 0, 0, &cache_section,
2334 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2335 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2336 };
2337 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2338
2339
2340 typedef struct TLB_PEFile
2341 {
2342 const IUnknownVtbl *lpvtbl;
2343 LONG refs;
2344 HMODULE dll;
2345 HRSRC typelib_resource;
2346 HGLOBAL typelib_global;
2347 LPVOID typelib_base;
2348 } TLB_PEFile;
2349
2350 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2351 {
2352 if (IsEqualIID(riid, &IID_IUnknown))
2353 {
2354 *ppv = iface;
2355 IUnknown_AddRef(iface);
2356 return S_OK;
2357 }
2358 *ppv = NULL;
2359 return E_NOINTERFACE;
2360 }
2361
2362 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2363 {
2364 TLB_PEFile *This = (TLB_PEFile *)iface;
2365 return InterlockedIncrement(&This->refs);
2366 }
2367
2368 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2369 {
2370 TLB_PEFile *This = (TLB_PEFile *)iface;
2371 ULONG refs = InterlockedDecrement(&This->refs);
2372 if (!refs)
2373 {
2374 if (This->typelib_global)
2375 FreeResource(This->typelib_global);
2376 if (This->dll)
2377 FreeLibrary(This->dll);
2378 HeapFree(GetProcessHeap(), 0, This);
2379 }
2380 return refs;
2381 }
2382
2383 static const IUnknownVtbl TLB_PEFile_Vtable =
2384 {
2385 TLB_PEFile_QueryInterface,
2386 TLB_PEFile_AddRef,
2387 TLB_PEFile_Release
2388 };
2389
2390 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2391 {
2392 TLB_PEFile *This;
2393
2394 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2395 if (!This)
2396 return E_OUTOFMEMORY;
2397
2398 This->lpvtbl = &TLB_PEFile_Vtable;
2399 This->refs = 1;
2400 This->dll = NULL;
2401 This->typelib_resource = NULL;
2402 This->typelib_global = NULL;
2403 This->typelib_base = NULL;
2404
2405 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2406 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2407
2408 if (This->dll)
2409 {
2410 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2411 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2412 if (This->typelib_resource)
2413 {
2414 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2415 if (This->typelib_global)
2416 {
2417 This->typelib_base = LockResource(This->typelib_global);
2418
2419 if (This->typelib_base)
2420 {
2421 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2422 *ppBase = This->typelib_base;
2423 *ppFile = (IUnknown *)&This->lpvtbl;
2424 return S_OK;
2425 }
2426 }
2427 }
2428 }
2429
2430 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2431 return TYPE_E_CANTLOADLIBRARY;
2432 }
2433
2434 typedef struct TLB_NEFile
2435 {
2436 const IUnknownVtbl *lpvtbl;
2437 LONG refs;
2438 LPVOID typelib_base;
2439 } TLB_NEFile;
2440
2441 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2442 {
2443 if (IsEqualIID(riid, &IID_IUnknown))
2444 {
2445 *ppv = iface;
2446 IUnknown_AddRef(iface);
2447 return S_OK;
2448 }
2449 *ppv = NULL;
2450 return E_NOINTERFACE;
2451 }
2452
2453 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2454 {
2455 TLB_NEFile *This = (TLB_NEFile *)iface;
2456 return InterlockedIncrement(&This->refs);
2457 }
2458
2459 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2460 {
2461 TLB_NEFile *This = (TLB_NEFile *)iface;
2462 ULONG refs = InterlockedDecrement(&This->refs);
2463 if (!refs)
2464 {
2465 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2466 HeapFree(GetProcessHeap(), 0, This);
2467 }
2468 return refs;
2469 }
2470
2471 static const IUnknownVtbl TLB_NEFile_Vtable =
2472 {
2473 TLB_NEFile_QueryInterface,
2474 TLB_NEFile_AddRef,
2475 TLB_NEFile_Release
2476 };
2477
2478 /***********************************************************************
2479 * read_xx_header [internal]
2480 */
2481 static int read_xx_header( HFILE lzfd )
2482 {
2483 IMAGE_DOS_HEADER mzh;
2484 char magic[3];
2485
2486 LZSeek( lzfd, 0, SEEK_SET );
2487 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2488 return 0;
2489 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2490 return 0;
2491
2492 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2493 if ( 2 != LZRead( lzfd, magic, 2 ) )
2494 return 0;
2495
2496 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2497
2498 if ( magic[0] == 'N' && magic[1] == 'E' )
2499 return IMAGE_OS2_SIGNATURE;
2500 if ( magic[0] == 'P' && magic[1] == 'E' )
2501 return IMAGE_NT_SIGNATURE;
2502
2503 magic[2] = '\0';
2504 WARN("Can't handle %s files.\n", magic );
2505 return 0;
2506 }
2507
2508
2509 /***********************************************************************
2510 * find_ne_resource [internal]
2511 */
2512 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2513 DWORD *resLen, DWORD *resOff )
2514 {
2515 IMAGE_OS2_HEADER nehd;
2516 NE_TYPEINFO *typeInfo;
2517 NE_NAMEINFO *nameInfo;
2518 DWORD nehdoffset;
2519 LPBYTE resTab;
2520 DWORD resTabSize;
2521 int count;
2522
2523 /* Read in NE header */
2524 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2525 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2526
2527 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2528 if ( !resTabSize )
2529 {
2530 TRACE("No resources in NE dll\n" );
2531 return FALSE;
2532 }
2533
2534 /* Read in resource table */
2535 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2536 if ( !resTab ) return FALSE;
2537
2538 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2539 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2540 {
2541 HeapFree( GetProcessHeap(), 0, resTab );
2542 return FALSE;
2543 }
2544
2545 /* Find resource */
2546 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2547
2548 if (!IS_INTRESOURCE(typeid)) /* named type */
2549 {
2550 BYTE len = strlen( typeid );
2551 while (typeInfo->type_id)
2552 {
2553 if (!(typeInfo->type_id & 0x8000))
2554 {
2555 BYTE *p = resTab + typeInfo->type_id;
2556 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2557 }
2558 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2559 typeInfo->count * sizeof(NE_NAMEINFO));
2560 }
2561 }
2562 else /* numeric type id */
2563 {
2564 WORD id = LOWORD(typeid) | 0x8000;
2565 while (typeInfo->type_id)
2566 {
2567 if (typeInfo->type_id == id) goto found_type;
2568 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2569 typeInfo->count * sizeof(NE_NAMEINFO));
2570 }
2571 }
2572 TRACE("No typeid entry found for %p\n", typeid );
2573 HeapFree( GetProcessHeap(), 0, resTab );
2574 return FALSE;
2575
2576 found_type:
2577 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2578
2579 if (!IS_INTRESOURCE(resid)) /* named resource */
2580 {
2581 BYTE len = strlen( resid );
2582 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2583 {
2584 BYTE *p = resTab + nameInfo->id;
2585 if (nameInfo->id & 0x8000) continue;
2586 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2587 }
2588 }
2589 else /* numeric resource id */
2590 {
2591 WORD id = LOWORD(resid) | 0x8000;
2592 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2593 if (nameInfo->id == id) goto found_name;
2594 }
2595 TRACE("No resid entry found for %p\n", typeid );
2596 HeapFree( GetProcessHeap(), 0, resTab );
2597 return FALSE;
2598
2599 found_name:
2600 /* Return resource data */
2601 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2602 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2603
2604 HeapFree( GetProcessHeap(), 0, resTab );
2605 return TRUE;
2606 }
2607
2608 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2609
2610 HFILE lzfd = -1;
2611 OFSTRUCT ofs;
2612 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2613 TLB_NEFile *This = NULL;
2614
2615 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2616 if (!This) return E_OUTOFMEMORY;
2617
2618 This->lpvtbl = &TLB_NEFile_Vtable;
2619 This->refs = 1;
2620 This->typelib_base = NULL;
2621
2622 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2623 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2624 {
2625 DWORD reslen, offset;
2626 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2627 {
2628 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2629 if( !This->typelib_base )
2630 hr = E_OUTOFMEMORY;
2631 else
2632 {
2633 LZSeek( lzfd, offset, SEEK_SET );
2634 reslen = LZRead( lzfd, This->typelib_base, reslen );
2635 LZClose( lzfd );
2636 *ppBase = This->typelib_base;
2637 *pdwTLBLength = reslen;
2638 *ppFile = (IUnknown *)&This->lpvtbl;
2639 return S_OK;
2640 }
2641 }
2642 }
2643
2644 if( lzfd >= 0) LZClose( lzfd );
2645 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2646 return hr;
2647 }
2648
2649 typedef struct TLB_Mapping
2650 {
2651 const IUnknownVtbl *lpvtbl;
2652 LONG refs;
2653 HANDLE file;
2654 HANDLE mapping;
2655 LPVOID typelib_base;
2656 } TLB_Mapping;
2657
2658 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2659 {
2660 if (IsEqualIID(riid, &IID_IUnknown))
2661 {
2662 *ppv = iface;
2663 IUnknown_AddRef(iface);
2664 return S_OK;
2665 }
2666 *ppv = NULL;
2667 return E_NOINTERFACE;
2668 }
2669
2670 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2671 {
2672 TLB_Mapping *This = (TLB_Mapping *)iface;
2673 return InterlockedIncrement(&This->refs);
2674 }
2675
2676 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2677 {
2678 TLB_Mapping *This = (TLB_Mapping *)iface;
2679 ULONG refs = InterlockedDecrement(&This->refs);
2680 if (!refs)
2681 {
2682 if (This->typelib_base)
2683 UnmapViewOfFile(This->typelib_base);
2684 if (This->mapping)
2685 CloseHandle(This->mapping);
2686 if (This->file != INVALID_HANDLE_VALUE)
2687 CloseHandle(This->file);
2688 HeapFree(GetProcessHeap(), 0, This);
2689 }
2690 return refs;
2691 }
2692
2693 static const IUnknownVtbl TLB_Mapping_Vtable =
2694 {
2695 TLB_Mapping_QueryInterface,
2696 TLB_Mapping_AddRef,
2697 TLB_Mapping_Release
2698 };
2699
2700 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2701 {
2702 TLB_Mapping *This;
2703
2704 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2705 if (!This)
2706 return E_OUTOFMEMORY;
2707
2708 This->lpvtbl = &TLB_Mapping_Vtable;
2709 This->refs = 1;
2710 This->file = INVALID_HANDLE_VALUE;
2711 This->mapping = NULL;
2712 This->typelib_base = NULL;
2713
2714 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2715 if (INVALID_HANDLE_VALUE != This->file)
2716 {
2717 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2718 if (This->mapping)
2719 {
2720 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2721 if(This->typelib_base)
2722 {
2723 /* retrieve file size */
2724 *pdwTLBLength = GetFileSize(This->file, NULL);
2725 *ppBase = This->typelib_base;
2726 *ppFile = (IUnknown *)&This->lpvtbl;
2727 return S_OK;
2728 }
2729 }
2730 }
2731
2732 IUnknown_Release((IUnknown *)&This->lpvtbl);
2733 return TYPE_E_CANTLOADLIBRARY;
2734 }
2735
2736 /****************************************************************************
2737 * TLB_ReadTypeLib
2738 *
2739 * find the type of the typelib file and map the typelib resource into
2740 * the memory
2741 */
2742 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2743 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2744 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2745 {
2746 ITypeLibImpl *entry;
2747 HRESULT ret;
2748 INT index = 1;
2749 LPWSTR index_str, file = (LPWSTR)pszFileName;
2750 LPVOID pBase = NULL;
2751 DWORD dwTLBLength = 0;
2752 IUnknown *pFile = NULL;
2753
2754 *ppTypeLib = NULL;
2755
2756 index_str = strrchrW(pszFileName, '\\');
2757 if(index_str && *++index_str != '\0')
2758 {
2759 LPWSTR end_ptr;
2760 LONG idx = strtolW(index_str, &end_ptr, 10);
2761 if(*end_ptr == '\0')
2762 {
2763 int str_len = index_str - pszFileName - 1;
2764 index = idx;
2765 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2766 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2767 file[str_len] = 0;
2768 }
2769 }
2770
2771 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2772 {
2773 if(strchrW(file, '\\'))
2774 {
2775 lstrcpyW(pszPath, file);
2776 }
2777 else
2778 {
2779 int len = GetSystemDirectoryW(pszPath, cchPath);
2780 pszPath[len] = '\\';
2781 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2782 }
2783 }
2784
2785 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2786
2787 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2788
2789 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2790 EnterCriticalSection(&cache_section);
2791 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2792 {
2793 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2794 {
2795 TRACE("cache hit\n");
2796 *ppTypeLib = (ITypeLib2*)entry;
2797 ITypeLib_AddRef(*ppTypeLib);
2798 LeaveCriticalSection(&cache_section);
2799 return S_OK;
2800 }
2801 }
2802 LeaveCriticalSection(&cache_section);
2803
2804 /* now actually load and parse the typelib */
2805
2806 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2807 if (ret == TYPE_E_CANTLOADLIBRARY)
2808 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2809 if (ret == TYPE_E_CANTLOADLIBRARY)
2810 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2811 if (SUCCEEDED(ret))
2812 {
2813 if (dwTLBLength >= 4)
2814 {
2815 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2816 if (dwSignature == MSFT_SIGNATURE)
2817 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2818 else if (dwSignature == SLTG_SIGNATURE)
2819 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2820 else
2821 {
2822 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2823 ret = TYPE_E_CANTLOADLIBRARY;
2824 }
2825 }
2826 else
2827 ret = TYPE_E_CANTLOADLIBRARY;
2828 IUnknown_Release(pFile);
2829 }
2830
2831 if(*ppTypeLib) {
2832 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2833
2834 TRACE("adding to cache\n");
2835 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2836 lstrcpyW(impl->path, pszPath);
2837 /* We should really canonicalise the path here. */
2838 impl->index = index;
2839
2840 /* FIXME: check if it has added already in the meantime */
2841 EnterCriticalSection(&cache_section);
2842 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2843 impl->prev = NULL;
2844 tlb_cache_first = impl;
2845 LeaveCriticalSection(&cache_section);
2846 ret = S_OK;
2847 } else
2848 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2849
2850 return ret;
2851 }
2852
2853 /*================== ITypeLib(2) Methods ===================================*/
2854
2855 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2856 {
2857 ITypeLibImpl* pTypeLibImpl;
2858
2859 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2860 if (!pTypeLibImpl) return NULL;
2861
2862 pTypeLibImpl->lpVtbl = &tlbvt;
2863 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2864 pTypeLibImpl->ref = 1;
2865
2866 list_init(&pTypeLibImpl->ref_list);
2867 pTypeLibImpl->dispatch_href = -1;
2868
2869 return pTypeLibImpl;
2870 }
2871
2872 /****************************************************************************
2873 * ITypeLib2_Constructor_MSFT
2874 *
2875 * loading an MSFT typelib from an in-memory image
2876 */
2877 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2878 {
2879 TLBContext cx;
2880 LONG lPSegDir;
2881 MSFT_Header tlbHeader;
2882 MSFT_SegDir tlbSegDir;
2883 ITypeLibImpl * pTypeLibImpl;
2884
2885 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2886
2887 pTypeLibImpl = TypeLibImpl_Constructor();
2888 if (!pTypeLibImpl) return NULL;
2889
2890 /* get pointer to beginning of typelib data */
2891 cx.pos = 0;
2892 cx.oStart=0;
2893 cx.mapping = pLib;
2894 cx.pLibInfo = pTypeLibImpl;
2895 cx.length = dwTLBLength;
2896
2897 /* read header */
2898 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2899 TRACE_(typelib)("header:\n");
2900 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2901 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2902 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2903 return NULL;
2904 }
2905 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2906
2907 /* there is a small amount of information here until the next important
2908 * part:
2909 * the segment directory . Try to calculate the amount of data */
2910 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2911
2912 /* now read the segment directory */
2913 TRACE("read segment directory (at %d)\n",lPSegDir);
2914 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2915 cx.pTblDir = &tlbSegDir;
2916
2917 /* just check two entries */
2918 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2919 {
2920 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
2921 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2922 return NULL;
2923 }
2924
2925 /* now fill our internal data */
2926 /* TLIBATTR fields */
2927 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2928
2929 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2930 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2931 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2932 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2933 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2934
2935 pTypeLibImpl->lcid = tlbHeader.lcid;
2936
2937 /* name, eventually add to a hash table */
2938 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2939
2940 /* help info */
2941 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2942 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2943
2944 if( tlbHeader.varflags & HELPDLLFLAG)
2945 {
2946 int offset;
2947 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2948 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2949 }
2950
2951 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2952
2953 /* custom data */
2954 if(tlbHeader.CustomDataOffset >= 0)
2955 {
2956 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2957 }
2958
2959 /* fill in type descriptions */
2960 if(tlbSegDir.pTypdescTab.length > 0)
2961 {
2962 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2963 INT16 td[4];
2964 pTypeLibImpl->ctTypeDesc = cTD;
2965 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2966 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2967 for(i=0; i<cTD; )
2968 {
2969 /* FIXME: add several sanity checks here */
2970 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2971 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2972 {
2973 /* FIXME: check safearray */
2974 if(td[3] < 0)
2975 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2976 else
2977 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2978 }
2979 else if(td[0] == VT_CARRAY)
2980 {
2981 /* array descr table here */
2982 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
2983 }
2984 else if(td[0] == VT_USERDEFINED)
2985 {
2986 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2987 }
2988 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2989 }
2990
2991 /* second time around to fill the array subscript info */
2992 for(i=0;i<cTD;i++)
2993 {
2994 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2995 if(tlbSegDir.pArrayDescriptions.offset>0)
2996 {
2997 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2998 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2999
3000 if(td[1]<0)
3001 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3002 else
3003 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3004
3005 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3006
3007 for(j = 0; j<td[2]; j++)
3008 {
3009 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3010 sizeof(INT), &cx, DO_NOT_SEEK);
3011 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3012 sizeof(INT), &cx, DO_NOT_SEEK);
3013 }
3014 }
3015 else
3016 {
3017 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3018 ERR("didn't find array description data\n");
3019 }
3020 }
3021 }
3022
3023 /* imported type libs */
3024 if(tlbSegDir.pImpFiles.offset>0)
3025 {
3026 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
3027 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3028 UINT16 size;
3029
3030 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3031 {
3032 char *name;
3033
3034 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
3035 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
3036 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3037
3038