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