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