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 (FAILED(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 (FAILED(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 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_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1088 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1089 case VT_PTR: sprintf(szVarType, "ptr to ");
1090 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1091 break;
1092 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1093 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1094 break;
1095 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1096 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1097 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1098 break;
1099
1100 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1101 }
1102 }
1103
1104 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1105 char buf[200];
1106 USHORT flags = edesc->u.paramdesc.wParamFlags;
1107 dump_TypeDesc(&edesc->tdesc,buf);
1108 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1109 MESSAGE("\t\tu.paramdesc.wParamFlags");
1110 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1111 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1112 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1113 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1114 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1115 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1116 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1117 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1118 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1119 }
1120 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1121 int i;
1122 MESSAGE("memid is %08x\n",funcdesc->memid);
1123 for (i=0;i<funcdesc->cParams;i++) {
1124 MESSAGE("Param %d:\n",i);
1125 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1126 }
1127 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1128 switch (funcdesc->funckind) {
1129 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1130 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1131 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1132 case FUNC_STATIC: MESSAGE("static");break;
1133 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1134 default: MESSAGE("unknown");break;
1135 }
1136 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1137 switch (funcdesc->invkind) {
1138 case INVOKE_FUNC: MESSAGE("func");break;
1139 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1140 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1141 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1142 }
1143 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1144 switch (funcdesc->callconv) {
1145 case CC_CDECL: MESSAGE("cdecl");break;
1146 case CC_PASCAL: MESSAGE("pascal");break;
1147 case CC_STDCALL: MESSAGE("stdcall");break;
1148 case CC_SYSCALL: MESSAGE("syscall");break;
1149 default:break;
1150 }
1151 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1152 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1153 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1154
1155 MESSAGE("\telemdescFunc (return value type):\n");
1156 dump_ELEMDESC(&funcdesc->elemdescFunc);
1157 }
1158
1159 static const char * const typekind_desc[] =
1160 {
1161 "TKIND_ENUM",
1162 "TKIND_RECORD",
1163 "TKIND_MODULE",
1164 "TKIND_INTERFACE",
1165 "TKIND_DISPATCH",
1166 "TKIND_COCLASS",
1167 "TKIND_ALIAS",
1168 "TKIND_UNION",
1169 "TKIND_MAX"
1170 };
1171
1172 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1173 {
1174 int i;
1175 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1176 for (i=0;i<pfd->funcdesc.cParams;i++)
1177 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1178
1179
1180 dump_FUNCDESC(&(pfd->funcdesc));
1181
1182 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1183 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1184 }
1185 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1186 {
1187 while (pfd)
1188 {
1189 dump_TLBFuncDescOne(pfd);
1190 pfd = pfd->next;
1191 };
1192 }
1193 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1194 {
1195 while (pvd)
1196 {
1197 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1198 pvd = pvd->next;
1199 };
1200 }
1201
1202 static void dump_TLBImpLib(const TLBImpLib *import)
1203 {
1204 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1205 debugstr_w(import->name));
1206 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1207 import->wVersionMinor, import->lcid, import->offset);
1208 }
1209
1210 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1211 {
1212 TLBRefType *ref;
1213
1214 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1215 {
1216 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1217 if(ref->index == -1)
1218 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1219 else
1220 TRACE_(typelib)("type no: %d\n", ref->index);
1221
1222 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1223 {
1224 TRACE_(typelib)("in lib\n");
1225 dump_TLBImpLib(ref->pImpTLInfo);
1226 }
1227 }
1228 }
1229
1230 static void dump_TLBImplType(const TLBImplType * impl)
1231 {
1232 while (impl) {
1233 TRACE_(typelib)(
1234 "implementing/inheriting interface hRef = %x implflags %x\n",
1235 impl->hRef, impl->implflags);
1236 impl = impl->next;
1237 }
1238 }
1239
1240 static void dump_Variant(const VARIANT * pvar)
1241 {
1242 SYSTEMTIME st;
1243
1244 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1245
1246 if (pvar)
1247 {
1248 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1249 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1250 {
1251 TRACE(",%p", V_BYREF(pvar));
1252 }
1253 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1254 {
1255 TRACE(",%p", V_ARRAY(pvar));
1256 }
1257 else switch (V_TYPE(pvar))
1258 {
1259 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1260 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1261 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1262 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1263 case VT_INT:
1264 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1265 case VT_UINT:
1266 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1267 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1268 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1269 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1270 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1271 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1272 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1273 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1274 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1275 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1276 V_CY(pvar).s.Lo); break;
1277 case VT_DATE:
1278 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1279 TRACE(",<invalid>");
1280 else
1281 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1282 st.wHour, st.wMinute, st.wSecond);
1283 break;
1284 case VT_ERROR:
1285 case VT_VOID:
1286 case VT_USERDEFINED:
1287 case VT_EMPTY:
1288 case VT_NULL: break;
1289 default: TRACE(",?"); break;
1290 }
1291 }
1292 TRACE("}\n");
1293 }
1294
1295 static void dump_DispParms(const DISPPARAMS * pdp)
1296 {
1297 int index;
1298
1299 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1300
1301 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1302 {
1303 TRACE("named args:\n");
1304 for (index = 0; index < pdp->cNamedArgs; index++)
1305 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1306 }
1307
1308 if (pdp->cArgs && pdp->rgvarg)
1309 {
1310 TRACE("args:\n");
1311 for (index = 0; index < pdp->cArgs; index++)
1312 dump_Variant( &pdp->rgvarg[index] );
1313 }
1314 }
1315
1316 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1317 {
1318 TRACE("%p ref=%u\n", pty, pty->ref);
1319 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1320 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1321 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1322 TRACE("fct:%u var:%u impl:%u\n",
1323 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1324 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1325 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1326 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1327 if (TRACE_ON(ole))
1328 dump_TLBFuncDesc(pty->funclist);
1329 dump_TLBVarDesc(pty->varlist);
1330 dump_TLBImplType(pty->impltypelist);
1331 }
1332
1333 static void dump_VARDESC(const VARDESC *v)
1334 {
1335 MESSAGE("memid %d\n",v->memid);
1336 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1337 MESSAGE("oInst %d\n",v->u.oInst);
1338 dump_ELEMDESC(&(v->elemdescVar));
1339 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1340 MESSAGE("varkind %d\n",v->varkind);
1341 }
1342
1343 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1344 {
1345 /* VT_LPWSTR is largest type that */
1346 /* may appear in type description*/
1347 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1348 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1349 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1350 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1351 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1352 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1353 {{0},30},{{0},31}
1354 };
1355
1356 static void TLB_abort(void)
1357 {
1358 DebugBreak();
1359 }
1360
1361 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1362 static void * TLB_Alloc(unsigned size)
1363 {
1364 void * ret;
1365 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1366 /* FIXME */
1367 ERR("cannot allocate memory\n");
1368 }
1369 return ret;
1370 }
1371
1372 static void TLB_Free(void * ptr)
1373 {
1374 HeapFree(GetProcessHeap(), 0, ptr);
1375 }
1376
1377 /* returns the size required for a deep copy of a typedesc into a
1378 * flat buffer */
1379 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1380 {
1381 SIZE_T size = 0;
1382
1383 if (alloc_initial_space)
1384 size += sizeof(TYPEDESC);
1385
1386 switch (tdesc->vt)
1387 {
1388 case VT_PTR:
1389 case VT_SAFEARRAY:
1390 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1391 break;
1392 case VT_CARRAY:
1393 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1394 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1395 break;
1396 }
1397 return size;
1398 }
1399
1400 /* deep copy a typedesc into a flat buffer */
1401 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1402 {
1403 if (!dest)
1404 {
1405 dest = buffer;
1406 buffer = (char *)buffer + sizeof(TYPEDESC);
1407 }
1408
1409 *dest = *src;
1410
1411 switch (src->vt)
1412 {
1413 case VT_PTR:
1414 case VT_SAFEARRAY:
1415 dest->u.lptdesc = buffer;
1416 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1417 break;
1418 case VT_CARRAY:
1419 dest->u.lpadesc = buffer;
1420 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1421 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1422 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1423 break;
1424 }
1425 return buffer;
1426 }
1427
1428 /* free custom data allocated by MSFT_CustData */
1429 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1430 {
1431 TLBCustData *pCustDataNext;
1432 for (; pCustData; pCustData = pCustDataNext)
1433 {
1434 VariantClear(&pCustData->data);
1435
1436 pCustDataNext = pCustData->next;
1437 TLB_Free(pCustData);
1438 }
1439 }
1440
1441 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1442 {
1443 DWORD len;
1444 BSTR ret;
1445
1446 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1447 ret = SysAllocStringLen(NULL, len - 1);
1448 if (!ret) return ret;
1449 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1450 return ret;
1451 }
1452
1453 /**********************************************************************
1454 *
1455 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1456 */
1457 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1458 {
1459 return pcx->pos;
1460 }
1461
1462 static inline void MSFT_Seek(TLBContext *pcx, long where)
1463 {
1464 if (where != DO_NOT_SEEK)
1465 {
1466 where += pcx->oStart;
1467 if (where > pcx->length)
1468 {
1469 /* FIXME */
1470 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1471 TLB_abort();
1472 }
1473 pcx->pos = where;
1474 }
1475 }
1476
1477 /* read function */
1478 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1479 {
1480 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1481 pcx->pos, count, pcx->oStart, pcx->length, where);
1482
1483 MSFT_Seek(pcx, where);
1484 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1485 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1486 pcx->pos += count;
1487 return count;
1488 }
1489
1490 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1491 long where )
1492 {
1493 DWORD ret;
1494
1495 ret = MSFT_Read(buffer, count, pcx, where);
1496 FromLEDWords(buffer, ret);
1497
1498 return ret;
1499 }
1500
1501 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1502 long where )
1503 {
1504 DWORD ret;
1505
1506 ret = MSFT_Read(buffer, count, pcx, where);
1507 FromLEWords(buffer, ret);
1508
1509 return ret;
1510 }
1511
1512 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1513 {
1514 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1515 memset(pGuid,0, sizeof(GUID));
1516 return;
1517 }
1518 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1519 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1520 pGuid->Data2 = FromLEWord(pGuid->Data2);
1521 pGuid->Data3 = FromLEWord(pGuid->Data3);
1522 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1523 }
1524
1525 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1526 {
1527 MSFT_NameIntro niName;
1528
1529 if (offset < 0)
1530 {
1531 ERR_(typelib)("bad offset %d\n", offset);
1532 return -1;
1533 }
1534
1535 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1536 pcx->pTblDir->pNametab.offset+offset);
1537
1538 return niName.hreftype;
1539 }
1540
1541 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1542 {
1543 char * name;
1544 MSFT_NameIntro niName;
1545 int lengthInChars;
1546 BSTR bstrName = NULL;
1547
1548 if (offset < 0)
1549 {
1550 ERR_(typelib)("bad offset %d\n", offset);
1551 return NULL;
1552 }
1553 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1554 pcx->pTblDir->pNametab.offset+offset);
1555 niName.namelen &= 0xFF; /* FIXME: correct ? */
1556 name=TLB_Alloc((niName.namelen & 0xff) +1);
1557 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1558 name[niName.namelen & 0xff]='\0';
1559
1560 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1561 name, -1, NULL, 0);
1562
1563 /* no invalid characters in string */
1564 if (lengthInChars)
1565 {
1566 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1567
1568 /* don't check for invalid character since this has been done previously */
1569 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1570 }
1571 TLB_Free(name);
1572
1573 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1574 return bstrName;
1575 }
1576
1577 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1578 {
1579 char * string;
1580 INT16 length;
1581 int lengthInChars;
1582 BSTR bstr = NULL;
1583
1584 if(offset<0) return NULL;
1585 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1586 if(length <= 0) return 0;
1587 string=TLB_Alloc(length +1);
1588 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1589 string[length]='\0';
1590
1591 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1592 string, -1, NULL, 0);
1593
1594 /* no invalid characters in string */
1595 if (lengthInChars)
1596 {
1597 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1598
1599 /* don't check for invalid character since this has been done previously */
1600 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1601 }
1602 TLB_Free(string);
1603
1604 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1605 return bstr;
1606 }
1607 /*
1608 * read a value and fill a VARIANT structure
1609 */
1610 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1611 {
1612 int size;
1613
1614 TRACE_(typelib)("\n");
1615
1616 if(offset <0) { /* data are packed in here */
1617 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1618 V_I4(pVar) = offset & 0x3ffffff;
1619 return;
1620 }
1621 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1622 pcx->pTblDir->pCustData.offset + offset );
1623 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1624 switch (V_VT(pVar)){
1625 case VT_EMPTY: /* FIXME: is this right? */
1626 case VT_NULL: /* FIXME: is this right? */
1627 case VT_I2 : /* this should not happen */
1628 case VT_I4 :
1629 case VT_R4 :
1630 case VT_ERROR :
1631 case VT_BOOL :
1632 case VT_I1 :
1633 case VT_UI1 :
1634 case VT_UI2 :
1635 case VT_UI4 :
1636 case VT_INT :
1637 case VT_UINT :
1638 case VT_VOID : /* FIXME: is this right? */
1639 case VT_HRESULT :
1640 size=4; break;
1641 case VT_R8 :
1642 case VT_CY :
1643 case VT_DATE :
1644 case VT_I8 :
1645 case VT_UI8 :
1646 case VT_DECIMAL : /* FIXME: is this right? */
1647 case VT_FILETIME :
1648 size=8;break;
1649 /* pointer types with known behaviour */
1650 case VT_BSTR :{
1651 char * ptr;
1652 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1653 if(size < 0) {
1654 char next;
1655 DWORD origPos = MSFT_Tell(pcx), nullPos;
1656
1657 do {
1658 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1659 } while (next);
1660 nullPos = MSFT_Tell(pcx);
1661 size = nullPos - origPos;
1662 MSFT_Seek(pcx, origPos);
1663 }
1664 ptr=TLB_Alloc(size);/* allocate temp buffer */
1665 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1666 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1667 /* FIXME: do we need a AtoW conversion here? */
1668 V_UNION(pVar, bstrVal[size])='\0';
1669 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1670 TLB_Free(ptr);
1671 }
1672 size=-4; break;
1673 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1674 case VT_DISPATCH :
1675 case VT_VARIANT :
1676 case VT_UNKNOWN :
1677 case VT_PTR :
1678 case VT_SAFEARRAY :
1679 case VT_CARRAY :
1680 case VT_USERDEFINED :
1681 case VT_LPSTR :
1682 case VT_LPWSTR :
1683 case VT_BLOB :
1684 case VT_STREAM :
1685 case VT_STORAGE :
1686 case VT_STREAMED_OBJECT :
1687 case VT_STORED_OBJECT :
1688 case VT_BLOB_OBJECT :
1689 case VT_CF :
1690 case VT_CLSID :
1691 default:
1692 size=0;
1693 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1694 V_VT(pVar));
1695 }
1696
1697 if(size>0) /* (big|small) endian correct? */
1698 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1699 return;
1700 }
1701 /*
1702 * create a linked list with custom data
1703 */
1704 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1705 {
1706 MSFT_CDGuid entry;
1707 TLBCustData* pNew;
1708 int count=0;
1709
1710 TRACE_(typelib)("\n");
1711
1712 while(offset >=0){
1713 count++;
1714 pNew=TLB_Alloc(sizeof(TLBCustData));
1715 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1716 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1717 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1718 /* add new custom data at head of the list */
1719 pNew->next=*ppCustData;
1720 *ppCustData=pNew;
1721 offset = entry.next;
1722 }
1723 return count;
1724 }
1725
1726 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1727 ITypeInfoImpl *pTI)
1728 {
1729 if(type <0)
1730 pTd->vt=type & VT_TYPEMASK;
1731 else
1732 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1733
1734 if(pTd->vt == VT_USERDEFINED)
1735 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1736
1737 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1738 }
1739
1740 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1741 {
1742 /* resolve referenced type if any */
1743 while (lpTypeDesc)
1744 {
1745 switch (lpTypeDesc->vt)
1746 {
1747 case VT_PTR:
1748 lpTypeDesc = lpTypeDesc->u.lptdesc;
1749 break;
1750
1751 case VT_CARRAY:
1752 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1753 break;
1754
1755 case VT_USERDEFINED:
1756 MSFT_DoRefType(pcx, pTI->pTypeLib,
1757 lpTypeDesc->u.hreftype);
1758
1759 lpTypeDesc = NULL;
1760 break;
1761
1762 default:
1763 lpTypeDesc = NULL;
1764 }
1765 }
1766 }
1767
1768 static void
1769 MSFT_DoFuncs(TLBContext* pcx,
1770 ITypeInfoImpl* pTI,
1771 int cFuncs,
1772 int cVars,
1773 int offset,
1774 TLBFuncDesc** pptfd)
1775 {
1776 /*
1777 * member information is stored in a data structure at offset
1778 * indicated by the memoffset field of the typeinfo structure
1779 * There are several distinctive parts.
1780 * The first part starts with a field that holds the total length
1781 * of this (first) part excluding this field. Then follow the records,
1782 * for each member there is one record.
1783 *
1784 * The first entry is always the length of the record (including this
1785 * length word).
1786 * The rest of the record depends on the type of the member. If there is
1787 * a field indicating the member type (function, variable, interface, etc)
1788 * I have not found it yet. At this time we depend on the information
1789 * in the type info and the usual order how things are stored.
1790 *
1791 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1792 * for each member;
1793 *
1794 * Third is an equal sized array with file offsets to the name entry
1795 * of each member.
1796 *
1797 * The fourth and last (?) part is an array with offsets to the records
1798 * in the first part of this file segment.
1799 */
1800
1801 int infolen, nameoffset, reclength, nrattributes, i;
1802 int recoffset = offset + sizeof(INT);
1803
1804 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1805 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1806 TLBFuncDesc *ptfd_prev = NULL;
1807
1808 TRACE_(typelib)("\n");
1809
1810 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1811
1812 for ( i = 0; i < cFuncs ; i++ )
1813 {
1814 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1815
1816 /* name, eventually add to a hash table */
1817 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1818 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1819
1820 /* nameoffset is sometimes -1 on the second half of a propget/propput
1821 * pair of functions */
1822 if ((nameoffset == -1) && (i > 0))
1823 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1824 else
1825 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1826
1827 /* read the function information record */
1828 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1829
1830 reclength &= 0xffff;
1831
1832 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1833
1834 /* do the attributes */
1835 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1836 / sizeof(int);
1837
1838 if ( nrattributes > 0 )
1839 {
1840 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1841
1842 if ( nrattributes > 1 )
1843 {
1844 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1845 pFuncRec->OptAttr[1]) ;
1846
1847 if ( nrattributes > 2 )
1848 {
1849 if ( pFuncRec->FKCCIC & 0x2000 )
1850 {
1851 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1852 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1853 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1854 }
1855 else
1856 {
1857 (*pptfd)->Entry = MSFT_ReadString(pcx,
1858 pFuncRec->OptAttr[2]);
1859 }
1860 if( nrattributes > 5 )
1861 {
1862 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1863
1864 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1865 {
1866 MSFT_CustData(pcx,
1867 pFuncRec->OptAttr[6],
1868 &(*pptfd)->pCustData);
1869 }
1870 }
1871 }
1872 else
1873 {
1874 (*pptfd)->Entry = (BSTR)-1;
1875 }
1876 }
1877 }
1878
1879 /* fill the FuncDesc Structure */
1880 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1881 offset + infolen + ( i + 1) * sizeof(INT));
1882
1883 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1884 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1885 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1886 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1887 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1888 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1889 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1890
1891 MSFT_GetTdesc(pcx,
1892 pFuncRec->DataType,
1893 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1894 pTI);
1895 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1896
1897 /* do the parameters/arguments */
1898 if(pFuncRec->nrargs)
1899 {
1900 int j = 0;
1901 MSFT_ParameterInfo paraminfo;
1902
1903 (*pptfd)->funcdesc.lprgelemdescParam =
1904 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1905
1906 (*pptfd)->pParamDesc =
1907 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1908
1909 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1910 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1911
1912 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1913 {
1914 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1915
1916 MSFT_GetTdesc(pcx,
1917 paraminfo.DataType,
1918 &elemdesc->tdesc,
1919 pTI);
1920
1921 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1922
1923 /* name */
1924 if (paraminfo.oName == -1)
1925 /* this occurs for [propput] or [propget] methods, so
1926 * we should just set the name of the parameter to the
1927 * name of the method. */
1928 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1929 else
1930 (*pptfd)->pParamDesc[j].Name =
1931 MSFT_ReadName( pcx, paraminfo.oName );
1932 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1933
1934 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1935
1936 /* default value */
1937 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1938 (pFuncRec->FKCCIC & 0x1000) )
1939 {
1940 INT* pInt = (INT *)((char *)pFuncRec +
1941 reclength -
1942 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1943
1944 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1945
1946 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1947 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1948
1949 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1950 pInt[j], pcx);
1951 }
1952 else
1953 elemdesc->u.paramdesc.pparamdescex = NULL;
1954 /* custom info */
1955 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1956 {
1957 MSFT_CustData(pcx,
1958 pFuncRec->OptAttr[7+j],
1959 &(*pptfd)->pParamDesc[j].pCustData);
1960 }
1961
1962 /* SEEK value = jump to offset,
1963 * from there jump to the end of record,
1964 * go back by (j-1) arguments
1965 */
1966 MSFT_ReadLEDWords( ¶minfo ,
1967 sizeof(MSFT_ParameterInfo), pcx,
1968 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1969 * sizeof(MSFT_ParameterInfo)));
1970 }
1971 }
1972
1973 /* scode is not used: archaic win16 stuff FIXME: right? */
1974 (*pptfd)->funcdesc.cScodes = 0 ;
1975 (*pptfd)->funcdesc.lprgscode = NULL ;
1976
1977 ptfd_prev = *pptfd;
1978 pptfd = & ((*pptfd)->next);
1979 recoffset += reclength;
1980 }
1981 HeapFree(GetProcessHeap(), 0, recbuf);
1982 }
1983
1984 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1985 int cVars, int offset, TLBVarDesc ** pptvd)
1986 {
1987 int infolen, nameoffset, reclength;
1988 char recbuf[256];
1989 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1990 int i;
1991 int recoffset;
1992
1993 TRACE_(typelib)("\n");
1994
1995 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1996 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1997 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1998 recoffset += offset+sizeof(INT);
1999 for(i=0;i<cVars;i++){
2000 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2001 /* name, eventually add to a hash table */
2002 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2003 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2004 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2005 /* read the variable information record */
2006 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2007 reclength &=0xff;
2008 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2009 /* Optional data */
2010 if(reclength >(6*sizeof(INT)) )
2011 (*pptvd)->HelpContext=pVarRec->HelpContext;
2012 if(reclength >(7*sizeof(INT)) )
2013 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2014 if(reclength >(8*sizeof(INT)) )
2015 if(reclength >(9*sizeof(INT)) )
2016 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2017 /* fill the VarDesc Structure */
2018 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2019 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2020 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2021 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2022 MSFT_GetTdesc(pcx, pVarRec->DataType,
2023 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2024 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2025 if(pVarRec->VarKind == VAR_CONST ){
2026 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2027 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2028 pVarRec->OffsValue, pcx);
2029 } else
2030 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2031 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2032 pptvd=&((*pptvd)->next);
2033 recoffset += reclength;
2034 }
2035 }
2036 /* fill in data for a hreftype (offset). When the referenced type is contained
2037 * in the typelib, it's just an (file) offset in the type info base dir.
2038 * If comes from import, it's an offset+1 in the ImpInfo table
2039 * */
2040 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2041 int offset)
2042 {
2043 TLBRefType *ref;
2044
2045 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2046
2047 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2048 {
2049 if(ref->reference == offset) return;
2050 }
2051
2052 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2053 list_add_tail(&pTL->ref_list, &ref->entry);
2054
2055 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2056 /* external typelib */
2057 MSFT_ImpInfo impinfo;
2058 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2059
2060 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2061
2062 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2063 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2064 while (pImpLib){ /* search the known offsets of all import libraries */
2065 if(pImpLib->offset==impinfo.oImpFile) break;
2066 pImpLib=pImpLib->next;
2067 }
2068 if(pImpLib){
2069 ref->reference = offset;
2070 ref->pImpTLInfo = pImpLib;
2071 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2072 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2073 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2074 ref->index = TLB_REF_USE_GUID;
2075 } else
2076 ref->index = impinfo.oGuid;
2077 }else{
2078 ERR("Cannot find a reference\n");
2079 ref->reference = -1;
2080 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2081 }
2082 }else{
2083 /* in this typelib */
2084 ref->index = MSFT_HREFTYPE_INDEX(offset);
2085 ref->reference = offset;
2086 ref->pImpTLInfo = TLB_REF_INTERNAL;
2087 }
2088 }
2089
2090 /* process Implemented Interfaces of a com class */
2091 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2092 int offset)
2093 {
2094 int i;
2095 MSFT_RefRecord refrec;
2096 TLBImplType **ppImpl = &pTI->impltypelist;
2097
2098 TRACE_(typelib)("\n");
2099
2100 for(i=0;i<count;i++){
2101 if(offset<0) break; /* paranoia */
2102 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2103 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2104 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2105 (*ppImpl)->hRef = refrec.reftype;
2106 (*ppImpl)->implflags=refrec.flags;
2107 (*ppImpl)->ctCustData=
2108 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2109 offset=refrec.onext;
2110 ppImpl=&((*ppImpl)->next);
2111 }
2112 }
2113 /*
2114 * process a typeinfo record
2115 */
2116 static ITypeInfoImpl * MSFT_DoTypeInfo(
2117 TLBContext *pcx,
2118 int count,
2119 ITypeLibImpl * pLibInfo)
2120 {
2121 MSFT_TypeInfoBase tiBase;
2122 ITypeInfoImpl *ptiRet;
2123
2124 TRACE_(typelib)("count=%u\n", count);
2125
2126 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2127 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2128 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2129
2130 /* this is where we are coming from */
2131 ptiRet->pTypeLib = pLibInfo;
2132 ptiRet->index=count;
2133 /* fill in the typeattr fields */
2134
2135 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2136 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2137 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2138 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2139 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2140 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2141 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2142 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2143 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2144 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2145 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2146 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2147 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2148 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2149 MSFT_GetTdesc(pcx, tiBase.datatype1,
2150 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2151
2152 /* FIXME: */
2153 /* IDLDESC idldescType; *//* never saw this one != zero */
2154
2155 /* name, eventually add to a hash table */
2156 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2157 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2158 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2159 /* help info */
2160 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2161 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2162 ptiRet->dwHelpContext=tiBase.helpcontext;
2163
2164 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2165 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2166
2167 /* note: InfoType's Help file and HelpStringDll come from the containing
2168 * library. Further HelpString and Docstring appear to be the same thing :(
2169 */
2170 /* functions */
2171 if(ptiRet->TypeAttr.cFuncs >0 )
2172 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2173 ptiRet->TypeAttr.cVars,
2174 tiBase.memoffset, & ptiRet->funclist);
2175 /* variables */
2176 if(ptiRet->TypeAttr.cVars >0 )
2177 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2178 ptiRet->TypeAttr.cVars,
2179 tiBase.memoffset, & ptiRet->varlist);
2180 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2181 switch(ptiRet->TypeAttr.typekind)
2182 {
2183 case TKIND_COCLASS:
2184 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2185 tiBase.datatype1);
2186 break;
2187 case TKIND_DISPATCH:
2188 /* This is not -1 when the interface is a non-base dual interface or
2189 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2190 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2191 not this interface.
2192 */
2193
2194 if (tiBase.datatype1 != -1)
2195 {
2196 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2197 ptiRet->impltypelist->hRef = tiBase.datatype1;
2198 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2199 }
2200 break;
2201 default:
2202 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2203 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2204 ptiRet->impltypelist->hRef = tiBase.datatype1;
2205 break;
2206 }
2207 }
2208 ptiRet->ctCustData=
2209 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2210
2211 TRACE_(typelib)("%s guid: %s kind:%s\n",
2212 debugstr_w(ptiRet->Name),
2213 debugstr_guid(&ptiRet->TypeAttr.guid),
2214 typekind_desc[ptiRet->TypeAttr.typekind]);
2215
2216 return ptiRet;
2217 }
2218
2219 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2220 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2221 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2222 * tradeoff here.
2223 */
2224 static ITypeLibImpl *tlb_cache_first;
2225 static CRITICAL_SECTION cache_section;
2226 static CRITICAL_SECTION_DEBUG cache_section_debug =
2227 {
2228 0, 0, &cache_section,
2229 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2230 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2231 };
2232 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2233
2234
2235 typedef struct TLB_PEFile
2236 {
2237 const IUnknownVtbl *lpvtbl;
2238 LONG refs;
2239 HMODULE dll;
2240 HRSRC typelib_resource;
2241 HGLOBAL typelib_global;
2242 LPVOID typelib_base;
2243 } TLB_PEFile;
2244
2245 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2246 {
2247 if (IsEqualIID(riid, &IID_IUnknown))
2248 {
2249 *ppv = iface;
2250 IUnknown_AddRef(iface);
2251 return S_OK;
2252 }
2253 *ppv = NULL;
2254 return E_NOINTERFACE;
2255 }
2256
2257 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2258 {
2259 TLB_PEFile *This = (TLB_PEFile *)iface;
2260 return InterlockedIncrement(&This->refs);
2261 }
2262
2263 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2264 {
2265 TLB_PEFile *This = (TLB_PEFile *)iface;
2266 ULONG refs = InterlockedDecrement(&This->refs);
2267 if (!refs)
2268 {
2269 if (This->typelib_global)
2270 FreeResource(This->typelib_global);
2271 if (This->dll)
2272 FreeLibrary(This->dll);
2273 HeapFree(GetProcessHeap(), 0, This);
2274 }
2275 return refs;
2276 }
2277
2278 static const IUnknownVtbl TLB_PEFile_Vtable =
2279 {
2280 TLB_PEFile_QueryInterface,
2281 TLB_PEFile_AddRef,
2282 TLB_PEFile_Release
2283 };
2284
2285 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2286 {
2287 TLB_PEFile *This;
2288
2289 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2290 if (!This)
2291 return E_OUTOFMEMORY;
2292
2293 This->lpvtbl = &TLB_PEFile_Vtable;
2294 This->refs = 1;
2295 This->dll = NULL;
2296 This->typelib_resource = NULL;
2297 This->typelib_global = NULL;
2298 This->typelib_base = NULL;
2299
2300 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2301 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2302
2303 if (This->dll)
2304 {
2305 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2306 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2307 if (This->typelib_resource)
2308 {
2309 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2310 if (This->typelib_global)
2311 {
2312 This->typelib_base = LockResource(This->typelib_global);
2313
2314 if (This->typelib_base)
2315 {
2316 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2317 *ppBase = This->typelib_base;
2318 *ppFile = (IUnknown *)&This->lpvtbl;
2319 return S_OK;
2320 }
2321 }
2322 }
2323 }
2324
2325 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2326 return TYPE_E_CANTLOADLIBRARY;
2327 }
2328
2329
2330 typedef struct TLB_Mapping
2331 {
2332 const IUnknownVtbl *lpvtbl;
2333 LONG refs;
2334 HANDLE file;
2335 HANDLE mapping;
2336 LPVOID typelib_base;
2337 } TLB_Mapping;
2338
2339 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2340 {
2341 if (IsEqualIID(riid, &IID_IUnknown))
2342 {
2343 *ppv = iface;
2344 IUnknown_AddRef(iface);
2345 return S_OK;
2346 }
2347 *ppv = NULL;
2348 return E_NOINTERFACE;
2349 }
2350
2351 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2352 {
2353 TLB_Mapping *This = (TLB_Mapping *)iface;
2354 return InterlockedIncrement(&This->refs);
2355 }
2356
2357 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2358 {
2359 TLB_Mapping *This = (TLB_Mapping *)iface;
2360 ULONG refs = InterlockedDecrement(&This->refs);
2361 if (!refs)
2362 {
2363 if (This->typelib_base)
2364 UnmapViewOfFile(This->typelib_base);
2365 if (This->mapping)
2366 CloseHandle(This->mapping);
2367 if (This->file != INVALID_HANDLE_VALUE)
2368 CloseHandle(This->file);
2369 HeapFree(GetProcessHeap(), 0, This);
2370 }
2371 return refs;
2372 }
2373
2374 static const IUnknownVtbl TLB_Mapping_Vtable =
2375 {
2376 TLB_Mapping_QueryInterface,
2377 TLB_Mapping_AddRef,
2378 TLB_Mapping_Release
2379 };
2380
2381 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2382 {
2383 TLB_Mapping *This;
2384
2385 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2386 if (!This)
2387 return E_OUTOFMEMORY;
2388
2389 This->lpvtbl = &TLB_Mapping_Vtable;
2390 This->refs = 1;
2391 This->file = INVALID_HANDLE_VALUE;
2392 This->mapping = NULL;
2393 This->typelib_base = NULL;
2394
2395 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2396 if (INVALID_HANDLE_VALUE != This->file)
2397 {
2398 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2399 if (This->mapping)
2400 {
2401 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2402 if(This->typelib_base)
2403 {
2404 /* retrieve file size */
2405 *pdwTLBLength = GetFileSize(This->file, NULL);
2406 *ppBase = This->typelib_base;
2407 *ppFile = (IUnknown *)&This->lpvtbl;
2408 return S_OK;
2409 }
2410 }
2411 }
2412
2413 IUnknown_Release((IUnknown *)&This->lpvtbl);
2414 return TYPE_E_CANTLOADLIBRARY;
2415 }
2416
2417 /****************************************************************************
2418 * TLB_ReadTypeLib
2419 *
2420 * find the type of the typelib file and map the typelib resource into
2421 * the memory
2422 */
2423 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2424 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2425 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2426 {
2427 ITypeLibImpl *entry;
2428 HRESULT ret;
2429 INT index = 1;
2430 LPWSTR index_str, file = (LPWSTR)pszFileName;
2431 LPVOID pBase = NULL;
2432 DWORD dwTLBLength = 0;
2433 IUnknown *pFile = NULL;
2434
2435 *ppTypeLib = NULL;
2436
2437 index_str = strrchrW(pszFileName, '\\');
2438 if(index_str && *++index_str != '\0')
2439 {
2440 LPWSTR end_ptr;
2441 long idx = strtolW(index_str, &end_ptr, 10);
2442 if(*end_ptr == '\0')
2443 {
2444 int str_len = index_str - pszFileName - 1;
2445 index = idx;
2446 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2447 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2448 file[str_len] = 0;
2449 }
2450 }
2451
2452 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2453 {
2454 if(strchrW(file, '\\'))
2455 {
2456 lstrcpyW(pszPath, file);
2457 }
2458 else
2459 {
2460 int len = GetSystemDirectoryW(pszPath, cchPath);
2461 pszPath[len] = '\\';
2462 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2463 }
2464 }
2465
2466 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2467
2468 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2469
2470 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2471 EnterCriticalSection(&cache_section);
2472 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2473 {
2474 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2475 {
2476 TRACE("cache hit\n");
2477 *ppTypeLib = (ITypeLib2*)entry;
2478 ITypeLib_AddRef(*ppTypeLib);
2479 LeaveCriticalSection(&cache_section);
2480 return S_OK;
2481 }
2482 }
2483 LeaveCriticalSection(&cache_section);
2484
2485 /* now actually load and parse the typelib */
2486
2487 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2488 if (ret == TYPE_E_CANTLOADLIBRARY)
2489 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2490 if (SUCCEEDED(ret))
2491 {
2492 if (dwTLBLength >= 4)
2493 {
2494 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2495 if (dwSignature == MSFT_SIGNATURE)
2496 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2497 else if (dwSignature == SLTG_SIGNATURE)
2498 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2499 else
2500 {
2501 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2502 ret = TYPE_E_CANTLOADLIBRARY;
2503 }
2504 }
2505 else
2506 ret = TYPE_E_CANTLOADLIBRARY;
2507 IUnknown_Release(pFile);
2508 }
2509
2510 if(*ppTypeLib) {
2511 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2512
2513 TRACE("adding to cache\n");
2514 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2515 lstrcpyW(impl->path, pszPath);
2516 /* We should really canonicalise the path here. */
2517 impl->index = index;
2518
2519 /* FIXME: check if it has added already in the meantime */
2520 EnterCriticalSection(&cache_section);
2521 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2522 impl->prev = NULL;
2523 tlb_cache_first = impl;
2524 LeaveCriticalSection(&cache_section);
2525 ret = S_OK;
2526 } else
2527 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2528
2529 return ret;
2530 }
2531
2532 /*================== ITypeLib(2) Methods ===================================*/
2533
2534 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2535 {
2536 ITypeLibImpl* pTypeLibImpl;
2537
2538 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2539 if (!pTypeLibImpl) return NULL;
2540
2541 pTypeLibImpl->lpVtbl = &tlbvt;
2542 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2543 pTypeLibImpl->ref = 1;
2544
2545 list_init(&pTypeLibImpl->ref_list);
2546 pTypeLibImpl->dispatch_href = -1;
2547
2548 return pTypeLibImpl;
2549 }
2550
2551 /****************************************************************************
2552 * ITypeLib2_Constructor_MSFT
2553 *
2554 * loading an MSFT typelib from an in-memory image
2555 */
2556 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2557 {
2558 TLBContext cx;
2559 long lPSegDir;
2560 MSFT_Header tlbHeader;
2561 MSFT_SegDir tlbSegDir;
2562 ITypeLibImpl * pTypeLibImpl;
2563
2564 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2565
2566 pTypeLibImpl = TypeLibImpl_Constructor();
2567 if (!pTypeLibImpl) return NULL;
2568
2569 /* get pointer to beginning of typelib data */
2570 cx.pos = 0;
2571 cx.oStart=0;
2572 cx.mapping = pLib;
2573 cx.pLibInfo = pTypeLibImpl;
2574 cx.length = dwTLBLength;
2575
2576 /* read header */
2577 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2578 TRACE_(typelib)("header:\n");
2579 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2580 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2581 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2582 return NULL;
2583 }
2584 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2585
2586 /* there is a small amount of information here until the next important
2587 * part:
2588 * the segment directory . Try to calculate the amount of data */
2589 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2590
2591 /* now read the segment directory */
2592 TRACE("read segment directory (at %ld)\n",lPSegDir);
2593 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2594 cx.pTblDir = &tlbSegDir;
2595
2596 /* just check two entries */
2597 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2598 {
2599 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2600 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2601 return NULL;
2602 }
2603
2604 /* now fill our internal data */
2605 /* TLIBATTR fields */
2606 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2607
2608 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2609 /* Windows seems to have zero here, is this correct? */
2610 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2611 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2612 else
2613 pTypeLibImpl->LibAttr.lcid = 0;
2614
2615 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2616 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2617 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2618 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2619
2620 /* name, eventually add to a hash table */
2621 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2622
2623 /* help info */
2624 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2625 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2626
2627 if( tlbHeader.varflags & HELPDLLFLAG)
2628 {
2629 int offset;
2630 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2631 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2632 }
2633
2634 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2635
2636 /* custom data */
2637 if(tlbHeader.CustomDataOffset >= 0)
2638 {
2639 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2640 }
2641
2642 /* fill in type descriptions */
2643 if(tlbSegDir.pTypdescTab.length > 0)
2644 {
2645 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2646 INT16 td[4];
2647 pTypeLibImpl->ctTypeDesc = cTD;
2648 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2649 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2650 for(i=0; i<cTD; )
2651 {
2652 /* FIXME: add several sanity checks here */
2653 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2654 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2655 {
2656 /* FIXME: check safearray */
2657 if(td[3] < 0)
2658 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2659 else
2660 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2661 }
2662 else if(td[0] == VT_CARRAY)
2663 {
2664 /* array descr table here */
2665 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2666 }
2667 else if(td[0] == VT_USERDEFINED)
2668 {
2669 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2670 }
2671 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2672 }
2673
2674 /* second time around to fill the array subscript info */
2675 for(i=0;i<cTD;i++)
2676 {
2677 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2678 if(tlbSegDir.pArrayDescriptions.offset>0)
2679 {
2680 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2681 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2682
2683 if(td[1]<0)
2684 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2685 else
2686 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2687
2688 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2689
2690 for(j = 0; j<td[2]; j++)
2691 {
2692 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2693 sizeof(INT), &cx, DO_NOT_SEEK);
2694 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2695 sizeof(INT), &cx, DO_NOT_SEEK);
2696 }
2697 }
2698 else
2699 {
2700 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2701 ERR("didn't find array description data\n");
2702 }
2703 }
2704 }
2705
2706 /* imported type libs */
2707 if(tlbSegDir.pImpFiles.offset>0)
2708 {
2709 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2710 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2711 UINT16 size;
2712
2713 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2714 {
2715 char *name;
2716
2717 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2718 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2719 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2720
2721 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2722 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2723 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2724 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2725
2726 size >>= 2;
2727 name = TLB_Alloc(size+1);
2728 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2729 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2730
2731 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2732 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2733
2734 ppImpLib = &(*ppImpLib)->next;
2735 }
2736 }
2737
2738 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2739 if(pTypeLibImpl->dispatch_href != -1)
2740 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2741
2742 /* type info's */
2743 if(tlbHeader.nrtypeinfos >= 0 )
2744 {
2745 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2746 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2747 int i;
2748
2749 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2750 {
2751 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2752
2753 ppTI = &((*ppTI)->next);
2754 (pTypeLibImpl->TypeInfoCount)++;
2755 }
2756 }
2757
2758 TRACE("(%p)\n", pTypeLibImpl);
2759 return (ITypeLib2*) pTypeLibImpl;
2760 }
2761
2762
2763 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2764 {
2765 char b[3];
2766 int i;
2767 short s;
2768
2769 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2770 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2771 return FALSE;
2772 }
2773
2774 guid->Data4[0] = s >> 8;
2775 guid->Data4[1] = s & 0xff;
2776
2777 b[2] = '\0';
2778 for(i = 0; i < 6; i++) {
2779 memcpy(b, str + 24 + 2 * i, 2);
2780 guid->Data4[i + 2] = strtol(b, NULL, 16);
2781 }
2782 return TRUE;
2783 }
2784
2785 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
2786 {
2787 WORD bytelen;
2788 DWORD len;
2789
2790 *pBstr = NULL;
2791 bytelen = *(const WORD*)ptr;
2792 if(bytelen == 0xffff) return 2;
2793 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2794 *pBstr = SysAllocStringLen(NULL, len - 1);
2795 if (*pBstr)
2796 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
2797 return bytelen + 2;
2798 }
2799
2800 static WORD SLTG_ReadStringA(const char *ptr, char **str)
2801 {
2802 WORD bytelen;
2803
2804 *str = NULL;
2805 bytelen = *(const WORD*)ptr;
2806 if(bytelen == 0xffff) return 2;
2807 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2808 memcpy(*str, ptr + 2, bytelen);
2809 (*str)[bytelen] = '\0';
2810 return bytelen + 2;
2811 }
2812
2813 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2814 {
2815 char *ptr = pLibBlk;
2816 WORD w;
2817
2818 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2819 FIXME("libblk magic = %04x\n", w);
2820 return 0;
2821 }
2822
2823 ptr += 6;
2824 if((w = *(WORD*)ptr) != 0xffff) {
2825 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2826 ptr += w;
2827 }
2828 ptr += 2;
2829
2830 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2831
2832 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2833
2834 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2835 ptr += 4;
2836
2837 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2838 ptr += 2;
2839
2840 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2841 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2842 else
2843 pTypeLibImpl->LibAttr.lcid = 0;
2844 ptr += 2;
2845
2846 ptr += 4; /* skip res12 */
2847
2848 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2849 ptr += 2;
2850
2851 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2852 ptr += 2;
2853
2854 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2855 ptr += 2;
2856
2857 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2858 ptr += sizeof(GUID);
2859
2860 return ptr - (char*)pLibBlk;
2861 }
2862
2863 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2864 typedef struct
2865 {
2866 unsigned int num;
2867 HREFTYPE refs[1];
2868 } sltg_ref_lookup_t;
2869
2870 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
2871 HREFTYPE *typelib_ref)
2872 {
2873 if(typeinfo_ref < table->num)
2874 {
2875 *typelib_ref = table->refs[typeinfo_ref];
2876 return S_OK;
2877 }
2878
2879 ERR_(typelib)("Unable to find reference\n");
2880 *typelib_ref = -1;
2881 return E_FAIL;
2882 }
2883
2884 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
2885 {
2886 BOOL done = FALSE;
2887
2888 while(!done) {
2889 if((*pType & 0xe00) == 0xe00) {
2890 pTD->vt = VT_PTR;
2891 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2892 sizeof(TYPEDESC));
2893 pTD = pTD->u.lptdesc;
2894 }
2895 switch(*pType & 0x3f) {
2896 case VT_PTR:
2897 pTD->vt = VT_PTR;
2898 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2899 sizeof(TYPEDESC));
2900 pTD = pTD->u.lptdesc;
2901 break;
2902
2903 case VT_USERDEFINED:
2904 pTD->vt = VT_USERDEFINED;
2905 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2906 done = TRUE;
2907 break;
2908
2909 case VT_CARRAY:
2910 {
2911 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2912 array */
2913
2914 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2915
2916 pTD->vt = VT_CARRAY;
2917 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2918 sizeof(ARRAYDESC) +
2919 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2920 pTD->u.lpadesc->cDims = pSA->cDims;
2921 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2922 pSA->cDims * sizeof(SAFEARRAYBOUND));
2923
2924 pTD = &pTD->u.lpadesc->tdescElem;
2925 break;
2926 }
2927
2928 case VT_SAFEARRAY:
2929 {
2930 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2931 useful? */
2932
2933 pType++;
2934 pTD->vt = VT_SAFEARRAY;
2935 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2936 sizeof(TYPEDESC));
2937 pTD = pTD->u.lptdesc;
2938 break;
2939 }
2940 default:
2941 pTD->vt = *pType & 0x3f;
2942 done = TRUE;
2943 break;
2944 }
2945 pType++;
2946 }
2947 return pType;
2948 }
2949
2950 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
2951 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
2952 {
2953 /* Handle [in/out] first */
2954 if((*pType & 0xc000) == 0xc000)
2955 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2956 else if(*pType & 0x8000)
2957 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2958 else if(*pType & 0x4000)
2959 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2960 else
2961 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2962
2963 if(*pType & 0x2000)
2964 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2965
2966 if(*pType & 0x80)
2967 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2968
2969 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2970 }
2971
2972
2973 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2974 char *pNameTable)
2975 {
2976 int ref;
2977 char *name;
2978 TLBRefType *ref_type;
2979 sltg_ref_lookup_t *table;
2980 HREFTYPE typelib_ref;
2981
2982 if(pRef->magic != SLTG_REF_MAGIC) {
2983 FIXME("Ref magic = %x\n", pRef->magic);
2984 return NULL;
2985 }
2986 name = ( (char*)pRef->names + pRef->number);
2987
2988 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2989 table->num = pRef->number >> 3;
2990
2991 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2992
2993 /* We don't want the first href to be 0 */
2994 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
2995
2996 for(ref = 0; ref < pRef->number >> 3; ref++) {
2997 char *refname;
2998 unsigned int lib_offs, type_num;
2999
3000 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3001
3002 name += SLTG_ReadStringA(name, &refname);
3003 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3004 FIXME_(typelib)("Can't sscanf ref\n");
3005 if(lib_offs != 0xffff) {
3006 TLBImpLib **import = &pTL->pImpLibs;
3007
3008 while(*import) {
3009 if((*import)->offset == lib_offs)
3010 break;
3011 import = &(*import)->next;
3012 }
3013 if(!*import) {
3014 char fname[MAX_PATH+1];
3015 int len;
3016
3017 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3018 sizeof(**import));
3019 (*import)->offset = lib_offs;
3020 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3021 &(*import)->guid);
3022 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3023 &(*import)->wVersionMajor,
3024 &(*import)->wVersionMinor,
3025 &(*import)->lcid, fname) != 4) {
3026 FIXME_(typelib)("can't sscanf ref %s\n",
3027 pNameTable + lib_offs + 40);
3028 }
3029 len = strlen(fname);
3030 if(fname[len-1] != '#')
3031 FIXME("fname = %s\n", fname);
3032 fname[len-1] = '\0';
3033 (*import)->name = TLB_MultiByteToBSTR(fname);
3034 }
3035 ref_type->pImpTLInfo = *import;
3036
3037 /* Store a reference to IDispatch */
3038 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3039 pTL->dispatch_href = typelib_ref;
3040
3041 } else { /* internal ref */
3042 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3043 }
3044 ref_type->reference = typelib_ref;
3045 ref_type->index = type_num;
3046
3047 HeapFree(GetProcessHeap(), 0, refname);
3048 list_add_tail(&pTL->ref_list, &ref_type->entry);
3049
3050 table->refs[ref] = typelib_ref;
3051 typelib_ref += 4;
3052 }
3053 if((BYTE)*name != SLTG_REF_MAGIC)
3054 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3055 dump_TLBRefType(pTL);
3056 return table;
3057 }
3058
3059 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3060 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3061 {
3062 SLTG_ImplInfo *info;
3063 TLBImplType **ppImplType = &pTI->impltypelist;
3064 /* I don't really get this structure, usually it's 0x16 bytes
3065 long, but iuser.tlb contains some that are 0x18 bytes long.
3066 That's ok because we can use the next ptr to jump to the next
3067 one. But how do we know the length of the last one? The WORD
3068 at offs 0x8 might be the clue. For now I'm just assuming that
3069 the last one is the regular 0x16 bytes. */
3070
3071 info = (SLTG_ImplInfo*)pBlk;
3072 while(1) {
3073 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3074 sizeof(**ppImplType));
3075 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3076 (*ppImplType)->implflags = info->impltypeflags;
3077 pTI->TypeAttr.cImplTypes++;
3078 ppImplType = &(*ppImplType)->next;
3079
3080 if(info->next == 0xffff)
3081 break;
3082 if(OneOnly)
3083 FIXME_(typelib)("Interface inheriting more than one interface\n");
3084 info = (SLTG_ImplInfo*)(pBlk + info->next);
3085 }
3086 info++; /* see comment at top of function */
3087 return (char*)info;
3088 }
3089
3090 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3091 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3092 {
3093 TLBVarDesc **ppVarDesc = &pTI->varlist;
3094 BSTR bstrPrevName = NULL;
3095 SLTG_Variable *pItem;
3096 unsigned short i;
3097 WORD *pType;
3098
3099 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3100 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3101
3102 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3103 sizeof(**ppVarDesc));
3104 (*ppVarDesc)->vardesc.memid = pItem->memid;
3105
3106 if (pItem->magic != SLTG_VAR_MAGIC &&
3107 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3108 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3109 return;
3110 }
3111
3112 if (pItem->name == 0xfffe)
3113 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3114 else
3115 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3116
3117 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3118 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3119 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3120
3121 if(pItem->flags & 0x02)
3122 pType = &pItem->type;
3123 else
3124 pType = (WORD*)(pBlk + pItem->type);
3125
3126 if (pItem->flags & ~0xda)
3127 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3128
3129 SLTG_DoElem(pType, pBlk,
3130 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3131
3132 if (TRACE_ON(typelib)) {
3133 char buf[300];
3134 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3135 TRACE_(typelib)("elemdescVar: %s\n", buf);
3136 }
3137
3138 if (pItem->flags & 0x40) {
3139 TRACE_(typelib)("VAR_DISPATCH\n");
3140 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3141 }
3142 else if (pItem->flags & 0x10) {
3143 TRACE_(typelib)("VAR_CONST\n");
3144 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3145 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3146 sizeof(VARIANT));
3147 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3148 if (pItem->flags & 0x08)
3149 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3150 else {
3151 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3152 {
3153 case VT_LPSTR:
3154 case VT_LPWSTR:
3155 case VT_BSTR:
3156 {
3157 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3158 BSTR str;
3159 TRACE_(typelib)("len = %u\n", len);
3160 if (len == 0xffff) {
3161 str = NULL;
3162 } else {
3163 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3164 str = SysAllocStringLen(NULL, alloc_len);
3165 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3166 }
3167 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3168 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3169 break;
3170 }
3171 case VT_I2:
3172 case VT_UI2:
3173 case VT_I4:
3174 case VT_UI4:
3175 case VT_INT:
3176 case VT_UINT:
3177 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3178 *(INT*)(pBlk + pItem->byte_offs);
3179 break;
3180 default:
3181 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3182 }
3183 }
3184 }
3185 else {
3186 TRACE_(typelib)("VAR_PERINSTANCE\n");
3187 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3188 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3189 }
3190
3191 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3192 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3193
3194 if (pItem->flags & 0x80)
3195 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3196
3197 bstrPrevName = (*ppVarDesc)->Name;
3198 ppVarDesc = &((*ppVarDesc)->next);
3199 }
3200 pTI->TypeAttr.cVars = cVars;
3201 }
3202
3203 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3204 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3205 {
3206 SLTG_Function *pFunc;
3207 unsigned short i;
3208 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3209
3210 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3211 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3212
3213 int param;
3214 WORD *pType, *pArg;
3215
3216 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3217 sizeof(**ppFuncDesc));
3218
3219 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3220 case SLTG_FUNCTION_MAGIC:
3221 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3222 break;
3223 case SLTG_DISPATCH_FUNCTION_MAGIC:
3224 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3225 break;
3226 case SLTG_STATIC_FUNCTION_MAGIC:
3227 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3228 break;
3229 default:
3230 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3231 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3232 *ppFuncDesc = NULL;
3233 return;
3234 }
3235 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3236
3237 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3238 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3239 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3240 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3241 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3242 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3243
3244 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3245 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3246
3247 if(pFunc->retnextopt & 0x80)
3248 pType = &pFunc->rettype;
3249 else
3250 pType = (WORD*)(pBlk + pFunc->rettype);
3251
3252 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3253
3254 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3255 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3256 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3257 (*ppFuncDesc)->pParamDesc =
3258 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3259 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3260
3261 pArg = (WORD*)(pBlk + pFunc->arg_off);
3262
3263 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3264 char *paramName = pNameTable + *pArg;
3265 BOOL HaveOffs;
3266 /* If arg type follows then paramName points to the 2nd
3267 letter of the name, else the next WORD is an offset to
3268 the arg type and paramName points to the first letter.
3269 So let's take one char off paramName and see if we're
3270 pointing at an alpha-numeric char. However if *pArg is
3271 0xffff or 0xfffe then the param has no name, the former
3272 meaning that the next WORD is the type, the latter
3273 meaning that the next WORD is an offset to the type. */
3274
3275 HaveOffs = FALSE;
3276 if(*pArg == 0xffff)
3277 paramName = NULL;
3278 else if(*pArg == 0xfffe) {
3279 paramName = NULL;
3280 HaveOffs = TRUE;
3281 }
3282 else if(paramName[-1] && !isalnum(paramName[-1]))
3283 HaveOffs = TRUE;
3284
3285 pArg++;
3286
3287 if(HaveOffs) { /* the next word is an offset to type */
3288 pType = (WORD*)(pBlk + *pArg);
3289 SLTG_DoElem(pType, pBlk,
3290 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3291 pArg++;
3292 } else {
3293 if(paramName)
3294 paramName--;
3295 pArg = SLTG_DoElem(pArg, pBlk,
3296 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3297 }
3298
3299 /* Are we an optional param ? */
3300 if((*ppFuncDesc)->funcdesc.cParams - param <=
3301 (*ppFuncDesc)->funcdesc.cParamsOpt)
3302 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3303
3304 if(paramName) {
3305 (*ppFuncDesc)->pParamDesc[param].Name =
3306 TLB_MultiByteToBSTR(paramName);
3307 } else {
3308 (*ppFuncDesc)->pParamDesc[param].Name =
3309 SysAllocString((*ppFuncDesc)->Name);
3310 }
3311 }
3312
3313 ppFuncDesc = &((*ppFuncDesc)->next);
3314 if(pFunc->next == 0xffff) break;
3315 }
3316 pTI->TypeAttr.cFuncs = cFuncs;
3317 }
3318
3319 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3320 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3321 SLTG_TypeInfoTail *pTITail)
3322 {
3323 char *pFirstItem;
3324 sltg_ref_lookup_t *ref_lookup = NULL;
3325
3326 if(pTIHeader->href_table != 0xffffffff) {
3327 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3328 pNameTable);
3329 }
3330
3331 pFirstItem = pBlk;
3332
3333 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3334 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3335 }
3336 HeapFree(GetProcessHeap(), 0, ref_lookup);
3337 }
3338
3339
3340 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3341 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3342 const SLTG_TypeInfoTail *pTITail)
3343 {
3344 char *pFirstItem;
3345 sltg_ref_lookup_t *ref_lookup = NULL;
3346
3347 if(pTIHeader->href_table != 0xffffffff) {
3348 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3349 pNameTable);
3350 }
3351
3352 pFirstItem = pBlk;
3353
3354 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3355 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3356 }
3357
3358 if (pTITail->funcs_off != 0xffff)
3359 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3360
3361 HeapFree(GetProcessHeap(), 0, ref_lookup);
3362
3363 if (TRACE_ON(typelib))
3364 dump_TLBFuncDesc(pTI->funclist);
3365 }
3366
3367 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3368 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3369 const SLTG_TypeInfoTail *pTITail)
3370 {
3371 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3372 }
3373
3374 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3375 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3376 const SLTG_TypeInfoTail *pTITail)
3377 {
3378 WORD *pType;
3379 sltg_ref_lookup_t *ref_lookup = NULL;
3380
3381 if (pTITail->simple_alias) {
3382 /* if simple alias, no more processing required */
3383 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3384 return;
3385 }
3386
3387 if(pTIHeader->href_table != 0xffffffff) {
3388 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3389 pNameTable);
3390 }
3391
3392 /* otherwise it is an offset to a type */
3393 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3394
3395 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3396
3397 HeapFree(GetProcessHeap(), 0, ref_lookup);
3398 }
3399
3400 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3401 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3402 const SLTG_TypeInfoTail *pTITail)
3403 {
3404 sltg_ref_lookup_t *ref_lookup = NULL;
3405 if (pTIHeader->href_table != 0xffffffff)
3406 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3407 pNameTable);
3408
3409 if (pTITail->vars_off != 0xffff)
3410 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3411
3412 if (pTITail->funcs_off != 0xffff)
3413 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3414
3415 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3416 * of dispinterface functions including the IDispatch ones, so
3417 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3418 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3419
3420 HeapFree(GetProcessHeap(), 0, ref_lookup);
3421 if (TRACE_ON(typelib))
3422 dump_TLBFuncDesc(pTI->funclist);
3423 }
3424
3425 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3426