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 /****************************************************************************
287 * QueryPathOfRegTypeLib [OLEAUT32.164]
288 *
289 * Gets the path to a registered type library.
290 *
291 * PARAMS
292 * guid [I] referenced guid
293 * wMaj [I] major version
294 * wMin [I] minor version
295 * lcid [I] locale id
296 * path [O] path of typelib
297 *
298 * RETURNS
299 * Success: S_OK.
300 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
301 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
302 * opened.
303 */
304 HRESULT WINAPI QueryPathOfRegTypeLib(
305 REFGUID guid,
306 WORD wMaj,
307 WORD wMin,
308 LCID lcid,
309 LPBSTR path )
310 {
311 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
312 LCID myLCID = lcid;
313 HKEY hkey;
314 WCHAR buffer[60];
315 WCHAR Path[MAX_PATH];
316 LONG res;
317
318 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
319
320 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
321 get_typelib_key( guid, wMaj, wMin, buffer );
322
323 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
324 if (res == ERROR_FILE_NOT_FOUND)
325 {
326 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
327 return TYPE_E_LIBNOTREGISTERED;
328 }
329 else if (res != ERROR_SUCCESS)
330 {
331 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
332 return TYPE_E_REGISTRYACCESS;
333 }
334
335 while (hr != S_OK)
336 {
337 LONG dwPathLen = sizeof(Path);
338
339 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
340
341 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
342 {
343 if (!lcid)
344 break;
345 else if (myLCID == lcid)
346 {
347 /* try with sub-langid */
348 myLCID = SUBLANGID(lcid);
349 }
350 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
351 {
352 /* try with system langid */
353 myLCID = 0;
354 }
355 else
356 {
357 break;
358 }
359 }
360 else
361 {
362 *path = SysAllocString( Path );
363 hr = S_OK;
364 }
365 }
366 RegCloseKey( hkey );
367 TRACE_(typelib)("-- 0x%08x\n", hr);
368 return hr;
369 }
370
371 /******************************************************************************
372 * CreateTypeLib [OLEAUT32.160] creates a typelib
373 *
374 * RETURNS
375 * Success: S_OK
376 * Failure: Status
377 */
378 HRESULT WINAPI CreateTypeLib(
379 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
380 ) {
381 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
382 return E_FAIL;
383 }
384
385 /******************************************************************************
386 * LoadTypeLib [OLEAUT32.161]
387 *
388 * Loads a type library
389 *
390 * PARAMS
391 * szFile [I] Name of file to load from.
392 * pptLib [O] Pointer that receives ITypeLib object on success.
393 *
394 * RETURNS
395 * Success: S_OK
396 * Failure: Status
397 *
398 * SEE
399 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
400 */
401 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
402 {
403 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
404 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
405 }
406
407 /******************************************************************************
408 * LoadTypeLibEx [OLEAUT32.183]
409 *
410 * Loads and optionally registers a type library
411 *
412 * RETURNS
413 * Success: S_OK
414 * Failure: Status
415 */
416 HRESULT WINAPI LoadTypeLibEx(
417 LPCOLESTR szFile, /* [in] Name of file to load from */
418 REGKIND regkind, /* [in] Specify kind of registration */
419 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
420 {
421 WCHAR szPath[MAX_PATH+1];
422 HRESULT res;
423
424 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
425
426 *pptLib = NULL;
427
428 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
429
430 if (SUCCEEDED(res))
431 switch(regkind)
432 {
433 case REGKIND_DEFAULT:
434 /* don't register typelibs supplied with full path. Experimentation confirms the following */
435 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
436 (szFile[0] && (szFile[1] == ':'))) break;
437 /* else fall-through */
438
439 case REGKIND_REGISTER:
440 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
441 {
442 IUnknown_Release(*pptLib);
443 *pptLib = 0;
444 }
445 break;
446 case REGKIND_NONE:
447 break;
448 }
449
450 TRACE(" returns %08x\n",res);
451 return res;
452 }
453
454 /******************************************************************************
455 * LoadRegTypeLib [OLEAUT32.162]
456 *
457 * Loads a registered type library.
458 *
459 * PARAMS
460 * rguid [I] GUID of the registered type library.
461 * wVerMajor [I] major version.
462 * wVerMinor [I] minor version.
463 * lcid [I] locale ID.
464 * ppTLib [O] pointer that receives an ITypeLib object on success.
465 *
466 * RETURNS
467 * Success: S_OK.
468 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
469 * LoadTypeLib.
470 */
471 HRESULT WINAPI LoadRegTypeLib(
472 REFGUID rguid,
473 WORD wVerMajor,
474 WORD wVerMinor,
475 LCID lcid,
476 ITypeLib **ppTLib)
477 {
478 BSTR bstr=NULL;
479 HRESULT res;
480
481 *ppTLib = NULL;
482
483 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
484
485 if(SUCCEEDED(res))
486 {
487 res= LoadTypeLib(bstr, ppTLib);
488 SysFreeString(bstr);
489 }
490
491 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
492
493 return res;
494 }
495
496
497 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
498 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
499 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
500 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
501 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
502 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
503
504 /******************************************************************************
505 * RegisterTypeLib [OLEAUT32.163]
506 * Adds information about a type library to the System Registry
507 * NOTES
508 * Docs: ITypeLib FAR * ptlib
509 * Docs: OLECHAR FAR* szFullPath
510 * Docs: OLECHAR FAR* szHelpDir
511 *
512 * RETURNS
513 * Success: S_OK
514 * Failure: Status
515 */
516 HRESULT WINAPI RegisterTypeLib(
517 ITypeLib * ptlib, /* [in] Pointer to the library*/
518 OLECHAR * szFullPath, /* [in] full Path of the library*/
519 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
520 may be NULL*/
521 {
522 static const WCHAR PSOA[] = {'{','','','','2','','4','2','4','-',
523 '','','','','-','','','','','-','C','','','','-',
524 '','','','','','','','','','','4','6','}',0};
525 HRESULT res;
526 TLIBATTR *attr;
527 WCHAR keyName[60];
528 WCHAR tmp[16];
529 HKEY key, subKey;
530 UINT types, tidx;
531 TYPEKIND kind;
532 DWORD disposition;
533
534 if (ptlib == NULL || szFullPath == NULL)
535 return E_INVALIDARG;
536
537 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
538 return E_FAIL;
539
540 #ifdef _WIN64
541 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
542 #else
543 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
544 #endif
545
546 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
547
548 res = S_OK;
549 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
550 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
551 {
552 LPOLESTR doc;
553
554 /* Set the human-readable name of the typelib */
555 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
556 {
557 if (RegSetValueExW(key, NULL, 0, REG_SZ,
558 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
559 res = E_FAIL;
560
561 SysFreeString(doc);
562 }
563 else
564 res = E_FAIL;
565
566 /* Make up the name of the typelib path subkey */
567 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
568
569 /* Create the typelib path subkey */
570 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
571 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
572 {
573 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
574 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
575 res = E_FAIL;
576
577 RegCloseKey(subKey);
578 }
579 else
580 res = E_FAIL;
581
582 /* Create the flags subkey */
583 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
584 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
585 {
586 /* FIXME: is %u correct? */
587 static const WCHAR formatW[] = {'%','u',0};
588 WCHAR buf[20];
589 sprintfW(buf, formatW, attr->wLibFlags);
590 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
591 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
592 res = E_FAIL;
593
594 RegCloseKey(subKey);
595 }
596 else
597 res = E_FAIL;
598
599 /* create the helpdir subkey */
600 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
601 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
602 {
603 BOOL freeHelpDir = FALSE;
604 OLECHAR* pIndexStr;
605
606 /* if we created a new key, and helpDir was null, set the helpdir
607 to the directory which contains the typelib. However,
608 if we just opened an existing key, we leave the helpdir alone */
609 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
610 szHelpDir = SysAllocString(szFullPath);
611 pIndexStr = strrchrW(szHelpDir, '\\');
612 if (pIndexStr) {
613 *pIndexStr = 0;
614 }
615 freeHelpDir = TRUE;
616 }
617
618 /* if we have an szHelpDir, set it! */
619 if (szHelpDir != NULL) {
620 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
621 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
622 res = E_FAIL;
623 }
624 }
625
626 /* tidy up */
627 if (freeHelpDir) SysFreeString(szHelpDir);
628 RegCloseKey(subKey);
629
630 } else {
631 res = E_FAIL;
632 }
633
634 RegCloseKey(key);
635 }
636 else
637 res = E_FAIL;
638
639 /* register OLE Automation-compatible interfaces for this typelib */
640 types = ITypeLib_GetTypeInfoCount(ptlib);
641 for (tidx=0; tidx<types; tidx++) {
642 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
643 LPOLESTR name = NULL;
644 ITypeInfo *tinfo = NULL;
645
646 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
647
648 switch (kind) {
649 case TKIND_INTERFACE:
650 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
651 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
652 break;
653
654 case TKIND_DISPATCH:
655 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
656 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
657 break;
658
659 default:
660 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
661 break;
662 }
663
664 if (tinfo) {
665 TYPEATTR *tattr = NULL;
666 ITypeInfo_GetTypeAttr(tinfo, &tattr);
667
668 if (tattr) {
669 TRACE_(typelib)("guid=%s, flags=%04x (",
670 debugstr_guid(&tattr->guid),
671 tattr->wTypeFlags);
672
673 if (TRACE_ON(typelib)) {
674 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
675 XX(FAPPOBJECT);
676 XX(FCANCREATE);
677 XX(FLICENSED);
678 XX(FPREDECLID);
679 XX(FHIDDEN);
680 XX(FCONTROL);
681 XX(FDUAL);
682 XX(FNONEXTENSIBLE);
683 XX(FOLEAUTOMATION);
684 XX(FRESTRICTED);
685 XX(FAGGREGATABLE);
686 XX(FREPLACEABLE);
687 XX(FDISPATCHABLE);
688 XX(FREVERSEBIND);
689 XX(FPROXY);
690 #undef XX
691 MESSAGE("\n");
692 }
693
694 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
695 {
696 /* register interface<->typelib coupling */
697 get_interface_key( &tattr->guid, keyName );
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
699 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
700 {
701 if (name)
702 RegSetValueExW(key, NULL, 0, REG_SZ,
703 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
704
705 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
706 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
707 RegSetValueExW(subKey, NULL, 0, REG_SZ,
708 (const BYTE *)PSOA, sizeof PSOA);
709 RegCloseKey(subKey);
710 }
711
712 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
713 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
714 RegSetValueExW(subKey, NULL, 0, REG_SZ,
715 (const BYTE *)PSOA, sizeof PSOA);
716 RegCloseKey(subKey);
717 }
718
719 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
720 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
721 {
722 WCHAR buffer[40];
723 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
724 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
725
726 StringFromGUID2(&attr->guid, buffer, 40);
727 RegSetValueExW(subKey, NULL, 0, REG_SZ,
728 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
729 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
730 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
731 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
732 RegCloseKey(subKey);
733 }
734
735 RegCloseKey(key);
736 }
737 }
738
739 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
740 }
741
742 ITypeInfo_Release(tinfo);
743 }
744
745 SysFreeString(name);
746 }
747 }
748
749 ITypeLib_ReleaseTLibAttr(ptlib, attr);
750
751 return res;
752 }
753
754
755 /******************************************************************************
756 * UnRegisterTypeLib [OLEAUT32.186]
757 * Removes information about a type library from the System Registry
758 * NOTES
759 *
760 * RETURNS
761 * Success: S_OK
762 * Failure: Status
763 */
764 HRESULT WINAPI UnRegisterTypeLib(
765 REFGUID libid, /* [in] Guid of the library */
766 WORD wVerMajor, /* [in] major version */
767 WORD wVerMinor, /* [in] minor version */
768 LCID lcid, /* [in] locale id */
769 SYSKIND syskind)
770 {
771 BSTR tlibPath = NULL;
772 DWORD tmpLength;
773 WCHAR keyName[60];
774 WCHAR subKeyName[50];
775 int result = S_OK;
776 DWORD i = 0;
777 BOOL deleteOtherStuff;
778 HKEY key = NULL;
779 HKEY subKey = NULL;
780 TYPEATTR* typeAttr = NULL;
781 TYPEKIND kind;
782 ITypeInfo* typeInfo = NULL;
783 ITypeLib* typeLib = NULL;
784 int numTypes;
785
786 TRACE("(IID: %s)\n",debugstr_guid(libid));
787
788 /* Create the path to the key */
789 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
790
791 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
792 {
793 TRACE("Unsupported syskind %i\n", syskind);
794 result = E_INVALIDARG;
795 goto end;
796 }
797
798 /* get the path to the typelib on disk */
799 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
800 result = E_INVALIDARG;
801 goto end;
802 }
803
804 /* Try and open the key to the type library. */
805 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
806 result = E_INVALIDARG;
807 goto end;
808 }
809
810 /* Try and load the type library */
811 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
812 result = TYPE_E_INVALIDSTATE;
813 goto end;
814 }
815
816 /* remove any types registered with this typelib */
817 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
818 for (i=0; i<numTypes; i++) {
819 /* get the kind of type */
820 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
821 goto enddeleteloop;
822 }
823
824 /* skip non-interfaces, and get type info for the type */
825 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
826 goto enddeleteloop;
827 }
828 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
829 goto enddeleteloop;
830 }
831 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
832 goto enddeleteloop;
833 }
834
835 /* the path to the type */
836 get_interface_key( &typeAttr->guid, subKeyName );
837
838 /* Delete its bits */
839 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
840 goto enddeleteloop;
841 }
842 RegDeleteKeyW(subKey, ProxyStubClsidW);
843 RegDeleteKeyW(subKey, ProxyStubClsid32W);
844 RegDeleteKeyW(subKey, TypeLibW);
845 RegCloseKey(subKey);
846 subKey = NULL;
847 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
848
849 enddeleteloop:
850 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
851 typeAttr = NULL;
852 if (typeInfo) ITypeInfo_Release(typeInfo);
853 typeInfo = NULL;
854 }
855
856 /* Now, delete the type library path subkey */
857 get_lcid_subkey( lcid, syskind, subKeyName );
858 RegDeleteKeyW(key, subKeyName);
859 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
860 RegDeleteKeyW(key, subKeyName);
861
862 /* check if there is anything besides the FLAGS/HELPDIR keys.
863 If there is, we don't delete them */
864 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
865 deleteOtherStuff = TRUE;
866 i = 0;
867 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
868 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
869
870 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
871 if (!strcmpW(subKeyName, FLAGSW)) continue;
872 if (!strcmpW(subKeyName, HELPDIRW)) continue;
873 deleteOtherStuff = FALSE;
874 break;
875 }
876
877 /* only delete the other parts of the key if we're absolutely sure */
878 if (deleteOtherStuff) {
879 RegDeleteKeyW(key, FLAGSW);
880 RegDeleteKeyW(key, HELPDIRW);
881 RegCloseKey(key);
882 key = NULL;
883
884 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
885 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
886 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
887 }
888
889 end:
890 SysFreeString(tlibPath);
891 if (typeLib) ITypeLib_Release(typeLib);
892 if (subKey) RegCloseKey(subKey);
893 if (key) RegCloseKey(key);
894 return result;
895 }
896
897 /*======================= ITypeLib implementation =======================*/
898
899 typedef struct tagTLBCustData
900 {
901 GUID guid;
902 VARIANT data;
903 struct tagTLBCustData* next;
904 } TLBCustData;
905
906 /* data structure for import typelibs */
907 typedef struct tagTLBImpLib
908 {
909 int offset; /* offset in the file (MSFT)
910 offset in nametable (SLTG)
911 just used to identify library while reading
912 data from file */
913 GUID guid; /* libid */
914 BSTR name; /* name */
915
916 LCID lcid; /* lcid of imported typelib */
917
918 WORD wVersionMajor; /* major version number */
919 WORD wVersionMinor; /* minor version number */
920
921 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
922 NULL if not yet loaded */
923 struct tagTLBImpLib * next;
924 } TLBImpLib;
925
926 /* internal ITypeLib data */
927 typedef struct tagITypeLibImpl
928 {
929 const ITypeLib2Vtbl *lpVtbl;
930 const ITypeCompVtbl *lpVtblTypeComp;
931 LONG ref;
932 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
933 LCID lcid;
934
935 /* strings can be stored in tlb as multibyte strings BUT they are *always*
936 * exported to the application as a UNICODE string.
937 */
938 BSTR Name;
939 BSTR DocString;
940 BSTR HelpFile;
941 BSTR HelpStringDll;
942 DWORD dwHelpContext;
943 int TypeInfoCount; /* nr of typeinfo's in librarry */
944 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
945 int ctCustData; /* number of items in cust data list */
946 TLBCustData * pCustData; /* linked list to cust data */
947 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
948 int ctTypeDesc; /* number of items in type desc array */
949 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
950 library. Only used while reading MSFT
951 typelibs */
952 struct list ref_list; /* list of ref types in this typelib */
953 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
954
955
956 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
957 struct tagITypeLibImpl *next, *prev;
958 WCHAR *path;
959 INT index;
960 } ITypeLibImpl;
961
962 static const ITypeLib2Vtbl tlbvt;
963 static const ITypeCompVtbl tlbtcvt;
964
965 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
966 {
967 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
968 }
969
970 /* ITypeLib methods */
971 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
972 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
973
974 /*======================= ITypeInfo implementation =======================*/
975
976 /* data for referenced types */
977 typedef struct tagTLBRefType
978 {
979 INT index; /* Type index for internal ref or for external ref
980 it the format is SLTG. -2 indicates to
981 use guid */
982
983 GUID guid; /* guid of the referenced type */
984 /* if index == TLB_REF_USE_GUID */
985
986 HREFTYPE reference; /* The href of this ref */
987 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
988 TLB_REF_INTERNAL for internal refs
989 TLB_REF_NOT_FOUND for broken refs */
990
991 struct list entry;
992 } TLBRefType;
993
994 #define TLB_REF_USE_GUID -2
995
996 #define TLB_REF_INTERNAL (void*)-2
997 #define TLB_REF_NOT_FOUND (void*)-1
998
999 /* internal Parameter data */
1000 typedef struct tagTLBParDesc
1001 {
1002 BSTR Name;
1003 int ctCustData;
1004 TLBCustData * pCustData; /* linked list to cust data */
1005 } TLBParDesc;
1006
1007 /* internal Function data */
1008 typedef struct tagTLBFuncDesc
1009 {
1010 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1011 BSTR Name; /* the name of this function */
1012 TLBParDesc *pParamDesc; /* array with param names and custom data */
1013 int helpcontext;
1014 int HelpStringContext;
1015 BSTR HelpString;
1016 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
1017 int ctCustData;
1018 TLBCustData * pCustData; /* linked list to cust data; */
1019 struct tagTLBFuncDesc * next;
1020 } TLBFuncDesc;
1021
1022 /* internal Variable data */
1023 typedef struct tagTLBVarDesc
1024 {
1025 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1026 BSTR Name; /* the name of this variable */
1027 int HelpContext;
1028 int HelpStringContext; /* FIXME: where? */
1029 BSTR HelpString;
1030 int ctCustData;
1031 TLBCustData * pCustData;/* linked list to cust data; */
1032 struct tagTLBVarDesc * next;
1033 } TLBVarDesc;
1034
1035 /* internal implemented interface data */
1036 typedef struct tagTLBImplType
1037 {
1038 HREFTYPE hRef; /* hRef of interface */
1039 int implflags; /* IMPLFLAG_*s */
1040 int ctCustData;
1041 TLBCustData * pCustData;/* linked list to custom data; */
1042 struct tagTLBImplType *next;
1043 } TLBImplType;
1044
1045 /* internal TypeInfo data */
1046 typedef struct tagITypeInfoImpl
1047 {
1048 const ITypeInfo2Vtbl *lpVtbl;
1049 const ITypeCompVtbl *lpVtblTypeComp;
1050 LONG ref;
1051 BOOL no_free_data; /* don't free data structures */
1052 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1053 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1054 int index; /* index in this typelib; */
1055 HREFTYPE hreftype; /* hreftype for app object binding */
1056 /* type libs seem to store the doc strings in ascii
1057 * so why should we do it in unicode?
1058 */
1059 BSTR Name;
1060 BSTR DocString;
1061 BSTR DllName;
1062 DWORD dwHelpContext;
1063 DWORD dwHelpStringContext;
1064
1065 /* functions */
1066 TLBFuncDesc * funclist; /* linked list with function descriptions */
1067
1068 /* variables */
1069 TLBVarDesc * varlist; /* linked list with variable descriptions */
1070
1071 /* Implemented Interfaces */
1072 TLBImplType * impltypelist;
1073
1074 int ctCustData;
1075 TLBCustData * pCustData; /* linked list to cust data; */
1076 struct tagITypeInfoImpl * next;
1077 } ITypeInfoImpl;
1078
1079 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1080 {
1081 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1082 }
1083
1084 static const ITypeInfo2Vtbl tinfvt;
1085 static const ITypeCompVtbl tcompvt;
1086
1087 static ITypeInfo2 * ITypeInfo_Constructor(void);
1088
1089 typedef struct tagTLBContext
1090 {
1091 unsigned int oStart; /* start of TLB in file */
1092 unsigned int pos; /* current pos */
1093 unsigned int length; /* total length */
1094 void *mapping; /* memory mapping */
1095 MSFT_SegDir * pTblDir;
1096 ITypeLibImpl* pLibInfo;
1097 } TLBContext;
1098
1099
1100 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1101
1102 /*
1103 debug
1104 */
1105 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1106 if (pTD->vt & VT_RESERVED)
1107 szVarType += strlen(strcpy(szVarType, "reserved | "));
1108 if (pTD->vt & VT_BYREF)
1109 szVarType += strlen(strcpy(szVarType, "ref to "));
1110 if (pTD->vt & VT_ARRAY)
1111 szVarType += strlen(strcpy(szVarType, "array of "));
1112 if (pTD->vt & VT_VECTOR)
1113 szVarType += strlen(strcpy(szVarType, "vector of "));
1114 switch(pTD->vt & VT_TYPEMASK) {
1115 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1116 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1117 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1118 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1119 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1120 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1121 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1122 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1123 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1124 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1125 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1126 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1127 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1128 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1129 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1130 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1131 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1132 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1133 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1134 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1135 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1136 pTD->u.hreftype); break;
1137 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1138 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1139 case VT_PTR: sprintf(szVarType, "ptr to ");
1140 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1141 break;
1142 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1143 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1144 break;
1145 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1146 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1147 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1148 break;
1149
1150 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1151 }
1152 }
1153
1154 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1155 char buf[200];
1156 USHORT flags = edesc->u.paramdesc.wParamFlags;
1157 dump_TypeDesc(&edesc->tdesc,buf);
1158 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1159 MESSAGE("\t\tu.paramdesc.wParamFlags");
1160 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1161 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1162 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1163 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1164 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1165 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1166 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1167 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1168 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1169 }
1170 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1171 int i;
1172 MESSAGE("memid is %08x\n",funcdesc->memid);
1173 for (i=0;i<funcdesc->cParams;i++) {
1174 MESSAGE("Param %d:\n",i);
1175 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1176 }
1177 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1178 switch (funcdesc->funckind) {
1179 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1180 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1181 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1182 case FUNC_STATIC: MESSAGE("static");break;
1183 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1184 default: MESSAGE("unknown");break;
1185 }
1186 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1187 switch (funcdesc->invkind) {
1188 case INVOKE_FUNC: MESSAGE("func");break;
1189 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1190 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1191 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1192 }
1193 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1194 switch (funcdesc->callconv) {
1195 case CC_CDECL: MESSAGE("cdecl");break;
1196 case CC_PASCAL: MESSAGE("pascal");break;
1197 case CC_STDCALL: MESSAGE("stdcall");break;
1198 case CC_SYSCALL: MESSAGE("syscall");break;
1199 default:break;
1200 }
1201 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1202 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1203 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1204
1205 MESSAGE("\telemdescFunc (return value type):\n");
1206 dump_ELEMDESC(&funcdesc->elemdescFunc);
1207 }
1208
1209 static const char * const typekind_desc[] =
1210 {
1211 "TKIND_ENUM",
1212 "TKIND_RECORD",
1213 "TKIND_MODULE",
1214 "TKIND_INTERFACE",
1215 "TKIND_DISPATCH",
1216 "TKIND_COCLASS",
1217 "TKIND_ALIAS",
1218 "TKIND_UNION",
1219 "TKIND_MAX"
1220 };
1221
1222 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1223 {
1224 int i;
1225 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1226 for (i=0;i<pfd->funcdesc.cParams;i++)
1227 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1228
1229
1230 dump_FUNCDESC(&(pfd->funcdesc));
1231
1232 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1233 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1234 }
1235 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1236 {
1237 while (pfd)
1238 {
1239 dump_TLBFuncDescOne(pfd);
1240 pfd = pfd->next;
1241 };
1242 }
1243 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1244 {
1245 while (pvd)
1246 {
1247 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1248 pvd = pvd->next;
1249 };
1250 }
1251
1252 static void dump_TLBImpLib(const TLBImpLib *import)
1253 {
1254 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1255 debugstr_w(import->name));
1256 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1257 import->wVersionMinor, import->lcid, import->offset);
1258 }
1259
1260 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1261 {
1262 TLBRefType *ref;
1263
1264 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1265 {
1266 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1267 if(ref->index == -1)
1268 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1269 else
1270 TRACE_(typelib)("type no: %d\n", ref->index);
1271
1272 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1273 {
1274 TRACE_(typelib)("in lib\n");
1275 dump_TLBImpLib(ref->pImpTLInfo);
1276 }
1277 }
1278 }
1279
1280 static void dump_TLBImplType(const TLBImplType * impl)
1281 {
1282 while (impl) {
1283 TRACE_(typelib)(
1284 "implementing/inheriting interface hRef = %x implflags %x\n",
1285 impl->hRef, impl->implflags);
1286 impl = impl->next;
1287 }
1288 }
1289
1290 static void dump_Variant(const VARIANT * pvar)
1291 {
1292 SYSTEMTIME st;
1293
1294 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1295
1296 if (pvar)
1297 {
1298 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1299 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1300 {
1301 TRACE(",%p", V_BYREF(pvar));
1302 }
1303 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1304 {
1305 TRACE(",%p", V_ARRAY(pvar));
1306 }
1307 else switch (V_TYPE(pvar))
1308 {
1309 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1310 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1311 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1312 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1313 case VT_INT:
1314 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1315 case VT_UINT:
1316 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1317 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1318 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1319 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1320 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1321 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1322 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1323 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1324 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1325 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1326 V_CY(pvar).s.Lo); break;
1327 case VT_DATE:
1328 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1329 TRACE(",<invalid>");
1330 else
1331 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1332 st.wHour, st.wMinute, st.wSecond);
1333 break;
1334 case VT_ERROR:
1335 case VT_VOID:
1336 case VT_USERDEFINED:
1337 case VT_EMPTY:
1338 case VT_NULL: break;
1339 default: TRACE(",?"); break;
1340 }
1341 }
1342 TRACE("}\n");
1343 }
1344
1345 static void dump_DispParms(const DISPPARAMS * pdp)
1346 {
1347 unsigned int index;
1348
1349 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1350
1351 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1352 {
1353 TRACE("named args:\n");
1354 for (index = 0; index < pdp->cNamedArgs; index++)
1355 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1356 }
1357
1358 if (pdp->cArgs && pdp->rgvarg)
1359 {
1360 TRACE("args:\n");
1361 for (index = 0; index < pdp->cArgs; index++)
1362 dump_Variant( &pdp->rgvarg[index] );
1363 }
1364 }
1365
1366 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1367 {
1368 TRACE("%p ref=%u\n", pty, pty->ref);
1369 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1370 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1371 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1372 TRACE("fct:%u var:%u impl:%u\n",
1373 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1374 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1375 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1376 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1377 if (TRACE_ON(ole))
1378 dump_TLBFuncDesc(pty->funclist);
1379 dump_TLBVarDesc(pty->varlist);
1380 dump_TLBImplType(pty->impltypelist);
1381 }
1382
1383 static void dump_VARDESC(const VARDESC *v)
1384 {
1385 MESSAGE("memid %d\n",v->memid);
1386 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1387 MESSAGE("oInst %d\n",v->u.oInst);
1388 dump_ELEMDESC(&(v->elemdescVar));
1389 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1390 MESSAGE("varkind %d\n",v->varkind);
1391 }
1392
1393 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1394 {
1395 /* VT_LPWSTR is largest type that */
1396 /* may appear in type description*/
1397 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1398 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1399 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1400 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1401 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1402 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1403 {{0},30},{{0},31}
1404 };
1405
1406 static void TLB_abort(void)
1407 {
1408 DebugBreak();
1409 }
1410
1411 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1412 static void * TLB_Alloc(unsigned size)
1413 {
1414 void * ret;
1415 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1416 /* FIXME */
1417 ERR("cannot allocate memory\n");
1418 }
1419 return ret;
1420 }
1421
1422 static void TLB_Free(void * ptr)
1423 {
1424 HeapFree(GetProcessHeap(), 0, ptr);
1425 }
1426
1427 /* returns the size required for a deep copy of a typedesc into a
1428 * flat buffer */
1429 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1430 {
1431 SIZE_T size = 0;
1432
1433 if (alloc_initial_space)
1434 size += sizeof(TYPEDESC);
1435
1436 switch (tdesc->vt)
1437 {
1438 case VT_PTR:
1439 case VT_SAFEARRAY:
1440 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1441 break;
1442 case VT_CARRAY:
1443 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1444 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1445 break;
1446 }
1447 return size;
1448 }
1449
1450 /* deep copy a typedesc into a flat buffer */
1451 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1452 {
1453 if (!dest)
1454 {
1455 dest = buffer;
1456 buffer = (char *)buffer + sizeof(TYPEDESC);
1457 }
1458
1459 *dest = *src;
1460
1461 switch (src->vt)
1462 {
1463 case VT_PTR:
1464 case VT_SAFEARRAY:
1465 dest->u.lptdesc = buffer;
1466 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1467 break;
1468 case VT_CARRAY:
1469 dest->u.lpadesc = buffer;
1470 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1471 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1472 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1473 break;
1474 }
1475 return buffer;
1476 }
1477
1478 /* free custom data allocated by MSFT_CustData */
1479 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1480 {
1481 TLBCustData *pCustDataNext;
1482 for (; pCustData; pCustData = pCustDataNext)
1483 {
1484 VariantClear(&pCustData->data);
1485
1486 pCustDataNext = pCustData->next;
1487 TLB_Free(pCustData);
1488 }
1489 }
1490
1491 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1492 {
1493 DWORD len;
1494 BSTR ret;
1495
1496 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1497 ret = SysAllocStringLen(NULL, len - 1);
1498 if (!ret) return ret;
1499 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1500 return ret;
1501 }
1502
1503 /**********************************************************************
1504 *
1505 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1506 */
1507 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1508 {
1509 return pcx->pos;
1510 }
1511
1512 static inline void MSFT_Seek(TLBContext *pcx, long where)
1513 {
1514 if (where != DO_NOT_SEEK)
1515 {
1516 where += pcx->oStart;
1517 if (where > pcx->length)
1518 {
1519 /* FIXME */
1520 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1521 TLB_abort();
1522 }
1523 pcx->pos = where;
1524 }
1525 }
1526
1527 /* read function */
1528 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1529 {
1530 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1531 pcx->pos, count, pcx->oStart, pcx->length, where);
1532
1533 MSFT_Seek(pcx, where);
1534 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1535 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1536 pcx->pos += count;
1537 return count;
1538 }
1539
1540 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1541 long where )
1542 {
1543 DWORD ret;
1544
1545 ret = MSFT_Read(buffer, count, pcx, where);
1546 FromLEDWords(buffer, ret);
1547
1548 return ret;
1549 }
1550
1551 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1552 long where )
1553 {
1554 DWORD ret;
1555
1556 ret = MSFT_Read(buffer, count, pcx, where);
1557 FromLEWords(buffer, ret);
1558
1559 return ret;
1560 }
1561
1562 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1563 {
1564 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1565 memset(pGuid,0, sizeof(GUID));
1566 return;
1567 }
1568 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1569 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1570 pGuid->Data2 = FromLEWord(pGuid->Data2);
1571 pGuid->Data3 = FromLEWord(pGuid->Data3);
1572 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1573 }
1574
1575 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1576 {
1577 MSFT_NameIntro niName;
1578
1579 if (offset < 0)
1580 {
1581 ERR_(typelib)("bad offset %d\n", offset);
1582 return -1;
1583 }
1584
1585 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1586 pcx->pTblDir->pNametab.offset+offset);
1587
1588 return niName.hreftype;
1589 }
1590
1591 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1592 {
1593 char * name;
1594 MSFT_NameIntro niName;
1595 int lengthInChars;
1596 BSTR bstrName = NULL;
1597
1598 if (offset < 0)
1599 {
1600 ERR_(typelib)("bad offset %d\n", offset);
1601 return NULL;
1602 }
1603 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1604 pcx->pTblDir->pNametab.offset+offset);
1605 niName.namelen &= 0xFF; /* FIXME: correct ? */
1606 name=TLB_Alloc((niName.namelen & 0xff) +1);
1607 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1608 name[niName.namelen & 0xff]='\0';
1609
1610 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1611 name, -1, NULL, 0);
1612
1613 /* no invalid characters in string */
1614 if (lengthInChars)
1615 {
1616 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1617
1618 /* don't check for invalid character since this has been done previously */
1619 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1620 }
1621 TLB_Free(name);
1622
1623 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1624 return bstrName;
1625 }
1626
1627 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1628 {
1629 char * string;
1630 INT16 length;
1631 int lengthInChars;
1632 BSTR bstr = NULL;
1633
1634 if(offset<0) return NULL;
1635 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1636 if(length <= 0) return 0;
1637 string=TLB_Alloc(length +1);
1638 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1639 string[length]='\0';
1640
1641 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1642 string, -1, NULL, 0);
1643
1644 /* no invalid characters in string */
1645 if (lengthInChars)
1646 {
1647 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1648
1649 /* don't check for invalid character since this has been done previously */
1650 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1651 }
1652 TLB_Free(string);
1653
1654 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1655 return bstr;
1656 }
1657 /*
1658 * read a value and fill a VARIANT structure
1659 */
1660 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1661 {
1662 int size;
1663
1664 TRACE_(typelib)("\n");
1665
1666 if(offset <0) { /* data are packed in here */
1667 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1668 V_I4(pVar) = offset & 0x3ffffff;
1669 return;
1670 }
1671 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1672 pcx->pTblDir->pCustData.offset + offset );
1673 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1674 switch (V_VT(pVar)){
1675 case VT_EMPTY: /* FIXME: is this right? */
1676 case VT_NULL: /* FIXME: is this right? */
1677 case VT_I2 : /* this should not happen */
1678 case VT_I4 :
1679 case VT_R4 :
1680 case VT_ERROR :
1681 case VT_BOOL :
1682 case VT_I1 :
1683 case VT_UI1 :
1684 case VT_UI2 :
1685 case VT_UI4 :
1686 case VT_INT :
1687 case VT_UINT :
1688 case VT_VOID : /* FIXME: is this right? */
1689 case VT_HRESULT :
1690 size=4; break;
1691 case VT_R8 :
1692 case VT_CY :
1693 case VT_DATE :
1694 case VT_I8 :
1695 case VT_UI8 :
1696 case VT_DECIMAL : /* FIXME: is this right? */
1697 case VT_FILETIME :
1698 size=8;break;
1699 /* pointer types with known behaviour */
1700 case VT_BSTR :{
1701 char * ptr;
1702 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1703 if(size < 0) {
1704 char next;
1705 DWORD origPos = MSFT_Tell(pcx), nullPos;
1706
1707 do {
1708 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1709 } while (next);
1710 nullPos = MSFT_Tell(pcx);
1711 size = nullPos - origPos;
1712 MSFT_Seek(pcx, origPos);
1713 }
1714 ptr=TLB_Alloc(size);/* allocate temp buffer */
1715 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1716 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1717 /* FIXME: do we need a AtoW conversion here? */
1718 V_UNION(pVar, bstrVal[size])='\0';
1719 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1720 TLB_Free(ptr);
1721 }
1722 size=-4; break;
1723 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1724 case VT_DISPATCH :
1725 case VT_VARIANT :
1726 case VT_UNKNOWN :
1727 case VT_PTR :
1728 case VT_SAFEARRAY :
1729 case VT_CARRAY :
1730 case VT_USERDEFINED :
1731 case VT_LPSTR :
1732 case VT_LPWSTR :
1733 case VT_BLOB :
1734 case VT_STREAM :
1735 case VT_STORAGE :
1736 case VT_STREAMED_OBJECT :
1737 case VT_STORED_OBJECT :
1738 case VT_BLOB_OBJECT :
1739 case VT_CF :
1740 case VT_CLSID :
1741 default:
1742 size=0;
1743 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1744 V_VT(pVar));
1745 }
1746
1747 if(size>0) /* (big|small) endian correct? */
1748 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1749 return;
1750 }
1751 /*
1752 * create a linked list with custom data
1753 */
1754 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1755 {
1756 MSFT_CDGuid entry;
1757 TLBCustData* pNew;
1758 int count=0;
1759
1760 TRACE_(typelib)("\n");
1761
1762 while(offset >=0){
1763 count++;
1764 pNew=TLB_Alloc(sizeof(TLBCustData));
1765 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1766 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1767 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1768 /* add new custom data at head of the list */
1769 pNew->next=*ppCustData;
1770 *ppCustData=pNew;
1771 offset = entry.next;
1772 }
1773 return count;
1774 }
1775
1776 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1777 ITypeInfoImpl *pTI)
1778 {
1779 if(type <0)
1780 pTd->vt=type & VT_TYPEMASK;
1781 else
1782 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1783
1784 if(pTd->vt == VT_USERDEFINED)
1785 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1786
1787 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1788 }
1789
1790 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1791 {
1792 /* resolve referenced type if any */
1793 while (lpTypeDesc)
1794 {
1795 switch (lpTypeDesc->vt)
1796 {
1797 case VT_PTR:
1798 lpTypeDesc = lpTypeDesc->u.lptdesc;
1799 break;
1800
1801 case VT_CARRAY:
1802 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1803 break;
1804
1805 case VT_USERDEFINED:
1806 MSFT_DoRefType(pcx, pTI->pTypeLib,
1807 lpTypeDesc->u.hreftype);
1808
1809 lpTypeDesc = NULL;
1810 break;
1811
1812 default:
1813 lpTypeDesc = NULL;
1814 }
1815 }
1816 }
1817
1818 static void
1819 MSFT_DoFuncs(TLBContext* pcx,
1820 ITypeInfoImpl* pTI,
1821 int cFuncs,
1822 int cVars,
1823 int offset,
1824 TLBFuncDesc** pptfd)
1825 {
1826 /*
1827 * member information is stored in a data structure at offset
1828 * indicated by the memoffset field of the typeinfo structure
1829 * There are several distinctive parts.
1830 * The first part starts with a field that holds the total length
1831 * of this (first) part excluding this field. Then follow the records,
1832 * for each member there is one record.
1833 *
1834 * The first entry is always the length of the record (including this
1835 * length word).
1836 * The rest of the record depends on the type of the member. If there is
1837 * a field indicating the member type (function, variable, interface, etc)
1838 * I have not found it yet. At this time we depend on the information
1839 * in the type info and the usual order how things are stored.
1840 *
1841 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1842 * for each member;
1843 *
1844 * Third is an equal sized array with file offsets to the name entry
1845 * of each member.
1846 *
1847 * The fourth and last (?) part is an array with offsets to the records
1848 * in the first part of this file segment.
1849 */
1850
1851 int infolen, nameoffset, reclength, nrattributes, i;
1852 int recoffset = offset + sizeof(INT);
1853
1854 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1855 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1856 TLBFuncDesc *ptfd_prev = NULL;
1857
1858 TRACE_(typelib)("\n");
1859
1860 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1861
1862 for ( i = 0; i < cFuncs ; i++ )
1863 {
1864 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1865
1866 /* name, eventually add to a hash table */
1867 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1868 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1869
1870 /* nameoffset is sometimes -1 on the second half of a propget/propput
1871 * pair of functions */
1872 if ((nameoffset == -1) && (i > 0))
1873 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1874 else
1875 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1876
1877 /* read the function information record */
1878 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1879
1880 reclength &= 0xffff;
1881
1882 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1883
1884 /* do the attributes */
1885 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1886 / sizeof(int);
1887
1888 if ( nrattributes > 0 )
1889 {
1890 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1891
1892 if ( nrattributes > 1 )
1893 {
1894 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1895 pFuncRec->OptAttr[1]) ;
1896
1897 if ( nrattributes > 2 )
1898 {
1899 if ( pFuncRec->FKCCIC & 0x2000 )
1900 {
1901 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1902 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1903 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1904 }
1905 else
1906 {
1907 (*pptfd)->Entry = MSFT_ReadString(pcx,
1908 pFuncRec->OptAttr[2]);
1909 }
1910 if( nrattributes > 5 )
1911 {
1912 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1913
1914 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1915 {
1916 MSFT_CustData(pcx,
1917 pFuncRec->OptAttr[6],
1918 &(*pptfd)->pCustData);
1919 }
1920 }
1921 }
1922 else
1923 {
1924 (*pptfd)->Entry = (BSTR)-1;
1925 }
1926 }
1927 }
1928
1929 /* fill the FuncDesc Structure */
1930 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1931 offset + infolen + ( i + 1) * sizeof(INT));
1932
1933 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1934 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1935 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1936 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1937 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1938 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1939 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1940
1941 MSFT_GetTdesc(pcx,
1942 pFuncRec->DataType,
1943 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1944 pTI);
1945 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1946
1947 /* do the parameters/arguments */
1948 if(pFuncRec->nrargs)
1949 {
1950 int j = 0;
1951 MSFT_ParameterInfo paraminfo;
1952
1953 (*pptfd)->funcdesc.lprgelemdescParam =
1954 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1955
1956 (*pptfd)->pParamDesc =
1957 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1958
1959 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1960 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1961
1962 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1963 {
1964 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1965
1966 MSFT_GetTdesc(pcx,
1967 paraminfo.DataType,
1968 &elemdesc->tdesc,
1969 pTI);
1970
1971 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1972
1973 /* name */
1974 if (paraminfo.oName == -1)
1975 /* this occurs for [propput] or [propget] methods, so
1976 * we should just set the name of the parameter to the
1977 * name of the method. */
1978 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1979 else
1980 (*pptfd)->pParamDesc[j].Name =
1981 MSFT_ReadName( pcx, paraminfo.oName );
1982 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1983
1984 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1985
1986 /* default value */
1987 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1988 (pFuncRec->FKCCIC & 0x1000) )
1989 {
1990 INT* pInt = (INT *)((char *)pFuncRec +
1991 reclength -
1992 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1993
1994 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1995
1996 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1997 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1998
1999 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2000 pInt[j], pcx);
2001 }
2002 else
2003 elemdesc->u.paramdesc.pparamdescex = NULL;
2004 /* custom info */
2005 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2006 {
2007 MSFT_CustData(pcx,
2008 pFuncRec->OptAttr[7+j],
2009 &(*pptfd)->pParamDesc[j].pCustData);
2010 }
2011
2012 /* SEEK value = jump to offset,
2013 * from there jump to the end of record,
2014 * go back by (j-1) arguments
2015 */
2016 MSFT_ReadLEDWords( ¶minfo ,
2017 sizeof(MSFT_ParameterInfo), pcx,
2018 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2019 * sizeof(MSFT_ParameterInfo)));
2020 }
2021 }
2022
2023 /* scode is not used: archaic win16 stuff FIXME: right? */
2024 (*pptfd)->funcdesc.cScodes = 0 ;
2025 (*pptfd)->funcdesc.lprgscode = NULL ;
2026
2027 ptfd_prev = *pptfd;
2028 pptfd = & ((*pptfd)->next);
2029 recoffset += reclength;
2030 }
2031 HeapFree(GetProcessHeap(), 0, recbuf);
2032 }
2033
2034 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2035 int cVars, int offset, TLBVarDesc ** pptvd)
2036 {
2037 int infolen, nameoffset, reclength;
2038 char recbuf[256];
2039 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2040 int i;
2041 int recoffset;
2042
2043 TRACE_(typelib)("\n");
2044
2045 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2046 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2047 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2048 recoffset += offset+sizeof(INT);
2049 for(i=0;i<cVars;i++){
2050 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2051 /* name, eventually add to a hash table */
2052 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2053 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2054 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2055 /* read the variable information record */
2056 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2057 reclength &=0xff;
2058 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2059 /* Optional data */
2060 if(reclength >(6*sizeof(INT)) )
2061 (*pptvd)->HelpContext=pVarRec->HelpContext;
2062 if(reclength >(7*sizeof(INT)) )
2063 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2064 if(reclength >(8*sizeof(INT)) )
2065 if(reclength >(9*sizeof(INT)) )
2066 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2067 /* fill the VarDesc Structure */
2068 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2069 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2070 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2071 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2072 MSFT_GetTdesc(pcx, pVarRec->DataType,
2073 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2074 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2075 if(pVarRec->VarKind == VAR_CONST ){
2076 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2077 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2078 pVarRec->OffsValue, pcx);
2079 } else
2080 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2081 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2082 pptvd=&((*pptvd)->next);
2083 recoffset += reclength;
2084 }
2085 }
2086 /* fill in data for a hreftype (offset). When the referenced type is contained
2087 * in the typelib, it's just an (file) offset in the type info base dir.
2088 * If comes from import, it's an offset+1 in the ImpInfo table
2089 * */
2090 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2091 int offset)
2092 {
2093 TLBRefType *ref;
2094
2095 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2096
2097 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2098 {
2099 if(ref->reference == offset) return;
2100 }
2101
2102 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2103 list_add_tail(&pTL->ref_list, &ref->entry);
2104
2105 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2106 /* external typelib */
2107 MSFT_ImpInfo impinfo;
2108 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2109
2110 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2111
2112 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2113 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2114 while (pImpLib){ /* search the known offsets of all import libraries */
2115 if(pImpLib->offset==impinfo.oImpFile) break;
2116 pImpLib=pImpLib->next;
2117 }
2118 if(pImpLib){
2119 ref->reference = offset;
2120 ref->pImpTLInfo = pImpLib;
2121 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2122 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2123 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2124 ref->index = TLB_REF_USE_GUID;
2125 } else
2126 ref->index = impinfo.oGuid;
2127 }else{
2128 ERR("Cannot find a reference\n");
2129 ref->reference = -1;
2130 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2131 }
2132 }else{
2133 /* in this typelib */
2134 ref->index = MSFT_HREFTYPE_INDEX(offset);
2135 ref->reference = offset;
2136 ref->pImpTLInfo = TLB_REF_INTERNAL;
2137 }
2138 }
2139
2140 /* process Implemented Interfaces of a com class */
2141 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2142 int offset)
2143 {
2144 int i;
2145 MSFT_RefRecord refrec;
2146 TLBImplType **ppImpl = &pTI->impltypelist;
2147
2148 TRACE_(typelib)("\n");
2149
2150 for(i=0;i<count;i++){
2151 if(offset<0) break; /* paranoia */
2152 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2153 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2154 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2155 (*ppImpl)->hRef = refrec.reftype;
2156 (*ppImpl)->implflags=refrec.flags;
2157 (*ppImpl)->ctCustData=
2158 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2159 offset=refrec.onext;
2160 ppImpl=&((*ppImpl)->next);
2161 }
2162 }
2163 /*
2164 * process a typeinfo record
2165 */
2166 static ITypeInfoImpl * MSFT_DoTypeInfo(
2167 TLBContext *pcx,
2168 int count,
2169 ITypeLibImpl * pLibInfo)
2170 {
2171 MSFT_TypeInfoBase tiBase;
2172 ITypeInfoImpl *ptiRet;
2173
2174 TRACE_(typelib)("count=%u\n", count);
2175
2176 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2177 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2178 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2179
2180 /* this is where we are coming from */
2181 ptiRet->pTypeLib = pLibInfo;
2182 ptiRet->index=count;
2183 /* fill in the typeattr fields */
2184
2185 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2186 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2187 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2188 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2189 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2190 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2191 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2192 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2193 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2194 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2195 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2196 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2197 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2198 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2199 MSFT_GetTdesc(pcx, tiBase.datatype1,
2200 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2201
2202 /* FIXME: */
2203 /* IDLDESC idldescType; *//* never saw this one != zero */
2204
2205 /* name, eventually add to a hash table */
2206 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2207 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2208 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2209 /* help info */
2210 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2211 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2212 ptiRet->dwHelpContext=tiBase.helpcontext;
2213
2214 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2215 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2216
2217 /* note: InfoType's Help file and HelpStringDll come from the containing
2218 * library. Further HelpString and Docstring appear to be the same thing :(
2219 */
2220 /* functions */
2221 if(ptiRet->TypeAttr.cFuncs >0 )
2222 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2223 ptiRet->TypeAttr.cVars,
2224 tiBase.memoffset, & ptiRet->funclist);
2225 /* variables */
2226 if(ptiRet->TypeAttr.cVars >0 )
2227 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2228 ptiRet->TypeAttr.cVars,
2229 tiBase.memoffset, & ptiRet->varlist);
2230 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2231 switch(ptiRet->TypeAttr.typekind)
2232 {
2233 case TKIND_COCLASS:
2234 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2235 tiBase.datatype1);
2236 break;
2237 case TKIND_DISPATCH:
2238 /* This is not -1 when the interface is a non-base dual interface or
2239 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2240 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2241 not this interface.
2242 */
2243
2244 if (tiBase.datatype1 != -1)
2245 {
2246 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2247 ptiRet->impltypelist->hRef = tiBase.datatype1;
2248 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2249 }
2250 break;
2251 default:
2252 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2253 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2254 ptiRet->impltypelist->hRef = tiBase.datatype1;
2255 break;
2256 }
2257 }
2258 ptiRet->ctCustData=
2259 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2260
2261 TRACE_(typelib)("%s guid: %s kind:%s\n",
2262 debugstr_w(ptiRet->Name),
2263 debugstr_guid(&ptiRet->TypeAttr.guid),
2264 typekind_desc[ptiRet->TypeAttr.typekind]);
2265 if (TRACE_ON(typelib))
2266 dump_TypeInfo(ptiRet);
2267
2268 return ptiRet;
2269 }
2270
2271 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2272 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2273 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2274 * tradeoff here.
2275 */
2276 static ITypeLibImpl *tlb_cache_first;
2277 static CRITICAL_SECTION cache_section;
2278 static CRITICAL_SECTION_DEBUG cache_section_debug =
2279 {
2280 0, 0, &cache_section,
2281 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2282 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2283 };
2284 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2285
2286
2287 typedef struct TLB_PEFile
2288 {
2289 const IUnknownVtbl *lpvtbl;
2290 LONG refs;
2291 HMODULE dll;
2292 HRSRC typelib_resource;
2293 HGLOBAL typelib_global;
2294 LPVOID typelib_base;
2295 } TLB_PEFile;
2296
2297 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2298 {
2299 if (IsEqualIID(riid, &IID_IUnknown))
2300 {
2301 *ppv = iface;
2302 IUnknown_AddRef(iface);
2303 return S_OK;
2304 }
2305 *ppv = NULL;
2306 return E_NOINTERFACE;
2307 }
2308
2309 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2310 {
2311 TLB_PEFile *This = (TLB_PEFile *)iface;
2312 return InterlockedIncrement(&This->refs);
2313 }
2314
2315 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2316 {
2317 TLB_PEFile *This = (TLB_PEFile *)iface;
2318 ULONG refs = InterlockedDecrement(&This->refs);
2319 if (!refs)
2320 {
2321 if (This->typelib_global)
2322 FreeResource(This->typelib_global);
2323 if (This->dll)
2324 FreeLibrary(This->dll);
2325 HeapFree(GetProcessHeap(), 0, This);
2326 }
2327 return refs;
2328 }
2329
2330 static const IUnknownVtbl TLB_PEFile_Vtable =
2331 {
2332 TLB_PEFile_QueryInterface,
2333 TLB_PEFile_AddRef,
2334 TLB_PEFile_Release
2335 };
2336
2337 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2338 {
2339 TLB_PEFile *This;
2340
2341 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2342 if (!This)
2343 return E_OUTOFMEMORY;
2344
2345 This->lpvtbl = &TLB_PEFile_Vtable;
2346 This->refs = 1;
2347 This->dll = NULL;
2348 This->typelib_resource = NULL;
2349 This->typelib_global = NULL;
2350 This->typelib_base = NULL;
2351
2352 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2353 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2354
2355 if (This->dll)
2356 {
2357 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2358 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2359 if (This->typelib_resource)
2360 {
2361 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2362 if (This->typelib_global)
2363 {
2364 This->typelib_base = LockResource(This->typelib_global);
2365
2366 if (This->typelib_base)
2367 {
2368 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2369 *ppBase = This->typelib_base;
2370 *ppFile = (IUnknown *)&This->lpvtbl;
2371 return S_OK;
2372 }
2373 }
2374 }
2375 }
2376
2377 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2378 return TYPE_E_CANTLOADLIBRARY;
2379 }
2380
2381 typedef struct TLB_NEFile
2382 {
2383 const IUnknownVtbl *lpvtbl;
2384 LONG refs;
2385 LPVOID typelib_base;
2386 } TLB_NEFile;
2387
2388 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2389 {
2390 if (IsEqualIID(riid, &IID_IUnknown))
2391 {
2392 *ppv = iface;
2393 IUnknown_AddRef(iface);
2394 return S_OK;
2395 }
2396 *ppv = NULL;
2397 return E_NOINTERFACE;
2398 }
2399
2400 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2401 {
2402 TLB_NEFile *This = (TLB_NEFile *)iface;
2403 return InterlockedIncrement(&This->refs);
2404 }
2405
2406 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2407 {
2408 TLB_NEFile *This = (TLB_NEFile *)iface;
2409 ULONG refs = InterlockedDecrement(&This->refs);
2410 if (!refs)
2411 {
2412 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2413 HeapFree(GetProcessHeap(), 0, This);
2414 }
2415 return refs;
2416 }
2417
2418 static const IUnknownVtbl TLB_NEFile_Vtable =
2419 {
2420 TLB_NEFile_QueryInterface,
2421 TLB_NEFile_AddRef,
2422 TLB_NEFile_Release
2423 };
2424
2425 /***********************************************************************
2426 * read_xx_header [internal]
2427 */
2428 static int read_xx_header( HFILE lzfd )
2429 {
2430 IMAGE_DOS_HEADER mzh;
2431 char magic[3];
2432
2433 LZSeek( lzfd, 0, SEEK_SET );
2434 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2435 return 0;
2436 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2437 return 0;
2438
2439 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2440 if ( 2 != LZRead( lzfd, magic, 2 ) )
2441 return 0;
2442
2443 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2444
2445 if ( magic[0] == 'N' && magic[1] == 'E' )
2446 return IMAGE_OS2_SIGNATURE;
2447 if ( magic[0] == 'P' && magic[1] == 'E' )
2448 return IMAGE_NT_SIGNATURE;
2449
2450 magic[2] = '\0';
2451 WARN("Can't handle %s files.\n", magic );
2452 return 0;
2453 }
2454
2455
2456 /***********************************************************************
2457 * find_ne_resource [internal]
2458 */
2459 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2460 DWORD *resLen, DWORD *resOff )
2461 {
2462 IMAGE_OS2_HEADER nehd;
2463 NE_TYPEINFO *typeInfo;
2464 NE_NAMEINFO *nameInfo;
2465 DWORD nehdoffset;
2466 LPBYTE resTab;
2467 DWORD resTabSize;
2468 int count;
2469
2470 /* Read in NE header */
2471 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2472 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2473
2474 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2475 if ( !resTabSize )
2476 {
2477 TRACE("No resources in NE dll\n" );
2478 return FALSE;
2479 }
2480
2481 /* Read in resource table */
2482 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2483 if ( !resTab ) return FALSE;
2484
2485 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2486 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2487 {
2488 HeapFree( GetProcessHeap(), 0, resTab );
2489 return FALSE;
2490 }
2491
2492 /* Find resource */
2493 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2494
2495 if (HIWORD(typeid) != 0) /* named type */
2496 {
2497 BYTE len = strlen( typeid );
2498 while (typeInfo->type_id)
2499 {
2500 if (!(typeInfo->type_id & 0x8000))
2501 {
2502 BYTE *p = resTab + typeInfo->type_id;
2503 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2504 }
2505 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2506 typeInfo->count * sizeof(NE_NAMEINFO));
2507 }
2508 }
2509 else /* numeric type id */
2510 {
2511 WORD id = LOWORD(typeid) | 0x8000;
2512 while (typeInfo->type_id)
2513 {
2514 if (typeInfo->type_id == id) goto found_type;
2515 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2516 typeInfo->count * sizeof(NE_NAMEINFO));
2517 }
2518 }
2519 TRACE("No typeid entry found for %p\n", typeid );
2520 HeapFree( GetProcessHeap(), 0, resTab );
2521 return FALSE;
2522
2523 found_type:
2524 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2525
2526 if (HIWORD(resid) != 0) /* named resource */
2527 {
2528 BYTE len = strlen( resid );
2529 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2530 {
2531 BYTE *p = resTab + nameInfo->id;
2532 if (nameInfo->id & 0x8000) continue;
2533 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2534 }
2535 }
2536 else /* numeric resource id */
2537 {
2538 WORD id = LOWORD(resid) | 0x8000;
2539 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2540 if (nameInfo->id == id) goto found_name;
2541 }
2542 TRACE("No resid entry found for %p\n", typeid );
2543 HeapFree( GetProcessHeap(), 0, resTab );
2544 return FALSE;
2545
2546 found_name:
2547 /* Return resource data */
2548 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2549 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2550
2551 HeapFree( GetProcessHeap(), 0, resTab );
2552 return TRUE;
2553 }
2554
2555 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2556
2557 HFILE lzfd = -1;
2558 OFSTRUCT ofs;
2559 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2560 TLB_NEFile *This = NULL;
2561
2562 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2563 if (!This) return E_OUTOFMEMORY;
2564
2565 This->lpvtbl = &TLB_NEFile_Vtable;
2566 This->refs = 1;
2567 This->typelib_base = NULL;
2568
2569 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2570 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2571 {
2572 DWORD reslen, offset;
2573 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2574 {
2575 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2576 if( !This->typelib_base )
2577 hr = E_OUTOFMEMORY;
2578 else
2579 {
2580 LZSeek( lzfd, offset, SEEK_SET );
2581 reslen = LZRead( lzfd, This->typelib_base, reslen );
2582 LZClose( lzfd );
2583 *ppBase = This->typelib_base;
2584 *pdwTLBLength = reslen;
2585 *ppFile = (IUnknown *)&This->lpvtbl;
2586 return S_OK;
2587 }
2588 }
2589 }
2590
2591 if( lzfd >= 0) LZClose( lzfd );
2592 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2593 return hr;
2594 }
2595
2596 typedef struct TLB_Mapping
2597 {
2598 const IUnknownVtbl *lpvtbl;
2599 LONG refs;
2600 HANDLE file;
2601 HANDLE mapping;
2602 LPVOID typelib_base;
2603 } TLB_Mapping;
2604
2605 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2606 {
2607 if (IsEqualIID(riid, &IID_IUnknown))
2608 {
2609 *ppv = iface;
2610 IUnknown_AddRef(iface);
2611 return S_OK;
2612 }
2613 *ppv = NULL;
2614 return E_NOINTERFACE;
2615 }
2616
2617 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2618 {
2619 TLB_Mapping *This = (TLB_Mapping *)iface;
2620 return InterlockedIncrement(&This->refs);
2621 }
2622
2623 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2624 {
2625 TLB_Mapping *This = (TLB_Mapping *)iface;
2626 ULONG refs = InterlockedDecrement(&This->refs);
2627 if (!refs)
2628 {
2629 if (This->typelib_base)
2630 UnmapViewOfFile(This->typelib_base);
2631 if (This->mapping)
2632 CloseHandle(This->mapping);
2633 if (This->file != INVALID_HANDLE_VALUE)
2634 CloseHandle(This->file);
2635 HeapFree(GetProcessHeap(), 0, This);
2636 }
2637 return refs;
2638 }
2639
2640 static const IUnknownVtbl TLB_Mapping_Vtable =
2641 {
2642 TLB_Mapping_QueryInterface,
2643 TLB_Mapping_AddRef,
2644 TLB_Mapping_Release
2645 };
2646
2647 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2648 {
2649 TLB_Mapping *This;
2650
2651 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2652 if (!This)
2653 return E_OUTOFMEMORY;
2654
2655 This->lpvtbl = &TLB_Mapping_Vtable;
2656 This->refs = 1;
2657 This->file = INVALID_HANDLE_VALUE;
2658 This->mapping = NULL;
2659 This->typelib_base = NULL;
2660
2661 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2662 if (INVALID_HANDLE_VALUE != This->file)
2663 {
2664 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2665 if (This->mapping)
2666 {
2667 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2668 if(This->typelib_base)
2669 {
2670 /* retrieve file size */
2671 *pdwTLBLength = GetFileSize(This->file, NULL);
2672 *ppBase = This->typelib_base;
2673 *ppFile = (IUnknown *)&This->lpvtbl;
2674 return S_OK;
2675 }
2676 }
2677 }
2678
2679 IUnknown_Release((IUnknown *)&This->lpvtbl);
2680 return TYPE_E_CANTLOADLIBRARY;
2681 }
2682
2683 /****************************************************************************
2684 * TLB_ReadTypeLib
2685 *
2686 * find the type of the typelib file and map the typelib resource into
2687 * the memory
2688 */
2689 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2690 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2691 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2692 {
2693 ITypeLibImpl *entry;
2694 HRESULT ret;
2695 INT index = 1;
2696 LPWSTR index_str, file = (LPWSTR)pszFileName;
2697 LPVOID pBase = NULL;
2698 DWORD dwTLBLength = 0;
2699 IUnknown *pFile = NULL;
2700
2701 *ppTypeLib = NULL;
2702
2703 index_str = strrchrW(pszFileName, '\\');
2704 if(index_str && *++index_str != '\0')
2705 {
2706 LPWSTR end_ptr;
2707 long idx = strtolW(index_str, &end_ptr, 10);
2708 if(*end_ptr == '\0')
2709 {
2710 int str_len = index_str - pszFileName - 1;
2711 index = idx;
2712 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2713 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2714 file[str_len] = 0;
2715 }
2716 }
2717
2718 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2719 {
2720 if(strchrW(file, '\\'))
2721 {
2722 lstrcpyW(pszPath, file);
2723 }
2724 else
2725 {
2726 int len = GetSystemDirectoryW(pszPath, cchPath);
2727 pszPath[len] = '\\';
2728 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2729 }
2730 }
2731
2732 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2733
2734 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2735
2736 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2737 EnterCriticalSection(&cache_section);
2738 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2739 {
2740 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2741 {
2742 TRACE("cache hit\n");
2743 *ppTypeLib = (ITypeLib2*)entry;
2744 ITypeLib_AddRef(*ppTypeLib);
2745 LeaveCriticalSection(&cache_section);
2746 return S_OK;
2747 }
2748 }
2749 LeaveCriticalSection(&cache_section);
2750
2751 /* now actually load and parse the typelib */
2752
2753 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2754 if (ret == TYPE_E_CANTLOADLIBRARY)
2755 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2756 if (ret == TYPE_E_CANTLOADLIBRARY)
2757 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2758 if (SUCCEEDED(ret))
2759 {
2760 if (dwTLBLength >= 4)
2761 {
2762 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2763 if (dwSignature == MSFT_SIGNATURE)
2764 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2765 else if (dwSignature == SLTG_SIGNATURE)
2766 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2767 else
2768 {
2769 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2770 ret = TYPE_E_CANTLOADLIBRARY;
2771 }
2772 }
2773 else
2774 ret = TYPE_E_CANTLOADLIBRARY;
2775 IUnknown_Release(pFile);
2776 }
2777
2778 if(*ppTypeLib) {
2779 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2780
2781 TRACE("adding to cache\n");
2782 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2783 lstrcpyW(impl->path, pszPath);
2784 /* We should really canonicalise the path here. */
2785 impl->index = index;
2786
2787 /* FIXME: check if it has added already in the meantime */
2788 EnterCriticalSection(&cache_section);
2789 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2790 impl->prev = NULL;
2791 tlb_cache_first = impl;
2792 LeaveCriticalSection(&cache_section);
2793 ret = S_OK;
2794 } else
2795 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2796
2797 return ret;
2798 }
2799
2800 /*================== ITypeLib(2) Methods ===================================*/
2801
2802 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2803 {
2804 ITypeLibImpl* pTypeLibImpl;
2805
2806 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2807 if (!pTypeLibImpl) return NULL;
2808
2809 pTypeLibImpl->lpVtbl = &tlbvt;
2810 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2811 pTypeLibImpl->ref = 1;
2812
2813 list_init(&pTypeLibImpl->ref_list);
2814 pTypeLibImpl->dispatch_href = -1;
2815
2816 return pTypeLibImpl;
2817 }
2818
2819 /****************************************************************************
2820 * ITypeLib2_Constructor_MSFT
2821 *
2822 * loading an MSFT typelib from an in-memory image
2823 */
2824 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2825 {
2826 TLBContext cx;
2827 long lPSegDir;
2828 MSFT_Header tlbHeader;
2829 MSFT_SegDir tlbSegDir;
2830 ITypeLibImpl * pTypeLibImpl;
2831
2832 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2833
2834 pTypeLibImpl = TypeLibImpl_Constructor();
2835 if (!pTypeLibImpl) return NULL;
2836
2837 /* get pointer to beginning of typelib data */
2838 cx.pos = 0;
2839 cx.oStart=0;
2840 cx.mapping = pLib;
2841 cx.pLibInfo = pTypeLibImpl;
2842 cx.length = dwTLBLength;
2843
2844 /* read header */
2845 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2846 TRACE_(typelib)("header:\n");
2847 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2848 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2849 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2850 return NULL;
2851 }
2852 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2853
2854 /* there is a small amount of information here until the next important
2855 * part:
2856 * the segment directory . Try to calculate the amount of data */
2857 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2858
2859 /* now read the segment directory */
2860 TRACE("read segment directory (at %ld)\n",lPSegDir);
2861 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2862 cx.pTblDir = &tlbSegDir;
2863
2864 /* just check two entries */
2865 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2866 {
2867 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2868 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2869 return NULL;
2870 }
2871
2872 /* now fill our internal data */
2873 /* TLIBATTR fields */
2874 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2875
2876 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2877 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2878 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2879 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2880 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2881
2882 pTypeLibImpl->lcid = tlbHeader.lcid;
2883
2884 /* name, eventually add to a hash table */
2885 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2886
2887 /* help info */
2888 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2889 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2890
2891 if( tlbHeader.varflags & HELPDLLFLAG)
2892 {
2893 int offset;
2894 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2895 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2896 }
2897
2898 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2899
2900 /* custom data */
2901 if(tlbHeader.CustomDataOffset >= 0)
2902 {
2903 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2904 }
2905
2906 /* fill in type descriptions */
2907 if(tlbSegDir.pTypdescTab.length > 0)
2908 {
2909 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2910 INT16 td[4];
2911 pTypeLibImpl->ctTypeDesc = cTD;
2912 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2913 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2914 for(i=0; i<cTD; )
2915 {
2916 /* FIXME: add several sanity checks here */
2917 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2918 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2919 {
2920 /* FIXME: check safearray */
2921 if(td[3] < 0)
2922 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2923 else
2924 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2925 }
2926 else if(td[0] == VT_CARRAY)
2927 {
2928 /* array descr table here */
2929 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2930 }
2931 else if(td[0] == VT_USERDEFINED)
2932 {
2933 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2934 }
2935 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2936 }
2937
2938 /* second time around to fill the array subscript info */
2939 for(i=0;i<cTD;i++)
2940 {
2941 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2942 if(tlbSegDir.pArrayDescriptions.offset>0)
2943 {
2944 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2945 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2946
2947 if(td[1]<0)
2948 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2949 else
2950 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
2951
2952 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2953
2954 for(j = 0; j<td[2]; j++)
2955 {
2956 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2957 sizeof(INT), &cx, DO_NOT_SEEK);
2958 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2959 sizeof(INT), &cx, DO_NOT_SEEK);
2960 }
2961 }
2962 else
2963 {
2964 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2965 ERR("didn't find array description data\n");
2966 }
2967 }
2968 }
2969
2970 /* imported type libs */
2971 if(tlbSegDir.pImpFiles.offset>0)
2972 {
2973 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2974 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2975 UINT16 size;
2976
2977 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2978 {
2979 char *name;
2980
2981 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2982 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2983 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2984
2985 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2986 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2987 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2988 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2989
2990 size >>= 2;
2991 name = TLB_Alloc(size+1);
2992 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2993 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2994
2995 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2996 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2997
2998 ppImpLib = &(*ppImpLib)->next;
2999 }
3000 }
3001
3002 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3003 if(pTypeLibImpl->dispatch_href != -1)
3004 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3005
3006 /* type info's */
3007 if(tlbHeader.nrtypeinfos >= 0 )
3008 {
3009 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3010 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3011 int i;
3012
3013 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3014 {
3015 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3016
3017 ppTI = &((*ppTI)->next);
3018 (pTypeLibImpl->TypeInfoCount)++;
3019 }
3020 }
3021
3022 TRACE("(%p)\n", pTypeLibImpl);
3023 return (ITypeLib2*) pTypeLibImpl;
3024 }
3025
3026
3027 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3028 {
3029 char b[3];
3030 int i;
3031 short s;
3032
3033 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3034 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3035 return FALSE;
3036 }
3037
3038 guid->Data4[0] = s >> 8;
3039 guid->Data4[1] = s & 0xff;
3040
3041 b[2] = '\0';
3042 for(i = 0; i < 6; i++) {
3043 memcpy(b, str + 24 + 2 * i, 2);
3044 guid->Data4[i + 2] = strtol(b, NULL, 16);
3045 }
3046 return TRUE;
3047 }
3048
3049 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3050 {
3051 WORD bytelen;
3052 DWORD len;
3053
3054 *pBstr = NULL;
3055 bytelen = *(const WORD*)ptr;
3056 if(bytelen == 0xffff) return 2;
3057 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3058 *pBstr = SysAllocStringLen(NULL, len);
3059 if (*pBstr)
3060 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3061 return bytelen + 2;
3062 }
3063
3064 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3065 {
3066 WORD bytelen;
3067
3068 *str = NULL;
3069 bytelen = *(const WORD*)ptr;
3070 if(bytelen == 0xffff) return 2;
3071 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3072 memcpy(*str, ptr + 2, bytelen);
3073 (*str)[bytelen] = '\0';
3074 return bytelen + 2;
3075 }
3076
3077 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3078 {
3079 char *ptr = pLibBlk;
3080 WORD w;
3081
3082 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3083 FIXME("libblk magic = %04x\n", w);
3084 return 0;
3085 }
3086
3087 ptr += 6;
3088 if((w = *(WORD*)ptr) != 0xffff) {
3089 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3090 ptr += w;
3091 }
3092 ptr += 2;
3093
3094 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3095
3096 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3097
3098 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3099 ptr += 4;
3100
3101 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3102 ptr += 2;
3103
3104 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3105 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3106 else
3107 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3108 ptr += 2;
3109
3110 ptr += 4; /* skip res12 */
3111
3112 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3113 ptr += 2;
3114
3115 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3116 ptr += 2;
3117
3118 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3119 ptr += 2;
3120
3121 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3122 ptr += sizeof(GUID);
3123
3124 return ptr - (char*)pLibBlk;
3125 }
3126
3127 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3128 typedef struct
3129 {
3130 unsigned int num;
3131 HREFTYPE refs[1];
3132 } sltg_ref_lookup_t;
3133
3134 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3135 HREFTYPE *typelib_ref)
3136 {
3137 if(table && typeinfo_ref < table->num)
3138 {
3139 *typelib_ref = table->refs[typeinfo_ref];
3140 return S_OK;
3141 }
3142
3143 ERR_(typelib)("Unable to find reference\n");
3144 *typelib_ref = -1;
3145 return E_FAIL;
3146 }
3147
3148 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3149 {
3150 BOOL done = FALSE;
3151
3152 while(!done) {
3153 if((*pType & 0xe00) == 0xe00) {
3154 pTD->vt = VT_PTR;
3155 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3156 sizeof(TYPEDESC));
3157 pTD = pTD->u.lptdesc;
3158 }
3159 switch(*pType & 0x3f) {
3160 case VT_PTR:
3161 pTD->vt = VT_PTR;
3162 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3163 sizeof(TYPEDESC));
3164 pTD = pTD->u.lptdesc;
3165 break;
3166
3167 case VT_USERDEFINED:
3168 pTD->vt = VT_USERDEFINED;
3169 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3170 done = TRUE;
3171 break;
3172
3173 case VT_CARRAY:
3174 {
3175 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3176 array */
3177
3178 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3179
3180 pTD->vt = VT_CARRAY;
3181 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3182 sizeof(ARRAYDESC) +
3183 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3184 pTD->u.lpadesc->cDims = pSA->cDims;
3185 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3186 pSA->cDims * sizeof(SAFEARRAYBOUND));
3187
3188 pTD = &pTD->u.lpadesc->tdescElem;
3189 break;
3190 }
3191
3192 case VT_SAFEARRAY:
3193 {
3194 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3195 useful? */
3196
3197 pType++;
3198 pTD->vt = VT_SAFEARRAY;
3199 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3200 sizeof(TYPEDESC));
3201 pTD = pTD->u.lptdesc;
3202 break;
3203 }
3204 default:
3205 pTD->vt = *pType & 0x3f;
3206 done = TRUE;
3207 break;
3208 }
3209 pType++;
3210 }
3211 return pType;
3212 }
3213
3214 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3215 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3216 {
3217 /* Handle [in/out] first */
3218 if((*pType & 0xc000) == 0xc000)
3219 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3220 else if(*pType & 0x8000)
3221 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3222 else if(*pType & 0x4000)
3223 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3224 else
3225 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3226
3227 if(*pType & 0x2000)
3228 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3229
3230 if(*pType & 0x80)
3231 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3232
3233 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3234 }
3235
3236
3237 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3238 char *pNameTable)
3239 {
3240 unsigned int ref;
3241 char *name;
3242 TLBRefType *ref_type;
3243 sltg_ref_lookup_t *table;
3244 HREFTYPE typelib_ref;
3245
3246 if(pRef->magic != SLTG_REF_MAGIC) {
3247 FIXME("Ref magic = %x\n", pRef->magic);
3248 return NULL;
3249 }
3250 name = ( (char*)pRef->names + pRef->number);
3251
3252 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3253 table->num = pRef->number >> 3;
3254
3255 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3256
3257 /* We don't want the first href to be 0 */
3258 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3259
3260 for(ref = 0; ref < pRef->number >> 3; ref++) {
3261 char *refname;
3262 unsigned int lib_offs, type_num;
3263
3264 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3265
3266 name += SLTG_ReadStringA(name, &refname);
3267 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3268 FIXME_(typelib)("Can't sscanf ref\n");
3269 if(lib_offs != 0xffff) {
3270 TLBImpLib **import = &pTL->pImpLibs;
3271
3272 while(*import) {
3273 if((*import)->offset == lib_offs)
3274 break;
3275 import = &(*import)->next;
3276 }
3277 if(!*import) {
3278 char fname[MAX_PATH+1];
3279 int len;
3280
3281 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3282 sizeof(**import));
3283 (*import)->offset = lib_offs;
3284 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3285 &(*import)->guid);
3286 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3287 &(*import)->wVersionMajor,
3288 &(*import)->wVersionMinor,
3289 &(*import)->lcid, fname) != 4) {
3290 FIXME_(typelib)("can't sscanf ref %s\n",
3291 pNameTable + lib_offs + 40);
3292 }
3293 len = strlen(fname);
3294 if(fname[len-1] != '#')
3295 FIXME("fname = %s\n", fname);
3296 fname[len-1] = '\0';
3297 (*import)->name = TLB_MultiByteToBSTR(fname);
3298 }
3299 ref_type->pImpTLInfo = *import;
3300
3301 /* Store a reference to IDispatch */
3302 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3303 pTL->dispatch_href = typelib_ref;
3304
3305 } else { /* internal ref */
3306 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3307 }
3308 ref_type->reference = typelib_ref;
3309 ref_type->index = type_num;
3310
3311 HeapFree(GetProcessHeap(), 0, refname);
3312 list_add_tail(&pTL->ref_list, &ref_type->entry);
3313
3314 table->refs[ref] = typelib_ref;
3315 typelib_ref += 4;
3316 }
3317 if((BYTE)*name != SLTG_REF_MAGIC)
3318 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3319 dump_TLBRefType(pTL);
3320 return table;
3321 }
3322
3323 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3324 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3325 {
3326 SLTG_ImplInfo *info;
3327 TLBImplType **ppImplType = &pTI->impltypelist;
3328 /* I don't really get this structure, usually it's 0x16 bytes
3329 long, but iuser.tlb contains some that are 0x18 bytes long.
3330 That's ok because we can use the next ptr to jump to the next
3331 one. But how do we know the length of the last one? The WORD
3332 at offs 0x8 might be the clue. For now I'm just assuming that
3333 the last one is the regular 0x16 bytes. */
3334
3335 info = (SLTG_ImplInfo*)pBlk;
3336 while(1) {
3337 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3338 sizeof(**ppImplType));
3339 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3340 (*ppImplType)->implflags = info->impltypeflags;
3341 pTI->TypeAttr.cImplTypes++;
3342 ppImplType = &(*ppImplType)->next;
3343
3344 if(info->next == 0xffff)
3345 break;
3346 if(OneOnly)
3347 FIXME_(typelib)("Interface inheriting more than one interface\n");
3348 info = (SLTG_ImplInfo*)(pBlk + info->next);
3349 }
3350 info++; /* see comment at top of function */
3351 return (char*)info;
3352 }
3353
3354 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3355 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3356 {
3357 TLBVarDesc **ppVarDesc = &pTI->varlist;
3358 BSTR bstrPrevName = NULL;
3359 SLTG_Variable *pItem;
3360 unsigned short i;
3361 WORD *pType;
3362
3363 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3364 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3365
3366 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3367 sizeof(**ppVarDesc));
3368 (*ppVarDesc)->vardesc.memid = pItem->memid;
3369
3370 if (pItem->magic != SLTG_VAR_MAGIC &&
3371 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3372 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3373 return;
3374 }
3375
3376 if (pItem->name == 0xfffe)
3377 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3378 else
3379 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3380
3381 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3382 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3383 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3384
3385 if(pItem->flags & 0x02)
3386 pType = &pItem->type;
3387 else
3388 pType = (WORD*)(pBlk + pItem->type);
3389
3390 if (pItem->flags & ~0xda)
3391 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3392
3393 SLTG_DoElem(pType, pBlk,
3394 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3395
3396 if (TRACE_ON(typelib)) {
3397 char buf[300];
3398 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3399 TRACE_(typelib)("elemdescVar: %s\n", buf);
3400 }
3401
3402 if (pItem->flags & 0x40) {
3403 TRACE_(typelib)("VAR_DISPATCH\n");
3404 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3405 }
3406 else if (pItem->flags & 0x10) {
3407 TRACE_(typelib)("VAR_CONST\n");
3408 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3409 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3410 sizeof(VARIANT));
3411 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3412 if (pItem->flags & 0x08)
3413 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3414 else {
3415 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3416 {
3417 case VT_LPSTR:
3418 case VT_LPWSTR:
3419 case VT_BSTR:
3420 {
3421 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3422 BSTR str;
3423 TRACE_(typelib)("len = %u\n", len);
3424 if (len == 0xffff) {
3425 str = NULL;
3426 } else {
3427 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3428 str = SysAllocStringLen(NULL, alloc_len);
3429 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3430 }
3431 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3432 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3433 break;
3434 }
3435 case VT_I2:
3436 case VT_UI2:
3437 case VT_I4:
3438 case VT_UI4:
3439 case VT_INT:
3440 case VT_UINT:
3441 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3442 *(INT*)(pBlk + pItem->byte_offs);
3443 break;
3444 default:
3445 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3446 }
3447 }
3448 }
3449 else {
3450 TRACE_(typelib)("VAR_PERINSTANCE\n");
3451 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3452 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3453 }
3454
3455 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3456 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3457
3458 if (pItem->flags & 0x80)
3459 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3460
3461 bstrPrevName = (*ppVarDesc)->Name;
3462 ppVarDesc = &((*ppVarDesc)->next);
3463 }
3464 pTI->TypeAttr.cVars = cVars;
3465 }
3466
3467 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3468 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3469 {
3470 SLTG_Function *pFunc;
3471 unsigned short i;
3472 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3473
3474 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3475 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3476
3477 int param;
3478 WORD *pType, *pArg;
3479
3480 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3481 sizeof(**ppFuncDesc));
3482
3483 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3484 case SLTG_FUNCTION_MAGIC:
3485 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3486 break;
3487 case SLTG_DISPATCH_FUNCTION_MAGIC:
3488 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3489 break;
3490 case SLTG_STATIC_FUNCTION_MAGIC:
3491 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3492 break;
3493 default:
3494 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3495 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3496 *ppFuncDesc = NULL;
3497 return;
3498 }
3499 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3500
3501 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3502 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3503 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3504 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3505 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3506 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3507
3508 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3509 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3510
3511 if(pFunc->retnextopt & 0x80)
3512 pType = &pFunc->rettype;
3513 else
3514 pType = (WORD*)(pBlk + pFunc->rettype);
3515
3516 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3517
3518 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3519 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3520 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3521 (*ppFuncDesc)->pParamDesc =
3522 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3523 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3524
3525 pArg = (WORD*)(pBlk + pFunc->arg_off);
3526
3527 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3528 char *paramName = pNameTable + *pArg;
3529 BOOL HaveOffs;
3530 /* If arg type follows then paramName points to the 2nd
3531 letter of the name, else the next WORD is an offset to
3532 the arg type and paramName points to the first letter.
3533 So let's take one char off paramName and see if we're
3534 pointing at an alpha-numeric char. However if *pArg is
3535 0xffff or 0xfffe then the param has no name, the former
3536 meaning that the next WORD is the type, the latter
3537 meaning that the next WORD is an offset to the type. */
3538
3539 HaveOffs = FALSE;
3540 if(*pArg == 0xffff)
3541 paramName = NULL;
3542 else if(*pArg == 0xfffe) {
3543 paramName = NULL;
3544 HaveOffs = TRUE;
3545 }
3546 else if(paramName[-1] && !isalnum(paramName[-1]))
3547 HaveOffs = TRUE;
3548
3549 pArg++;
3550
3551 if(HaveOffs) { /* the next word is an offset to type */
3552 pType = (WORD*)(pBlk + *pArg);
3553 SLTG_DoElem(pType, pBlk,
3554 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3555 pArg++;
3556 } else {
3557 if(paramName)
3558 paramName--;
3559 pArg = SLTG_DoElem(pArg, pBlk,
3560 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3561 }
3562
3563 /* Are we an optional param ? */
3564 if((*ppFuncDesc)->funcdesc.cParams - param <=
3565 (*ppFuncDesc)->funcdesc.cParamsOpt)
3566 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3567
3568 if(paramName) {
3569 (*ppFuncDesc)->pParamDesc[param].Name =
3570 TLB_MultiByteToBSTR(paramName);
3571 } else {
3572 (*ppFuncDesc)->pParamDesc[param].Name =
3573 SysAllocString((*ppFuncDesc)->Name);
3574 }
3575 }
3576
3577 ppFuncDesc = &((*ppFuncDesc)->next);
3578 if(pFunc->next == 0xffff) break;
3579 }
3580 pTI->TypeAttr.cFuncs = cFuncs;
3581 }
3582
3583 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3584 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3585 SLTG_TypeInfoTail *pTITail)
3586 {
3587 char *pFirstItem;
3588 sltg_ref_lookup_t *ref_lookup = NULL;
3589
3590 if(pTIHeader->href_table != 0xffffffff) {
3591 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3592 pNameTable);
3593 }
3594
3595 pFirstItem = pBlk;
3596
3597 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3598 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3599 }
3600 HeapFree(GetProcessHeap(), 0, ref_lookup);
3601 }
3602
3603
3604 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3605 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3606 const SLTG_TypeInfoTail *pTITail)
3607 {
3608 char *pFirstItem;
3609 sltg_ref_lookup_t *ref_lookup = NULL;
3610
3611 if(pTIHeader->href_table != 0xffffffff) {
3612 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3613 pNameTable);
3614 }
3615
3616 pFirstItem = pBlk;
3617
3618 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3619 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3620 }
3621
3622 if (pTITail->funcs_off != 0xffff)
3623 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3624
3625 HeapFree(GetProcessHeap(), 0, ref_lookup);
3626
3627 if (TRACE_ON(typelib))
3628 dump_TLBFuncDesc(pTI->funclist);
3629 }
3630
3631 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3632 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3633 const SLTG_TypeInfoTail *pTITail)
3634 {
3635 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3636 }
3637
3638 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3639 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3640 const SLTG_TypeInfoTail *pTITail)
3641 {
3642 WORD *pType;
3643 sltg_ref_lookup_t *ref_lookup = NULL;
3644
3645 if (pTITail->simple_alias) {
3646 /* if simple alias, no more processing required */
3647 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3648 return;
3649 }
3650
3651 if(pTIHeader->href_table != 0xffffffff) {
3652 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3653 pNameTable);
3654 }
3655
3656 /* otherwise it is an offset to a type */
3657 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3658
3659 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3660
3661 HeapFree(GetProcessHeap(), 0, ref_lookup);
3662 }
3663
3664 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3665 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3666 const SLTG_TypeInfoTail *pTITail)
3667 {
3668 sltg_ref_lookup_t *ref_lookup = NULL;
3669 if (pTIHeader->href_table != 0xffffffff)
3670 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3671 pNameTable);
3672
3673 if (pTITail->vars_off != 0xffff)
3674 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3675
3676 if (pTITail->funcs_off != 0xffff)
3677 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3678
3679 if (pTITail->impls_off != 0xffff)
3680 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3681
3682 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3683 * of dispinterface functions including the IDispatch ones, so
3684 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3685 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3686
3687 HeapFree(GetProcessHeap(), 0, ref_lookup);
3688 if (TRACE_ON(typelib))
3689 dump_TLBFuncDesc(pTI->funclist);
3690 }
3691
3692 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3693 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3694 const SLTG_TypeInfoTail *pTITail)
3695 {
3696 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3697 }
3698
3699 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3700 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3701 const SLTG_TypeInfoTail *pTITail)
3702 {
3703 sltg_ref_lookup_t *ref_lookup = NULL;
3704 if (pTIHeader->href_table != 0xffffffff)
3705 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3706 pNameTable);
3707
3708 if (pTITail->vars_off != 0xffff)
3709 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3710
3711 if (pTITail->funcs_off != 0xffff)
3712 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3713 HeapFree(GetProcessHeap(), 0, ref_lookup);
3714 if (TRACE_ON(typelib))
3715 dump_TypeInfo(pTI);
3716 }
3717
3718 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3719 managable copy of it into this */
3720 typedef struct {
3721 WORD small_no;
3722 char *index_name;
3723 char *other_name;
3724 WORD res1a;
3725 WORD name_offs;
3726 WORD more_bytes;
3727 char *extra;
3728 WORD res20;
3729 DWORD helpcontext;
3730 WORD res26;
3731 GUID uuid;
3732 } SLTG_InternalOtherTypeInfo;
3733
3734 /****************************************************************************
3735 * ITypeLib2_Constructor_SLTG
3736 *
3737 * loading a SLTG typelib from an in-memory image
3738 */
3739 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3740 {
3741 ITypeLibImpl *pTypeLibImpl;
3742 SLTG_Header *pHeader;
3743 SLTG_BlkEntry *pBlkEntry;
3744 SLTG_Magic *pMagic;
3745 SLTG_Index *pIndex;
3746 SLTG_Pad9 *pPad9;
3747 LPVOID pBlk, pFirstBlk;
3748 SLTG_LibBlk *pLibBlk;
3749 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3750 char *pAfterOTIBlks = NULL;
3751 char *pNameTable, *ptr;
3752 int i;
3753 DWORD len, order;
3754 ITypeInfoImpl **ppTypeInfoImpl;
3755
3756 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3757
3758
3759 pTypeLibImpl = TypeLibImpl_Constructor();
3760 if (!pTypeLibImpl) return NULL;
3761
3762 pHeader = pLib;
3763
3764 TRACE_(typelib)("header:\n");
3765 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3766 pHeader->nrOfFileBlks );
3767 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3768 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3769 pHeader->SLTG_magic);
3770 return NULL;
3771 }
3772
3773 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3774 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3775
3776 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3777 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3778
3779 /* Next we have a magic block */
3780 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3781
3782 /* Let's see if we're still in sync */
3783 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3784 sizeof(SLTG_COMPOBJ_MAGIC))) {
3785 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3786 return NULL;
3787 }
3788 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3789 sizeof(SLTG_DIR_MAGIC))) {
3790 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3791 return NULL;
3792 }
3793
3794 pIndex = (SLTG_Index*)(pMagic+1);
3795
3796 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3797
3798 pFirstBlk = pPad9 + 1;
3799
3800 /* We'll set up a ptr to the main library block, which is the last one. */
3801
3802 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3803 pBlkEntry[order].next != 0;
3804 order = pBlkEntry[order].next - 1, i++) {
3805 pBlk = (char*)pBlk + pBlkEntry[order].len;
3806 }
3807 pLibBlk = pBlk;
3808
3809 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3810
3811 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3812 interspersed */
3813
3814 len += 0x40;
3815
3816 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3817
3818 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3819 sizeof(*pOtherTypeInfoBlks) *
3820 pTypeLibImpl->TypeInfoCount);
3821
3822
3823 ptr = (char*)pLibBlk + len;
3824
3825 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3826 WORD w, extra;
3827 len = 0;
3828
3829 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3830
3831 w = *(WORD*)(ptr + 2);
3832 if(w != 0xffff) {
3833 len += w;
3834 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3835 w+1);
3836 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3837 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3838 }
3839 w = *(WORD*)(ptr + 4 + len);
3840 if(w != 0xffff) {
3841 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3842 len += w;
3843 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3844 w+1);
3845 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3846 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3847 }
3848 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3849 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3850 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3851 if(extra) {
3852 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3853 extra);
3854 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3855 len += extra;
3856 }
3857 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3858 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3859 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3860 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3861 len += sizeof(SLTG_OtherTypeInfo);
3862 ptr += len;
3863 }
3864
3865 pAfterOTIBlks = ptr;
3866
3867 /* Skip this WORD and get the next DWORD */
3868 len = *(DWORD*)(pAfterOTIBlks + 2);
3869
3870 /* Now add this to pLibBLk look at what we're pointing at and
3871 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3872 dust and we should be pointing at the beginning of the name
3873 table */
3874
3875 pNameTable = (char*)pLibBlk + len;
3876
3877 switch(*(WORD*)pNameTable) {
3878 case 0xffff:
3879 break;
3880 case 0x0200:
3881 pNameTable += 0x20;
3882 break;
3883 default:
3884 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3885 break;
3886 }
3887
3888 pNameTable += 0x216;
3889
3890 pNameTable += 2;
3891
3892 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3893
3894 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3895
3896
3897 /* Hopefully we now have enough ptrs set up to actually read in
3898 some TypeInfos. It's not clear which order to do them in, so
3899 I'll just follow the links along the BlkEntry chain and read
3900 them in the order in which they are in the file */
3901
3902 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3903
3904 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3905 pBlkEntry[order].next != 0;
3906 order = pBlkEntry[order].next - 1, i++) {
3907
3908 SLTG_TypeInfoHeader *pTIHeader;
3909 SLTG_TypeInfoTail *pTITail;
3910 SLTG_MemberHeader *pMemHeader;
3911
3912 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3913 pOtherTypeInfoBlks[i].index_name)) {
3914 FIXME_(typelib)("Index strings don't match\n");
3915 return NULL;
3916 }
3917
3918 pTIHeader = pBlk;
3919 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3920 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3921 return NULL;
3922 }
3923 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3924 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3925 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3926
3927 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3928 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3929 (*ppTypeInfoImpl)->index = i;
3930 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3931 pOtherTypeInfoBlks[i].name_offs +
3932 pNameTable);
3933 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3934 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3935 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3936 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3937 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3938 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3939 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3940
3941 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3942 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3943
3944 if((pTIHeader->typeflags1 & 7) != 2)
3945 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3946 if(pTIHeader->typeflags3 != 2)
3947 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3948
3949 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3950 debugstr_w((*ppTypeInfoImpl)->Name),
3951 typekind_desc[pTIHeader->typekind],
3952 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3953 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3954
3955 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3956
3957 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3958
3959 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3960 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3961 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3962
3963 switch(pTIHeader->typekind) {
3964 case TKIND_ENUM:
3965 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3966 pTIHeader, pTITail);
3967 break;
3968
3969 case TKIND_RECORD:
3970 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3971 pTIHeader, pTITail);
3972 break;
3973
3974 case TKIND_INTERFACE:
3975 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3976 pTIHeader, pTITail);
3977 break;
3978
3979 case TKIND_COCLASS:
3980 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3981 pTIHeader, pTITail);
3982 break;
3983
3984 case TKIND_ALIAS:
3985 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3986 pTIHeader, pTITail);
3987 break;
3988
3989 case TKIND_DISPATCH:
3990 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3991 pTIHeader, pTITail);
3992 break;
3993
3994 case TKIND_MODULE:
3995 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3996 pTIHeader, pTITail);
3997 break;
3998
3999 default:
4000 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4001 break;
4002
4003 }
4004
4005 /* could get cFuncs, cVars and cImplTypes from here
4006 but we've already set those */
4007 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4008 X(06);
4009 X(16);
4010 X(18);
4011 X(1a);
4012 X(1e);
4013 X(24);
4014 X(26);
4015 X(2a);
4016 X(2c);
4017 X(2e);
4018 X(30);
4019 X(32);
4020 X(34);
4021 #undef X
4022 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4023 pBlk = (char*)pBlk + pBlkEntry[order].len;
4024 }
4025
4026 if(i != pTypeLibImpl->TypeInfoCount) {
4027 FIXME("Somehow processed %d TypeInfos\n", i);
4028 return NULL;
4029 }
4030
4031 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4032 return (ITypeLib2*)pTypeLibImpl;
4033 }
4034
4035 /* ITypeLib::QueryInterface
4036 */
4037 static HRESULT WINAPI ITypeLib2_fnQueryInterface