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