oleaut32: Use containing TypeLib's HelpFile in ITypeInfo::GetDocumentation.
[wine.git] / dlls / oleaut32 / typelib.c
blobb0a18b923a721c5580e70977d67a0306bc92865a
1 /*
2 * TYPELIB
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
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.
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.
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
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
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.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
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
48 #include "config.h"
49 #include "wine/port.h"
51 #include <stdlib.h>
52 #include <string.h>
53 #include <stdarg.h>
54 #include <stdio.h>
55 #include <ctype.h>
57 #define COBJMACROS
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
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"
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"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
79 typedef struct
81 WORD offset;
82 WORD length;
83 WORD flags;
84 WORD id;
85 WORD handle;
86 WORD usage;
87 } NE_NAMEINFO;
89 typedef struct
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
95 * Name info array.
97 } NE_TYPEINFO;
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
102 /****************************************************************************
103 * FromLExxx
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
123 #else
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
126 #endif
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
132 * FromLExxx
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
139 WORD *Val = p_Val;
141 p_iSize /= sizeof(WORD);
143 while (p_iSize) {
144 *Val = FromLEWord(*Val);
145 Val++;
146 p_iSize--;
151 static void FromLEDWords(void *p_Val, int p_iSize)
153 DWORD *Val = p_Val;
155 p_iSize /= sizeof(DWORD);
157 while (p_iSize) {
158 *Val = FromLEDWord(*Val);
159 Val++;
160 p_iSize--;
163 #else
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
166 #endif
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
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;
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
184 return FALSE;
186 len = sizeof(key_name);
187 i = 0;
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
190 INT v_maj, v_min;
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
203 best_maj = v_maj;
205 if (*wMin == v_min)
207 best_min = v_min;
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
215 RegCloseKey( hkey );
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
223 *wMaj = best_maj;
224 *wMin = best_min;
225 return TRUE;
229 if (*wMaj == best_maj && best_min >= 0)
231 *wMin = best_min;
232 return TRUE;
234 return FALSE;
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 )
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
247 return buffer;
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 )
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
258 return buffer;
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 )
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};
270 sprintfW( buffer, LcidFormatW, lcid );
271 switch(syskind)
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;
280 return buffer;
283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
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 )
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;
297 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
299 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
300 get_typelib_key( guid, wMaj, wMin, buffer );
302 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
303 if (res == ERROR_FILE_NOT_FOUND)
305 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
306 return TYPE_E_LIBNOTREGISTERED;
308 else if (res != ERROR_SUCCESS)
310 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
311 return TYPE_E_REGISTRYACCESS;
314 while (hr != S_OK)
316 LONG dwPathLen = sizeof(Path);
318 get_lcid_subkey( myLCID, syskind, buffer );
320 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
322 if (!lcid)
323 break;
324 else if (myLCID == lcid)
326 /* try with sub-langid */
327 myLCID = SUBLANGID(lcid);
329 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
331 /* try with system langid */
332 myLCID = 0;
334 else
336 break;
339 else
341 *path = SysAllocString( Path );
342 hr = S_OK;
345 RegCloseKey( hkey );
346 TRACE_(typelib)("-- 0x%08x\n", hr);
347 return hr;
350 /****************************************************************************
351 * QueryPathOfRegTypeLib [OLEAUT32.164]
353 * Gets the path to a registered type library.
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
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.
368 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
370 #ifdef _WIN64
371 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path );
372 if(SUCCEEDED(hres))
373 return hres;
374 #endif
375 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
378 /******************************************************************************
379 * CreateTypeLib [OLEAUT32.160] creates a typelib
381 * RETURNS
382 * Success: S_OK
383 * Failure: Status
385 HRESULT WINAPI CreateTypeLib(
386 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
388 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
389 return E_FAIL;
392 /******************************************************************************
393 * LoadTypeLib [OLEAUT32.161]
395 * Loads a type library
397 * PARAMS
398 * szFile [I] Name of file to load from.
399 * pptLib [O] Pointer that receives ITypeLib object on success.
401 * RETURNS
402 * Success: S_OK
403 * Failure: Status
405 * SEE
406 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
408 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
410 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
411 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
414 /******************************************************************************
415 * LoadTypeLibEx [OLEAUT32.183]
417 * Loads and optionally registers a type library
419 * RETURNS
420 * Success: S_OK
421 * Failure: Status
423 HRESULT WINAPI LoadTypeLibEx(
424 LPCOLESTR szFile, /* [in] Name of file to load from */
425 REGKIND regkind, /* [in] Specify kind of registration */
426 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
428 WCHAR szPath[MAX_PATH+1];
429 HRESULT res;
431 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
433 *pptLib = NULL;
435 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
437 if (SUCCEEDED(res))
438 switch(regkind)
440 case REGKIND_DEFAULT:
441 /* don't register typelibs supplied with full path. Experimentation confirms the following */
442 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
443 (szFile[0] && (szFile[1] == ':'))) break;
444 /* else fall-through */
446 case REGKIND_REGISTER:
447 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
449 ITypeLib_Release(*pptLib);
450 *pptLib = 0;
452 break;
453 case REGKIND_NONE:
454 break;
457 TRACE(" returns %08x\n",res);
458 return res;
461 /******************************************************************************
462 * LoadRegTypeLib [OLEAUT32.162]
464 * Loads a registered type library.
466 * PARAMS
467 * rguid [I] GUID of the registered type library.
468 * wVerMajor [I] major version.
469 * wVerMinor [I] minor version.
470 * lcid [I] locale ID.
471 * ppTLib [O] pointer that receives an ITypeLib object on success.
473 * RETURNS
474 * Success: S_OK.
475 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
476 * LoadTypeLib.
478 HRESULT WINAPI LoadRegTypeLib(
479 REFGUID rguid,
480 WORD wVerMajor,
481 WORD wVerMinor,
482 LCID lcid,
483 ITypeLib **ppTLib)
485 BSTR bstr=NULL;
486 HRESULT res;
488 *ppTLib = NULL;
490 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
492 if(SUCCEEDED(res))
494 res= LoadTypeLib(bstr, ppTLib);
495 SysFreeString(bstr);
498 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
500 return res;
504 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
505 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
506 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
507 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
508 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
509 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
511 /******************************************************************************
512 * RegisterTypeLib [OLEAUT32.163]
513 * Adds information about a type library to the System Registry
514 * NOTES
515 * Docs: ITypeLib FAR * ptlib
516 * Docs: OLECHAR FAR* szFullPath
517 * Docs: OLECHAR FAR* szHelpDir
519 * RETURNS
520 * Success: S_OK
521 * Failure: Status
523 HRESULT WINAPI RegisterTypeLib(
524 ITypeLib * ptlib, /* [in] Pointer to the library*/
525 OLECHAR * szFullPath, /* [in] full Path of the library*/
526 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
527 may be NULL*/
529 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
530 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
531 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
532 HRESULT res;
533 TLIBATTR *attr;
534 WCHAR keyName[60];
535 WCHAR tmp[16];
536 HKEY key, subKey;
537 UINT types, tidx;
538 TYPEKIND kind;
539 DWORD disposition;
541 if (ptlib == NULL || szFullPath == NULL)
542 return E_INVALIDARG;
544 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
545 return E_FAIL;
547 #ifdef _WIN64
548 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
549 #else
550 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
551 #endif
553 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
555 res = S_OK;
556 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
557 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
559 LPOLESTR doc;
561 /* Set the human-readable name of the typelib */
562 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
563 res = E_FAIL;
564 else if (doc)
566 if (RegSetValueExW(key, NULL, 0, REG_SZ,
567 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
568 res = E_FAIL;
570 SysFreeString(doc);
573 /* Make up the name of the typelib path subkey */
574 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
576 /* Create the typelib path subkey */
577 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
578 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
580 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
581 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
582 res = E_FAIL;
584 RegCloseKey(subKey);
586 else
587 res = E_FAIL;
589 /* Create the flags subkey */
590 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
591 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
593 /* FIXME: is %u correct? */
594 static const WCHAR formatW[] = {'%','u',0};
595 WCHAR buf[20];
596 sprintfW(buf, formatW, attr->wLibFlags);
597 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
598 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
599 res = E_FAIL;
601 RegCloseKey(subKey);
603 else
604 res = E_FAIL;
606 /* create the helpdir subkey */
607 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
608 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
610 BOOL freeHelpDir = FALSE;
611 OLECHAR* pIndexStr;
613 /* if we created a new key, and helpDir was null, set the helpdir
614 to the directory which contains the typelib. However,
615 if we just opened an existing key, we leave the helpdir alone */
616 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
617 szHelpDir = SysAllocString(szFullPath);
618 pIndexStr = strrchrW(szHelpDir, '\\');
619 if (pIndexStr) {
620 *pIndexStr = 0;
622 freeHelpDir = TRUE;
625 /* if we have an szHelpDir, set it! */
626 if (szHelpDir != NULL) {
627 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
628 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
629 res = E_FAIL;
633 /* tidy up */
634 if (freeHelpDir) SysFreeString(szHelpDir);
635 RegCloseKey(subKey);
637 } else {
638 res = E_FAIL;
641 RegCloseKey(key);
643 else
644 res = E_FAIL;
646 /* register OLE Automation-compatible interfaces for this typelib */
647 types = ITypeLib_GetTypeInfoCount(ptlib);
648 for (tidx=0; tidx<types; tidx++) {
649 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
650 LPOLESTR name = NULL;
651 ITypeInfo *tinfo = NULL;
653 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
655 switch (kind) {
656 case TKIND_INTERFACE:
657 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
658 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
659 break;
661 case TKIND_DISPATCH:
662 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
663 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
664 break;
666 default:
667 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
668 break;
671 if (tinfo) {
672 TYPEATTR *tattr = NULL;
673 ITypeInfo_GetTypeAttr(tinfo, &tattr);
675 if (tattr) {
676 TRACE_(typelib)("guid=%s, flags=%04x (",
677 debugstr_guid(&tattr->guid),
678 tattr->wTypeFlags);
680 if (TRACE_ON(typelib)) {
681 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
682 XX(FAPPOBJECT);
683 XX(FCANCREATE);
684 XX(FLICENSED);
685 XX(FPREDECLID);
686 XX(FHIDDEN);
687 XX(FCONTROL);
688 XX(FDUAL);
689 XX(FNONEXTENSIBLE);
690 XX(FOLEAUTOMATION);
691 XX(FRESTRICTED);
692 XX(FAGGREGATABLE);
693 XX(FREPLACEABLE);
694 XX(FDISPATCHABLE);
695 XX(FREVERSEBIND);
696 XX(FPROXY);
697 #undef XX
698 MESSAGE("\n");
701 /* Register all dispinterfaces (which includes dual interfaces) and
702 oleautomation interfaces */
703 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
704 kind == TKIND_DISPATCH)
706 /* register interface<->typelib coupling */
707 get_interface_key( &tattr->guid, keyName );
708 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
709 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
711 if (name)
712 RegSetValueExW(key, NULL, 0, REG_SZ,
713 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
715 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
716 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
717 RegSetValueExW(subKey, NULL, 0, REG_SZ,
718 (const BYTE *)PSOA, sizeof PSOA);
719 RegCloseKey(subKey);
722 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
723 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
724 RegSetValueExW(subKey, NULL, 0, REG_SZ,
725 (const BYTE *)PSOA, sizeof PSOA);
726 RegCloseKey(subKey);
729 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
730 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
732 WCHAR buffer[40];
733 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
734 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
736 StringFromGUID2(&attr->guid, buffer, 40);
737 RegSetValueExW(subKey, NULL, 0, REG_SZ,
738 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
739 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
740 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
741 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
742 RegCloseKey(subKey);
745 RegCloseKey(key);
749 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
752 ITypeInfo_Release(tinfo);
755 SysFreeString(name);
759 ITypeLib_ReleaseTLibAttr(ptlib, attr);
761 return res;
765 /******************************************************************************
766 * UnRegisterTypeLib [OLEAUT32.186]
767 * Removes information about a type library from the System Registry
768 * NOTES
770 * RETURNS
771 * Success: S_OK
772 * Failure: Status
774 HRESULT WINAPI UnRegisterTypeLib(
775 REFGUID libid, /* [in] Guid of the library */
776 WORD wVerMajor, /* [in] major version */
777 WORD wVerMinor, /* [in] minor version */
778 LCID lcid, /* [in] locale id */
779 SYSKIND syskind)
781 BSTR tlibPath = NULL;
782 DWORD tmpLength;
783 WCHAR keyName[60];
784 WCHAR subKeyName[50];
785 int result = S_OK;
786 DWORD i = 0;
787 BOOL deleteOtherStuff;
788 HKEY key = NULL;
789 HKEY subKey = NULL;
790 TYPEATTR* typeAttr = NULL;
791 TYPEKIND kind;
792 ITypeInfo* typeInfo = NULL;
793 ITypeLib* typeLib = NULL;
794 int numTypes;
796 TRACE("(IID: %s)\n",debugstr_guid(libid));
798 /* Create the path to the key */
799 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
801 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
803 TRACE("Unsupported syskind %i\n", syskind);
804 result = E_INVALIDARG;
805 goto end;
808 /* get the path to the typelib on disk */
809 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
810 result = E_INVALIDARG;
811 goto end;
814 /* Try and open the key to the type library. */
815 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
816 result = E_INVALIDARG;
817 goto end;
820 /* Try and load the type library */
821 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
822 result = TYPE_E_INVALIDSTATE;
823 goto end;
826 /* remove any types registered with this typelib */
827 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
828 for (i=0; i<numTypes; i++) {
829 /* get the kind of type */
830 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
831 goto enddeleteloop;
834 /* skip non-interfaces, and get type info for the type */
835 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
836 goto enddeleteloop;
838 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
839 goto enddeleteloop;
841 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
842 goto enddeleteloop;
845 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
846 kind == TKIND_DISPATCH)
848 /* the path to the type */
849 get_interface_key( &typeAttr->guid, subKeyName );
851 /* Delete its bits */
852 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
853 goto enddeleteloop;
855 RegDeleteKeyW(subKey, ProxyStubClsidW);
856 RegDeleteKeyW(subKey, ProxyStubClsid32W);
857 RegDeleteKeyW(subKey, TypeLibW);
858 RegCloseKey(subKey);
859 subKey = NULL;
860 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
863 enddeleteloop:
864 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
865 typeAttr = NULL;
866 if (typeInfo) ITypeInfo_Release(typeInfo);
867 typeInfo = NULL;
870 /* Now, delete the type library path subkey */
871 get_lcid_subkey( lcid, syskind, subKeyName );
872 RegDeleteKeyW(key, subKeyName);
873 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
874 RegDeleteKeyW(key, subKeyName);
876 /* check if there is anything besides the FLAGS/HELPDIR keys.
877 If there is, we don't delete them */
878 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
879 deleteOtherStuff = TRUE;
880 i = 0;
881 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
882 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
884 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
885 if (!strcmpW(subKeyName, FLAGSW)) continue;
886 if (!strcmpW(subKeyName, HELPDIRW)) continue;
887 deleteOtherStuff = FALSE;
888 break;
891 /* only delete the other parts of the key if we're absolutely sure */
892 if (deleteOtherStuff) {
893 RegDeleteKeyW(key, FLAGSW);
894 RegDeleteKeyW(key, HELPDIRW);
895 RegCloseKey(key);
896 key = NULL;
898 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
899 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
900 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
903 end:
904 SysFreeString(tlibPath);
905 if (typeLib) ITypeLib_Release(typeLib);
906 if (subKey) RegCloseKey(subKey);
907 if (key) RegCloseKey(key);
908 return result;
911 /******************************************************************************
912 * RegisterTypeLibForUser [OLEAUT32.442]
913 * Adds information about a type library to the user registry
914 * NOTES
915 * Docs: ITypeLib FAR * ptlib
916 * Docs: OLECHAR FAR* szFullPath
917 * Docs: OLECHAR FAR* szHelpDir
919 * RETURNS
920 * Success: S_OK
921 * Failure: Status
923 HRESULT WINAPI RegisterTypeLibForUser(
924 ITypeLib * ptlib, /* [in] Pointer to the library*/
925 OLECHAR * szFullPath, /* [in] full Path of the library*/
926 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
927 may be NULL*/
929 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
930 debugstr_w(szFullPath), debugstr_w(szHelpDir));
931 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
934 /******************************************************************************
935 * UnRegisterTypeLibForUser [OLEAUT32.443]
936 * Removes information about a type library from the user registry
938 * RETURNS
939 * Success: S_OK
940 * Failure: Status
942 HRESULT WINAPI UnRegisterTypeLibForUser(
943 REFGUID libid, /* [in] GUID of the library */
944 WORD wVerMajor, /* [in] major version */
945 WORD wVerMinor, /* [in] minor version */
946 LCID lcid, /* [in] locale id */
947 SYSKIND syskind)
949 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
950 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
951 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
954 /*======================= ITypeLib implementation =======================*/
956 typedef struct tagTLBCustData
958 GUID guid;
959 VARIANT data;
960 struct list entry;
961 } TLBCustData;
963 /* data structure for import typelibs */
964 typedef struct tagTLBImpLib
966 int offset; /* offset in the file (MSFT)
967 offset in nametable (SLTG)
968 just used to identify library while reading
969 data from file */
970 GUID guid; /* libid */
971 BSTR name; /* name */
973 LCID lcid; /* lcid of imported typelib */
975 WORD wVersionMajor; /* major version number */
976 WORD wVersionMinor; /* minor version number */
978 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
979 NULL if not yet loaded */
980 struct list entry;
981 } TLBImpLib;
983 /* internal ITypeLib data */
984 typedef struct tagITypeLibImpl
986 ITypeLib2 ITypeLib2_iface;
987 ITypeComp ITypeComp_iface;
988 LONG ref;
989 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
990 LCID lcid;
992 /* strings can be stored in tlb as multibyte strings BUT they are *always*
993 * exported to the application as a UNICODE string.
995 BSTR Name;
996 BSTR DocString;
997 BSTR HelpFile;
998 BSTR HelpStringDll;
999 DWORD dwHelpContext;
1000 int TypeInfoCount; /* nr of typeinfo's in librarry */
1001 struct tagITypeInfoImpl **typeinfos;
1002 struct list custdata_list;
1003 struct list implib_list;
1004 int ctTypeDesc; /* number of items in type desc array */
1005 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1006 library. Only used while reading MSFT
1007 typelibs */
1008 struct list ref_list; /* list of ref types in this typelib */
1009 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1012 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1013 struct list entry;
1014 WCHAR *path;
1015 INT index;
1016 } ITypeLibImpl;
1018 static const ITypeLib2Vtbl tlbvt;
1019 static const ITypeCompVtbl tlbtcvt;
1021 static inline ITypeLibImpl *impl_from_ITypeLib2(ITypeLib2 *iface)
1023 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeLib2_iface);
1026 static inline ITypeLibImpl *impl_from_ITypeLib(ITypeLib *iface)
1028 return impl_from_ITypeLib2((ITypeLib2*)iface);
1031 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1033 return CONTAINING_RECORD(iface, ITypeLibImpl, ITypeComp_iface);
1036 /* ITypeLib methods */
1037 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1038 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1040 /*======================= ITypeInfo implementation =======================*/
1042 /* data for referenced types */
1043 typedef struct tagTLBRefType
1045 INT index; /* Type index for internal ref or for external ref
1046 it the format is SLTG. -2 indicates to
1047 use guid */
1049 GUID guid; /* guid of the referenced type */
1050 /* if index == TLB_REF_USE_GUID */
1052 HREFTYPE reference; /* The href of this ref */
1053 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1054 TLB_REF_INTERNAL for internal refs
1055 TLB_REF_NOT_FOUND for broken refs */
1057 struct list entry;
1058 } TLBRefType;
1060 #define TLB_REF_USE_GUID -2
1062 #define TLB_REF_INTERNAL (void*)-2
1063 #define TLB_REF_NOT_FOUND (void*)-1
1065 /* internal Parameter data */
1066 typedef struct tagTLBParDesc
1068 BSTR Name;
1069 struct list custdata_list;
1070 } TLBParDesc;
1072 /* internal Function data */
1073 typedef struct tagTLBFuncDesc
1075 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1076 BSTR Name; /* the name of this function */
1077 TLBParDesc *pParamDesc; /* array with param names and custom data */
1078 int helpcontext;
1079 int HelpStringContext;
1080 BSTR HelpString;
1081 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1082 struct list custdata_list;
1083 } TLBFuncDesc;
1085 /* internal Variable data */
1086 typedef struct tagTLBVarDesc
1088 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1089 BSTR Name; /* the name of this variable */
1090 int HelpContext;
1091 int HelpStringContext;
1092 BSTR HelpString;
1093 struct list custdata_list;
1094 } TLBVarDesc;
1096 /* internal implemented interface data */
1097 typedef struct tagTLBImplType
1099 HREFTYPE hRef; /* hRef of interface */
1100 int implflags; /* IMPLFLAG_*s */
1101 struct list custdata_list;
1102 } TLBImplType;
1104 /* internal TypeInfo data */
1105 typedef struct tagITypeInfoImpl
1107 ITypeInfo2 ITypeInfo2_iface;
1108 ITypeComp ITypeComp_iface;
1109 LONG ref;
1110 BOOL not_attached_to_typelib;
1111 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1112 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1113 int index; /* index in this typelib; */
1114 HREFTYPE hreftype; /* hreftype for app object binding */
1115 /* type libs seem to store the doc strings in ascii
1116 * so why should we do it in unicode?
1118 BSTR Name;
1119 BSTR DocString;
1120 BSTR DllName;
1121 DWORD dwHelpContext;
1122 DWORD dwHelpStringContext;
1124 /* functions */
1125 TLBFuncDesc *funcdescs;
1127 /* variables */
1128 TLBVarDesc *vardescs;
1130 /* Implemented Interfaces */
1131 TLBImplType *impltypes;
1133 struct list custdata_list;
1134 } ITypeInfoImpl;
1136 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1138 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeComp_iface);
1141 static inline ITypeInfoImpl *impl_from_ITypeInfo2( ITypeInfo2 *iface )
1143 return CONTAINING_RECORD(iface, ITypeInfoImpl, ITypeInfo2_iface);
1146 static inline ITypeInfoImpl *impl_from_ITypeInfo( ITypeInfo *iface )
1148 return impl_from_ITypeInfo2((ITypeInfo2*)iface);
1151 static const ITypeInfo2Vtbl tinfvt;
1152 static const ITypeCompVtbl tcompvt;
1154 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1155 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1157 typedef struct tagTLBContext
1159 unsigned int oStart; /* start of TLB in file */
1160 unsigned int pos; /* current pos */
1161 unsigned int length; /* total length */
1162 void *mapping; /* memory mapping */
1163 MSFT_SegDir * pTblDir;
1164 ITypeLibImpl* pLibInfo;
1165 } TLBContext;
1168 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1171 debug
1173 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1174 if (pTD->vt & VT_RESERVED)
1175 szVarType += strlen(strcpy(szVarType, "reserved | "));
1176 if (pTD->vt & VT_BYREF)
1177 szVarType += strlen(strcpy(szVarType, "ref to "));
1178 if (pTD->vt & VT_ARRAY)
1179 szVarType += strlen(strcpy(szVarType, "array of "));
1180 if (pTD->vt & VT_VECTOR)
1181 szVarType += strlen(strcpy(szVarType, "vector of "));
1182 switch(pTD->vt & VT_TYPEMASK) {
1183 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1184 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1185 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1186 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1187 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1188 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1189 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1190 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1191 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1192 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1193 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1194 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1195 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1196 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1197 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1198 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1199 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1200 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1201 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1202 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1203 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1204 pTD->u.hreftype); break;
1205 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1206 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1207 case VT_PTR: sprintf(szVarType, "ptr to ");
1208 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1209 break;
1210 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1211 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1212 break;
1213 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1214 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1215 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1216 break;
1218 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1222 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1223 char buf[200];
1224 USHORT flags = edesc->u.paramdesc.wParamFlags;
1225 dump_TypeDesc(&edesc->tdesc,buf);
1226 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1227 MESSAGE("\t\tu.paramdesc.wParamFlags");
1228 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1229 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1230 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1231 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1232 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1233 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1234 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1235 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1236 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1238 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1239 int i;
1240 MESSAGE("memid is %08x\n",funcdesc->memid);
1241 for (i=0;i<funcdesc->cParams;i++) {
1242 MESSAGE("Param %d:\n",i);
1243 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1245 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1246 switch (funcdesc->funckind) {
1247 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1248 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1249 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1250 case FUNC_STATIC: MESSAGE("static");break;
1251 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1252 default: MESSAGE("unknown");break;
1254 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1255 switch (funcdesc->invkind) {
1256 case INVOKE_FUNC: MESSAGE("func");break;
1257 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1258 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1259 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1261 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1262 switch (funcdesc->callconv) {
1263 case CC_CDECL: MESSAGE("cdecl");break;
1264 case CC_PASCAL: MESSAGE("pascal");break;
1265 case CC_STDCALL: MESSAGE("stdcall");break;
1266 case CC_SYSCALL: MESSAGE("syscall");break;
1267 default:break;
1269 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1270 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1271 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1273 MESSAGE("\telemdescFunc (return value type):\n");
1274 dump_ELEMDESC(&funcdesc->elemdescFunc);
1277 static const char * const typekind_desc[] =
1279 "TKIND_ENUM",
1280 "TKIND_RECORD",
1281 "TKIND_MODULE",
1282 "TKIND_INTERFACE",
1283 "TKIND_DISPATCH",
1284 "TKIND_COCLASS",
1285 "TKIND_ALIAS",
1286 "TKIND_UNION",
1287 "TKIND_MAX"
1290 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1292 int i;
1293 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1294 for (i=0;i<pfd->funcdesc.cParams;i++)
1295 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1298 dump_FUNCDESC(&(pfd->funcdesc));
1300 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1301 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1303 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1305 while (n)
1307 dump_TLBFuncDescOne(pfd);
1308 ++pfd;
1309 --n;
1312 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1314 while (n)
1316 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1317 ++pvd;
1318 --n;
1322 static void dump_TLBImpLib(const TLBImpLib *import)
1324 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1325 debugstr_w(import->name));
1326 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1327 import->wVersionMinor, import->lcid, import->offset);
1330 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1332 TLBRefType *ref;
1334 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1336 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1337 if(ref->index == -1)
1338 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1339 else
1340 TRACE_(typelib)("type no: %d\n", ref->index);
1342 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1344 TRACE_(typelib)("in lib\n");
1345 dump_TLBImpLib(ref->pImpTLInfo);
1350 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1352 if(!impl)
1353 return;
1354 while (n) {
1355 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1356 impl->hRef, impl->implflags);
1357 ++impl;
1358 --n;
1362 static void dump_Variant(const VARIANT * pvar)
1364 SYSTEMTIME st;
1366 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1368 if (pvar)
1370 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1371 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1373 TRACE(",%p", V_BYREF(pvar));
1375 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1377 TRACE(",%p", V_ARRAY(pvar));
1379 else switch (V_TYPE(pvar))
1381 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1382 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1383 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1384 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1385 case VT_INT:
1386 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1387 case VT_UINT:
1388 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1389 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1390 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1391 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1392 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1393 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1394 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1395 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1396 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1397 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1398 V_CY(pvar).s.Lo); break;
1399 case VT_DATE:
1400 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1401 TRACE(",<invalid>");
1402 else
1403 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1404 st.wHour, st.wMinute, st.wSecond);
1405 break;
1406 case VT_ERROR:
1407 case VT_VOID:
1408 case VT_USERDEFINED:
1409 case VT_EMPTY:
1410 case VT_NULL: break;
1411 default: TRACE(",?"); break;
1414 TRACE("}\n");
1417 static void dump_DispParms(const DISPPARAMS * pdp)
1419 unsigned int index;
1421 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1423 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1425 TRACE("named args:\n");
1426 for (index = 0; index < pdp->cNamedArgs; index++)
1427 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1430 if (pdp->cArgs && pdp->rgvarg)
1432 TRACE("args:\n");
1433 for (index = 0; index < pdp->cArgs; index++)
1434 dump_Variant( &pdp->rgvarg[index] );
1438 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1440 TRACE("%p ref=%u\n", pty, pty->ref);
1441 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1442 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1443 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1444 TRACE("fct:%u var:%u impl:%u\n",
1445 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1446 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1447 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1448 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1449 if (TRACE_ON(ole))
1450 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1451 dump_TLBVarDesc(pty->vardescs, pty->TypeAttr.cVars);
1452 dump_TLBImplType(pty->impltypes, pty->TypeAttr.cImplTypes);
1455 static void dump_VARDESC(const VARDESC *v)
1457 MESSAGE("memid %d\n",v->memid);
1458 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1459 MESSAGE("oInst %d\n",v->u.oInst);
1460 dump_ELEMDESC(&(v->elemdescVar));
1461 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1462 MESSAGE("varkind %d\n",v->varkind);
1465 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1467 /* VT_LPWSTR is largest type that, may appear in type description */
1468 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1469 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1470 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1471 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1472 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1473 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1474 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1475 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1478 static void TLB_abort(void)
1480 DebugBreak();
1483 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1485 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1486 if (!ret) ERR("cannot allocate memory\n");
1487 return ret;
1490 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1492 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1493 if (!ret) ERR("cannot allocate memory\n");
1494 return ret;
1497 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1499 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1502 void heap_free(void *ptr)
1504 HeapFree(GetProcessHeap(), 0, ptr);
1507 /* returns the size required for a deep copy of a typedesc into a
1508 * flat buffer */
1509 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1511 SIZE_T size = 0;
1513 if (alloc_initial_space)
1514 size += sizeof(TYPEDESC);
1516 switch (tdesc->vt)
1518 case VT_PTR:
1519 case VT_SAFEARRAY:
1520 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1521 break;
1522 case VT_CARRAY:
1523 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1524 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1525 break;
1527 return size;
1530 /* deep copy a typedesc into a flat buffer */
1531 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1533 if (!dest)
1535 dest = buffer;
1536 buffer = (char *)buffer + sizeof(TYPEDESC);
1539 *dest = *src;
1541 switch (src->vt)
1543 case VT_PTR:
1544 case VT_SAFEARRAY:
1545 dest->u.lptdesc = buffer;
1546 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1547 break;
1548 case VT_CARRAY:
1549 dest->u.lpadesc = buffer;
1550 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1551 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1552 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1553 break;
1555 return buffer;
1558 /* free custom data allocated by MSFT_CustData */
1559 static inline void TLB_FreeCustData(struct list *custdata_list)
1561 TLBCustData *cd, *cdn;
1562 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1564 list_remove(&cd->entry);
1565 VariantClear(&cd->data);
1566 heap_free(cd);
1570 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1572 DWORD len;
1573 BSTR ret;
1575 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1576 ret = SysAllocStringLen(NULL, len - 1);
1577 if (!ret) return ret;
1578 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1579 return ret;
1582 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1583 UINT n, MEMBERID memid)
1585 while(n){
1586 if(funcdescs->funcdesc.memid == memid)
1587 return funcdescs;
1588 ++funcdescs;
1589 --n;
1591 return NULL;
1594 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1595 UINT n, const OLECHAR *name)
1597 while(n){
1598 if(!lstrcmpiW(funcdescs->Name, name))
1599 return funcdescs;
1600 ++funcdescs;
1601 --n;
1603 return NULL;
1606 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1607 UINT n, MEMBERID memid)
1609 while(n){
1610 if(vardescs->vardesc.memid == memid)
1611 return vardescs;
1612 ++vardescs;
1613 --n;
1615 return NULL;
1618 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1619 UINT n, const OLECHAR *name)
1621 while(n){
1622 if(!lstrcmpiW(vardescs->Name, name))
1623 return vardescs;
1624 ++vardescs;
1625 --n;
1627 return NULL;
1630 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1632 TLBCustData *cust_data;
1633 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1634 if(IsEqualIID(&cust_data->guid, guid))
1635 return cust_data;
1636 return NULL;
1639 static TLBVarDesc *TLBVarDesc_Constructor(UINT n)
1641 TLBVarDesc *ret;
1643 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1644 if(!ret)
1645 return NULL;
1647 while(n){
1648 list_init(&ret[n-1].custdata_list);
1649 --n;
1652 return ret;
1655 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1657 TLBParDesc *ret;
1659 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1660 if(!ret)
1661 return NULL;
1663 while(n){
1664 list_init(&ret[n-1].custdata_list);
1665 --n;
1668 return ret;
1671 static TLBFuncDesc *TLBFuncDesc_Constructor(UINT n)
1673 TLBFuncDesc *ret;
1675 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1676 if(!ret)
1677 return NULL;
1679 while(n){
1680 list_init(&ret[n-1].custdata_list);
1681 --n;
1684 return ret;
1687 static TLBImplType *TLBImplType_Constructor(UINT n)
1689 TLBImplType *ret;
1691 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1692 if(!ret)
1693 return NULL;
1695 while(n){
1696 list_init(&ret[n-1].custdata_list);
1697 --n;
1700 return ret;
1703 /**********************************************************************
1705 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1707 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1709 return pcx->pos;
1712 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1714 if (where != DO_NOT_SEEK)
1716 where += pcx->oStart;
1717 if (where > pcx->length)
1719 /* FIXME */
1720 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1721 TLB_abort();
1723 pcx->pos = where;
1727 /* read function */
1728 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1730 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1731 pcx->pos, count, pcx->oStart, pcx->length, where);
1733 MSFT_Seek(pcx, where);
1734 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1735 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1736 pcx->pos += count;
1737 return count;
1740 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1741 LONG where )
1743 DWORD ret;
1745 ret = MSFT_Read(buffer, count, pcx, where);
1746 FromLEDWords(buffer, ret);
1748 return ret;
1751 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1752 LONG where )
1754 DWORD ret;
1756 ret = MSFT_Read(buffer, count, pcx, where);
1757 FromLEWords(buffer, ret);
1759 return ret;
1762 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1764 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1765 memset(pGuid,0, sizeof(GUID));
1766 return;
1768 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1769 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1770 pGuid->Data2 = FromLEWord(pGuid->Data2);
1771 pGuid->Data3 = FromLEWord(pGuid->Data3);
1772 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1775 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1777 MSFT_NameIntro niName;
1779 if (offset < 0)
1781 ERR_(typelib)("bad offset %d\n", offset);
1782 return -1;
1785 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1786 pcx->pTblDir->pNametab.offset+offset);
1788 return niName.hreftype;
1791 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1793 char * name;
1794 MSFT_NameIntro niName;
1795 int lengthInChars;
1796 BSTR bstrName = NULL;
1798 if (offset < 0)
1800 ERR_(typelib)("bad offset %d\n", offset);
1801 return NULL;
1803 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1804 pcx->pTblDir->pNametab.offset+offset);
1805 niName.namelen &= 0xFF; /* FIXME: correct ? */
1806 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1807 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1808 name[niName.namelen & 0xff]='\0';
1810 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1811 name, -1, NULL, 0);
1813 /* no invalid characters in string */
1814 if (lengthInChars)
1816 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1818 /* don't check for invalid character since this has been done previously */
1819 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1821 heap_free(name);
1823 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1824 return bstrName;
1827 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1829 char * string;
1830 INT16 length;
1831 int lengthInChars;
1832 BSTR bstr = NULL;
1834 if(offset<0) return NULL;
1835 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1836 if(length <= 0) return 0;
1837 string = heap_alloc_zero(length +1);
1838 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1839 string[length]='\0';
1841 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1842 string, -1, NULL, 0);
1844 /* no invalid characters in string */
1845 if (lengthInChars)
1847 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1849 /* don't check for invalid character since this has been done previously */
1850 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1852 heap_free(string);
1854 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1855 return bstr;
1858 * read a value and fill a VARIANT structure
1860 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1862 int size;
1864 TRACE_(typelib)("\n");
1866 if(offset <0) { /* data are packed in here */
1867 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1868 V_I4(pVar) = offset & 0x3ffffff;
1869 return;
1871 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1872 pcx->pTblDir->pCustData.offset + offset );
1873 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1874 switch (V_VT(pVar)){
1875 case VT_EMPTY: /* FIXME: is this right? */
1876 case VT_NULL: /* FIXME: is this right? */
1877 case VT_I2 : /* this should not happen */
1878 case VT_I4 :
1879 case VT_R4 :
1880 case VT_ERROR :
1881 case VT_BOOL :
1882 case VT_I1 :
1883 case VT_UI1 :
1884 case VT_UI2 :
1885 case VT_UI4 :
1886 case VT_INT :
1887 case VT_UINT :
1888 case VT_VOID : /* FIXME: is this right? */
1889 case VT_HRESULT :
1890 size=4; break;
1891 case VT_R8 :
1892 case VT_CY :
1893 case VT_DATE :
1894 case VT_I8 :
1895 case VT_UI8 :
1896 case VT_DECIMAL : /* FIXME: is this right? */
1897 case VT_FILETIME :
1898 size=8;break;
1899 /* pointer types with known behaviour */
1900 case VT_BSTR :{
1901 char * ptr;
1902 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1903 if(size < 0) {
1904 char next;
1905 DWORD origPos = MSFT_Tell(pcx), nullPos;
1907 do {
1908 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1909 } while (next);
1910 nullPos = MSFT_Tell(pcx);
1911 size = nullPos - origPos;
1912 MSFT_Seek(pcx, origPos);
1914 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1915 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1916 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1917 /* FIXME: do we need a AtoW conversion here? */
1918 V_UNION(pVar, bstrVal[size])='\0';
1919 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1920 heap_free(ptr);
1922 size=-4; break;
1923 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1924 case VT_DISPATCH :
1925 case VT_VARIANT :
1926 case VT_UNKNOWN :
1927 case VT_PTR :
1928 case VT_SAFEARRAY :
1929 case VT_CARRAY :
1930 case VT_USERDEFINED :
1931 case VT_LPSTR :
1932 case VT_LPWSTR :
1933 case VT_BLOB :
1934 case VT_STREAM :
1935 case VT_STORAGE :
1936 case VT_STREAMED_OBJECT :
1937 case VT_STORED_OBJECT :
1938 case VT_BLOB_OBJECT :
1939 case VT_CF :
1940 case VT_CLSID :
1941 default:
1942 size=0;
1943 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1944 V_VT(pVar));
1947 if(size>0) /* (big|small) endian correct? */
1948 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1949 return;
1952 * create a linked list with custom data
1954 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
1956 MSFT_CDGuid entry;
1957 TLBCustData* pNew;
1958 int count=0;
1960 TRACE_(typelib)("\n");
1962 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
1964 while(offset >=0){
1965 count++;
1966 pNew=heap_alloc_zero(sizeof(TLBCustData));
1967 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1968 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1969 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1970 list_add_head(custdata_list, &pNew->entry);
1971 offset = entry.next;
1973 return count;
1976 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1977 ITypeInfoImpl *pTI)
1979 if(type <0)
1980 pTd->vt=type & VT_TYPEMASK;
1981 else
1982 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1984 if(pTd->vt == VT_USERDEFINED)
1985 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1987 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1990 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1992 /* resolve referenced type if any */
1993 while (lpTypeDesc)
1995 switch (lpTypeDesc->vt)
1997 case VT_PTR:
1998 lpTypeDesc = lpTypeDesc->u.lptdesc;
1999 break;
2001 case VT_CARRAY:
2002 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
2003 break;
2005 case VT_USERDEFINED:
2006 MSFT_DoRefType(pcx, pTI->pTypeLib,
2007 lpTypeDesc->u.hreftype);
2009 lpTypeDesc = NULL;
2010 break;
2012 default:
2013 lpTypeDesc = NULL;
2018 static void
2019 MSFT_DoFuncs(TLBContext* pcx,
2020 ITypeInfoImpl* pTI,
2021 int cFuncs,
2022 int cVars,
2023 int offset,
2024 TLBFuncDesc** pptfd)
2027 * member information is stored in a data structure at offset
2028 * indicated by the memoffset field of the typeinfo structure
2029 * There are several distinctive parts.
2030 * The first part starts with a field that holds the total length
2031 * of this (first) part excluding this field. Then follow the records,
2032 * for each member there is one record.
2034 * The first entry is always the length of the record (including this
2035 * length word).
2036 * The rest of the record depends on the type of the member. If there is
2037 * a field indicating the member type (function, variable, interface, etc)
2038 * I have not found it yet. At this time we depend on the information
2039 * in the type info and the usual order how things are stored.
2041 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2042 * for each member;
2044 * Third is an equal sized array with file offsets to the name entry
2045 * of each member.
2047 * The fourth and last (?) part is an array with offsets to the records
2048 * in the first part of this file segment.
2051 int infolen, nameoffset, reclength, i;
2052 int recoffset = offset + sizeof(INT);
2054 char *recbuf = heap_alloc(0xffff);
2055 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2056 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2058 TRACE_(typelib)("\n");
2060 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2062 *pptfd = TLBFuncDesc_Constructor(cFuncs);
2063 ptfd = *pptfd;
2064 for ( i = 0; i < cFuncs ; i++ )
2066 int optional;
2068 /* name, eventually add to a hash table */
2069 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2070 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2072 /* nameoffset is sometimes -1 on the second half of a propget/propput
2073 * pair of functions */
2074 if ((nameoffset == -1) && (i > 0))
2075 ptfd->Name = SysAllocString(ptfd_prev->Name);
2076 else
2077 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2079 /* read the function information record */
2080 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2082 reclength &= 0xffff;
2084 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2086 /* size without argument data */
2087 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2089 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2090 ptfd->helpcontext = pFuncRec->HelpContext;
2092 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2093 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2095 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2097 if (pFuncRec->FKCCIC & 0x2000 )
2099 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2100 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2101 ptfd->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2103 else
2104 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2106 else
2107 ptfd->Entry = (BSTR)-1;
2109 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2110 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2112 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2113 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2115 /* fill the FuncDesc Structure */
2116 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2117 offset + infolen + ( i + 1) * sizeof(INT));
2119 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2120 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2121 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2122 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2123 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2124 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2125 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2127 MSFT_GetTdesc(pcx,
2128 pFuncRec->DataType,
2129 &ptfd->funcdesc.elemdescFunc.tdesc,
2130 pTI);
2131 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2133 /* do the parameters/arguments */
2134 if(pFuncRec->nrargs)
2136 int j = 0;
2137 MSFT_ParameterInfo paraminfo;
2139 ptfd->funcdesc.lprgelemdescParam =
2140 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2142 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2144 MSFT_ReadLEDWords(&paraminfo, sizeof(paraminfo), pcx,
2145 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2147 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2149 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2151 MSFT_GetTdesc(pcx,
2152 paraminfo.DataType,
2153 &elemdesc->tdesc,
2154 pTI);
2156 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2158 /* name */
2159 if (paraminfo.oName == -1)
2160 /* this occurs for [propput] or [propget] methods, so
2161 * we should just set the name of the parameter to the
2162 * name of the method. */
2163 ptfd->pParamDesc[j].Name = SysAllocString(ptfd->Name);
2164 else
2165 ptfd->pParamDesc[j].Name =
2166 MSFT_ReadName( pcx, paraminfo.oName );
2167 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(ptfd->pParamDesc[j].Name));
2169 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2171 /* default value */
2172 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2173 (pFuncRec->FKCCIC & 0x1000) )
2175 INT* pInt = (INT *)((char *)pFuncRec +
2176 reclength -
2177 (pFuncRec->nrargs * 4) * sizeof(INT) );
2179 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2181 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2182 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2184 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2185 pInt[j], pcx);
2187 else
2188 elemdesc->u.paramdesc.pparamdescex = NULL;
2190 /* custom info */
2191 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2192 j*sizeof(pFuncRec->oArgCustData[0])) &&
2193 pFuncRec->FKCCIC & 0x80 )
2195 MSFT_CustData(pcx,
2196 pFuncRec->oArgCustData[j],
2197 &ptfd->pParamDesc[j].custdata_list);
2200 /* SEEK value = jump to offset,
2201 * from there jump to the end of record,
2202 * go back by (j-1) arguments
2204 MSFT_ReadLEDWords( &paraminfo ,
2205 sizeof(MSFT_ParameterInfo), pcx,
2206 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2207 * sizeof(MSFT_ParameterInfo)));
2211 /* scode is not used: archaic win16 stuff FIXME: right? */
2212 ptfd->funcdesc.cScodes = 0 ;
2213 ptfd->funcdesc.lprgscode = NULL ;
2215 ptfd_prev = ptfd;
2216 ++ptfd;
2217 recoffset += reclength;
2219 heap_free(recbuf);
2222 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2223 int cVars, int offset, TLBVarDesc ** pptvd)
2225 int infolen, nameoffset, reclength;
2226 char recbuf[256];
2227 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2228 TLBVarDesc *ptvd;
2229 int i;
2230 int recoffset;
2232 TRACE_(typelib)("\n");
2234 ptvd = *pptvd = TLBVarDesc_Constructor(cVars);
2235 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2236 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2237 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2238 recoffset += offset+sizeof(INT);
2239 for(i=0;i<cVars;i++, ++ptvd){
2240 /* name, eventually add to a hash table */
2241 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2242 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2243 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2244 /* read the variable information record */
2245 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2246 reclength &= 0xff;
2247 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2249 /* optional data */
2250 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2251 ptvd->HelpContext = pVarRec->HelpContext;
2253 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2254 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2256 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2257 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2259 /* fill the VarDesc Structure */
2260 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2261 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2262 ptvd->vardesc.varkind = pVarRec->VarKind;
2263 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2264 MSFT_GetTdesc(pcx, pVarRec->DataType,
2265 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2266 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2267 if(pVarRec->VarKind == VAR_CONST ){
2268 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2269 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2270 pVarRec->OffsValue, pcx);
2271 } else
2272 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2273 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2274 recoffset += reclength;
2278 /* fill in data for a hreftype (offset). When the referenced type is contained
2279 * in the typelib, it's just an (file) offset in the type info base dir.
2280 * If comes from import, it's an offset+1 in the ImpInfo table
2281 * */
2282 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2283 int offset)
2285 TLBRefType *ref;
2287 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2289 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2291 if(ref->reference == offset) return;
2294 ref = heap_alloc_zero(sizeof(TLBRefType));
2295 list_add_tail(&pTL->ref_list, &ref->entry);
2297 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2298 /* external typelib */
2299 MSFT_ImpInfo impinfo;
2300 TLBImpLib *pImpLib;
2302 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2304 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2305 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2307 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2308 if(pImpLib->offset==impinfo.oImpFile)
2309 break;
2311 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2312 ref->reference = offset;
2313 ref->pImpTLInfo = pImpLib;
2314 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2315 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2316 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2317 ref->index = TLB_REF_USE_GUID;
2318 } else
2319 ref->index = impinfo.oGuid;
2320 }else{
2321 ERR("Cannot find a reference\n");
2322 ref->reference = -1;
2323 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2325 }else{
2326 /* in this typelib */
2327 ref->index = MSFT_HREFTYPE_INDEX(offset);
2328 ref->reference = offset;
2329 ref->pImpTLInfo = TLB_REF_INTERNAL;
2333 /* process Implemented Interfaces of a com class */
2334 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2335 int offset)
2337 int i;
2338 MSFT_RefRecord refrec;
2339 TLBImplType *pImpl;
2341 TRACE_(typelib)("\n");
2343 pTI->impltypes = TLBImplType_Constructor(count);
2344 pImpl = pTI->impltypes;
2345 for(i=0;i<count;i++){
2346 if(offset<0) break; /* paranoia */
2347 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2348 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2349 pImpl->hRef = refrec.reftype;
2350 pImpl->implflags=refrec.flags;
2351 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2352 offset=refrec.onext;
2353 ++pImpl;
2357 * process a typeinfo record
2359 static ITypeInfoImpl * MSFT_DoTypeInfo(
2360 TLBContext *pcx,
2361 int count,
2362 ITypeLibImpl * pLibInfo)
2364 MSFT_TypeInfoBase tiBase;
2365 ITypeInfoImpl *ptiRet;
2367 TRACE_(typelib)("count=%u\n", count);
2369 ptiRet = ITypeInfoImpl_Constructor();
2370 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2371 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2373 /* this is where we are coming from */
2374 ptiRet->pTypeLib = pLibInfo;
2375 ptiRet->index=count;
2376 /* fill in the typeattr fields */
2378 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2379 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2380 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2381 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2382 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2383 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2384 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2385 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2386 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2387 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2388 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2389 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2390 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2391 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2392 MSFT_GetTdesc(pcx, tiBase.datatype1,
2393 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2395 /* FIXME: */
2396 /* IDLDESC idldescType; *//* never saw this one != zero */
2398 /* name, eventually add to a hash table */
2399 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2400 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2401 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2402 /* help info */
2403 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2404 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2405 ptiRet->dwHelpContext=tiBase.helpcontext;
2407 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2408 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2410 /* note: InfoType's Help file and HelpStringDll come from the containing
2411 * library. Further HelpString and Docstring appear to be the same thing :(
2413 /* functions */
2414 if(ptiRet->TypeAttr.cFuncs >0 )
2415 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2416 ptiRet->TypeAttr.cVars,
2417 tiBase.memoffset, &ptiRet->funcdescs);
2418 /* variables */
2419 if(ptiRet->TypeAttr.cVars >0 )
2420 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2421 ptiRet->TypeAttr.cVars,
2422 tiBase.memoffset, &ptiRet->vardescs);
2423 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2424 switch(ptiRet->TypeAttr.typekind)
2426 case TKIND_COCLASS:
2427 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2428 tiBase.datatype1);
2429 break;
2430 case TKIND_DISPATCH:
2431 /* This is not -1 when the interface is a non-base dual interface or
2432 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2433 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2434 not this interface.
2437 if (tiBase.datatype1 != -1)
2439 ptiRet->impltypes = TLBImplType_Constructor(1);
2440 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2441 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2443 break;
2444 default:
2445 ptiRet->impltypes = TLBImplType_Constructor(1);
2446 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2447 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2448 break;
2451 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2453 TRACE_(typelib)("%s guid: %s kind:%s\n",
2454 debugstr_w(ptiRet->Name),
2455 debugstr_guid(&ptiRet->TypeAttr.guid),
2456 typekind_desc[ptiRet->TypeAttr.typekind]);
2457 if (TRACE_ON(typelib))
2458 dump_TypeInfo(ptiRet);
2460 return ptiRet;
2463 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2464 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2465 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2466 * tradeoff here.
2468 static struct list tlb_cache = LIST_INIT(tlb_cache);
2469 static CRITICAL_SECTION cache_section;
2470 static CRITICAL_SECTION_DEBUG cache_section_debug =
2472 0, 0, &cache_section,
2473 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2474 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2476 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2479 typedef struct TLB_PEFile
2481 IUnknown IUnknown_iface;
2482 LONG refs;
2483 HMODULE dll;
2484 HRSRC typelib_resource;
2485 HGLOBAL typelib_global;
2486 LPVOID typelib_base;
2487 } TLB_PEFile;
2489 static inline TLB_PEFile *pefile_impl_from_IUnknown(IUnknown *iface)
2491 return CONTAINING_RECORD(iface, TLB_PEFile, IUnknown_iface);
2494 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2496 if (IsEqualIID(riid, &IID_IUnknown))
2498 *ppv = iface;
2499 IUnknown_AddRef(iface);
2500 return S_OK;
2502 *ppv = NULL;
2503 return E_NOINTERFACE;
2506 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2508 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2509 return InterlockedIncrement(&This->refs);
2512 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2514 TLB_PEFile *This = pefile_impl_from_IUnknown(iface);
2515 ULONG refs = InterlockedDecrement(&This->refs);
2516 if (!refs)
2518 if (This->typelib_global)
2519 FreeResource(This->typelib_global);
2520 if (This->dll)
2521 FreeLibrary(This->dll);
2522 heap_free(This);
2524 return refs;
2527 static const IUnknownVtbl TLB_PEFile_Vtable =
2529 TLB_PEFile_QueryInterface,
2530 TLB_PEFile_AddRef,
2531 TLB_PEFile_Release
2534 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2536 TLB_PEFile *This;
2537 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2539 This = heap_alloc(sizeof(TLB_PEFile));
2540 if (!This)
2541 return E_OUTOFMEMORY;
2543 This->IUnknown_iface.lpVtbl = &TLB_PEFile_Vtable;
2544 This->refs = 1;
2545 This->dll = NULL;
2546 This->typelib_resource = NULL;
2547 This->typelib_global = NULL;
2548 This->typelib_base = NULL;
2550 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2551 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2553 if (This->dll)
2555 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2556 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2557 if (This->typelib_resource)
2559 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2560 if (This->typelib_global)
2562 This->typelib_base = LockResource(This->typelib_global);
2564 if (This->typelib_base)
2566 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2567 *ppBase = This->typelib_base;
2568 *ppFile = &This->IUnknown_iface;
2569 return S_OK;
2574 TRACE("No TYPELIB resource found\n");
2575 hr = E_FAIL;
2578 TLB_PEFile_Release(&This->IUnknown_iface);
2579 return hr;
2582 typedef struct TLB_NEFile
2584 IUnknown IUnknown_iface;
2585 LONG refs;
2586 LPVOID typelib_base;
2587 } TLB_NEFile;
2589 static inline TLB_NEFile *nefile_impl_from_IUnknown(IUnknown *iface)
2591 return CONTAINING_RECORD(iface, TLB_NEFile, IUnknown_iface);
2594 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2596 if (IsEqualIID(riid, &IID_IUnknown))
2598 *ppv = iface;
2599 IUnknown_AddRef(iface);
2600 return S_OK;
2602 *ppv = NULL;
2603 return E_NOINTERFACE;
2606 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2608 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2609 return InterlockedIncrement(&This->refs);
2612 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2614 TLB_NEFile *This = nefile_impl_from_IUnknown(iface);
2615 ULONG refs = InterlockedDecrement(&This->refs);
2616 if (!refs)
2618 heap_free(This->typelib_base);
2619 heap_free(This);
2621 return refs;
2624 static const IUnknownVtbl TLB_NEFile_Vtable =
2626 TLB_NEFile_QueryInterface,
2627 TLB_NEFile_AddRef,
2628 TLB_NEFile_Release
2631 /***********************************************************************
2632 * read_xx_header [internal]
2634 static int read_xx_header( HFILE lzfd )
2636 IMAGE_DOS_HEADER mzh;
2637 char magic[3];
2639 LZSeek( lzfd, 0, SEEK_SET );
2640 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2641 return 0;
2642 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2643 return 0;
2645 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2646 if ( 2 != LZRead( lzfd, magic, 2 ) )
2647 return 0;
2649 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2651 if ( magic[0] == 'N' && magic[1] == 'E' )
2652 return IMAGE_OS2_SIGNATURE;
2653 if ( magic[0] == 'P' && magic[1] == 'E' )
2654 return IMAGE_NT_SIGNATURE;
2656 magic[2] = '\0';
2657 WARN("Can't handle %s files.\n", magic );
2658 return 0;
2662 /***********************************************************************
2663 * find_ne_resource [internal]
2665 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2666 DWORD *resLen, DWORD *resOff )
2668 IMAGE_OS2_HEADER nehd;
2669 NE_TYPEINFO *typeInfo;
2670 NE_NAMEINFO *nameInfo;
2671 DWORD nehdoffset;
2672 LPBYTE resTab;
2673 DWORD resTabSize;
2674 int count;
2676 /* Read in NE header */
2677 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2678 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2680 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2681 if ( !resTabSize )
2683 TRACE("No resources in NE dll\n" );
2684 return FALSE;
2687 /* Read in resource table */
2688 resTab = heap_alloc( resTabSize );
2689 if ( !resTab ) return FALSE;
2691 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2692 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2694 heap_free( resTab );
2695 return FALSE;
2698 /* Find resource */
2699 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2701 if (!IS_INTRESOURCE(typeid)) /* named type */
2703 BYTE len = strlen( typeid );
2704 while (typeInfo->type_id)
2706 if (!(typeInfo->type_id & 0x8000))
2708 BYTE *p = resTab + typeInfo->type_id;
2709 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2711 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2712 typeInfo->count * sizeof(NE_NAMEINFO));
2715 else /* numeric type id */
2717 WORD id = LOWORD(typeid) | 0x8000;
2718 while (typeInfo->type_id)
2720 if (typeInfo->type_id == id) goto found_type;
2721 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2722 typeInfo->count * sizeof(NE_NAMEINFO));
2725 TRACE("No typeid entry found for %p\n", typeid );
2726 heap_free( resTab );
2727 return FALSE;
2729 found_type:
2730 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2732 if (!IS_INTRESOURCE(resid)) /* named resource */
2734 BYTE len = strlen( resid );
2735 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2737 BYTE *p = resTab + nameInfo->id;
2738 if (nameInfo->id & 0x8000) continue;
2739 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2742 else /* numeric resource id */
2744 WORD id = LOWORD(resid) | 0x8000;
2745 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2746 if (nameInfo->id == id) goto found_name;
2748 TRACE("No resid entry found for %p\n", typeid );
2749 heap_free( resTab );
2750 return FALSE;
2752 found_name:
2753 /* Return resource data */
2754 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2755 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2757 heap_free( resTab );
2758 return TRUE;
2761 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2763 HFILE lzfd = -1;
2764 OFSTRUCT ofs;
2765 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2766 TLB_NEFile *This;
2768 This = heap_alloc(sizeof(TLB_NEFile));
2769 if (!This) return E_OUTOFMEMORY;
2771 This->IUnknown_iface.lpVtbl = &TLB_NEFile_Vtable;
2772 This->refs = 1;
2773 This->typelib_base = NULL;
2775 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2776 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2778 DWORD reslen, offset;
2779 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2781 This->typelib_base = heap_alloc(reslen);
2782 if( !This->typelib_base )
2783 hr = E_OUTOFMEMORY;
2784 else
2786 LZSeek( lzfd, offset, SEEK_SET );
2787 reslen = LZRead( lzfd, This->typelib_base, reslen );
2788 LZClose( lzfd );
2789 *ppBase = This->typelib_base;
2790 *pdwTLBLength = reslen;
2791 *ppFile = &This->IUnknown_iface;
2792 return S_OK;
2797 if( lzfd >= 0) LZClose( lzfd );
2798 TLB_NEFile_Release(&This->IUnknown_iface);
2799 return hr;
2802 typedef struct TLB_Mapping
2804 IUnknown IUnknown_iface;
2805 LONG refs;
2806 HANDLE file;
2807 HANDLE mapping;
2808 LPVOID typelib_base;
2809 } TLB_Mapping;
2811 static inline TLB_Mapping *mapping_impl_from_IUnknown(IUnknown *iface)
2813 return CONTAINING_RECORD(iface, TLB_Mapping, IUnknown_iface);
2816 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2818 if (IsEqualIID(riid, &IID_IUnknown))
2820 *ppv = iface;
2821 IUnknown_AddRef(iface);
2822 return S_OK;
2824 *ppv = NULL;
2825 return E_NOINTERFACE;
2828 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2830 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
2831 return InterlockedIncrement(&This->refs);
2834 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2836 TLB_Mapping *This = mapping_impl_from_IUnknown(iface);
2837 ULONG refs = InterlockedDecrement(&This->refs);
2838 if (!refs)
2840 if (This->typelib_base)
2841 UnmapViewOfFile(This->typelib_base);
2842 if (This->mapping)
2843 CloseHandle(This->mapping);
2844 if (This->file != INVALID_HANDLE_VALUE)
2845 CloseHandle(This->file);
2846 heap_free(This);
2848 return refs;
2851 static const IUnknownVtbl TLB_Mapping_Vtable =
2853 TLB_Mapping_QueryInterface,
2854 TLB_Mapping_AddRef,
2855 TLB_Mapping_Release
2858 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2860 TLB_Mapping *This;
2862 This = heap_alloc(sizeof(TLB_Mapping));
2863 if (!This)
2864 return E_OUTOFMEMORY;
2866 This->IUnknown_iface.lpVtbl = &TLB_Mapping_Vtable;
2867 This->refs = 1;
2868 This->file = INVALID_HANDLE_VALUE;
2869 This->mapping = NULL;
2870 This->typelib_base = NULL;
2872 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2873 if (INVALID_HANDLE_VALUE != This->file)
2875 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2876 if (This->mapping)
2878 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2879 if(This->typelib_base)
2881 /* retrieve file size */
2882 *pdwTLBLength = GetFileSize(This->file, NULL);
2883 *ppBase = This->typelib_base;
2884 *ppFile = &This->IUnknown_iface;
2885 return S_OK;
2890 IUnknown_Release(&This->IUnknown_iface);
2891 return TYPE_E_CANTLOADLIBRARY;
2894 /****************************************************************************
2895 * TLB_ReadTypeLib
2897 * find the type of the typelib file and map the typelib resource into
2898 * the memory
2901 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2902 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2904 ITypeLibImpl *entry;
2905 HRESULT ret;
2906 INT index = 1;
2907 LPWSTR index_str, file = (LPWSTR)pszFileName;
2908 LPVOID pBase = NULL;
2909 DWORD dwTLBLength = 0;
2910 IUnknown *pFile = NULL;
2912 *ppTypeLib = NULL;
2914 index_str = strrchrW(pszFileName, '\\');
2915 if(index_str && *++index_str != '\0')
2917 LPWSTR end_ptr;
2918 LONG idx = strtolW(index_str, &end_ptr, 10);
2919 if(*end_ptr == '\0')
2921 int str_len = index_str - pszFileName - 1;
2922 index = idx;
2923 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2924 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2925 file[str_len] = 0;
2929 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2931 if(strchrW(file, '\\'))
2933 lstrcpyW(pszPath, file);
2935 else
2937 int len = GetSystemDirectoryW(pszPath, cchPath);
2938 pszPath[len] = '\\';
2939 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2943 if(file != pszFileName) heap_free(file);
2945 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2947 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2948 EnterCriticalSection(&cache_section);
2949 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
2951 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2953 TRACE("cache hit\n");
2954 *ppTypeLib = &entry->ITypeLib2_iface;
2955 ITypeLib2_AddRef(*ppTypeLib);
2956 LeaveCriticalSection(&cache_section);
2957 return S_OK;
2960 LeaveCriticalSection(&cache_section);
2962 /* now actually load and parse the typelib */
2964 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2965 if (ret == TYPE_E_CANTLOADLIBRARY)
2966 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2967 if (ret == TYPE_E_CANTLOADLIBRARY)
2968 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2969 if (SUCCEEDED(ret))
2971 if (dwTLBLength >= 4)
2973 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2974 if (dwSignature == MSFT_SIGNATURE)
2975 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2976 else if (dwSignature == SLTG_SIGNATURE)
2977 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2978 else
2980 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2981 ret = TYPE_E_CANTLOADLIBRARY;
2984 else
2985 ret = TYPE_E_CANTLOADLIBRARY;
2986 IUnknown_Release(pFile);
2989 if(*ppTypeLib) {
2990 ITypeLibImpl *impl = impl_from_ITypeLib2(*ppTypeLib);
2992 TRACE("adding to cache\n");
2993 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2994 lstrcpyW(impl->path, pszPath);
2995 /* We should really canonicalise the path here. */
2996 impl->index = index;
2998 /* FIXME: check if it has added already in the meantime */
2999 EnterCriticalSection(&cache_section);
3000 list_add_head(&tlb_cache, &impl->entry);
3001 LeaveCriticalSection(&cache_section);
3002 ret = S_OK;
3004 else
3006 if(ret != E_FAIL)
3007 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
3009 ret = TYPE_E_CANTLOADLIBRARY;
3013 return ret;
3016 /*================== ITypeLib(2) Methods ===================================*/
3018 static ITypeLibImpl* TypeLibImpl_Constructor(void)
3020 ITypeLibImpl* pTypeLibImpl;
3022 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
3023 if (!pTypeLibImpl) return NULL;
3025 pTypeLibImpl->ITypeLib2_iface.lpVtbl = &tlbvt;
3026 pTypeLibImpl->ITypeComp_iface.lpVtbl = &tlbtcvt;
3027 pTypeLibImpl->ref = 1;
3029 list_init(&pTypeLibImpl->implib_list);
3030 list_init(&pTypeLibImpl->custdata_list);
3031 list_init(&pTypeLibImpl->ref_list);
3032 pTypeLibImpl->dispatch_href = -1;
3034 return pTypeLibImpl;
3037 /****************************************************************************
3038 * ITypeLib2_Constructor_MSFT
3040 * loading an MSFT typelib from an in-memory image
3042 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3044 TLBContext cx;
3045 LONG lPSegDir;
3046 MSFT_Header tlbHeader;
3047 MSFT_SegDir tlbSegDir;
3048 ITypeLibImpl * pTypeLibImpl;
3050 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3052 pTypeLibImpl = TypeLibImpl_Constructor();
3053 if (!pTypeLibImpl) return NULL;
3055 /* get pointer to beginning of typelib data */
3056 cx.pos = 0;
3057 cx.oStart=0;
3058 cx.mapping = pLib;
3059 cx.pLibInfo = pTypeLibImpl;
3060 cx.length = dwTLBLength;
3062 /* read header */
3063 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3064 TRACE_(typelib)("header:\n");
3065 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3066 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3067 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3068 return NULL;
3070 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3072 /* there is a small amount of information here until the next important
3073 * part:
3074 * the segment directory . Try to calculate the amount of data */
3075 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3077 /* now read the segment directory */
3078 TRACE("read segment directory (at %d)\n",lPSegDir);
3079 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3080 cx.pTblDir = &tlbSegDir;
3082 /* just check two entries */
3083 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3085 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3086 heap_free(pTypeLibImpl);
3087 return NULL;
3090 /* now fill our internal data */
3091 /* TLIBATTR fields */
3092 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
3094 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
3095 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3096 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
3097 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
3098 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3100 pTypeLibImpl->lcid = tlbHeader.lcid;
3102 /* name, eventually add to a hash table */
3103 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3105 /* help info */
3106 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3107 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3109 if( tlbHeader.varflags & HELPDLLFLAG)
3111 int offset;
3112 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3113 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3116 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3118 /* custom data */
3119 if(tlbHeader.CustomDataOffset >= 0)
3121 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3124 /* fill in type descriptions */
3125 if(tlbSegDir.pTypdescTab.length > 0)
3127 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3128 INT16 td[4];
3129 pTypeLibImpl->ctTypeDesc = cTD;
3130 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3131 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3132 for(i=0; i<cTD; )
3134 /* FIXME: add several sanity checks here */
3135 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3136 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3138 /* FIXME: check safearray */
3139 if(td[3] < 0)
3140 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3141 else
3142 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3144 else if(td[0] == VT_CARRAY)
3146 /* array descr table here */
3147 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3149 else if(td[0] == VT_USERDEFINED)
3151 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3153 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3156 /* second time around to fill the array subscript info */
3157 for(i=0;i<cTD;i++)
3159 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3160 if(tlbSegDir.pArrayDescriptions.offset>0)
3162 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3163 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3165 if(td[1]<0)
3166 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3167 else
3168 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3170 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3172 for(j = 0; j<td[2]; j++)
3174 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3175 sizeof(INT), &cx, DO_NOT_SEEK);
3176 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3177 sizeof(INT), &cx, DO_NOT_SEEK);
3180 else
3182 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3183 ERR("didn't find array description data\n");
3188 /* imported type libs */
3189 if(tlbSegDir.pImpFiles.offset>0)
3191 TLBImpLib *pImpLib;
3192 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3193 UINT16 size;
3195 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3197 char *name;
3199 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3200 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3201 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3203 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3204 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3205 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3206 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3208 size >>= 2;
3209 name = heap_alloc_zero(size+1);
3210 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3211 pImpLib->name = TLB_MultiByteToBSTR(name);
3212 heap_free(name);
3214 MSFT_ReadGuid(&pImpLib->guid, oGuid, &cx);
3215 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3217 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3221 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3222 if(pTypeLibImpl->dispatch_href != -1)
3223 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3225 /* type infos */
3226 if(tlbHeader.nrtypeinfos >= 0 )
3228 ITypeInfoImpl **ppTI;
3229 int i;
3231 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3233 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3235 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3237 ++ppTI;
3238 (pTypeLibImpl->TypeInfoCount)++;
3242 TRACE("(%p)\n", pTypeLibImpl);
3243 return &pTypeLibImpl->ITypeLib2_iface;
3247 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3249 char b[3];
3250 int i;
3251 short s;
3253 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3254 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3255 return FALSE;
3258 guid->Data4[0] = s >> 8;
3259 guid->Data4[1] = s & 0xff;
3261 b[2] = '\0';
3262 for(i = 0; i < 6; i++) {
3263 memcpy(b, str + 24 + 2 * i, 2);
3264 guid->Data4[i + 2] = strtol(b, NULL, 16);
3266 return TRUE;
3269 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3271 WORD bytelen;
3272 DWORD len;
3274 *pBstr = NULL;
3275 bytelen = *(const WORD*)ptr;
3276 if(bytelen == 0xffff) return 2;
3277 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3278 *pBstr = SysAllocStringLen(NULL, len);
3279 if (*pBstr)
3280 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3281 return bytelen + 2;
3284 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3286 WORD bytelen;
3288 *str = NULL;
3289 bytelen = *(const WORD*)ptr;
3290 if(bytelen == 0xffff) return 2;
3291 *str = heap_alloc(bytelen + 1);
3292 memcpy(*str, ptr + 2, bytelen);
3293 (*str)[bytelen] = '\0';
3294 return bytelen + 2;
3297 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3299 char *ptr = pLibBlk;
3300 WORD w;
3302 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3303 FIXME("libblk magic = %04x\n", w);
3304 return 0;
3307 ptr += 6;
3308 if((w = *(WORD*)ptr) != 0xffff) {
3309 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3310 ptr += w;
3312 ptr += 2;
3314 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3316 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3318 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3319 ptr += 4;
3321 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3322 ptr += 2;
3324 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3325 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3326 else
3327 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3328 ptr += 2;
3330 ptr += 4; /* skip res12 */
3332 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3333 ptr += 2;
3335 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3336 ptr += 2;
3338 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3339 ptr += 2;
3341 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3342 ptr += sizeof(GUID);
3344 return ptr - (char*)pLibBlk;
3347 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3348 typedef struct
3350 unsigned int num;
3351 HREFTYPE refs[1];
3352 } sltg_ref_lookup_t;
3354 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3355 HREFTYPE *typelib_ref)
3357 if(table && typeinfo_ref < table->num)
3359 *typelib_ref = table->refs[typeinfo_ref];
3360 return S_OK;
3363 ERR_(typelib)("Unable to find reference\n");
3364 *typelib_ref = -1;
3365 return E_FAIL;
3368 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3370 BOOL done = FALSE;
3372 while(!done) {
3373 if((*pType & 0xe00) == 0xe00) {
3374 pTD->vt = VT_PTR;
3375 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3376 pTD = pTD->u.lptdesc;
3378 switch(*pType & 0x3f) {
3379 case VT_PTR:
3380 pTD->vt = VT_PTR;
3381 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3382 pTD = pTD->u.lptdesc;
3383 break;
3385 case VT_USERDEFINED:
3386 pTD->vt = VT_USERDEFINED;
3387 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3388 done = TRUE;
3389 break;
3391 case VT_CARRAY:
3393 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3394 array */
3396 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3398 pTD->vt = VT_CARRAY;
3399 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3400 pTD->u.lpadesc->cDims = pSA->cDims;
3401 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3402 pSA->cDims * sizeof(SAFEARRAYBOUND));
3404 pTD = &pTD->u.lpadesc->tdescElem;
3405 break;
3408 case VT_SAFEARRAY:
3410 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3411 useful? */
3413 pType++;
3414 pTD->vt = VT_SAFEARRAY;
3415 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3416 pTD = pTD->u.lptdesc;
3417 break;
3419 default:
3420 pTD->vt = *pType & 0x3f;
3421 done = TRUE;
3422 break;
3424 pType++;
3426 return pType;
3429 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3430 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3432 /* Handle [in/out] first */
3433 if((*pType & 0xc000) == 0xc000)
3434 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3435 else if(*pType & 0x8000)
3436 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3437 else if(*pType & 0x4000)
3438 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3439 else
3440 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3442 if(*pType & 0x2000)
3443 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3445 if(*pType & 0x80)
3446 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3448 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3452 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3453 char *pNameTable)
3455 unsigned int ref;
3456 char *name;
3457 TLBRefType *ref_type;
3458 sltg_ref_lookup_t *table;
3459 HREFTYPE typelib_ref;
3461 if(pRef->magic != SLTG_REF_MAGIC) {
3462 FIXME("Ref magic = %x\n", pRef->magic);
3463 return NULL;
3465 name = ( (char*)pRef->names + pRef->number);
3467 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3468 table->num = pRef->number >> 3;
3470 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3472 /* We don't want the first href to be 0 */
3473 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3475 for(ref = 0; ref < pRef->number >> 3; ref++) {
3476 char *refname;
3477 unsigned int lib_offs, type_num;
3479 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3481 name += SLTG_ReadStringA(name, &refname);
3482 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3483 FIXME_(typelib)("Can't sscanf ref\n");
3484 if(lib_offs != 0xffff) {
3485 TLBImpLib *import;
3487 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3488 if(import->offset == lib_offs)
3489 break;
3491 if(&import->entry == &pTL->implib_list) {
3492 char fname[MAX_PATH+1];
3493 int len;
3495 import = heap_alloc_zero(sizeof(*import));
3496 import->offset = lib_offs;
3497 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3498 &import->guid);
3499 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3500 &import->wVersionMajor,
3501 &import->wVersionMinor,
3502 &import->lcid, fname) != 4) {
3503 FIXME_(typelib)("can't sscanf ref %s\n",
3504 pNameTable + lib_offs + 40);
3506 len = strlen(fname);
3507 if(fname[len-1] != '#')
3508 FIXME("fname = %s\n", fname);
3509 fname[len-1] = '\0';
3510 import->name = TLB_MultiByteToBSTR(fname);
3511 list_add_tail(&pTL->implib_list, &import->entry);
3513 ref_type->pImpTLInfo = import;
3515 /* Store a reference to IDispatch */
3516 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid, &IID_StdOle) && type_num == 4)
3517 pTL->dispatch_href = typelib_ref;
3519 } else { /* internal ref */
3520 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3522 ref_type->reference = typelib_ref;
3523 ref_type->index = type_num;
3525 heap_free(refname);
3526 list_add_tail(&pTL->ref_list, &ref_type->entry);
3528 table->refs[ref] = typelib_ref;
3529 typelib_ref += 4;
3531 if((BYTE)*name != SLTG_REF_MAGIC)
3532 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3533 dump_TLBRefType(pTL);
3534 return table;
3537 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3538 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3540 SLTG_ImplInfo *info;
3541 TLBImplType *pImplType;
3542 /* I don't really get this structure, usually it's 0x16 bytes
3543 long, but iuser.tlb contains some that are 0x18 bytes long.
3544 That's ok because we can use the next ptr to jump to the next
3545 one. But how do we know the length of the last one? The WORD
3546 at offs 0x8 might be the clue. For now I'm just assuming that
3547 the last one is the regular 0x16 bytes. */
3549 info = (SLTG_ImplInfo*)pBlk;
3550 while(1){
3551 pTI->TypeAttr.cImplTypes++;
3552 if(info->next == 0xffff)
3553 break;
3554 info = (SLTG_ImplInfo*)(pBlk + info->next);
3557 info = (SLTG_ImplInfo*)pBlk;
3558 pTI->impltypes = TLBImplType_Constructor(pTI->TypeAttr.cImplTypes);
3559 pImplType = pTI->impltypes;
3560 while(1) {
3561 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3562 pImplType->implflags = info->impltypeflags;
3563 ++pImplType;
3565 if(info->next == 0xffff)
3566 break;
3567 if(OneOnly)
3568 FIXME_(typelib)("Interface inheriting more than one interface\n");
3569 info = (SLTG_ImplInfo*)(pBlk + info->next);
3571 info++; /* see comment at top of function */
3572 return (char*)info;
3575 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3576 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3578 TLBVarDesc *pVarDesc;
3579 BSTR bstrPrevName = NULL;
3580 SLTG_Variable *pItem;
3581 unsigned short i;
3582 WORD *pType;
3584 pVarDesc = pTI->vardescs = TLBVarDesc_Constructor(cVars);
3586 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3587 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3589 pVarDesc->vardesc.memid = pItem->memid;
3591 if (pItem->magic != SLTG_VAR_MAGIC &&
3592 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3593 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3594 return;
3597 if (pItem->name == 0xfffe)
3598 pVarDesc->Name = SysAllocString(bstrPrevName);
3599 else
3600 pVarDesc->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3602 TRACE_(typelib)("name: %s\n", debugstr_w(pVarDesc->Name));
3603 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3604 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3606 if(pItem->flags & 0x02)
3607 pType = &pItem->type;
3608 else
3609 pType = (WORD*)(pBlk + pItem->type);
3611 if (pItem->flags & ~0xda)
3612 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3614 SLTG_DoElem(pType, pBlk,
3615 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3617 if (TRACE_ON(typelib)) {
3618 char buf[300];
3619 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3620 TRACE_(typelib)("elemdescVar: %s\n", buf);
3623 if (pItem->flags & 0x40) {
3624 TRACE_(typelib)("VAR_DISPATCH\n");
3625 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3627 else if (pItem->flags & 0x10) {
3628 TRACE_(typelib)("VAR_CONST\n");
3629 pVarDesc->vardesc.varkind = VAR_CONST;
3630 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3631 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3632 if (pItem->flags & 0x08)
3633 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3634 else {
3635 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3637 case VT_LPSTR:
3638 case VT_LPWSTR:
3639 case VT_BSTR:
3641 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3642 BSTR str;
3643 TRACE_(typelib)("len = %u\n", len);
3644 if (len == 0xffff) {
3645 str = NULL;
3646 } else {
3647 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3648 str = SysAllocStringLen(NULL, alloc_len);
3649 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3651 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3652 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3653 break;
3655 case VT_I2:
3656 case VT_UI2:
3657 case VT_I4:
3658 case VT_UI4:
3659 case VT_INT:
3660 case VT_UINT:
3661 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3662 *(INT*)(pBlk + pItem->byte_offs);
3663 break;
3664 default:
3665 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3669 else {
3670 TRACE_(typelib)("VAR_PERINSTANCE\n");
3671 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3672 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3675 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3676 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3678 if (pItem->flags & 0x80)
3679 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3681 bstrPrevName = pVarDesc->Name;
3683 pTI->TypeAttr.cVars = cVars;
3686 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3687 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3689 SLTG_Function *pFunc;
3690 unsigned short i;
3691 TLBFuncDesc *pFuncDesc;
3693 pTI->funcdescs = TLBFuncDesc_Constructor(cFuncs);
3695 pFuncDesc = pTI->funcdescs;
3696 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3697 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3699 int param;
3700 WORD *pType, *pArg;
3702 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3703 case SLTG_FUNCTION_MAGIC:
3704 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3705 break;
3706 case SLTG_DISPATCH_FUNCTION_MAGIC:
3707 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3708 break;
3709 case SLTG_STATIC_FUNCTION_MAGIC:
3710 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3711 break;
3712 default:
3713 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3714 continue;
3716 pFuncDesc->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3718 pFuncDesc->funcdesc.memid = pFunc->dispid;
3719 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3720 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3721 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3722 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3723 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3725 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3726 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3728 if(pFunc->retnextopt & 0x80)
3729 pType = &pFunc->rettype;
3730 else
3731 pType = (WORD*)(pBlk + pFunc->rettype);
3733 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3735 pFuncDesc->funcdesc.lprgelemdescParam =
3736 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3737 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
3739 pArg = (WORD*)(pBlk + pFunc->arg_off);
3741 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3742 char *paramName = pNameTable + *pArg;
3743 BOOL HaveOffs;
3744 /* If arg type follows then paramName points to the 2nd
3745 letter of the name, else the next WORD is an offset to
3746 the arg type and paramName points to the first letter.
3747 So let's take one char off paramName and see if we're
3748 pointing at an alpha-numeric char. However if *pArg is
3749 0xffff or 0xfffe then the param has no name, the former
3750 meaning that the next WORD is the type, the latter
3751 meaning that the next WORD is an offset to the type. */
3753 HaveOffs = FALSE;
3754 if(*pArg == 0xffff)
3755 paramName = NULL;
3756 else if(*pArg == 0xfffe) {
3757 paramName = NULL;
3758 HaveOffs = TRUE;
3760 else if(paramName[-1] && !isalnum(paramName[-1]))
3761 HaveOffs = TRUE;
3763 pArg++;
3765 if(HaveOffs) { /* the next word is an offset to type */
3766 pType = (WORD*)(pBlk + *pArg);
3767 SLTG_DoElem(pType, pBlk,
3768 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3769 pArg++;
3770 } else {
3771 if(paramName)
3772 paramName--;
3773 pArg = SLTG_DoElem(pArg, pBlk,
3774 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3777 /* Are we an optional param ? */
3778 if(pFuncDesc->funcdesc.cParams - param <=
3779 pFuncDesc->funcdesc.cParamsOpt)
3780 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3782 if(paramName) {
3783 pFuncDesc->pParamDesc[param].Name =
3784 TLB_MultiByteToBSTR(paramName);
3785 } else {
3786 pFuncDesc->pParamDesc[param].Name =
3787 SysAllocString(pFuncDesc->Name);
3791 pTI->TypeAttr.cFuncs = cFuncs;
3794 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3795 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3796 SLTG_TypeInfoTail *pTITail)
3798 char *pFirstItem;
3799 sltg_ref_lookup_t *ref_lookup = NULL;
3801 if(pTIHeader->href_table != 0xffffffff) {
3802 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3803 pNameTable);
3806 pFirstItem = pBlk;
3808 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3809 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3811 heap_free(ref_lookup);
3815 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3816 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3817 const SLTG_TypeInfoTail *pTITail)
3819 char *pFirstItem;
3820 sltg_ref_lookup_t *ref_lookup = NULL;
3822 if(pTIHeader->href_table != 0xffffffff) {
3823 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3824 pNameTable);
3827 pFirstItem = pBlk;
3829 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3830 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3833 if (pTITail->funcs_off != 0xffff)
3834 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3836 heap_free(ref_lookup);
3838 if (TRACE_ON(typelib))
3839 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3842 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3843 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3844 const SLTG_TypeInfoTail *pTITail)
3846 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3849 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3850 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3851 const SLTG_TypeInfoTail *pTITail)
3853 WORD *pType;
3854 sltg_ref_lookup_t *ref_lookup = NULL;
3856 if (pTITail->simple_alias) {
3857 /* if simple alias, no more processing required */
3858 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3859 return;
3862 if(pTIHeader->href_table != 0xffffffff) {
3863 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3864 pNameTable);
3867 /* otherwise it is an offset to a type */
3868 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3870 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3872 heap_free(ref_lookup);
3875 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3876 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3877 const SLTG_TypeInfoTail *pTITail)
3879 sltg_ref_lookup_t *ref_lookup = NULL;
3880 if (pTIHeader->href_table != 0xffffffff)
3881 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3882 pNameTable);
3884 if (pTITail->vars_off != 0xffff)
3885 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3887 if (pTITail->funcs_off != 0xffff)
3888 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3890 if (pTITail->impls_off != 0xffff)
3891 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3893 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3894 * of dispinterface functions including the IDispatch ones, so
3895 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3896 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3898 heap_free(ref_lookup);
3899 if (TRACE_ON(typelib))
3900 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3903 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3904 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3905 const SLTG_TypeInfoTail *pTITail)
3907 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3910 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3911 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3912 const SLTG_TypeInfoTail *pTITail)
3914 sltg_ref_lookup_t *ref_lookup = NULL;
3915 if (pTIHeader->href_table != 0xffffffff)
3916 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3917 pNameTable);
3919 if (pTITail->vars_off != 0xffff)
3920 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3922 if (pTITail->funcs_off != 0xffff)
3923 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3924 heap_free(ref_lookup);
3925 if (TRACE_ON(typelib))
3926 dump_TypeInfo(pTI);
3929 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3930 manageable copy of it into this */
3931 typedef struct {
3932 WORD small_no;
3933 char *index_name;
3934 char *other_name;
3935 WORD res1a;
3936 WORD name_offs;
3937 WORD more_bytes;
3938 char *extra;
3939 WORD res20;
3940 DWORD helpcontext;
3941 WORD res26;
3942 GUID uuid;
3943 } SLTG_InternalOtherTypeInfo;
3945 /****************************************************************************
3946 * ITypeLib2_Constructor_SLTG
3948 * loading a SLTG typelib from an in-memory image
3950 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3952 ITypeLibImpl *pTypeLibImpl;
3953 SLTG_Header *pHeader;
3954 SLTG_BlkEntry *pBlkEntry;
3955 SLTG_Magic *pMagic;
3956 SLTG_Index *pIndex;
3957 SLTG_Pad9 *pPad9;
3958 LPVOID pBlk, pFirstBlk;
3959 SLTG_LibBlk *pLibBlk;
3960 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3961 char *pAfterOTIBlks = NULL;
3962 char *pNameTable, *ptr;
3963 int i;
3964 DWORD len, order;
3965 ITypeInfoImpl **ppTypeInfoImpl;
3967 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3970 pTypeLibImpl = TypeLibImpl_Constructor();
3971 if (!pTypeLibImpl) return NULL;
3973 pHeader = pLib;
3975 TRACE_(typelib)("header:\n");
3976 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3977 pHeader->nrOfFileBlks );
3978 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3979 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3980 pHeader->SLTG_magic);
3981 return NULL;
3984 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3985 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3987 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3988 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3990 /* Next we have a magic block */
3991 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3993 /* Let's see if we're still in sync */
3994 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3995 sizeof(SLTG_COMPOBJ_MAGIC))) {
3996 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3997 return NULL;
3999 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
4000 sizeof(SLTG_DIR_MAGIC))) {
4001 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
4002 return NULL;
4005 pIndex = (SLTG_Index*)(pMagic+1);
4007 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
4009 pFirstBlk = pPad9 + 1;
4011 /* We'll set up a ptr to the main library block, which is the last one. */
4013 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4014 pBlkEntry[order].next != 0;
4015 order = pBlkEntry[order].next - 1, i++) {
4016 pBlk = (char*)pBlk + pBlkEntry[order].len;
4018 pLibBlk = pBlk;
4020 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
4022 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4023 interspersed */
4025 len += 0x40;
4027 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4029 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
4032 ptr = (char*)pLibBlk + len;
4034 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
4035 WORD w, extra;
4036 len = 0;
4038 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
4040 w = *(WORD*)(ptr + 2);
4041 if(w != 0xffff) {
4042 len += w;
4043 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
4044 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
4045 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4047 w = *(WORD*)(ptr + 4 + len);
4048 if(w != 0xffff) {
4049 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4050 len += w;
4051 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4052 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4053 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4055 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4056 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4057 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4058 if(extra) {
4059 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4060 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4061 len += extra;
4063 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4064 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4065 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4066 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4067 len += sizeof(SLTG_OtherTypeInfo);
4068 ptr += len;
4071 pAfterOTIBlks = ptr;
4073 /* Skip this WORD and get the next DWORD */
4074 len = *(DWORD*)(pAfterOTIBlks + 2);
4076 /* Now add this to pLibBLk look at what we're pointing at and
4077 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4078 dust and we should be pointing at the beginning of the name
4079 table */
4081 pNameTable = (char*)pLibBlk + len;
4083 switch(*(WORD*)pNameTable) {
4084 case 0xffff:
4085 break;
4086 case 0x0200:
4087 pNameTable += 0x20;
4088 break;
4089 default:
4090 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4091 break;
4094 pNameTable += 0x216;
4096 pNameTable += 2;
4098 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4100 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
4103 /* Hopefully we now have enough ptrs set up to actually read in
4104 some TypeInfos. It's not clear which order to do them in, so
4105 I'll just follow the links along the BlkEntry chain and read
4106 them in the order in which they are in the file */
4108 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4109 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4111 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4112 pBlkEntry[order].next != 0;
4113 order = pBlkEntry[order].next - 1, i++) {
4115 SLTG_TypeInfoHeader *pTIHeader;
4116 SLTG_TypeInfoTail *pTITail;
4117 SLTG_MemberHeader *pMemHeader;
4119 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4120 FIXME_(typelib)("Index strings don't match\n");
4121 heap_free(pOtherTypeInfoBlks);
4122 return NULL;
4125 pTIHeader = pBlk;
4126 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4127 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4128 heap_free(pOtherTypeInfoBlks);
4129 return NULL;
4131 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4132 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4133 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4135 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4136 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4137 (*ppTypeInfoImpl)->index = i;
4138 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
4139 pOtherTypeInfoBlks[i].name_offs +
4140 pNameTable);
4141 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4142 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
4143 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
4144 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4145 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4146 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4147 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4149 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4150 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4152 if((pTIHeader->typeflags1 & 7) != 2)
4153 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4154 if(pTIHeader->typeflags3 != 2)
4155 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4157 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4158 debugstr_w((*ppTypeInfoImpl)->Name),
4159 typekind_desc[pTIHeader->typekind],
4160 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4161 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4163 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4165 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4167 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4168 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4169 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4171 switch(pTIHeader->typekind) {
4172 case TKIND_ENUM:
4173 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4174 pTIHeader, pTITail);
4175 break;
4177 case TKIND_RECORD:
4178 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4179 pTIHeader, pTITail);
4180 break;
4182 case TKIND_INTERFACE:
4183 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4184 pTIHeader, pTITail);
4185 break;
4187 case TKIND_COCLASS:
4188 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4189 pTIHeader, pTITail);
4190 break;
4192 case TKIND_ALIAS:
4193 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4194 pTIHeader, pTITail);
4195 break;
4197 case TKIND_DISPATCH:
4198 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4199 pTIHeader, pTITail);
4200 break;
4202 case TKIND_MODULE:
4203 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4204 pTIHeader, pTITail);
4205 break;
4207 default:
4208 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4209 break;
4213 /* could get cFuncs, cVars and cImplTypes from here
4214 but we've already set those */
4215 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4216 X(06);
4217 X(16);
4218 X(18);
4219 X(1a);
4220 X(1e);
4221 X(24);
4222 X(26);
4223 X(2a);
4224 X(2c);
4225 X(2e);
4226 X(30);
4227 X(32);
4228 X(34);
4229 #undef X
4230 ++ppTypeInfoImpl;
4231 pBlk = (char*)pBlk + pBlkEntry[order].len;
4234 if(i != pTypeLibImpl->TypeInfoCount) {
4235 FIXME("Somehow processed %d TypeInfos\n", i);
4236 heap_free(pOtherTypeInfoBlks);
4237 return NULL;
4240 heap_free(pOtherTypeInfoBlks);
4241 return &pTypeLibImpl->ITypeLib2_iface;
4244 static HRESULT WINAPI ITypeLib2_fnQueryInterface(ITypeLib2 *iface, REFIID riid, void **ppv)
4246 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4248 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4250 if(IsEqualIID(riid, &IID_IUnknown) ||
4251 IsEqualIID(riid,&IID_ITypeLib)||
4252 IsEqualIID(riid,&IID_ITypeLib2))
4254 *ppv = &This->ITypeLib2_iface;
4256 else
4258 *ppv = NULL;
4259 TRACE("-- Interface: E_NOINTERFACE\n");
4260 return E_NOINTERFACE;
4263 IUnknown_AddRef((IUnknown*)*ppv);
4264 return S_OK;
4267 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4269 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4270 ULONG ref = InterlockedIncrement(&This->ref);
4272 TRACE("(%p) ref=%u\n", This, ref);
4274 return ref;
4277 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4279 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4280 ULONG ref = InterlockedDecrement(&This->ref);
4282 TRACE("(%p) ref=%u\n",This, ref);
4284 if (!ref)
4286 TLBImpLib *pImpLib, *pImpLibNext;
4287 TLBRefType *ref_type;
4288 void *cursor2;
4289 int i;
4291 /* remove cache entry */
4292 if(This->path)
4294 TRACE("removing from cache list\n");
4295 EnterCriticalSection(&cache_section);
4296 if(This->entry.next)
4297 list_remove(&This->entry);
4298 LeaveCriticalSection(&cache_section);
4299 heap_free(This->path);
4301 TRACE(" destroying ITypeLib(%p)\n",This);
4303 SysFreeString(This->Name);
4304 This->Name = NULL;
4306 SysFreeString(This->DocString);
4307 This->DocString = NULL;
4309 SysFreeString(This->HelpFile);
4310 This->HelpFile = NULL;
4312 SysFreeString(This->HelpStringDll);
4313 This->HelpStringDll = NULL;
4315 TLB_FreeCustData(&This->custdata_list);
4317 for (i = 0; i < This->ctTypeDesc; i++)
4318 if (This->pTypeDesc[i].vt == VT_CARRAY)
4319 heap_free(This->pTypeDesc[i].u.lpadesc);
4321 heap_free(This->pTypeDesc);
4323 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4325 if (pImpLib->pImpTypeLib)
4326 ITypeLib2_Release(&pImpLib->pImpTypeLib->ITypeLib2_iface);
4327 SysFreeString(pImpLib->name);
4329 list_remove(&pImpLib->entry);
4330 heap_free(pImpLib);
4333 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4335 list_remove(&ref_type->entry);
4336 heap_free(ref_type);
4339 for (i = 0; i < This->TypeInfoCount; ++i)
4340 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4341 heap_free(This->typeinfos);
4342 heap_free(This);
4343 return 0;
4346 return ref;
4349 /* ITypeLib::GetTypeInfoCount
4351 * Returns the number of type descriptions in the type library
4353 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4355 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4356 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4357 return This->TypeInfoCount;
4360 /* ITypeLib::GetTypeInfo
4362 * retrieves the specified type description in the library.
4364 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4365 ITypeLib2 *iface,
4366 UINT index,
4367 ITypeInfo **ppTInfo)
4369 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4371 TRACE("%p %u %p\n", This, index, ppTInfo);
4373 if(!ppTInfo)
4374 return E_INVALIDARG;
4376 if(index >= This->TypeInfoCount)
4377 return TYPE_E_ELEMENTNOTFOUND;
4379 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4380 ITypeInfo_AddRef(*ppTInfo);
4382 return S_OK;
4386 /* ITypeLibs::GetTypeInfoType
4388 * Retrieves the type of a type description.
4390 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4391 ITypeLib2 *iface,
4392 UINT index,
4393 TYPEKIND *pTKind)
4395 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4397 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4399 if(!pTKind)
4400 return E_INVALIDARG;
4402 if(index >= This->TypeInfoCount)
4403 return TYPE_E_ELEMENTNOTFOUND;
4405 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4407 return S_OK;
4410 /* ITypeLib::GetTypeInfoOfGuid
4412 * Retrieves the type description that corresponds to the specified GUID.
4415 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4416 ITypeLib2 *iface,
4417 REFGUID guid,
4418 ITypeInfo **ppTInfo)
4420 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4421 int i;
4423 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4425 for(i = 0; i < This->TypeInfoCount; ++i){
4426 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4427 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4428 ITypeInfo_AddRef(*ppTInfo);
4429 return S_OK;
4433 return TYPE_E_ELEMENTNOTFOUND;
4436 /* ITypeLib::GetLibAttr
4438 * Retrieves the structure that contains the library's attributes.
4441 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4442 ITypeLib2 *iface,
4443 LPTLIBATTR *attr)
4445 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4447 TRACE("(%p, %p)\n", This, attr);
4449 if (!attr) return E_INVALIDARG;
4451 *attr = heap_alloc(sizeof(**attr));
4452 if (!*attr) return E_OUTOFMEMORY;
4454 **attr = This->LibAttr;
4455 return S_OK;
4458 /* ITypeLib::GetTypeComp
4460 * Enables a client compiler to bind to a library's types, variables,
4461 * constants, and global functions.
4464 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4465 ITypeLib2 *iface,
4466 ITypeComp **ppTComp)
4468 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4470 TRACE("(%p)->(%p)\n",This,ppTComp);
4471 *ppTComp = &This->ITypeComp_iface;
4472 ITypeComp_AddRef(*ppTComp);
4474 return S_OK;
4477 /* ITypeLib::GetDocumentation
4479 * Retrieves the library's documentation string, the complete Help file name
4480 * and path, and the context identifier for the library Help topic in the Help
4481 * file.
4483 * On a successful return all non-null BSTR pointers will have been set,
4484 * possibly to NULL.
4486 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4487 ITypeLib2 *iface,
4488 INT index,
4489 BSTR *pBstrName,
4490 BSTR *pBstrDocString,
4491 DWORD *pdwHelpContext,
4492 BSTR *pBstrHelpFile)
4494 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4495 HRESULT result = E_INVALIDARG;
4496 ITypeInfo *pTInfo;
4498 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4499 This, index,
4500 pBstrName, pBstrDocString,
4501 pdwHelpContext, pBstrHelpFile);
4503 if(index<0)
4505 /* documentation for the typelib */
4506 if(pBstrName)
4508 if (This->Name)
4510 if(!(*pBstrName = SysAllocString(This->Name)))
4511 goto memerr1;
4513 else
4514 *pBstrName = NULL;
4516 if(pBstrDocString)
4518 if (This->DocString)
4520 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4521 goto memerr2;
4523 else if (This->Name)
4525 if(!(*pBstrDocString = SysAllocString(This->Name)))
4526 goto memerr2;
4528 else
4529 *pBstrDocString = NULL;
4531 if(pdwHelpContext)
4533 *pdwHelpContext = This->dwHelpContext;
4535 if(pBstrHelpFile)
4537 if (This->HelpFile)
4539 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4540 goto memerr3;
4542 else
4543 *pBstrHelpFile = NULL;
4546 result = S_OK;
4548 else
4550 /* for a typeinfo */
4551 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4553 if(SUCCEEDED(result))
4555 result = ITypeInfo_GetDocumentation(pTInfo,
4556 MEMBERID_NIL,
4557 pBstrName,
4558 pBstrDocString,
4559 pdwHelpContext, pBstrHelpFile);
4561 ITypeInfo_Release(pTInfo);
4564 return result;
4565 memerr3:
4566 if (pBstrDocString) SysFreeString (*pBstrDocString);
4567 memerr2:
4568 if (pBstrName) SysFreeString (*pBstrName);
4569 memerr1:
4570 return STG_E_INSUFFICIENTMEMORY;
4573 /* ITypeLib::IsName
4575 * Indicates whether a passed-in string contains the name of a type or member
4576 * described in the library.
4579 static HRESULT WINAPI ITypeLib2_fnIsName(
4580 ITypeLib2 *iface,
4581 LPOLESTR szNameBuf,
4582 ULONG lHashVal,
4583 BOOL *pfName)
4585 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4586 int tic;
4587 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), fdc, vrc;
4589 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4590 pfName);
4592 *pfName=TRUE;
4593 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4594 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4595 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4596 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4597 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4598 int pc;
4600 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4601 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++)
4602 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name, nNameBufLen))
4603 goto ITypeLib2_fnIsName_exit;
4605 for(vrc = 0; vrc < pTInfo->TypeAttr.cVars; ++vrc){
4606 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4607 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4611 *pfName=FALSE;
4613 ITypeLib2_fnIsName_exit:
4614 TRACE("(%p)slow! search for %s: %s found!\n", This,
4615 debugstr_w(szNameBuf), *pfName?"NOT":"");
4617 return S_OK;
4620 /* ITypeLib::FindName
4622 * Finds occurrences of a type description in a type library. This may be used
4623 * to quickly verify that a name exists in a type library.
4626 static HRESULT WINAPI ITypeLib2_fnFindName(
4627 ITypeLib2 *iface,
4628 LPOLESTR name,
4629 ULONG hash,
4630 ITypeInfo **ppTInfo,
4631 MEMBERID *memid,
4632 UINT16 *found)
4634 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4635 int tic;
4636 UINT count = 0;
4637 UINT len;
4639 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4641 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4642 return E_INVALIDARG;
4644 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4645 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4646 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4647 TLBVarDesc *var;
4648 UINT fdc;
4650 if(!memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4651 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4652 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4653 int pc;
4655 if(!memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4656 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4657 if(!memcmp(name, func->pParamDesc[pc].Name, len))
4658 goto ITypeLib2_fnFindName_exit;
4662 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->TypeAttr.cVars, name);
4663 if (var)
4664 goto ITypeLib2_fnFindName_exit;
4666 continue;
4667 ITypeLib2_fnFindName_exit:
4668 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4669 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4670 count++;
4672 TRACE("found %d typeinfos\n", count);
4674 *found = count;
4676 return S_OK;
4679 /* ITypeLib::ReleaseTLibAttr
4681 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4684 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4685 ITypeLib2 *iface,
4686 TLIBATTR *pTLibAttr)
4688 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4689 TRACE("(%p)->(%p)\n", This, pTLibAttr);
4690 heap_free(pTLibAttr);
4693 /* ITypeLib2::GetCustData
4695 * gets the custom data
4697 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4698 ITypeLib2 * iface,
4699 REFGUID guid,
4700 VARIANT *pVarVal)
4702 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4703 TLBCustData *pCData;
4705 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(guid), pVarVal);
4707 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
4708 if(!pCData)
4709 return TYPE_E_ELEMENTNOTFOUND;
4711 VariantInit(pVarVal);
4712 VariantCopy(pVarVal, &pCData->data);
4714 return S_OK;
4717 /* ITypeLib2::GetLibStatistics
4719 * Returns statistics about a type library that are required for efficient
4720 * sizing of hash tables.
4723 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4724 ITypeLib2 * iface,
4725 ULONG *pcUniqueNames,
4726 ULONG *pcchUniqueNames)
4728 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4730 FIXME("(%p): stub!\n", This);
4732 if(pcUniqueNames) *pcUniqueNames=1;
4733 if(pcchUniqueNames) *pcchUniqueNames=1;
4734 return S_OK;
4737 /* ITypeLib2::GetDocumentation2
4739 * Retrieves the library's documentation string, the complete Help file name
4740 * and path, the localization context to use, and the context ID for the
4741 * library Help topic in the Help file.
4744 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4745 ITypeLib2 * iface,
4746 INT index,
4747 LCID lcid,
4748 BSTR *pbstrHelpString,
4749 DWORD *pdwHelpStringContext,
4750 BSTR *pbstrHelpStringDll)
4752 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4753 HRESULT result;
4754 ITypeInfo *pTInfo;
4756 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4758 /* the help string should be obtained from the helpstringdll,
4759 * using the _DLLGetDocumentation function, based on the supplied
4760 * lcid. Nice to do sometime...
4762 if(index<0)
4764 /* documentation for the typelib */
4765 if(pbstrHelpString)
4766 *pbstrHelpString=SysAllocString(This->DocString);
4767 if(pdwHelpStringContext)
4768 *pdwHelpStringContext=This->dwHelpContext;
4769 if(pbstrHelpStringDll)
4770 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4772 result = S_OK;
4774 else
4776 /* for a typeinfo */
4777 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4779 if(SUCCEEDED(result))
4781 ITypeInfo2 * pTInfo2;
4782 result = ITypeInfo_QueryInterface(pTInfo,
4783 &IID_ITypeInfo2,
4784 (LPVOID*) &pTInfo2);
4786 if(SUCCEEDED(result))
4788 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4789 MEMBERID_NIL,
4790 lcid,
4791 pbstrHelpString,
4792 pdwHelpStringContext,
4793 pbstrHelpStringDll);
4795 ITypeInfo2_Release(pTInfo2);
4798 ITypeInfo_Release(pTInfo);
4801 return result;
4804 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
4806 TLBCustData *pCData;
4807 unsigned int ct;
4808 CUSTDATAITEM *cdi;
4810 ct = list_count(custdata_list);
4812 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
4813 if(!pCustData->prgCustData)
4814 return E_OUTOFMEMORY;
4816 pCustData->cCustData = ct;
4818 cdi = pCustData->prgCustData;
4819 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
4820 cdi->guid = pCData->guid;
4821 VariantCopy(&cdi->varValue, &pCData->data);
4822 ++cdi;
4825 return S_OK;
4829 /* ITypeLib2::GetAllCustData
4831 * Gets all custom data items for the library.
4834 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4835 ITypeLib2 * iface,
4836 CUSTDATA *pCustData)
4838 ITypeLibImpl *This = impl_from_ITypeLib2(iface);
4839 TRACE("(%p)->(%p)\n", This, pCustData);
4840 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
4843 static const ITypeLib2Vtbl tlbvt = {
4844 ITypeLib2_fnQueryInterface,
4845 ITypeLib2_fnAddRef,
4846 ITypeLib2_fnRelease,
4847 ITypeLib2_fnGetTypeInfoCount,
4848 ITypeLib2_fnGetTypeInfo,
4849 ITypeLib2_fnGetTypeInfoType,
4850 ITypeLib2_fnGetTypeInfoOfGuid,
4851 ITypeLib2_fnGetLibAttr,
4852 ITypeLib2_fnGetTypeComp,
4853 ITypeLib2_fnGetDocumentation,
4854 ITypeLib2_fnIsName,
4855 ITypeLib2_fnFindName,
4856 ITypeLib2_fnReleaseTLibAttr,
4858 ITypeLib2_fnGetCustData,
4859 ITypeLib2_fnGetLibStatistics,
4860 ITypeLib2_fnGetDocumentation2,
4861 ITypeLib2_fnGetAllCustData
4865 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4867 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4869 return ITypeLib2_QueryInterface(&This->ITypeLib2_iface, riid, ppv);
4872 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4874 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4876 return ITypeLib2_AddRef(&This->ITypeLib2_iface);
4879 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4881 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4883 return ITypeLib2_Release(&This->ITypeLib2_iface);
4886 static HRESULT WINAPI ITypeLibComp_fnBind(
4887 ITypeComp * iface,
4888 OLECHAR * szName,
4889 ULONG lHash,
4890 WORD wFlags,
4891 ITypeInfo ** ppTInfo,
4892 DESCKIND * pDescKind,
4893 BINDPTR * pBindPtr)
4895 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4896 int typemismatch=0, i;
4898 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4900 *pDescKind = DESCKIND_NONE;
4901 pBindPtr->lptcomp = NULL;
4902 *ppTInfo = NULL;
4904 for(i = 0; i < This->TypeInfoCount; ++i){
4905 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4906 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4908 /* FIXME: check wFlags here? */
4909 /* FIXME: we should use a hash table to look this info up using lHash
4910 * instead of an O(n) search */
4911 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4912 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4914 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4916 *pDescKind = DESCKIND_TYPECOMP;
4917 pBindPtr->lptcomp = &pTypeInfo->ITypeComp_iface;
4918 ITypeComp_AddRef(pBindPtr->lptcomp);
4919 TRACE("module or enum: %s\n", debugstr_w(szName));
4920 return S_OK;
4924 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4925 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4927 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
4928 HRESULT hr;
4930 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4931 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4933 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4934 return S_OK;
4936 else if (hr == TYPE_E_TYPEMISMATCH)
4937 typemismatch = 1;
4940 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4941 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4943 ITypeComp *pSubTypeComp = &pTypeInfo->ITypeComp_iface;
4944 HRESULT hr;
4945 ITypeInfo *subtypeinfo;
4946 BINDPTR subbindptr;
4947 DESCKIND subdesckind;
4949 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4950 &subtypeinfo, &subdesckind, &subbindptr);
4951 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4953 TYPEDESC tdesc_appobject;
4954 const VARDESC vardesc_appobject =
4956 -2, /* memid */
4957 NULL, /* lpstrSchema */
4959 0 /* oInst */
4962 /* ELEMDESC */
4964 /* TYPEDESC */
4966 &tdesc_appobject
4968 VT_PTR
4971 0, /* wVarFlags */
4972 VAR_STATIC /* varkind */
4975 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4976 tdesc_appobject.vt = VT_USERDEFINED;
4978 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4980 /* cleanup things filled in by Bind call so we can put our
4981 * application object data in there instead */
4982 switch (subdesckind)
4984 case DESCKIND_FUNCDESC:
4985 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4986 break;
4987 case DESCKIND_VARDESC:
4988 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4989 break;
4990 default:
4991 break;
4993 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4995 if (pTypeInfo->hreftype == -1)
4996 FIXME("no hreftype for interface %p\n", pTypeInfo);
4998 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4999 if (FAILED(hr))
5000 return hr;
5002 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
5003 *ppTInfo = (ITypeInfo *)pTypeInfo;
5004 ITypeInfo_AddRef(*ppTInfo);
5005 return S_OK;
5007 else if (hr == TYPE_E_TYPEMISMATCH)
5008 typemismatch = 1;
5012 if (typemismatch)
5014 TRACE("type mismatch %s\n", debugstr_w(szName));
5015 return TYPE_E_TYPEMISMATCH;
5017 else
5019 TRACE("name not found %s\n", debugstr_w(szName));
5020 return S_OK;
5024 static HRESULT WINAPI ITypeLibComp_fnBindType(
5025 ITypeComp * iface,
5026 OLECHAR * szName,
5027 ULONG lHash,
5028 ITypeInfo ** ppTInfo,
5029 ITypeComp ** ppTComp)
5031 ITypeLibImpl *This = impl_from_ITypeComp(iface);
5032 int i;
5034 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5036 if(!szName || !ppTInfo || !ppTComp)
5037 return E_INVALIDARG;
5039 for(i = 0; i < This->TypeInfoCount; ++i)
5041 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5042 /* FIXME: should use lHash to do the search */
5043 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
5045 TRACE("returning %p\n", pTypeInfo);
5046 *ppTInfo = (ITypeInfo *)&pTypeInfo->ITypeInfo2_iface;
5047 ITypeInfo_AddRef(*ppTInfo);
5048 *ppTComp = &pTypeInfo->ITypeComp_iface;
5049 ITypeComp_AddRef(*ppTComp);
5050 return S_OK;
5054 TRACE("not found\n");
5055 *ppTInfo = NULL;
5056 *ppTComp = NULL;
5057 return S_OK;
5060 static const ITypeCompVtbl tlbtcvt =
5063 ITypeLibComp_fnQueryInterface,
5064 ITypeLibComp_fnAddRef,
5065 ITypeLibComp_fnRelease,
5067 ITypeLibComp_fnBind,
5068 ITypeLibComp_fnBindType
5071 /*================== ITypeInfo(2) Methods ===================================*/
5072 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5074 ITypeInfoImpl *pTypeInfoImpl;
5076 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5077 if (pTypeInfoImpl)
5079 pTypeInfoImpl->ITypeInfo2_iface.lpVtbl = &tinfvt;
5080 pTypeInfoImpl->ITypeComp_iface.lpVtbl = &tcompvt;
5081 pTypeInfoImpl->ref = 0;
5082 pTypeInfoImpl->hreftype = -1;
5083 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
5084 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
5085 list_init(&pTypeInfoImpl->custdata_list);
5087 TRACE("(%p)\n", pTypeInfoImpl);
5088 return pTypeInfoImpl;
5091 /* ITypeInfo::QueryInterface
5093 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5094 ITypeInfo2 *iface,
5095 REFIID riid,
5096 VOID **ppvObject)
5098 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5100 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5102 *ppvObject=NULL;
5103 if(IsEqualIID(riid, &IID_IUnknown) ||
5104 IsEqualIID(riid,&IID_ITypeInfo)||
5105 IsEqualIID(riid,&IID_ITypeInfo2))
5106 *ppvObject = This;
5108 if(*ppvObject){
5109 ITypeInfo2_AddRef(iface);
5110 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5111 return S_OK;
5113 TRACE("-- Interface: E_NOINTERFACE\n");
5114 return E_NOINTERFACE;
5117 /* ITypeInfo::AddRef
5119 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5121 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5122 ULONG ref = InterlockedIncrement(&This->ref);
5124 TRACE("(%p)->ref is %u\n",This, ref);
5126 if (ref == 1 /* incremented from 0 */)
5127 ITypeLib2_AddRef(&This->pTypeLib->ITypeLib2_iface);
5129 return ref;
5132 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5134 UINT i;
5136 TRACE("destroying ITypeInfo(%p)\n",This);
5138 SysFreeString(This->Name);
5139 This->Name = NULL;
5141 SysFreeString(This->DocString);
5142 This->DocString = NULL;
5144 SysFreeString(This->DllName);
5145 This->DllName = NULL;
5147 for (i = 0; i < This->TypeAttr.cFuncs; ++i)
5149 int j;
5150 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5151 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5153 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5154 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5156 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5157 heap_free(elemdesc->u.paramdesc.pparamdescex);
5159 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5160 SysFreeString(pFInfo->pParamDesc[j].Name);
5162 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5163 heap_free(pFInfo->pParamDesc);
5164 TLB_FreeCustData(&pFInfo->custdata_list);
5165 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5166 SysFreeString(pFInfo->Entry);
5167 SysFreeString(pFInfo->HelpString);
5168 SysFreeString(pFInfo->Name);
5170 heap_free(This->funcdescs);
5172 for(i = 0; i < This->TypeAttr.cVars; ++i)
5174 TLBVarDesc *pVInfo = &This->vardescs[i];
5175 if (pVInfo->vardesc.varkind == VAR_CONST)
5177 VariantClear(pVInfo->vardesc.u.lpvarValue);
5178 heap_free(pVInfo->vardesc.u.lpvarValue);
5180 TLB_FreeCustData(&pVInfo->custdata_list);
5181 SysFreeString(pVInfo->Name);
5182 SysFreeString(pVInfo->HelpString);
5184 heap_free(This->vardescs);
5186 if(This->impltypes){
5187 for (i = 0; i < This->TypeAttr.cImplTypes; ++i){
5188 TLBImplType *pImpl = &This->impltypes[i];
5189 TLB_FreeCustData(&pImpl->custdata_list);
5191 heap_free(This->impltypes);
5194 TLB_FreeCustData(&This->custdata_list);
5196 heap_free(This);
5199 /* ITypeInfo::Release
5201 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5203 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5204 ULONG ref = InterlockedDecrement(&This->ref);
5206 TRACE("(%p)->(%u)\n",This, ref);
5208 if (!ref)
5210 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5211 ITypeLib2_Release(&This->pTypeLib->ITypeLib2_iface);
5212 if (not_attached_to_typelib)
5213 heap_free(This);
5214 /* otherwise This will be freed when typelib is freed */
5217 return ref;
5220 /* ITypeInfo::GetTypeAttr
5222 * Retrieves a TYPEATTR structure that contains the attributes of the type
5223 * description.
5226 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5227 LPTYPEATTR *ppTypeAttr)
5229 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5230 SIZE_T size;
5232 TRACE("(%p)\n",This);
5234 size = sizeof(**ppTypeAttr);
5235 if (This->TypeAttr.typekind == TKIND_ALIAS)
5236 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5238 *ppTypeAttr = heap_alloc(size);
5239 if (!*ppTypeAttr)
5240 return E_OUTOFMEMORY;
5242 **ppTypeAttr = This->TypeAttr;
5244 if (This->TypeAttr.typekind == TKIND_ALIAS)
5245 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5246 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5248 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5249 /* This should include all the inherited funcs */
5250 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5251 /* This is always the size of IDispatch's vtbl */
5252 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5253 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5255 return S_OK;
5258 /* ITypeInfo::GetTypeComp
5260 * Retrieves the ITypeComp interface for the type description, which enables a
5261 * client compiler to bind to the type description's members.
5264 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5265 ITypeComp * *ppTComp)
5267 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5269 TRACE("(%p)->(%p)\n", This, ppTComp);
5271 *ppTComp = &This->ITypeComp_iface;
5272 ITypeComp_AddRef(*ppTComp);
5273 return S_OK;
5276 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5278 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5279 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5280 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5281 return size;
5284 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5286 *dest = *src;
5287 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5288 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5290 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5291 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5292 *buffer += sizeof(PARAMDESCEX);
5293 *pparamdescex_dest = *pparamdescex_src;
5294 VariantInit(&pparamdescex_dest->varDefaultValue);
5295 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5296 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5298 else
5299 dest->u.paramdesc.pparamdescex = NULL;
5300 return S_OK;
5303 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5305 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5306 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5309 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5311 FUNCDESC *dest;
5312 char *buffer;
5313 SIZE_T size = sizeof(*src);
5314 SHORT i;
5315 HRESULT hr;
5317 size += sizeof(*src->lprgscode) * src->cScodes;
5318 size += TLB_SizeElemDesc(&src->elemdescFunc);
5319 for (i = 0; i < src->cParams; i++)
5321 size += sizeof(ELEMDESC);
5322 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5325 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5326 if (!dest) return E_OUTOFMEMORY;
5328 *dest = *src;
5329 if (dispinterface) /* overwrite funckind */
5330 dest->funckind = FUNC_DISPATCH;
5331 buffer = (char *)(dest + 1);
5333 dest->lprgscode = (SCODE *)buffer;
5334 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5335 buffer += sizeof(*src->lprgscode) * src->cScodes;
5337 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5338 if (FAILED(hr))
5340 SysFreeString((BSTR)dest);
5341 return hr;
5344 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5345 buffer += sizeof(ELEMDESC) * src->cParams;
5346 for (i = 0; i < src->cParams; i++)
5348 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5349 if (FAILED(hr))
5350 break;
5352 if (FAILED(hr))
5354 /* undo the above actions */
5355 for (i = i - 1; i >= 0; i--)
5356 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5357 TLB_FreeElemDesc(&dest->elemdescFunc);
5358 SysFreeString((BSTR)dest);
5359 return hr;
5362 /* special treatment for dispinterfaces: this makes functions appear
5363 * to return their [retval] value when it is really returning an
5364 * HRESULT */
5365 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5367 if (dest->cParams &&
5368 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5370 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5371 if (elemdesc->tdesc.vt != VT_PTR)
5373 ERR("elemdesc should have started with VT_PTR instead of:\n");
5374 if (ERR_ON(ole))
5375 dump_ELEMDESC(elemdesc);
5376 return E_UNEXPECTED;
5379 /* copy last parameter to the return value. we are using a flat
5380 * buffer so there is no danger of leaking memory in
5381 * elemdescFunc */
5382 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5384 /* remove the last parameter */
5385 dest->cParams--;
5387 else
5388 /* otherwise this function is made to appear to have no return
5389 * value */
5390 dest->elemdescFunc.tdesc.vt = VT_VOID;
5394 *dest_ptr = dest;
5395 return S_OK;
5398 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5400 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5402 if (index >= This->TypeAttr.cFuncs)
5403 return TYPE_E_ELEMENTNOTFOUND;
5405 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5406 return S_OK;
5409 /* internal function to make the inherited interfaces' methods appear
5410 * part of the interface */
5411 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5412 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5414 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
5415 HRESULT hr;
5416 UINT implemented_funcs = 0;
5418 if (funcs)
5419 *funcs = 0;
5420 else
5421 *hrefoffset = DISPATCH_HREF_OFFSET;
5423 if(This->impltypes)
5425 ITypeInfo *pSubTypeInfo;
5426 UINT sub_funcs;
5428 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5429 if (FAILED(hr))
5430 return hr;
5432 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5433 index,
5434 ppFuncDesc,
5435 &sub_funcs, hrefoffset);
5436 implemented_funcs += sub_funcs;
5437 ITypeInfo_Release(pSubTypeInfo);
5438 if (SUCCEEDED(hr))
5439 return hr;
5440 *hrefoffset += DISPATCH_HREF_OFFSET;
5443 if (funcs)
5444 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5445 else
5446 *hrefoffset = 0;
5448 if (index < implemented_funcs)
5449 return E_INVALIDARG;
5450 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5451 ppFuncDesc);
5454 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5456 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5457 while (TRUE)
5459 switch (pTypeDesc->vt)
5461 case VT_USERDEFINED:
5462 pTypeDesc->u.hreftype += hrefoffset;
5463 return;
5464 case VT_PTR:
5465 case VT_SAFEARRAY:
5466 pTypeDesc = pTypeDesc->u.lptdesc;
5467 break;
5468 case VT_CARRAY:
5469 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5470 break;
5471 default:
5472 return;
5477 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5479 SHORT i;
5480 for (i = 0; i < pFuncDesc->cParams; i++)
5481 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5482 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5485 /* ITypeInfo::GetFuncDesc
5487 * Retrieves the FUNCDESC structure that contains information about a
5488 * specified function.
5491 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5492 LPFUNCDESC *ppFuncDesc)
5494 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5495 const FUNCDESC *internal_funcdesc;
5496 HRESULT hr;
5497 UINT hrefoffset = 0;
5499 TRACE("(%p) index %d\n", This, index);
5501 if (!ppFuncDesc)
5502 return E_INVALIDARG;
5504 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5505 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5506 &internal_funcdesc, NULL,
5507 &hrefoffset);
5508 else
5509 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5510 &internal_funcdesc);
5511 if (FAILED(hr))
5513 WARN("description for function %d not found\n", index);
5514 return hr;
5517 hr = TLB_AllocAndInitFuncDesc(
5518 internal_funcdesc,
5519 ppFuncDesc,
5520 This->TypeAttr.typekind == TKIND_DISPATCH);
5522 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5523 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5525 TRACE("-- 0x%08x\n", hr);
5526 return hr;
5529 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5531 VARDESC *dest;
5532 char *buffer;
5533 SIZE_T size = sizeof(*src);
5534 HRESULT hr;
5536 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5537 if (src->varkind == VAR_CONST)
5538 size += sizeof(VARIANT);
5539 size += TLB_SizeElemDesc(&src->elemdescVar);
5541 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5542 if (!dest) return E_OUTOFMEMORY;
5544 *dest = *src;
5545 buffer = (char *)(dest + 1);
5546 if (src->lpstrSchema)
5548 int len;
5549 dest->lpstrSchema = (LPOLESTR)buffer;
5550 len = strlenW(src->lpstrSchema);
5551 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5552 buffer += (len + 1) * sizeof(WCHAR);
5555 if (src->varkind == VAR_CONST)
5557 HRESULT hr;
5559 dest->u.lpvarValue = (VARIANT *)buffer;
5560 *dest->u.lpvarValue = *src->u.lpvarValue;
5561 buffer += sizeof(VARIANT);
5562 VariantInit(dest->u.lpvarValue);
5563 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5564 if (FAILED(hr))
5566 SysFreeString((BSTR)dest);
5567 return hr;
5570 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5571 if (FAILED(hr))
5573 if (src->varkind == VAR_CONST)
5574 VariantClear(dest->u.lpvarValue);
5575 SysFreeString((BSTR)dest);
5576 return hr;
5578 *dest_ptr = dest;
5579 return S_OK;
5582 /* ITypeInfo::GetVarDesc
5584 * Retrieves a VARDESC structure that describes the specified variable.
5587 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5588 LPVARDESC *ppVarDesc)
5590 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5591 const TLBVarDesc *pVDesc = &This->vardescs[index];
5593 TRACE("(%p) index %d\n", This, index);
5595 if(index >= This->TypeAttr.cVars)
5596 return TYPE_E_ELEMENTNOTFOUND;
5598 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5601 /* ITypeInfo_GetNames
5603 * Retrieves the variable with the specified member ID (or the name of the
5604 * property or method and its parameters) that correspond to the specified
5605 * function ID.
5607 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5608 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5610 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5611 const TLBFuncDesc *pFDesc;
5612 const TLBVarDesc *pVDesc;
5613 int i;
5614 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5615 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5616 if(pFDesc)
5618 /* function found, now return function and parameter names */
5619 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5621 if(!i)
5622 *rgBstrNames=SysAllocString(pFDesc->Name);
5623 else
5624 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5626 *pcNames=i;
5628 else
5630 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
5631 if(pVDesc)
5633 *rgBstrNames=SysAllocString(pVDesc->Name);
5634 *pcNames=1;
5636 else
5638 if(This->impltypes &&
5639 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5640 /* recursive search */
5641 ITypeInfo *pTInfo;
5642 HRESULT result;
5643 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5644 if(SUCCEEDED(result))
5646 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5647 ITypeInfo_Release(pTInfo);
5648 return result;
5650 WARN("Could not search inherited interface!\n");
5652 else
5654 WARN("no names found\n");
5656 *pcNames=0;
5657 return TYPE_E_ELEMENTNOTFOUND;
5660 return S_OK;
5664 /* ITypeInfo::GetRefTypeOfImplType
5666 * If a type description describes a COM class, it retrieves the type
5667 * description of the implemented interface types. For an interface,
5668 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5669 * if any exist.
5672 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5673 ITypeInfo2 *iface,
5674 UINT index,
5675 HREFTYPE *pRefType)
5677 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5678 HRESULT hr = S_OK;
5680 TRACE("(%p) index %d\n", This, index);
5681 if (TRACE_ON(ole)) dump_TypeInfo(This);
5683 if(index==(UINT)-1)
5685 /* only valid on dual interfaces;
5686 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5688 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5690 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5692 *pRefType = -1;
5694 else
5696 hr = TYPE_E_ELEMENTNOTFOUND;
5699 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5701 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5702 *pRefType = This->pTypeLib->dispatch_href;
5704 else
5706 if(index >= This->TypeAttr.cImplTypes)
5707 hr = TYPE_E_ELEMENTNOTFOUND;
5708 else
5709 *pRefType = This->impltypes[index].hRef;
5712 if(TRACE_ON(ole))
5714 if(SUCCEEDED(hr))
5715 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5716 else
5717 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5720 return hr;
5723 /* ITypeInfo::GetImplTypeFlags
5725 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5726 * or base interface in a type description.
5728 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5729 UINT index, INT *pImplTypeFlags)
5731 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5733 TRACE("(%p) index %d\n", This, index);
5735 if(!pImplTypeFlags)
5736 return E_INVALIDARG;
5738 if(This->TypeAttr.typekind == TKIND_DISPATCH && index == 0){
5739 *pImplTypeFlags = 0;
5740 return S_OK;
5743 if(index >= This->TypeAttr.cImplTypes)
5744 return TYPE_E_ELEMENTNOTFOUND;
5746 *pImplTypeFlags = This->impltypes[index].implflags;
5748 return S_OK;
5751 /* GetIDsOfNames
5752 * Maps between member names and member IDs, and parameter names and
5753 * parameter IDs.
5755 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5756 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5758 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
5759 const TLBVarDesc *pVDesc;
5760 HRESULT ret=S_OK;
5761 UINT i, fdc;
5763 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5764 cNames);
5766 /* init out parameters in case of failure */
5767 for (i = 0; i < cNames; i++)
5768 pMemId[i] = MEMBERID_NIL;
5770 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
5771 int j;
5772 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
5773 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5774 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5775 for(i=1; i < cNames; i++){
5776 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5777 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5778 break;
5779 if( j<pFDesc->funcdesc.cParams)
5780 pMemId[i]=j;
5781 else
5782 ret=DISP_E_UNKNOWNNAME;
5784 TRACE("-- 0x%08x\n", ret);
5785 return ret;
5788 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, *rgszNames);
5789 if(pVDesc){
5790 if(cNames)
5791 *pMemId = pVDesc->vardesc.memid;
5792 return ret;
5794 /* not found, see if it can be found in an inherited interface */
5795 if(This->impltypes) {
5796 /* recursive search */
5797 ITypeInfo *pTInfo;
5798 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5799 if(SUCCEEDED(ret)){
5800 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5801 ITypeInfo_Release(pTInfo);
5802 return ret;
5804 WARN("Could not search inherited interface!\n");
5805 } else
5806 WARN("no names found\n");
5807 return DISP_E_UNKNOWNNAME;
5811 #ifdef __i386__
5813 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5814 __ASM_GLOBAL_FUNC( call_method,
5815 "pushl %ebp\n\t"
5816 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5817 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5818 "movl %esp,%ebp\n\t"
5819 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5820 "pushl %esi\n\t"
5821 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5822 "pushl %edi\n\t"
5823 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5824 "movl 12(%ebp),%edx\n\t"
5825 "movl %esp,%edi\n\t"
5826 "shll $2,%edx\n\t"
5827 "jz 1f\n\t"
5828 "subl %edx,%edi\n\t"
5829 "andl $~15,%edi\n\t"
5830 "movl %edi,%esp\n\t"
5831 "movl 12(%ebp),%ecx\n\t"
5832 "movl 16(%ebp),%esi\n\t"
5833 "cld\n\t"
5834 "rep; movsl\n"
5835 "1:\tcall *8(%ebp)\n\t"
5836 "subl %esp,%edi\n\t"
5837 "movl 20(%ebp),%ecx\n\t"
5838 "movl %edi,(%ecx)\n\t"
5839 "leal -8(%ebp),%esp\n\t"
5840 "popl %edi\n\t"
5841 __ASM_CFI(".cfi_same_value %edi\n\t")
5842 "popl %esi\n\t"
5843 __ASM_CFI(".cfi_same_value %esi\n\t")
5844 "popl %ebp\n\t"
5845 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5846 __ASM_CFI(".cfi_same_value %ebp\n\t")
5847 "ret" )
5849 /* same function but returning floating point */
5850 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5852 /* ITypeInfo::Invoke
5854 * Invokes a method, or accesses a property of an object, that implements the
5855 * interface described by the type description.
5857 DWORD
5858 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5859 DWORD res;
5860 int stack_offset;
5862 if (TRACE_ON(ole)) {
5863 int i;
5864 TRACE("Calling %p(",func);
5865 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5866 if (nrargs > 30) TRACE("...");
5867 TRACE(")\n");
5870 switch (callconv) {
5871 case CC_STDCALL:
5872 case CC_CDECL:
5873 res = call_method( func, nrargs, args, &stack_offset );
5874 break;
5875 default:
5876 FIXME("unsupported calling convention %d\n",callconv);
5877 res = -1;
5878 break;
5880 TRACE("returns %08x\n",res);
5881 return res;
5884 #elif defined(__x86_64__)
5886 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5887 __ASM_GLOBAL_FUNC( call_method,
5888 "pushq %rbp\n\t"
5889 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5890 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5891 "movq %rsp,%rbp\n\t"
5892 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5893 "pushq %rsi\n\t"
5894 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5895 "pushq %rdi\n\t"
5896 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5897 "movq %rcx,%rax\n\t"
5898 "movq $4,%rcx\n\t"
5899 "cmp %rcx,%rdx\n\t"
5900 "cmovgq %rdx,%rcx\n\t"
5901 "leaq 0(,%rcx,8),%rdx\n\t"
5902 "subq %rdx,%rsp\n\t"
5903 "andq $~15,%rsp\n\t"
5904 "movq %rsp,%rdi\n\t"
5905 "movq %r8,%rsi\n\t"
5906 "rep; movsq\n\t"
5907 "movq 0(%rsp),%rcx\n\t"
5908 "movq 8(%rsp),%rdx\n\t"
5909 "movq 16(%rsp),%r8\n\t"
5910 "movq 24(%rsp),%r9\n\t"
5911 "movq %rcx,%xmm0\n\t"
5912 "movq %rdx,%xmm1\n\t"
5913 "movq %r8,%xmm2\n\t"
5914 "movq %r9,%xmm3\n\t"
5915 "callq *%rax\n\t"
5916 "leaq -16(%rbp),%rsp\n\t"
5917 "popq %rdi\n\t"
5918 __ASM_CFI(".cfi_same_value %rdi\n\t")
5919 "popq %rsi\n\t"
5920 __ASM_CFI(".cfi_same_value %rsi\n\t")
5921 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5922 "popq %rbp\n\t"
5923 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5924 __ASM_CFI(".cfi_same_value %rbp\n\t")
5925 "ret")
5927 /* same function but returning floating point */
5928 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5930 #endif /* __x86_64__ */
5932 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5934 HRESULT hr = S_OK;
5935 ITypeInfo *tinfo2 = NULL;
5936 TYPEATTR *tattr = NULL;
5938 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5939 if (hr)
5941 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5942 "hr = 0x%08x\n",
5943 tdesc->u.hreftype, hr);
5944 return hr;
5946 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5947 if (hr)
5949 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5950 ITypeInfo_Release(tinfo2);
5951 return hr;
5954 switch (tattr->typekind)
5956 case TKIND_ENUM:
5957 *vt |= VT_I4;
5958 break;
5960 case TKIND_ALIAS:
5961 tdesc = &tattr->tdescAlias;
5962 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5963 break;
5965 case TKIND_INTERFACE:
5966 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5967 *vt |= VT_DISPATCH;
5968 else
5969 *vt |= VT_UNKNOWN;
5970 break;
5972 case TKIND_DISPATCH:
5973 *vt |= VT_DISPATCH;
5974 break;
5976 case TKIND_COCLASS:
5977 *vt |= VT_DISPATCH;
5978 break;
5980 case TKIND_RECORD:
5981 FIXME("TKIND_RECORD unhandled.\n");
5982 hr = E_NOTIMPL;
5983 break;
5985 case TKIND_UNION:
5986 FIXME("TKIND_UNION unhandled.\n");
5987 hr = E_NOTIMPL;
5988 break;
5990 default:
5991 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5992 hr = E_NOTIMPL;
5993 break;
5995 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5996 ITypeInfo_Release(tinfo2);
5997 return hr;
6000 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
6002 HRESULT hr = S_OK;
6004 /* enforce only one level of pointer indirection */
6005 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
6007 tdesc = tdesc->u.lptdesc;
6009 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6010 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6011 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6012 if ((tdesc->vt == VT_USERDEFINED) ||
6013 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
6015 VARTYPE vt_userdefined = 0;
6016 const TYPEDESC *tdesc_userdefined = tdesc;
6017 if (tdesc->vt == VT_PTR)
6019 vt_userdefined = VT_BYREF;
6020 tdesc_userdefined = tdesc->u.lptdesc;
6022 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
6023 if ((hr == S_OK) &&
6024 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
6025 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
6027 *vt |= vt_userdefined;
6028 return S_OK;
6031 *vt = VT_BYREF;
6034 switch (tdesc->vt)
6036 case VT_HRESULT:
6037 *vt |= VT_ERROR;
6038 break;
6039 case VT_USERDEFINED:
6040 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6041 break;
6042 case VT_VOID:
6043 case VT_CARRAY:
6044 case VT_PTR:
6045 case VT_LPSTR:
6046 case VT_LPWSTR:
6047 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6048 hr = DISP_E_BADVARTYPE;
6049 break;
6050 case VT_SAFEARRAY:
6051 *vt |= VT_ARRAY;
6052 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6053 break;
6054 case VT_INT:
6055 *vt |= VT_I4;
6056 break;
6057 case VT_UINT:
6058 *vt |= VT_UI4;
6059 break;
6060 default:
6061 *vt |= tdesc->vt;
6062 break;
6064 return hr;
6067 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6069 ITypeInfo *tinfo2;
6070 TYPEATTR *tattr;
6071 HRESULT hres;
6073 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6074 if(FAILED(hres))
6075 return hres;
6077 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6078 if(FAILED(hres)) {
6079 ITypeInfo_Release(tinfo2);
6080 return hres;
6083 switch(tattr->typekind) {
6084 case TKIND_ALIAS:
6085 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6086 break;
6088 case TKIND_INTERFACE:
6089 case TKIND_DISPATCH:
6090 *guid = tattr->guid;
6091 break;
6093 default:
6094 ERR("Unexpected typekind %d\n", tattr->typekind);
6095 hres = E_UNEXPECTED;
6098 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6099 ITypeInfo_Release(tinfo2);
6100 return hres;
6103 /***********************************************************************
6104 * DispCallFunc (OLEAUT32.@)
6106 * Invokes a function of the specified calling convention, passing the
6107 * specified arguments and returns the result.
6109 * PARAMS
6110 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6111 * oVft [I] The offset in the vtable. See notes.
6112 * cc [I] Calling convention of the function to call.
6113 * vtReturn [I] The return type of the function.
6114 * cActuals [I] Number of parameters.
6115 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6116 * prgpvarg [I] The arguments to pass.
6117 * pvargResult [O] The return value of the function. Can be NULL.
6119 * RETURNS
6120 * Success: S_OK.
6121 * Failure: HRESULT code.
6123 * NOTES
6124 * The HRESULT return value of this function is not affected by the return
6125 * value of the user supplied function, which is returned in pvargResult.
6127 * If pvInstance is NULL then a non-object function is to be called and oVft
6128 * is the address of the function to call.
6130 * The cc parameter can be one of the following values:
6131 *|CC_FASTCALL
6132 *|CC_CDECL
6133 *|CC_PASCAL
6134 *|CC_STDCALL
6135 *|CC_FPFASTCALL
6136 *|CC_SYSCALL
6137 *|CC_MPWCDECL
6138 *|CC_MPWPASCAL
6141 HRESULT WINAPI
6142 DispCallFunc(
6143 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6144 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6146 #ifdef __i386__
6147 int argspos, stack_offset;
6148 void *func;
6149 UINT i;
6150 DWORD *args;
6152 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6153 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6154 pvargResult, V_VT(pvargResult));
6156 if (cc != CC_STDCALL && cc != CC_CDECL)
6158 FIXME("unsupported calling convention %d\n",cc);
6159 return E_INVALIDARG;
6162 /* maximum size for an argument is sizeof(VARIANT) */
6163 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6165 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6166 argspos = 1;
6167 if (pvInstance)
6169 const FARPROC *vtable = *(FARPROC **)pvInstance;
6170 func = vtable[oVft/sizeof(void *)];
6171 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6173 else func = (void *)oVft;
6175 for (i = 0; i < cActuals; i++)
6177 VARIANT *arg = prgpvarg[i];
6179 switch (prgvt[i])
6181 case VT_EMPTY:
6182 break;
6183 case VT_I8:
6184 case VT_UI8:
6185 case VT_R8:
6186 case VT_DATE:
6187 case VT_CY:
6188 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6189 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6190 break;
6191 case VT_DECIMAL:
6192 case VT_VARIANT:
6193 memcpy( &args[argspos], arg, sizeof(*arg) );
6194 argspos += sizeof(*arg) / sizeof(DWORD);
6195 break;
6196 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6197 args[argspos++] = V_BOOL(arg);
6198 break;
6199 default:
6200 args[argspos++] = V_UI4(arg);
6201 break;
6203 TRACE("arg %u: type %d\n",i,prgvt[i]);
6204 dump_Variant(arg);
6207 switch (vtReturn)
6209 case VT_EMPTY:
6210 call_method( func, argspos - 1, args + 1, &stack_offset );
6211 break;
6212 case VT_R4:
6213 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6214 break;
6215 case VT_R8:
6216 case VT_DATE:
6217 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6218 break;
6219 case VT_DECIMAL:
6220 case VT_VARIANT:
6221 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6222 call_method( func, argspos, args, &stack_offset );
6223 break;
6224 case VT_I8:
6225 case VT_UI8:
6226 case VT_CY:
6227 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6228 break;
6229 case VT_HRESULT:
6230 WARN("invalid return type %u\n", vtReturn);
6231 heap_free( args );
6232 return E_INVALIDARG;
6233 default:
6234 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6235 break;
6237 heap_free( args );
6238 if (stack_offset && cc == CC_STDCALL)
6240 WARN( "stack pointer off by %d\n", stack_offset );
6241 return DISP_E_BADCALLEE;
6243 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6244 TRACE("retval: "); dump_Variant(pvargResult);
6245 return S_OK;
6247 #elif defined(__x86_64__)
6248 int argspos;
6249 UINT i;
6250 DWORD_PTR *args;
6251 void *func;
6253 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6254 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6255 pvargResult, V_VT(pvargResult));
6257 if (cc != CC_STDCALL && cc != CC_CDECL)
6259 FIXME("unsupported calling convention %d\n",cc);
6260 return E_INVALIDARG;
6263 /* maximum size for an argument is sizeof(DWORD_PTR) */
6264 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6266 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6267 argspos = 1;
6268 if (pvInstance)
6270 const FARPROC *vtable = *(FARPROC **)pvInstance;
6271 func = vtable[oVft/sizeof(void *)];
6272 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6274 else func = (void *)oVft;
6276 for (i = 0; i < cActuals; i++)
6278 VARIANT *arg = prgpvarg[i];
6280 switch (prgvt[i])
6282 case VT_DECIMAL:
6283 case VT_VARIANT:
6284 args[argspos++] = (ULONG_PTR)arg;
6285 break;
6286 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6287 args[argspos++] = V_BOOL(arg);
6288 break;
6289 default:
6290 args[argspos++] = V_UI8(arg);
6291 break;
6293 TRACE("arg %u: type %d\n",i,prgvt[i]);
6294 dump_Variant(arg);
6297 switch (vtReturn)
6299 case VT_R4:
6300 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6301 break;
6302 case VT_R8:
6303 case VT_DATE:
6304 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6305 break;
6306 case VT_DECIMAL:
6307 case VT_VARIANT:
6308 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6309 call_method( func, argspos, args );
6310 break;
6311 case VT_HRESULT:
6312 WARN("invalid return type %u\n", vtReturn);
6313 heap_free( args );
6314 return E_INVALIDARG;
6315 default:
6316 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6317 break;
6319 heap_free( args );
6320 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6321 TRACE("retval: "); dump_Variant(pvargResult);
6322 return S_OK;
6324 #else
6325 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6326 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6327 return E_NOTIMPL;
6328 #endif
6331 static inline BOOL func_restricted( const FUNCDESC *desc )
6333 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6336 #define INVBUF_ELEMENT_SIZE \
6337 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6338 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6339 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6340 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6341 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6342 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6343 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6344 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6346 static HRESULT WINAPI ITypeInfo_fnInvoke(
6347 ITypeInfo2 *iface,
6348 VOID *pIUnk,
6349 MEMBERID memid,
6350 UINT16 wFlags,
6351 DISPPARAMS *pDispParams,
6352 VARIANT *pVarResult,
6353 EXCEPINFO *pExcepInfo,
6354 UINT *pArgErr)
6356 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6357 int i;
6358 unsigned int var_index;
6359 TYPEKIND type_kind;
6360 HRESULT hres;
6361 const TLBFuncDesc *pFuncInfo;
6362 UINT fdc;
6364 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6365 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6368 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6369 return DISP_E_MEMBERNOTFOUND;
6371 if (!pDispParams)
6373 ERR("NULL pDispParams not allowed\n");
6374 return E_INVALIDARG;
6377 dump_DispParms(pDispParams);
6379 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6381 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6382 pDispParams->cNamedArgs, pDispParams->cArgs);
6383 return E_INVALIDARG;
6386 /* we do this instead of using GetFuncDesc since it will return a fake
6387 * FUNCDESC for dispinterfaces and we want the real function description */
6388 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6389 pFuncInfo = &This->funcdescs[fdc];
6390 if ((memid == pFuncInfo->funcdesc.memid) &&
6391 (wFlags & pFuncInfo->funcdesc.invkind) &&
6392 !func_restricted( &pFuncInfo->funcdesc ))
6393 break;
6396 if (fdc < This->TypeAttr.cFuncs) {
6397 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6399 if (TRACE_ON(ole))
6401 TRACE("invoking:\n");
6402 dump_TLBFuncDescOne(pFuncInfo);
6405 switch (func_desc->funckind) {
6406 case FUNC_PUREVIRTUAL:
6407 case FUNC_VIRTUAL: {
6408 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6409 VARIANT varresult;
6410 VARIANT retval; /* pointer for storing byref retvals in */
6411 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6412 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6413 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6414 UINT cNamedArgs = pDispParams->cNamedArgs;
6415 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6416 UINT vargs_converted=0;
6418 hres = S_OK;
6420 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6422 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6424 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6425 hres = DISP_E_PARAMNOTFOUND;
6426 goto func_fail;
6430 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6432 ERR("functions with the vararg attribute do not support named arguments\n");
6433 hres = DISP_E_NONAMEDARGS;
6434 goto func_fail;
6437 for (i = 0; i < func_desc->cParams; i++)
6439 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6440 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6441 if (FAILED(hres))
6442 goto func_fail;
6445 TRACE("changing args\n");
6446 for (i = 0; i < func_desc->cParams; i++)
6448 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6449 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6450 VARIANTARG *src_arg;
6452 if (wParamFlags & PARAMFLAG_FLCID)
6454 VARIANTARG *arg;
6455 arg = prgpvarg[i] = &rgvarg[i];
6456 V_VT(arg) = VT_I4;
6457 V_I4(arg) = This->pTypeLib->lcid;
6458 continue;
6461 src_arg = NULL;
6463 if (cNamedArgs)
6465 USHORT j;
6466 for (j = 0; j < cNamedArgs; j++)
6467 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6469 src_arg = &pDispParams->rgvarg[j];
6470 break;
6474 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6476 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6477 vargs_converted++;
6480 if (wParamFlags & PARAMFLAG_FRETVAL)
6482 /* under most conditions the caller is not allowed to
6483 * pass in a dispparam arg in the index of what would be
6484 * the retval parameter. however, there is an exception
6485 * where the extra parameter is used in an extra
6486 * IDispatch::Invoke below */
6487 if ((i < pDispParams->cArgs) &&
6488 ((func_desc->cParams != 1) || !pVarResult ||
6489 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6491 hres = DISP_E_BADPARAMCOUNT;
6492 break;
6495 /* note: this check is placed so that if the caller passes
6496 * in a VARIANTARG for the retval we just ignore it, like
6497 * native does */
6498 if (i == func_desc->cParams - 1)
6500 VARIANTARG *arg;
6501 arg = prgpvarg[i] = &rgvarg[i];
6502 memset(arg, 0, sizeof(*arg));
6503 V_VT(arg) = rgvt[i];
6504 memset(&retval, 0, sizeof(retval));
6505 V_BYREF(arg) = &retval;
6507 else
6509 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6510 hres = E_UNEXPECTED;
6511 break;
6514 else if (src_arg)
6516 dump_Variant(src_arg);
6518 if(rgvt[i]!=V_VT(src_arg))
6520 if (rgvt[i] == VT_VARIANT)
6521 hres = VariantCopy(&rgvarg[i], src_arg);
6522 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6524 if (rgvt[i] == V_VT(src_arg))
6525 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6526 else
6528 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6529 if (wParamFlags & PARAMFLAG_FIN)
6530 hres = VariantCopy(&missing_arg[i], src_arg);
6531 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6533 V_VT(&rgvarg[i]) = rgvt[i];
6535 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6537 SAFEARRAY *a;
6538 SAFEARRAYBOUND bound;
6539 VARIANT *v;
6540 LONG j;
6541 bound.lLbound = 0;
6542 bound.cElements = pDispParams->cArgs-i;
6543 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6545 ERR("SafeArrayCreate failed\n");
6546 break;
6548 hres = SafeArrayAccessData(a, (LPVOID)&v);
6549 if (hres != S_OK)
6551 ERR("SafeArrayAccessData failed with %x\n", hres);
6552 SafeArrayDestroy(a);
6553 break;
6555 for (j = 0; j < bound.cElements; j++)
6556 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6557 hres = SafeArrayUnaccessData(a);
6558 if (hres != S_OK)
6560 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6561 SafeArrayDestroy(a);
6562 break;
6564 V_ARRAY(&rgvarg[i]) = a;
6565 V_VT(&rgvarg[i]) = rgvt[i];
6567 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6569 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6570 if (wParamFlags & PARAMFLAG_FIN)
6571 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6572 else
6573 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6574 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6575 V_VT(&rgvarg[i]) = rgvt[i];
6577 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6579 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6580 V_VT(&rgvarg[i]) = rgvt[i];
6582 else
6584 /* FIXME: this doesn't work for VT_BYREF arguments if
6585 * they are not the same type as in the paramdesc */
6586 V_VT(&rgvarg[i]) = V_VT(src_arg);
6587 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6588 V_VT(&rgvarg[i]) = rgvt[i];
6591 if (FAILED(hres))
6593 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6594 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6595 debugstr_VT(src_arg), debugstr_VF(src_arg));
6596 break;
6598 prgpvarg[i] = &rgvarg[i];
6600 else
6602 prgpvarg[i] = src_arg;
6605 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6606 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6607 && V_UNKNOWN(prgpvarg[i])) {
6608 IUnknown *userdefined_iface;
6609 GUID guid;
6611 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6612 if(FAILED(hres))
6613 break;
6615 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6616 if(FAILED(hres)) {
6617 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6618 break;
6621 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6622 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6625 else if (wParamFlags & PARAMFLAG_FOPT)
6627 VARIANTARG *arg;
6628 arg = prgpvarg[i] = &rgvarg[i];
6629 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6631 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6632 if (FAILED(hres))
6633 break;
6635 else
6637 VARIANTARG *missing_arg;
6638 /* if the function wants a pointer to a variant then
6639 * set that up, otherwise just pass the VT_ERROR in
6640 * the argument by value */
6641 if (rgvt[i] & VT_BYREF)
6643 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6644 V_VT(arg) = VT_VARIANT | VT_BYREF;
6645 V_VARIANTREF(arg) = missing_arg;
6647 else
6648 missing_arg = arg;
6649 V_VT(missing_arg) = VT_ERROR;
6650 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6653 else
6655 hres = DISP_E_BADPARAMCOUNT;
6656 break;
6659 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6661 /* VT_VOID is a special case for return types, so it is not
6662 * handled in the general function */
6663 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6664 V_VT(&varresult) = VT_EMPTY;
6665 else
6667 V_VT(&varresult) = 0;
6668 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6669 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6672 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6673 V_VT(&varresult), func_desc->cParams, rgvt,
6674 prgpvarg, &varresult);
6676 vargs_converted = 0;
6678 for (i = 0; i < func_desc->cParams; i++)
6680 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6681 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6683 if (wParamFlags & PARAMFLAG_FLCID)
6684 continue;
6685 else if (wParamFlags & PARAMFLAG_FRETVAL)
6687 if (TRACE_ON(ole))
6689 TRACE("[retval] value: ");
6690 dump_Variant(prgpvarg[i]);
6693 if (pVarResult)
6695 VariantInit(pVarResult);
6696 /* deref return value */
6697 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6700 VARIANT_ClearInd(prgpvarg[i]);
6702 else if (vargs_converted < pDispParams->cArgs)
6704 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6705 if (wParamFlags & PARAMFLAG_FOUT)
6707 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6709 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6711 if (FAILED(hres))
6713 ERR("failed to convert param %d to vt %d\n", i,
6714 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6715 break;
6719 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6720 func_desc->cParamsOpt < 0 &&
6721 i == func_desc->cParams-1)
6723 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6724 LONG j, ubound;
6725 VARIANT *v;
6726 hres = SafeArrayGetUBound(a, 1, &ubound);
6727 if (hres != S_OK)
6729 ERR("SafeArrayGetUBound failed with %x\n", hres);
6730 break;
6732 hres = SafeArrayAccessData(a, (LPVOID)&v);
6733 if (hres != S_OK)
6735 ERR("SafeArrayAccessData failed with %x\n", hres);
6736 break;
6738 for (j = 0; j <= ubound; j++)
6739 VariantClear(&v[j]);
6740 hres = SafeArrayUnaccessData(a);
6741 if (hres != S_OK)
6743 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6744 break;
6747 VariantClear(&rgvarg[i]);
6748 vargs_converted++;
6750 else if (wParamFlags & PARAMFLAG_FOPT)
6752 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6753 VariantClear(&rgvarg[i]);
6756 VariantClear(&missing_arg[i]);
6759 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6761 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6762 hres = DISP_E_EXCEPTION;
6763 if (pExcepInfo)
6765 IErrorInfo *pErrorInfo;
6766 pExcepInfo->scode = V_ERROR(&varresult);
6767 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6769 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6770 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6771 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6772 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6774 IErrorInfo_Release(pErrorInfo);
6778 if (V_VT(&varresult) != VT_ERROR)
6780 TRACE("varresult value: ");
6781 dump_Variant(&varresult);
6783 if (pVarResult)
6785 VariantClear(pVarResult);
6786 *pVarResult = varresult;
6788 else
6789 VariantClear(&varresult);
6792 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6793 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6794 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6795 (pDispParams->cArgs != 0))
6797 if (V_VT(pVarResult) == VT_DISPATCH)
6799 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6800 /* Note: not VariantClear; we still need the dispatch
6801 * pointer to be valid */
6802 VariantInit(pVarResult);
6803 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6804 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6805 pDispParams, pVarResult, pExcepInfo, pArgErr);
6806 IDispatch_Release(pDispatch);
6808 else
6810 VariantClear(pVarResult);
6811 hres = DISP_E_NOTACOLLECTION;
6815 func_fail:
6816 heap_free(buffer);
6817 break;
6819 case FUNC_DISPATCH: {
6820 IDispatch *disp;
6822 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6823 if (SUCCEEDED(hres)) {
6824 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6825 hres = IDispatch_Invoke(
6826 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6827 pVarResult,pExcepInfo,pArgErr
6829 if (FAILED(hres))
6830 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6831 IDispatch_Release(disp);
6832 } else
6833 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6834 break;
6836 default:
6837 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6838 hres = E_FAIL;
6839 break;
6842 TRACE("-- 0x%08x\n", hres);
6843 return hres;
6845 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6846 VARDESC *var_desc;
6848 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6849 if(FAILED(hres)) return hres;
6851 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6852 dump_VARDESC(var_desc);
6853 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6854 return E_NOTIMPL;
6857 /* not found, look for it in inherited interfaces */
6858 ITypeInfo2_GetTypeKind(iface, &type_kind);
6859 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6860 if(This->impltypes) {
6861 /* recursive search */
6862 ITypeInfo *pTInfo;
6863 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6864 if(SUCCEEDED(hres)){
6865 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6866 ITypeInfo_Release(pTInfo);
6867 return hres;
6869 WARN("Could not search inherited interface!\n");
6872 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6873 return DISP_E_MEMBERNOTFOUND;
6876 /* ITypeInfo::GetDocumentation
6878 * Retrieves the documentation string, the complete Help file name and path,
6879 * and the context ID for the Help topic for a specified type description.
6881 * (Can be tested by the Visual Basic Editor in Word for instance.)
6883 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6884 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6885 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6887 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6888 const TLBFuncDesc *pFDesc;
6889 const TLBVarDesc *pVDesc;
6890 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6891 " HelpContext(%p) HelpFile(%p)\n",
6892 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6893 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6894 if(pBstrName)
6895 *pBstrName=SysAllocString(This->Name);
6896 if(pBstrDocString)
6897 *pBstrDocString=SysAllocString(This->DocString);
6898 if(pdwHelpContext)
6899 *pdwHelpContext=This->dwHelpContext;
6900 if(pBstrHelpFile)
6901 *pBstrHelpFile=SysAllocString(This->pTypeLib->HelpFile);
6902 return S_OK;
6903 }else {/* for a member */
6904 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6905 if(pFDesc){
6906 if(pBstrName)
6907 *pBstrName = SysAllocString(pFDesc->Name);
6908 if(pBstrDocString)
6909 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6910 if(pdwHelpContext)
6911 *pdwHelpContext=pFDesc->helpcontext;
6912 return S_OK;
6914 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
6915 if(pVDesc){
6916 if(pBstrName)
6917 *pBstrName = SysAllocString(pVDesc->Name);
6918 if(pBstrDocString)
6919 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6920 if(pdwHelpContext)
6921 *pdwHelpContext=pVDesc->HelpContext;
6922 if(pBstrHelpFile)
6923 *pBstrHelpFile = SysAllocString(This->pTypeLib->HelpFile);
6924 return S_OK;
6928 if(This->impltypes &&
6929 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6930 /* recursive search */
6931 ITypeInfo *pTInfo;
6932 HRESULT result;
6933 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6934 if(SUCCEEDED(result)) {
6935 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6936 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6937 ITypeInfo_Release(pTInfo);
6938 return result;
6940 WARN("Could not search inherited interface!\n");
6943 WARN("member %d not found\n", memid);
6944 return TYPE_E_ELEMENTNOTFOUND;
6947 /* ITypeInfo::GetDllEntry
6949 * Retrieves a description or specification of an entry point for a function
6950 * in a DLL.
6952 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6953 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6954 WORD *pwOrdinal)
6956 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
6957 const TLBFuncDesc *pFDesc;
6959 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6961 if (pBstrDllName) *pBstrDllName = NULL;
6962 if (pBstrName) *pBstrName = NULL;
6963 if (pwOrdinal) *pwOrdinal = 0;
6965 if (This->TypeAttr.typekind != TKIND_MODULE)
6966 return TYPE_E_BADMODULEKIND;
6968 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6969 if(pFDesc){
6970 dump_TypeInfo(This);
6971 if (TRACE_ON(ole))
6972 dump_TLBFuncDescOne(pFDesc);
6974 if (pBstrDllName)
6975 *pBstrDllName = SysAllocString(This->DllName);
6977 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6978 if (pBstrName)
6979 *pBstrName = SysAllocString(pFDesc->Entry);
6980 if (pwOrdinal)
6981 *pwOrdinal = -1;
6982 return S_OK;
6984 if (pBstrName)
6985 *pBstrName = NULL;
6986 if (pwOrdinal)
6987 *pwOrdinal = LOWORD(pFDesc->Entry);
6988 return S_OK;
6990 return TYPE_E_ELEMENTNOTFOUND;
6993 /* internal function to make the inherited interfaces' methods appear
6994 * part of the interface */
6995 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6996 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6998 ITypeInfoImpl *This = impl_from_ITypeInfo(iface);
6999 HRESULT hr;
7001 TRACE("%p, 0x%x\n", iface, *hRefType);
7003 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
7005 ITypeInfo *pSubTypeInfo;
7007 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
7008 if (FAILED(hr))
7009 return hr;
7011 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
7012 hRefType, ppTInfo);
7013 ITypeInfo_Release(pSubTypeInfo);
7014 if (SUCCEEDED(hr))
7015 return hr;
7017 *hRefType -= DISPATCH_HREF_OFFSET;
7019 if (!(*hRefType & DISPATCH_HREF_MASK))
7020 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
7021 else
7022 return E_FAIL;
7025 /* ITypeInfo::GetRefTypeInfo
7027 * If a type description references other type descriptions, it retrieves
7028 * the referenced type descriptions.
7030 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
7031 ITypeInfo2 *iface,
7032 HREFTYPE hRefType,
7033 ITypeInfo **ppTInfo)
7035 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7036 HRESULT result = E_FAIL;
7038 if(!ppTInfo)
7039 return E_INVALIDARG;
7041 if ((This->hreftype != -1) && (This->hreftype == hRefType))
7043 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
7044 ITypeInfo_AddRef(*ppTInfo);
7045 result = S_OK;
7047 else if (hRefType == -1 &&
7048 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
7049 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
7051 /* when we meet a DUAL dispinterface, we must create the interface
7052 * version of it.
7054 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
7057 /* the interface version contains the same information as the dispinterface
7058 * copy the contents of the structs.
7060 *pTypeInfoImpl = *This;
7061 pTypeInfoImpl->ref = 0;
7063 /* change the type to interface */
7064 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
7066 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
7068 /* the AddRef implicitly adds a reference to the parent typelib, which
7069 * stops the copied data from being destroyed until the new typeinfo's
7070 * refcount goes to zero, but we need to signal to the new instance to
7071 * not free its data structures when it is destroyed */
7072 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7074 ITypeInfo_AddRef(*ppTInfo);
7076 result = S_OK;
7078 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
7079 (This->TypeAttr.typekind == TKIND_DISPATCH))
7081 HREFTYPE href_dispatch = hRefType;
7082 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7083 } else {
7084 TLBRefType *ref_type;
7085 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7087 if(ref_type->reference == hRefType)
7088 break;
7090 if(&ref_type->entry == &This->pTypeLib->ref_list)
7092 FIXME("Can't find pRefType for ref %x\n", hRefType);
7093 goto end;
7095 if(hRefType != -1) {
7096 ITypeLib *pTLib = NULL;
7098 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7099 UINT Index;
7100 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7101 } else {
7102 if(ref_type->pImpTLInfo->pImpTypeLib) {
7103 TRACE("typeinfo in imported typelib that is already loaded\n");
7104 pTLib = (ITypeLib*)&ref_type->pImpTLInfo->pImpTypeLib->ITypeLib2_iface;
7105 ITypeLib_AddRef(pTLib);
7106 result = S_OK;
7107 } else {
7108 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7109 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
7110 ref_type->pImpTLInfo->wVersionMajor,
7111 ref_type->pImpTLInfo->wVersionMinor,
7112 ref_type->pImpTLInfo->lcid,
7113 &pTLib);
7115 if(FAILED(result)) {
7116 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
7117 result=LoadTypeLib(libnam, &pTLib);
7118 SysFreeString(libnam);
7120 if(SUCCEEDED(result)) {
7121 ref_type->pImpTLInfo->pImpTypeLib = impl_from_ITypeLib(pTLib);
7122 ITypeLib_AddRef(pTLib);
7126 if(SUCCEEDED(result)) {
7127 if(ref_type->index == TLB_REF_USE_GUID)
7128 result = ITypeLib_GetTypeInfoOfGuid(pTLib, &ref_type->guid, ppTInfo);
7129 else
7130 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7132 if (pTLib != NULL)
7133 ITypeLib_Release(pTLib);
7137 end:
7138 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7139 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7140 return result;
7143 /* ITypeInfo::AddressOfMember
7145 * Retrieves the addresses of static functions or variables, such as those
7146 * defined in a DLL.
7148 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7149 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7151 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7152 HRESULT hr;
7153 BSTR dll, entry;
7154 WORD ordinal;
7155 HMODULE module;
7157 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7159 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7160 if (FAILED(hr))
7161 return hr;
7163 module = LoadLibraryW(dll);
7164 if (!module)
7166 ERR("couldn't load %s\n", debugstr_w(dll));
7167 SysFreeString(dll);
7168 SysFreeString(entry);
7169 return STG_E_FILENOTFOUND;
7171 /* FIXME: store library somewhere where we can free it */
7173 if (entry)
7175 LPSTR entryA;
7176 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7177 entryA = heap_alloc(len);
7178 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7180 *ppv = GetProcAddress(module, entryA);
7181 if (!*ppv)
7182 ERR("function not found %s\n", debugstr_a(entryA));
7184 heap_free(entryA);
7186 else
7188 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7189 if (!*ppv)
7190 ERR("function not found %d\n", ordinal);
7193 SysFreeString(dll);
7194 SysFreeString(entry);
7196 if (!*ppv)
7197 return TYPE_E_DLLFUNCTIONNOTFOUND;
7199 return S_OK;
7202 /* ITypeInfo::CreateInstance
7204 * Creates a new instance of a type that describes a component object class
7205 * (coclass).
7207 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7208 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7210 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7211 HRESULT hr;
7212 TYPEATTR *pTA;
7214 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7216 *ppvObj = NULL;
7218 if(pOuterUnk)
7220 WARN("Not able to aggregate\n");
7221 return CLASS_E_NOAGGREGATION;
7224 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7225 if(FAILED(hr)) return hr;
7227 if(pTA->typekind != TKIND_COCLASS)
7229 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7230 hr = E_INVALIDARG;
7231 goto end;
7234 hr = S_FALSE;
7235 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7237 IUnknown *pUnk;
7238 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7239 TRACE("GetActiveObject rets %08x\n", hr);
7240 if(hr == S_OK)
7242 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7243 IUnknown_Release(pUnk);
7247 if(hr != S_OK)
7248 hr = CoCreateInstance(&pTA->guid, NULL,
7249 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7250 riid, ppvObj);
7252 end:
7253 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7254 return hr;
7257 /* ITypeInfo::GetMops
7259 * Retrieves marshalling information.
7261 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7262 BSTR *pBstrMops)
7264 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7265 FIXME("(%p %d) stub!\n", This, memid);
7266 *pBstrMops = NULL;
7267 return S_OK;
7270 /* ITypeInfo::GetContainingTypeLib
7272 * Retrieves the containing type library and the index of the type description
7273 * within that type library.
7275 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7276 ITypeLib * *ppTLib, UINT *pIndex)
7278 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7280 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7281 if (pIndex) {
7282 *pIndex=This->index;
7283 TRACE("returning pIndex=%d\n", *pIndex);
7286 if (ppTLib) {
7287 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7288 ITypeLib_AddRef(*ppTLib);
7289 TRACE("returning ppTLib=%p\n", *ppTLib);
7292 return S_OK;
7295 /* ITypeInfo::ReleaseTypeAttr
7297 * Releases a TYPEATTR previously returned by GetTypeAttr.
7300 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7301 TYPEATTR* pTypeAttr)
7303 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7304 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7305 heap_free(pTypeAttr);
7308 /* ITypeInfo::ReleaseFuncDesc
7310 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7312 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7313 ITypeInfo2 *iface,
7314 FUNCDESC *pFuncDesc)
7316 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7317 SHORT i;
7319 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7321 for (i = 0; i < pFuncDesc->cParams; i++)
7322 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7323 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7325 SysFreeString((BSTR)pFuncDesc);
7328 /* ITypeInfo::ReleaseVarDesc
7330 * Releases a VARDESC previously returned by GetVarDesc.
7332 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7333 VARDESC *pVarDesc)
7335 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7336 TRACE("(%p)->(%p)\n", This, pVarDesc);
7338 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7339 if (pVarDesc->varkind == VAR_CONST)
7340 VariantClear(pVarDesc->u.lpvarValue);
7341 SysFreeString((BSTR)pVarDesc);
7344 /* ITypeInfo2::GetTypeKind
7346 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7349 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7350 TYPEKIND *pTypeKind)
7352 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7353 *pTypeKind=This->TypeAttr.typekind;
7354 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7355 return S_OK;
7358 /* ITypeInfo2::GetTypeFlags
7360 * Returns the type flags without any allocations. This returns a DWORD type
7361 * flag, which expands the type flags without growing the TYPEATTR (type
7362 * attribute).
7365 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7367 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7368 *pTypeFlags=This->TypeAttr.wTypeFlags;
7369 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7370 return S_OK;
7373 /* ITypeInfo2::GetFuncIndexOfMemId
7374 * Binds to a specific member based on a known DISPID, where the member name
7375 * is not known (for example, when binding to a default member).
7378 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7379 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7381 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7382 UINT fdc;
7383 HRESULT result;
7385 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7386 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7387 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7388 break;
7390 if(fdc < This->TypeAttr.cFuncs) {
7391 *pFuncIndex = fdc;
7392 result = S_OK;
7393 } else
7394 result = TYPE_E_ELEMENTNOTFOUND;
7396 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7397 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7398 return result;
7401 /* TypeInfo2::GetVarIndexOfMemId
7403 * Binds to a specific member based on a known DISPID, where the member name
7404 * is not known (for example, when binding to a default member).
7407 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7408 MEMBERID memid, UINT *pVarIndex)
7410 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7411 TLBVarDesc *pVarInfo;
7413 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7415 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7416 if(!pVarInfo)
7417 return TYPE_E_ELEMENTNOTFOUND;
7419 *pVarIndex = (pVarInfo - This->vardescs);
7421 return S_OK;
7424 /* ITypeInfo2::GetCustData
7426 * Gets the custom data
7428 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7429 ITypeInfo2 * iface,
7430 REFGUID guid,
7431 VARIANT *pVarVal)
7433 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7434 TLBCustData *pCData;
7436 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7438 if(!guid || !pVarVal)
7439 return E_INVALIDARG;
7441 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7443 VariantInit( pVarVal);
7444 if (pCData)
7445 VariantCopy( pVarVal, &pCData->data);
7446 else
7447 VariantClear( pVarVal );
7448 return S_OK;
7451 /* ITypeInfo2::GetFuncCustData
7453 * Gets the custom data
7455 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7456 ITypeInfo2 * iface,
7457 UINT index,
7458 REFGUID guid,
7459 VARIANT *pVarVal)
7461 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7462 TLBCustData *pCData;
7463 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7465 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7467 if(index >= This->TypeAttr.cFuncs)
7468 return TYPE_E_ELEMENTNOTFOUND;
7470 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7471 if(!pCData)
7472 return TYPE_E_ELEMENTNOTFOUND;
7474 VariantInit(pVarVal);
7475 VariantCopy(pVarVal, &pCData->data);
7477 return S_OK;
7480 /* ITypeInfo2::GetParamCustData
7482 * Gets the custom data
7484 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7485 ITypeInfo2 * iface,
7486 UINT indexFunc,
7487 UINT indexParam,
7488 REFGUID guid,
7489 VARIANT *pVarVal)
7491 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7492 TLBCustData *pCData;
7493 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7495 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7496 debugstr_guid(guid), pVarVal);
7498 if(indexFunc >= This->TypeAttr.cFuncs)
7499 return TYPE_E_ELEMENTNOTFOUND;
7501 if(indexParam >= pFDesc->funcdesc.cParams)
7502 return TYPE_E_ELEMENTNOTFOUND;
7504 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7505 if(!pCData)
7506 return TYPE_E_ELEMENTNOTFOUND;
7508 VariantInit(pVarVal);
7509 VariantCopy(pVarVal, &pCData->data);
7511 return S_OK;
7514 /* ITypeInfo2::GetVarCustData
7516 * Gets the custom data
7518 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7519 ITypeInfo2 * iface,
7520 UINT index,
7521 REFGUID guid,
7522 VARIANT *pVarVal)
7524 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7525 TLBCustData *pCData;
7526 TLBVarDesc *pVDesc = &This->vardescs[index];
7528 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7530 if(index >= This->TypeAttr.cVars)
7531 return TYPE_E_ELEMENTNOTFOUND;
7533 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7534 if(!pCData)
7535 return TYPE_E_ELEMENTNOTFOUND;
7537 VariantInit(pVarVal);
7538 VariantCopy(pVarVal, &pCData->data);
7540 return S_OK;
7543 /* ITypeInfo2::GetImplCustData
7545 * Gets the custom data
7547 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7548 ITypeInfo2 * iface,
7549 UINT index,
7550 REFGUID guid,
7551 VARIANT *pVarVal)
7553 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7554 TLBCustData *pCData;
7555 TLBImplType *pRDesc = &This->impltypes[index];
7557 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7559 if(index >= This->TypeAttr.cImplTypes)
7560 return TYPE_E_ELEMENTNOTFOUND;
7562 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7563 if(!pCData)
7564 return TYPE_E_ELEMENTNOTFOUND;
7566 VariantInit(pVarVal);
7567 VariantCopy(pVarVal, &pCData->data);
7569 return S_OK;
7572 /* ITypeInfo2::GetDocumentation2
7574 * Retrieves the documentation string, the complete Help file name and path,
7575 * the localization context to use, and the context ID for the library Help
7576 * topic in the Help file.
7579 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7580 ITypeInfo2 * iface,
7581 MEMBERID memid,
7582 LCID lcid,
7583 BSTR *pbstrHelpString,
7584 DWORD *pdwHelpStringContext,
7585 BSTR *pbstrHelpStringDll)
7587 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7588 const TLBFuncDesc *pFDesc;
7589 const TLBVarDesc *pVDesc;
7590 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7591 "HelpStringContext(%p) HelpStringDll(%p)\n",
7592 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7593 pbstrHelpStringDll );
7594 /* the help string should be obtained from the helpstringdll,
7595 * using the _DLLGetDocumentation function, based on the supplied
7596 * lcid. Nice to do sometime...
7598 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7599 if(pbstrHelpString)
7600 *pbstrHelpString=SysAllocString(This->Name);
7601 if(pdwHelpStringContext)
7602 *pdwHelpStringContext=This->dwHelpStringContext;
7603 if(pbstrHelpStringDll)
7604 *pbstrHelpStringDll=
7605 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7606 return S_OK;
7607 }else {/* for a member */
7608 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7609 if(pFDesc){
7610 if(pbstrHelpString)
7611 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7612 if(pdwHelpStringContext)
7613 *pdwHelpStringContext=pFDesc->HelpStringContext;
7614 if(pbstrHelpStringDll)
7615 *pbstrHelpStringDll=
7616 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7617 return S_OK;
7619 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7620 if(pVDesc){
7621 if(pbstrHelpString)
7622 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7623 if(pdwHelpStringContext)
7624 *pdwHelpStringContext=pVDesc->HelpStringContext;
7625 if(pbstrHelpStringDll)
7626 *pbstrHelpStringDll=
7627 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7628 return S_OK;
7631 return TYPE_E_ELEMENTNOTFOUND;
7634 /* ITypeInfo2::GetAllCustData
7636 * Gets all custom data items for the Type info.
7639 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7640 ITypeInfo2 * iface,
7641 CUSTDATA *pCustData)
7643 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7645 TRACE("%p %p\n", This, pCustData);
7647 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
7650 /* ITypeInfo2::GetAllFuncCustData
7652 * Gets all custom data items for the specified Function
7655 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7656 ITypeInfo2 * iface,
7657 UINT index,
7658 CUSTDATA *pCustData)
7660 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7661 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7663 TRACE("%p %u %p\n", This, index, pCustData);
7665 if(index >= This->TypeAttr.cFuncs)
7666 return TYPE_E_ELEMENTNOTFOUND;
7668 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
7671 /* ITypeInfo2::GetAllParamCustData
7673 * Gets all custom data items for the Functions
7676 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7677 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7679 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7680 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7682 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
7684 if(indexFunc >= This->TypeAttr.cFuncs)
7685 return TYPE_E_ELEMENTNOTFOUND;
7687 if(indexParam >= pFDesc->funcdesc.cParams)
7688 return TYPE_E_ELEMENTNOTFOUND;
7690 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
7693 /* ITypeInfo2::GetAllVarCustData
7695 * Gets all custom data items for the specified Variable
7698 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7699 UINT index, CUSTDATA *pCustData)
7701 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7702 TLBVarDesc * pVDesc = &This->vardescs[index];
7704 TRACE("%p %u %p\n", This, index, pCustData);
7706 if(index >= This->TypeAttr.cVars)
7707 return TYPE_E_ELEMENTNOTFOUND;
7709 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
7712 /* ITypeInfo2::GetAllImplCustData
7714 * Gets all custom data items for the specified implementation type
7717 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7718 ITypeInfo2 * iface,
7719 UINT index,
7720 CUSTDATA *pCustData)
7722 ITypeInfoImpl *This = impl_from_ITypeInfo2(iface);
7723 TLBImplType *pRDesc = &This->impltypes[index];
7725 TRACE("%p %u %p\n", This, index, pCustData);
7727 if(index >= This->TypeAttr.cImplTypes)
7728 return TYPE_E_ELEMENTNOTFOUND;
7730 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
7733 static const ITypeInfo2Vtbl tinfvt =
7736 ITypeInfo_fnQueryInterface,
7737 ITypeInfo_fnAddRef,
7738 ITypeInfo_fnRelease,
7740 ITypeInfo_fnGetTypeAttr,
7741 ITypeInfo_fnGetTypeComp,
7742 ITypeInfo_fnGetFuncDesc,
7743 ITypeInfo_fnGetVarDesc,
7744 ITypeInfo_fnGetNames,
7745 ITypeInfo_fnGetRefTypeOfImplType,
7746 ITypeInfo_fnGetImplTypeFlags,
7747 ITypeInfo_fnGetIDsOfNames,
7748 ITypeInfo_fnInvoke,
7749 ITypeInfo_fnGetDocumentation,
7750 ITypeInfo_fnGetDllEntry,
7751 ITypeInfo_fnGetRefTypeInfo,
7752 ITypeInfo_fnAddressOfMember,
7753 ITypeInfo_fnCreateInstance,
7754 ITypeInfo_fnGetMops,
7755 ITypeInfo_fnGetContainingTypeLib,
7756 ITypeInfo_fnReleaseTypeAttr,
7757 ITypeInfo_fnReleaseFuncDesc,
7758 ITypeInfo_fnReleaseVarDesc,
7760 ITypeInfo2_fnGetTypeKind,
7761 ITypeInfo2_fnGetTypeFlags,
7762 ITypeInfo2_fnGetFuncIndexOfMemId,
7763 ITypeInfo2_fnGetVarIndexOfMemId,
7764 ITypeInfo2_fnGetCustData,
7765 ITypeInfo2_fnGetFuncCustData,
7766 ITypeInfo2_fnGetParamCustData,
7767 ITypeInfo2_fnGetVarCustData,
7768 ITypeInfo2_fnGetImplTypeCustData,
7769 ITypeInfo2_fnGetDocumentation2,
7770 ITypeInfo2_fnGetAllCustData,
7771 ITypeInfo2_fnGetAllFuncCustData,
7772 ITypeInfo2_fnGetAllParamCustData,
7773 ITypeInfo2_fnGetAllVarCustData,
7774 ITypeInfo2_fnGetAllImplTypeCustData,
7777 /******************************************************************************
7778 * CreateDispTypeInfo [OLEAUT32.31]
7780 * Build type information for an object so it can be called through an
7781 * IDispatch interface.
7783 * RETURNS
7784 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7785 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7787 * NOTES
7788 * This call allows an objects methods to be accessed through IDispatch, by
7789 * building an ITypeInfo object that IDispatch can use to call through.
7791 HRESULT WINAPI CreateDispTypeInfo(
7792 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7793 LCID lcid, /* [I] Locale Id */
7794 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7796 ITypeInfoImpl *pTIClass, *pTIIface;
7797 ITypeLibImpl *pTypeLibImpl;
7798 unsigned int param, func;
7799 TLBFuncDesc *pFuncDesc;
7800 TLBRefType *ref;
7802 TRACE("\n");
7803 pTypeLibImpl = TypeLibImpl_Constructor();
7804 if (!pTypeLibImpl) return E_FAIL;
7806 pTypeLibImpl->TypeInfoCount = 2;
7807 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
7809 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
7810 pTIIface->pTypeLib = pTypeLibImpl;
7811 pTIIface->index = 0;
7812 pTIIface->Name = NULL;
7813 pTIIface->dwHelpContext = -1;
7814 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7815 pTIIface->TypeAttr.lcid = lcid;
7816 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7817 pTIIface->TypeAttr.wMajorVerNum = 0;
7818 pTIIface->TypeAttr.wMinorVerNum = 0;
7819 pTIIface->TypeAttr.cbAlignment = 2;
7820 pTIIface->TypeAttr.cbSizeInstance = -1;
7821 pTIIface->TypeAttr.cbSizeVft = -1;
7822 pTIIface->TypeAttr.cFuncs = 0;
7823 pTIIface->TypeAttr.cImplTypes = 0;
7824 pTIIface->TypeAttr.cVars = 0;
7825 pTIIface->TypeAttr.wTypeFlags = 0;
7827 pTIIface->funcdescs = TLBFuncDesc_Constructor(pidata->cMembers);
7828 pFuncDesc = pTIIface->funcdescs;
7829 for(func = 0; func < pidata->cMembers; func++) {
7830 METHODDATA *md = pidata->pmethdata + func;
7831 pFuncDesc->Name = SysAllocString(md->szName);
7832 pFuncDesc->funcdesc.memid = md->dispid;
7833 pFuncDesc->funcdesc.lprgscode = NULL;
7834 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
7835 pFuncDesc->funcdesc.invkind = md->wFlags;
7836 pFuncDesc->funcdesc.callconv = md->cc;
7837 pFuncDesc->funcdesc.cParams = md->cArgs;
7838 pFuncDesc->funcdesc.cParamsOpt = 0;
7839 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
7840 pFuncDesc->funcdesc.cScodes = 0;
7841 pFuncDesc->funcdesc.wFuncFlags = 0;
7842 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7843 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7844 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7845 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7846 md->cArgs * sizeof(ELEMDESC));
7847 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
7848 for(param = 0; param < md->cArgs; param++) {
7849 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7850 pFuncDesc->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7852 pFuncDesc->helpcontext = 0;
7853 pFuncDesc->HelpStringContext = 0;
7854 pFuncDesc->HelpString = NULL;
7855 pFuncDesc->Entry = NULL;
7856 list_init(&pFuncDesc->custdata_list);
7857 pTIIface->TypeAttr.cFuncs++;
7858 ++pFuncDesc;
7861 dump_TypeInfo(pTIIface);
7863 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
7864 pTIClass->pTypeLib = pTypeLibImpl;
7865 pTIClass->index = 1;
7866 pTIClass->Name = NULL;
7867 pTIClass->dwHelpContext = -1;
7868 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7869 pTIClass->TypeAttr.lcid = lcid;
7870 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7871 pTIClass->TypeAttr.wMajorVerNum = 0;
7872 pTIClass->TypeAttr.wMinorVerNum = 0;
7873 pTIClass->TypeAttr.cbAlignment = 2;
7874 pTIClass->TypeAttr.cbSizeInstance = -1;
7875 pTIClass->TypeAttr.cbSizeVft = -1;
7876 pTIClass->TypeAttr.cFuncs = 0;
7877 pTIClass->TypeAttr.cImplTypes = 1;
7878 pTIClass->TypeAttr.cVars = 0;
7879 pTIClass->TypeAttr.wTypeFlags = 0;
7881 pTIClass->impltypes = TLBImplType_Constructor(1);
7883 ref = heap_alloc_zero(sizeof(*ref));
7884 ref->pImpTLInfo = TLB_REF_INTERNAL;
7885 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7887 dump_TypeInfo(pTIClass);
7889 *pptinfo = (ITypeInfo*)pTIClass;
7891 ITypeInfo_AddRef(*pptinfo);
7892 ITypeLib2_Release(&pTypeLibImpl->ITypeLib2_iface);
7894 return S_OK;
7898 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7900 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7902 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7905 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7907 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7909 return ITypeInfo_AddRef((ITypeInfo *)This);
7912 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7914 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7916 return ITypeInfo_Release((ITypeInfo *)This);
7919 static HRESULT WINAPI ITypeComp_fnBind(
7920 ITypeComp * iface,
7921 OLECHAR * szName,
7922 ULONG lHash,
7923 WORD wFlags,
7924 ITypeInfo ** ppTInfo,
7925 DESCKIND * pDescKind,
7926 BINDPTR * pBindPtr)
7928 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7929 const TLBFuncDesc *pFDesc;
7930 const TLBVarDesc *pVDesc;
7931 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7932 UINT fdc;
7934 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7936 *pDescKind = DESCKIND_NONE;
7937 pBindPtr->lpfuncdesc = NULL;
7938 *ppTInfo = NULL;
7940 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7941 pFDesc = &This->funcdescs[fdc];
7942 if (!strcmpiW(pFDesc->Name, szName)) {
7943 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7944 break;
7945 else
7946 /* name found, but wrong flags */
7947 hr = TYPE_E_TYPEMISMATCH;
7951 if (fdc < This->TypeAttr.cFuncs)
7953 HRESULT hr = TLB_AllocAndInitFuncDesc(
7954 &pFDesc->funcdesc,
7955 &pBindPtr->lpfuncdesc,
7956 This->TypeAttr.typekind == TKIND_DISPATCH);
7957 if (FAILED(hr))
7958 return hr;
7959 *pDescKind = DESCKIND_FUNCDESC;
7960 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
7961 ITypeInfo_AddRef(*ppTInfo);
7962 return S_OK;
7963 } else {
7964 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, szName);
7965 if(pVDesc){
7966 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7967 if (FAILED(hr))
7968 return hr;
7969 *pDescKind = DESCKIND_VARDESC;
7970 *ppTInfo = (ITypeInfo *)&This->ITypeInfo2_iface;
7971 ITypeInfo_AddRef(*ppTInfo);
7972 return S_OK;
7975 /* FIXME: search each inherited interface, not just the first */
7976 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
7977 /* recursive search */
7978 ITypeInfo *pTInfo;
7979 ITypeComp *pTComp;
7980 HRESULT hr;
7981 hr=ITypeInfo2_GetRefTypeInfo(&This->ITypeInfo2_iface, This->impltypes[0].hRef, &pTInfo);
7982 if (SUCCEEDED(hr))
7984 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7985 ITypeInfo_Release(pTInfo);
7987 if (SUCCEEDED(hr))
7989 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7990 ITypeComp_Release(pTComp);
7991 return hr;
7993 WARN("Could not search inherited interface!\n");
7995 if (hr == DISP_E_MEMBERNOTFOUND)
7996 hr = S_OK;
7997 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7998 return hr;
8001 static HRESULT WINAPI ITypeComp_fnBindType(
8002 ITypeComp * iface,
8003 OLECHAR * szName,
8004 ULONG lHash,
8005 ITypeInfo ** ppTInfo,
8006 ITypeComp ** ppTComp)
8008 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
8010 /* strange behaviour (does nothing) but like the
8011 * original */
8013 if (!ppTInfo || !ppTComp)
8014 return E_POINTER;
8016 *ppTInfo = NULL;
8017 *ppTComp = NULL;
8019 return S_OK;
8022 static const ITypeCompVtbl tcompvt =
8025 ITypeComp_fnQueryInterface,
8026 ITypeComp_fnAddRef,
8027 ITypeComp_fnRelease,
8029 ITypeComp_fnBind,
8030 ITypeComp_fnBindType