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