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