4 * Copyright 1997 Marcus Meissner
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
44 * -. lousy fatal error handling
49 #include "wine/port.h"
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
69 #include "wine/unicode.h"
72 #include "wine/debug.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
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 /****************************************************************************
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));
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
141 p_iSize /= sizeof(WORD);
144 *Val = FromLEWord(*Val);
151 static void FromLEDWords(void *p_Val, int p_iSize)
155 p_iSize /= sizeof(DWORD);
158 *Val = FromLEDWord(*Val);
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
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};
177 INT best_maj = -1, best_min = -1;
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)
186 len = sizeof(key_name);
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
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)
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
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)
229 if (*wMaj == best_maj && best_min >= 0)
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 );
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 );
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 );
273 case SYS_WIN16: strcatW( buffer, win16W ); break;
274 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 case SYS_WIN64: strcatW( buffer, win64W ); break;
277 TRACE("Typelib is for unsupported syskind %i\n", syskind);
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;
294 WCHAR Path[MAX_PATH];
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;
316 LONG dwPathLen = sizeof(Path);
318 get_lcid_subkey( myLCID, syskind, buffer );
320 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
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 */
341 *path = SysAllocString( Path );
346 TRACE_(typelib)("-- 0x%08x\n", hr);
350 /****************************************************************************
351 * QueryPathOfRegTypeLib [OLEAUT32.164]
353 * Gets the path to a registered type library.
356 * guid [I] referenced guid
357 * wMaj [I] major version
358 * wMin [I] minor version
360 * path [O] path of typelib
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
368 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
371 HRESULT hres = query_typelib_path( guid, wMaj, wMin, SYS_WIN64, lcid, path );
375 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
378 /******************************************************************************
379 * CreateTypeLib [OLEAUT32.160] creates a typelib
385 HRESULT WINAPI CreateTypeLib(
386 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
388 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
392 /******************************************************************************
393 * LoadTypeLib [OLEAUT32.161]
395 * Loads a type library
398 * szFile [I] Name of file to load from.
399 * pptLib [O] Pointer that receives ITypeLib object on success.
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
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];
431 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
435 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
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);
457 TRACE(" returns %08x\n",res);
461 /******************************************************************************
462 * LoadRegTypeLib [OLEAUT32.162]
464 * Loads a registered type library.
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.
475 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
478 HRESULT WINAPI LoadRegTypeLib(
490 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
494 res= LoadTypeLib(bstr, ppTLib);
498 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
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
515 * Docs: ITypeLib FAR * ptlib
516 * Docs: OLECHAR FAR* szFullPath
517 * Docs: OLECHAR FAR* szHelpDir
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,
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};
541 if (ptlib == NULL || szFullPath == NULL)
544 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
548 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
550 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
553 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
556 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
557 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
561 /* Set the human-readable name of the typelib */
562 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
566 if (RegSetValueExW(key, NULL, 0, REG_SZ,
567 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
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)
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};
596 sprintfW(buf, formatW, attr->wLibFlags);
597 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
598 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
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;
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, '\\');
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) {
634 if (freeHelpDir) SysFreeString(szHelpDir);
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);
656 case TKIND_INTERFACE:
657 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
658 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
662 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
663 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
667 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
672 TYPEATTR *tattr = NULL;
673 ITypeInfo_GetTypeAttr(tinfo, &tattr);
676 TRACE_(typelib)("guid=%s, flags=%04x (",
677 debugstr_guid(&tattr->guid),
680 if (TRACE_ON(typelib)) {
681 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
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)
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);
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);
729 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
730 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
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));
749 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
752 ITypeInfo_Release(tinfo);
759 ITypeLib_ReleaseTLibAttr(ptlib, attr);
765 /******************************************************************************
766 * UnRegisterTypeLib [OLEAUT32.186]
767 * Removes information about a type library from the System Registry
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 */
781 BSTR tlibPath = NULL;
784 WCHAR subKeyName[50];
787 BOOL deleteOtherStuff;
790 TYPEATTR* typeAttr = NULL;
792 ITypeInfo* typeInfo = NULL;
793 ITypeLib* typeLib = NULL;
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;
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;
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;
820 /* Try and load the type library */
821 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib) != S_OK) {
822 result = TYPE_E_INVALIDSTATE;
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) {
834 /* skip non-interfaces, and get type info for the type */
835 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
838 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
841 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
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)
855 RegDeleteKeyW(subKey, ProxyStubClsidW);
856 RegDeleteKeyW(subKey, ProxyStubClsid32W);
857 RegDeleteKeyW(subKey, TypeLibW);
860 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
864 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
866 if (typeInfo) ITypeInfo_Release(typeInfo);
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;
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;
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);
898 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
899 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
900 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
904 SysFreeString(tlibPath);
905 if (typeLib) ITypeLib_Release(typeLib);
906 if (subKey) RegCloseKey(subKey);
907 if (key) RegCloseKey(key);
911 /******************************************************************************
912 * RegisterTypeLibForUser [OLEAUT32.442]
913 * Adds information about a type library to the user registry
915 * Docs: ITypeLib FAR * ptlib
916 * Docs: OLECHAR FAR* szFullPath
917 * Docs: OLECHAR FAR* szHelpDir
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,
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
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 */
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
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
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 */
983 /* internal ITypeLib data */
984 typedef struct tagITypeLibImpl
986 const ITypeLib2Vtbl *lpVtbl;
987 const ITypeCompVtbl *lpVtblTypeComp;
989 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
992 /* strings can be stored in tlb as multibyte strings BUT they are *always*
993 * exported to the application as a UNICODE string.
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
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 */
1018 static const ITypeLib2Vtbl tlbvt;
1019 static const ITypeCompVtbl tlbtcvt;
1021 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1023 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1026 /* ITypeLib methods */
1027 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1028 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1030 /*======================= ITypeInfo implementation =======================*/
1032 /* data for referenced types */
1033 typedef struct tagTLBRefType
1035 INT index; /* Type index for internal ref or for external ref
1036 it the format is SLTG. -2 indicates to
1039 GUID guid; /* guid of the referenced type */
1040 /* if index == TLB_REF_USE_GUID */
1042 HREFTYPE reference; /* The href of this ref */
1043 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1044 TLB_REF_INTERNAL for internal refs
1045 TLB_REF_NOT_FOUND for broken refs */
1050 #define TLB_REF_USE_GUID -2
1052 #define TLB_REF_INTERNAL (void*)-2
1053 #define TLB_REF_NOT_FOUND (void*)-1
1055 /* internal Parameter data */
1056 typedef struct tagTLBParDesc
1059 struct list custdata_list;
1062 /* internal Function data */
1063 typedef struct tagTLBFuncDesc
1065 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1066 BSTR Name; /* the name of this function */
1067 TLBParDesc *pParamDesc; /* array with param names and custom data */
1069 int HelpStringContext;
1071 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1072 struct list custdata_list;
1075 /* internal Variable data */
1076 typedef struct tagTLBVarDesc
1078 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1079 BSTR Name; /* the name of this variable */
1081 int HelpStringContext;
1083 struct list custdata_list;
1086 /* internal implemented interface data */
1087 typedef struct tagTLBImplType
1089 HREFTYPE hRef; /* hRef of interface */
1090 int implflags; /* IMPLFLAG_*s */
1091 struct list custdata_list;
1094 /* internal TypeInfo data */
1095 typedef struct tagITypeInfoImpl
1097 const ITypeInfo2Vtbl *lpVtbl;
1098 const ITypeCompVtbl *lpVtblTypeComp;
1100 BOOL not_attached_to_typelib;
1101 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1102 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1103 int index; /* index in this typelib; */
1104 HREFTYPE hreftype; /* hreftype for app object binding */
1105 /* type libs seem to store the doc strings in ascii
1106 * so why should we do it in unicode?
1111 DWORD dwHelpContext;
1112 DWORD dwHelpStringContext;
1115 TLBFuncDesc *funcdescs;
1118 TLBVarDesc *vardescs;
1120 /* Implemented Interfaces */
1121 TLBImplType *impltypes;
1123 struct list custdata_list;
1126 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1128 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1131 static const ITypeInfo2Vtbl tinfvt;
1132 static const ITypeCompVtbl tcompvt;
1134 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1135 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1137 typedef struct tagTLBContext
1139 unsigned int oStart; /* start of TLB in file */
1140 unsigned int pos; /* current pos */
1141 unsigned int length; /* total length */
1142 void *mapping; /* memory mapping */
1143 MSFT_SegDir * pTblDir;
1144 ITypeLibImpl* pLibInfo;
1148 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1153 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1154 if (pTD->vt & VT_RESERVED)
1155 szVarType += strlen(strcpy(szVarType, "reserved | "));
1156 if (pTD->vt & VT_BYREF)
1157 szVarType += strlen(strcpy(szVarType, "ref to "));
1158 if (pTD->vt & VT_ARRAY)
1159 szVarType += strlen(strcpy(szVarType, "array of "));
1160 if (pTD->vt & VT_VECTOR)
1161 szVarType += strlen(strcpy(szVarType, "vector of "));
1162 switch(pTD->vt & VT_TYPEMASK) {
1163 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1164 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1165 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1166 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1167 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1168 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1169 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1170 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1171 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1172 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1173 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1174 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1175 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1176 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1177 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1178 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1179 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1180 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1181 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1182 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1183 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1184 pTD->u.hreftype); break;
1185 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1186 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1187 case VT_PTR: sprintf(szVarType, "ptr to ");
1188 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1190 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1191 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1193 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1194 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1195 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1198 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1202 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1204 USHORT flags = edesc->u.paramdesc.wParamFlags;
1205 dump_TypeDesc(&edesc->tdesc,buf);
1206 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1207 MESSAGE("\t\tu.paramdesc.wParamFlags");
1208 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1209 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1210 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1211 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1212 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1213 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1214 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1215 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1216 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1218 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1220 MESSAGE("memid is %08x\n",funcdesc->memid);
1221 for (i=0;i<funcdesc->cParams;i++) {
1222 MESSAGE("Param %d:\n",i);
1223 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1225 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1226 switch (funcdesc->funckind) {
1227 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1228 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1229 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1230 case FUNC_STATIC: MESSAGE("static");break;
1231 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1232 default: MESSAGE("unknown");break;
1234 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1235 switch (funcdesc->invkind) {
1236 case INVOKE_FUNC: MESSAGE("func");break;
1237 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1238 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1239 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1241 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1242 switch (funcdesc->callconv) {
1243 case CC_CDECL: MESSAGE("cdecl");break;
1244 case CC_PASCAL: MESSAGE("pascal");break;
1245 case CC_STDCALL: MESSAGE("stdcall");break;
1246 case CC_SYSCALL: MESSAGE("syscall");break;
1249 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1250 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1251 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1253 MESSAGE("\telemdescFunc (return value type):\n");
1254 dump_ELEMDESC(&funcdesc->elemdescFunc);
1257 static const char * const typekind_desc[] =
1270 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1273 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1274 for (i=0;i<pfd->funcdesc.cParams;i++)
1275 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1278 dump_FUNCDESC(&(pfd->funcdesc));
1280 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1281 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1283 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1287 dump_TLBFuncDescOne(pfd);
1292 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1296 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1302 static void dump_TLBImpLib(const TLBImpLib *import)
1304 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1305 debugstr_w(import->name));
1306 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1307 import->wVersionMinor, import->lcid, import->offset);
1310 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1314 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1316 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1317 if(ref->index == -1)
1318 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1320 TRACE_(typelib)("type no: %d\n", ref->index);
1322 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1324 TRACE_(typelib)("in lib\n");
1325 dump_TLBImpLib(ref->pImpTLInfo);
1330 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1335 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1336 impl->hRef, impl->implflags);
1342 static void dump_Variant(const VARIANT * pvar)
1346 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1350 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1351 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1353 TRACE(",%p", V_BYREF(pvar));
1355 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1357 TRACE(",%p", V_ARRAY(pvar));
1359 else switch (V_TYPE(pvar))
1361 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1362 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1363 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1364 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1366 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1368 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1369 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1370 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1371 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1372 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1373 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1374 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1375 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1376 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1377 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1378 V_CY(pvar).s.Lo); break;
1380 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1381 TRACE(",<invalid>");
1383 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1384 st.wHour, st.wMinute, st.wSecond);
1388 case VT_USERDEFINED:
1390 case VT_NULL: break;
1391 default: TRACE(",?"); break;
1397 static void dump_DispParms(const DISPPARAMS * pdp)
1401 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1403 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1405 TRACE("named args:\n");
1406 for (index = 0; index < pdp->cNamedArgs; index++)
1407 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1410 if (pdp->cArgs && pdp->rgvarg)
1413 for (index = 0; index < pdp->cArgs; index++)
1414 dump_Variant( &pdp->rgvarg[index] );
1418 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1420 TRACE("%p ref=%u\n", pty, pty->ref);
1421 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1422 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1423 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1424 TRACE("fct:%u var:%u impl:%u\n",
1425 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1426 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1427 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1428 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1430 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1431 dump_TLBVarDesc(pty->vardescs, pty->TypeAttr.cVars);
1432 dump_TLBImplType(pty->impltypes, pty->TypeAttr.cImplTypes);
1435 static void dump_VARDESC(const VARDESC *v)
1437 MESSAGE("memid %d\n",v->memid);
1438 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1439 MESSAGE("oInst %d\n",v->u.oInst);
1440 dump_ELEMDESC(&(v->elemdescVar));
1441 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1442 MESSAGE("varkind %d\n",v->varkind);
1445 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1447 /* VT_LPWSTR is largest type that, may appear in type description */
1448 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1449 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1450 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1451 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1452 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1453 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1454 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1455 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1458 static void TLB_abort(void)
1463 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1465 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1466 if (!ret) ERR("cannot allocate memory\n");
1470 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1472 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1473 if (!ret) ERR("cannot allocate memory\n");
1477 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1479 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1482 void heap_free(void *ptr)
1484 HeapFree(GetProcessHeap(), 0, ptr);
1487 /* returns the size required for a deep copy of a typedesc into a
1489 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1493 if (alloc_initial_space)
1494 size += sizeof(TYPEDESC);
1500 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1503 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1504 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1510 /* deep copy a typedesc into a flat buffer */
1511 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1516 buffer = (char *)buffer + sizeof(TYPEDESC);
1525 dest->u.lptdesc = buffer;
1526 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1529 dest->u.lpadesc = buffer;
1530 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1531 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1532 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1538 /* free custom data allocated by MSFT_CustData */
1539 static inline void TLB_FreeCustData(struct list *custdata_list)
1541 TLBCustData *cd, *cdn;
1542 LIST_FOR_EACH_ENTRY_SAFE(cd, cdn, custdata_list, TLBCustData, entry)
1544 list_remove(&cd->entry);
1545 VariantClear(&cd->data);
1550 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1555 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1556 ret = SysAllocStringLen(NULL, len - 1);
1557 if (!ret) return ret;
1558 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1562 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1563 UINT n, MEMBERID memid)
1566 if(funcdescs->funcdesc.memid == memid)
1574 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1575 UINT n, const OLECHAR *name)
1578 if(!lstrcmpiW(funcdescs->Name, name))
1586 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1587 UINT n, MEMBERID memid)
1590 if(vardescs->vardesc.memid == memid)
1598 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1599 UINT n, const OLECHAR *name)
1602 if(!lstrcmpiW(vardescs->Name, name))
1610 static inline TLBCustData *TLB_get_custdata_by_guid(struct list *custdata_list, REFGUID guid)
1612 TLBCustData *cust_data;
1613 LIST_FOR_EACH_ENTRY(cust_data, custdata_list, TLBCustData, entry)
1614 if(IsEqualIID(&cust_data->guid, guid))
1619 static TLBVarDesc *TLBVarDesc_Constructor(UINT n)
1623 ret = heap_alloc_zero(sizeof(TLBVarDesc) * n);
1628 list_init(&ret[n-1].custdata_list);
1635 static TLBParDesc *TLBParDesc_Constructor(UINT n)
1639 ret = heap_alloc_zero(sizeof(TLBParDesc) * n);
1644 list_init(&ret[n-1].custdata_list);
1651 static TLBFuncDesc *TLBFuncDesc_Constructor(UINT n)
1655 ret = heap_alloc_zero(sizeof(TLBFuncDesc) * n);
1660 list_init(&ret[n-1].custdata_list);
1667 static TLBImplType *TLBImplType_Constructor(UINT n)
1671 ret = heap_alloc_zero(sizeof(TLBImplType) * n);
1676 list_init(&ret[n-1].custdata_list);
1683 /**********************************************************************
1685 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1687 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1692 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1694 if (where != DO_NOT_SEEK)
1696 where += pcx->oStart;
1697 if (where > pcx->length)
1700 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1708 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1710 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1711 pcx->pos, count, pcx->oStart, pcx->length, where);
1713 MSFT_Seek(pcx, where);
1714 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1715 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1720 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1725 ret = MSFT_Read(buffer, count, pcx, where);
1726 FromLEDWords(buffer, ret);
1731 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1736 ret = MSFT_Read(buffer, count, pcx, where);
1737 FromLEWords(buffer, ret);
1742 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1744 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1745 memset(pGuid,0, sizeof(GUID));
1748 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1749 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1750 pGuid->Data2 = FromLEWord(pGuid->Data2);
1751 pGuid->Data3 = FromLEWord(pGuid->Data3);
1752 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1755 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1757 MSFT_NameIntro niName;
1761 ERR_(typelib)("bad offset %d\n", offset);
1765 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1766 pcx->pTblDir->pNametab.offset+offset);
1768 return niName.hreftype;
1771 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1774 MSFT_NameIntro niName;
1776 BSTR bstrName = NULL;
1780 ERR_(typelib)("bad offset %d\n", offset);
1783 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1784 pcx->pTblDir->pNametab.offset+offset);
1785 niName.namelen &= 0xFF; /* FIXME: correct ? */
1786 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1787 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1788 name[niName.namelen & 0xff]='\0';
1790 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1793 /* no invalid characters in string */
1796 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1798 /* don't check for invalid character since this has been done previously */
1799 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1803 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1807 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1814 if(offset<0) return NULL;
1815 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1816 if(length <= 0) return 0;
1817 string = heap_alloc_zero(length +1);
1818 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1819 string[length]='\0';
1821 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1822 string, -1, NULL, 0);
1824 /* no invalid characters in string */
1827 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1829 /* don't check for invalid character since this has been done previously */
1830 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1834 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1838 * read a value and fill a VARIANT structure
1840 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1844 TRACE_(typelib)("\n");
1846 if(offset <0) { /* data are packed in here */
1847 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1848 V_I4(pVar) = offset & 0x3ffffff;
1851 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1852 pcx->pTblDir->pCustData.offset + offset );
1853 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1854 switch (V_VT(pVar)){
1855 case VT_EMPTY: /* FIXME: is this right? */
1856 case VT_NULL: /* FIXME: is this right? */
1857 case VT_I2 : /* this should not happen */
1868 case VT_VOID : /* FIXME: is this right? */
1876 case VT_DECIMAL : /* FIXME: is this right? */
1879 /* pointer types with known behaviour */
1882 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1885 DWORD origPos = MSFT_Tell(pcx), nullPos;
1888 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1890 nullPos = MSFT_Tell(pcx);
1891 size = nullPos - origPos;
1892 MSFT_Seek(pcx, origPos);
1894 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1895 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1896 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1897 /* FIXME: do we need a AtoW conversion here? */
1898 V_UNION(pVar, bstrVal[size])='\0';
1899 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1903 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1910 case VT_USERDEFINED :
1916 case VT_STREAMED_OBJECT :
1917 case VT_STORED_OBJECT :
1918 case VT_BLOB_OBJECT :
1923 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1927 if(size>0) /* (big|small) endian correct? */
1928 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1932 * create a linked list with custom data
1934 static int MSFT_CustData( TLBContext *pcx, int offset, struct list *custdata_list)
1940 TRACE_(typelib)("\n");
1942 if (pcx->pTblDir->pCDGuids.offset < 0) return 0;
1946 pNew=heap_alloc_zero(sizeof(TLBCustData));
1947 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1948 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1949 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1950 list_add_head(custdata_list, &pNew->entry);
1951 offset = entry.next;
1956 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1960 pTd->vt=type & VT_TYPEMASK;
1962 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1964 if(pTd->vt == VT_USERDEFINED)
1965 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1967 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1970 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1972 /* resolve referenced type if any */
1975 switch (lpTypeDesc->vt)
1978 lpTypeDesc = lpTypeDesc->u.lptdesc;
1982 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1985 case VT_USERDEFINED:
1986 MSFT_DoRefType(pcx, pTI->pTypeLib,
1987 lpTypeDesc->u.hreftype);
1999 MSFT_DoFuncs(TLBContext* pcx,
2004 TLBFuncDesc** pptfd)
2007 * member information is stored in a data structure at offset
2008 * indicated by the memoffset field of the typeinfo structure
2009 * There are several distinctive parts.
2010 * The first part starts with a field that holds the total length
2011 * of this (first) part excluding this field. Then follow the records,
2012 * for each member there is one record.
2014 * The first entry is always the length of the record (including this
2016 * The rest of the record depends on the type of the member. If there is
2017 * a field indicating the member type (function, variable, interface, etc)
2018 * I have not found it yet. At this time we depend on the information
2019 * in the type info and the usual order how things are stored.
2021 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2024 * Third is an equal sized array with file offsets to the name entry
2027 * The fourth and last (?) part is an array with offsets to the records
2028 * in the first part of this file segment.
2031 int infolen, nameoffset, reclength, i;
2032 int recoffset = offset + sizeof(INT);
2034 char *recbuf = heap_alloc(0xffff);
2035 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
2036 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
2038 TRACE_(typelib)("\n");
2040 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
2042 *pptfd = TLBFuncDesc_Constructor(cFuncs);
2044 for ( i = 0; i < cFuncs ; i++ )
2048 /* name, eventually add to a hash table */
2049 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2050 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
2052 /* nameoffset is sometimes -1 on the second half of a propget/propput
2053 * pair of functions */
2054 if ((nameoffset == -1) && (i > 0))
2055 ptfd->Name = SysAllocString(ptfd_prev->Name);
2057 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
2059 /* read the function information record */
2060 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
2062 reclength &= 0xffff;
2064 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2066 /* size without argument data */
2067 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2069 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2070 ptfd->helpcontext = pFuncRec->HelpContext;
2072 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2073 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2075 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2077 if (pFuncRec->FKCCIC & 0x2000 )
2079 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2080 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2081 ptfd->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2084 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2087 ptfd->Entry = (BSTR)-1;
2089 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2090 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2092 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2093 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->custdata_list);
2095 /* fill the FuncDesc Structure */
2096 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2097 offset + infolen + ( i + 1) * sizeof(INT));
2099 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2100 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2101 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2102 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2103 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2104 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2105 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2109 &ptfd->funcdesc.elemdescFunc.tdesc,
2111 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2113 /* do the parameters/arguments */
2114 if(pFuncRec->nrargs)
2117 MSFT_ParameterInfo paraminfo;
2119 ptfd->funcdesc.lprgelemdescParam =
2120 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2122 ptfd->pParamDesc = TLBParDesc_Constructor(pFuncRec->nrargs);
2124 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
2125 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2127 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2129 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2136 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2139 if (paraminfo.oName == -1)
2140 /* this occurs for [propput] or [propget] methods, so
2141 * we should just set the name of the parameter to the
2142 * name of the method. */
2143 ptfd->pParamDesc[j].Name = SysAllocString(ptfd->Name);
2145 ptfd->pParamDesc[j].Name =
2146 MSFT_ReadName( pcx, paraminfo.oName );
2147 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(ptfd->pParamDesc[j].Name));
2149 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2152 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2153 (pFuncRec->FKCCIC & 0x1000) )
2155 INT* pInt = (INT *)((char *)pFuncRec +
2157 (pFuncRec->nrargs * 4) * sizeof(INT) );
2159 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2161 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2162 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2164 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2168 elemdesc->u.paramdesc.pparamdescex = NULL;
2171 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2172 j*sizeof(pFuncRec->oArgCustData[0])) &&
2173 pFuncRec->FKCCIC & 0x80 )
2176 pFuncRec->oArgCustData[j],
2177 &ptfd->pParamDesc[j].custdata_list);
2180 /* SEEK value = jump to offset,
2181 * from there jump to the end of record,
2182 * go back by (j-1) arguments
2184 MSFT_ReadLEDWords( ¶minfo ,
2185 sizeof(MSFT_ParameterInfo), pcx,
2186 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2187 * sizeof(MSFT_ParameterInfo)));
2191 /* scode is not used: archaic win16 stuff FIXME: right? */
2192 ptfd->funcdesc.cScodes = 0 ;
2193 ptfd->funcdesc.lprgscode = NULL ;
2197 recoffset += reclength;
2202 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2203 int cVars, int offset, TLBVarDesc ** pptvd)
2205 int infolen, nameoffset, reclength;
2207 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2212 TRACE_(typelib)("\n");
2214 ptvd = *pptvd = TLBVarDesc_Constructor(cVars);
2215 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2216 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2217 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2218 recoffset += offset+sizeof(INT);
2219 for(i=0;i<cVars;i++, ++ptvd){
2220 /* name, eventually add to a hash table */
2221 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2222 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2223 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2224 /* read the variable information record */
2225 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2227 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2230 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2231 ptvd->HelpContext = pVarRec->HelpContext;
2233 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2234 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2236 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2237 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2239 /* fill the VarDesc Structure */
2240 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2241 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2242 ptvd->vardesc.varkind = pVarRec->VarKind;
2243 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2244 MSFT_GetTdesc(pcx, pVarRec->DataType,
2245 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2246 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2247 if(pVarRec->VarKind == VAR_CONST ){
2248 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2249 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2250 pVarRec->OffsValue, pcx);
2252 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2253 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2254 recoffset += reclength;
2258 /* fill in data for a hreftype (offset). When the referenced type is contained
2259 * in the typelib, it's just an (file) offset in the type info base dir.
2260 * If comes from import, it's an offset+1 in the ImpInfo table
2262 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2267 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2269 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2271 if(ref->reference == offset) return;
2274 ref = heap_alloc_zero(sizeof(TLBRefType));
2275 list_add_tail(&pTL->ref_list, &ref->entry);
2277 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2278 /* external typelib */
2279 MSFT_ImpInfo impinfo;
2282 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2284 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2285 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2287 LIST_FOR_EACH_ENTRY(pImpLib, &pcx->pLibInfo->implib_list, TLBImpLib, entry)
2288 if(pImpLib->offset==impinfo.oImpFile)
2291 if(&pImpLib->entry != &pcx->pLibInfo->implib_list){
2292 ref->reference = offset;
2293 ref->pImpTLInfo = pImpLib;
2294 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2295 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2296 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2297 ref->index = TLB_REF_USE_GUID;
2299 ref->index = impinfo.oGuid;
2301 ERR("Cannot find a reference\n");
2302 ref->reference = -1;
2303 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2306 /* in this typelib */
2307 ref->index = MSFT_HREFTYPE_INDEX(offset);
2308 ref->reference = offset;
2309 ref->pImpTLInfo = TLB_REF_INTERNAL;
2313 /* process Implemented Interfaces of a com class */
2314 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2318 MSFT_RefRecord refrec;
2321 TRACE_(typelib)("\n");
2323 pTI->impltypes = TLBImplType_Constructor(count);
2324 pImpl = pTI->impltypes;
2325 for(i=0;i<count;i++){
2326 if(offset<0) break; /* paranoia */
2327 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2328 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2329 pImpl->hRef = refrec.reftype;
2330 pImpl->implflags=refrec.flags;
2331 MSFT_CustData(pcx, refrec.oCustData, &pImpl->custdata_list);
2332 offset=refrec.onext;
2337 * process a typeinfo record
2339 static ITypeInfoImpl * MSFT_DoTypeInfo(
2342 ITypeLibImpl * pLibInfo)
2344 MSFT_TypeInfoBase tiBase;
2345 ITypeInfoImpl *ptiRet;
2347 TRACE_(typelib)("count=%u\n", count);
2349 ptiRet = ITypeInfoImpl_Constructor();
2350 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2351 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2353 /* this is where we are coming from */
2354 ptiRet->pTypeLib = pLibInfo;
2355 ptiRet->index=count;
2356 /* fill in the typeattr fields */
2358 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2359 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2360 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2361 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2362 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2363 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2364 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2365 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2366 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2367 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2368 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2369 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2370 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2371 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2372 MSFT_GetTdesc(pcx, tiBase.datatype1,
2373 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2376 /* IDLDESC idldescType; *//* never saw this one != zero */
2378 /* name, eventually add to a hash table */
2379 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2380 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2381 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2383 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2384 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2385 ptiRet->dwHelpContext=tiBase.helpcontext;
2387 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2388 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2390 /* note: InfoType's Help file and HelpStringDll come from the containing
2391 * library. Further HelpString and Docstring appear to be the same thing :(
2394 if(ptiRet->TypeAttr.cFuncs >0 )
2395 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2396 ptiRet->TypeAttr.cVars,
2397 tiBase.memoffset, &ptiRet->funcdescs);
2399 if(ptiRet->TypeAttr.cVars >0 )
2400 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2401 ptiRet->TypeAttr.cVars,
2402 tiBase.memoffset, &ptiRet->vardescs);
2403 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2404 switch(ptiRet->TypeAttr.typekind)
2407 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2410 case TKIND_DISPATCH:
2411 /* This is not -1 when the interface is a non-base dual interface or
2412 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2413 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2417 if (tiBase.datatype1 != -1)
2419 ptiRet->impltypes = TLBImplType_Constructor(1);
2420 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2421 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2425 ptiRet->impltypes = TLBImplType_Constructor(1);
2426 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2427 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2431 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->custdata_list);
2433 TRACE_(typelib)("%s guid: %s kind:%s\n",
2434 debugstr_w(ptiRet->Name),
2435 debugstr_guid(&ptiRet->TypeAttr.guid),
2436 typekind_desc[ptiRet->TypeAttr.typekind]);
2437 if (TRACE_ON(typelib))
2438 dump_TypeInfo(ptiRet);
2443 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2444 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2445 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2448 static struct list tlb_cache = LIST_INIT(tlb_cache);
2449 static CRITICAL_SECTION cache_section;
2450 static CRITICAL_SECTION_DEBUG cache_section_debug =
2452 0, 0, &cache_section,
2453 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2454 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2456 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2459 typedef struct TLB_PEFile
2461 const IUnknownVtbl *lpvtbl;
2464 HRSRC typelib_resource;
2465 HGLOBAL typelib_global;
2466 LPVOID typelib_base;
2469 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2471 if (IsEqualIID(riid, &IID_IUnknown))
2474 IUnknown_AddRef(iface);
2478 return E_NOINTERFACE;
2481 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2483 TLB_PEFile *This = (TLB_PEFile *)iface;
2484 return InterlockedIncrement(&This->refs);
2487 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2489 TLB_PEFile *This = (TLB_PEFile *)iface;
2490 ULONG refs = InterlockedDecrement(&This->refs);
2493 if (This->typelib_global)
2494 FreeResource(This->typelib_global);
2496 FreeLibrary(This->dll);
2502 static const IUnknownVtbl TLB_PEFile_Vtable =
2504 TLB_PEFile_QueryInterface,
2509 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2513 This = heap_alloc(sizeof(TLB_PEFile));
2515 return E_OUTOFMEMORY;
2517 This->lpvtbl = &TLB_PEFile_Vtable;
2520 This->typelib_resource = NULL;
2521 This->typelib_global = NULL;
2522 This->typelib_base = NULL;
2524 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2525 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2529 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2530 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2531 if (This->typelib_resource)
2533 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2534 if (This->typelib_global)
2536 This->typelib_base = LockResource(This->typelib_global);
2538 if (This->typelib_base)
2540 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2541 *ppBase = This->typelib_base;
2542 *ppFile = (IUnknown *)&This->lpvtbl;
2549 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2550 return TYPE_E_CANTLOADLIBRARY;
2553 typedef struct TLB_NEFile
2555 const IUnknownVtbl *lpvtbl;
2557 LPVOID typelib_base;
2560 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2562 if (IsEqualIID(riid, &IID_IUnknown))
2565 IUnknown_AddRef(iface);
2569 return E_NOINTERFACE;
2572 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2574 TLB_NEFile *This = (TLB_NEFile *)iface;
2575 return InterlockedIncrement(&This->refs);
2578 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2580 TLB_NEFile *This = (TLB_NEFile *)iface;
2581 ULONG refs = InterlockedDecrement(&This->refs);
2584 heap_free(This->typelib_base);
2590 static const IUnknownVtbl TLB_NEFile_Vtable =
2592 TLB_NEFile_QueryInterface,
2597 /***********************************************************************
2598 * read_xx_header [internal]
2600 static int read_xx_header( HFILE lzfd )
2602 IMAGE_DOS_HEADER mzh;
2605 LZSeek( lzfd, 0, SEEK_SET );
2606 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2608 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2611 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2612 if ( 2 != LZRead( lzfd, magic, 2 ) )
2615 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2617 if ( magic[0] == 'N' && magic[1] == 'E' )
2618 return IMAGE_OS2_SIGNATURE;
2619 if ( magic[0] == 'P' && magic[1] == 'E' )
2620 return IMAGE_NT_SIGNATURE;
2623 WARN("Can't handle %s files.\n", magic );
2628 /***********************************************************************
2629 * find_ne_resource [internal]
2631 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2632 DWORD *resLen, DWORD *resOff )
2634 IMAGE_OS2_HEADER nehd;
2635 NE_TYPEINFO *typeInfo;
2636 NE_NAMEINFO *nameInfo;
2642 /* Read in NE header */
2643 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2644 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2646 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2649 TRACE("No resources in NE dll\n" );
2653 /* Read in resource table */
2654 resTab = heap_alloc( resTabSize );
2655 if ( !resTab ) return FALSE;
2657 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2658 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2660 heap_free( resTab );
2665 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2667 if (!IS_INTRESOURCE(typeid)) /* named type */
2669 BYTE len = strlen( typeid );
2670 while (typeInfo->type_id)
2672 if (!(typeInfo->type_id & 0x8000))
2674 BYTE *p = resTab + typeInfo->type_id;
2675 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2677 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2678 typeInfo->count * sizeof(NE_NAMEINFO));
2681 else /* numeric type id */
2683 WORD id = LOWORD(typeid) | 0x8000;
2684 while (typeInfo->type_id)
2686 if (typeInfo->type_id == id) goto found_type;
2687 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2688 typeInfo->count * sizeof(NE_NAMEINFO));
2691 TRACE("No typeid entry found for %p\n", typeid );
2692 heap_free( resTab );
2696 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2698 if (!IS_INTRESOURCE(resid)) /* named resource */
2700 BYTE len = strlen( resid );
2701 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2703 BYTE *p = resTab + nameInfo->id;
2704 if (nameInfo->id & 0x8000) continue;
2705 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2708 else /* numeric resource id */
2710 WORD id = LOWORD(resid) | 0x8000;
2711 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2712 if (nameInfo->id == id) goto found_name;
2714 TRACE("No resid entry found for %p\n", typeid );
2715 heap_free( resTab );
2719 /* Return resource data */
2720 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2721 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2723 heap_free( resTab );
2727 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2731 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2734 This = heap_alloc(sizeof(TLB_NEFile));
2735 if (!This) return E_OUTOFMEMORY;
2737 This->lpvtbl = &TLB_NEFile_Vtable;
2739 This->typelib_base = NULL;
2741 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2742 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2744 DWORD reslen, offset;
2745 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2747 This->typelib_base = heap_alloc(reslen);
2748 if( !This->typelib_base )
2752 LZSeek( lzfd, offset, SEEK_SET );
2753 reslen = LZRead( lzfd, This->typelib_base, reslen );
2755 *ppBase = This->typelib_base;
2756 *pdwTLBLength = reslen;
2757 *ppFile = (IUnknown *)&This->lpvtbl;
2763 if( lzfd >= 0) LZClose( lzfd );
2764 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2768 typedef struct TLB_Mapping
2770 const IUnknownVtbl *lpvtbl;
2774 LPVOID typelib_base;
2777 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2779 if (IsEqualIID(riid, &IID_IUnknown))
2782 IUnknown_AddRef(iface);
2786 return E_NOINTERFACE;
2789 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2791 TLB_Mapping *This = (TLB_Mapping *)iface;
2792 return InterlockedIncrement(&This->refs);
2795 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2797 TLB_Mapping *This = (TLB_Mapping *)iface;
2798 ULONG refs = InterlockedDecrement(&This->refs);
2801 if (This->typelib_base)
2802 UnmapViewOfFile(This->typelib_base);
2804 CloseHandle(This->mapping);
2805 if (This->file != INVALID_HANDLE_VALUE)
2806 CloseHandle(This->file);
2812 static const IUnknownVtbl TLB_Mapping_Vtable =
2814 TLB_Mapping_QueryInterface,
2819 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2823 This = heap_alloc(sizeof(TLB_Mapping));
2825 return E_OUTOFMEMORY;
2827 This->lpvtbl = &TLB_Mapping_Vtable;
2829 This->file = INVALID_HANDLE_VALUE;
2830 This->mapping = NULL;
2831 This->typelib_base = NULL;
2833 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2834 if (INVALID_HANDLE_VALUE != This->file)
2836 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2839 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2840 if(This->typelib_base)
2842 /* retrieve file size */
2843 *pdwTLBLength = GetFileSize(This->file, NULL);
2844 *ppBase = This->typelib_base;
2845 *ppFile = (IUnknown *)&This->lpvtbl;
2851 IUnknown_Release((IUnknown *)&This->lpvtbl);
2852 return TYPE_E_CANTLOADLIBRARY;
2855 /****************************************************************************
2858 * find the type of the typelib file and map the typelib resource into
2862 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2863 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2865 ITypeLibImpl *entry;
2868 LPWSTR index_str, file = (LPWSTR)pszFileName;
2869 LPVOID pBase = NULL;
2870 DWORD dwTLBLength = 0;
2871 IUnknown *pFile = NULL;
2875 index_str = strrchrW(pszFileName, '\\');
2876 if(index_str && *++index_str != '\0')
2879 LONG idx = strtolW(index_str, &end_ptr, 10);
2880 if(*end_ptr == '\0')
2882 int str_len = index_str - pszFileName - 1;
2884 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2885 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2890 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2892 if(strchrW(file, '\\'))
2894 lstrcpyW(pszPath, file);
2898 int len = GetSystemDirectoryW(pszPath, cchPath);
2899 pszPath[len] = '\\';
2900 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2904 if(file != pszFileName) heap_free(file);
2906 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2908 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2909 EnterCriticalSection(&cache_section);
2910 LIST_FOR_EACH_ENTRY(entry, &tlb_cache, ITypeLibImpl, entry)
2912 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2914 TRACE("cache hit\n");
2915 *ppTypeLib = (ITypeLib2*)entry;
2916 ITypeLib2_AddRef(*ppTypeLib);
2917 LeaveCriticalSection(&cache_section);
2921 LeaveCriticalSection(&cache_section);
2923 /* now actually load and parse the typelib */
2925 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2926 if (ret == TYPE_E_CANTLOADLIBRARY)
2927 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2928 if (ret == TYPE_E_CANTLOADLIBRARY)
2929 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2932 if (dwTLBLength >= 4)
2934 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2935 if (dwSignature == MSFT_SIGNATURE)
2936 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2937 else if (dwSignature == SLTG_SIGNATURE)
2938 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2941 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2942 ret = TYPE_E_CANTLOADLIBRARY;
2946 ret = TYPE_E_CANTLOADLIBRARY;
2947 IUnknown_Release(pFile);
2951 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2953 TRACE("adding to cache\n");
2954 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2955 lstrcpyW(impl->path, pszPath);
2956 /* We should really canonicalise the path here. */
2957 impl->index = index;
2959 /* FIXME: check if it has added already in the meantime */
2960 EnterCriticalSection(&cache_section);
2961 list_add_head(&tlb_cache, &impl->entry);
2962 LeaveCriticalSection(&cache_section);
2965 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2970 /*================== ITypeLib(2) Methods ===================================*/
2972 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2974 ITypeLibImpl* pTypeLibImpl;
2976 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2977 if (!pTypeLibImpl) return NULL;
2979 pTypeLibImpl->lpVtbl = &tlbvt;
2980 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2981 pTypeLibImpl->ref = 1;
2983 list_init(&pTypeLibImpl->implib_list);
2984 list_init(&pTypeLibImpl->custdata_list);
2985 list_init(&pTypeLibImpl->ref_list);
2986 pTypeLibImpl->dispatch_href = -1;
2988 return pTypeLibImpl;
2991 /****************************************************************************
2992 * ITypeLib2_Constructor_MSFT
2994 * loading an MSFT typelib from an in-memory image
2996 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
3000 MSFT_Header tlbHeader;
3001 MSFT_SegDir tlbSegDir;
3002 ITypeLibImpl * pTypeLibImpl;
3004 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
3006 pTypeLibImpl = TypeLibImpl_Constructor();
3007 if (!pTypeLibImpl) return NULL;
3009 /* get pointer to beginning of typelib data */
3013 cx.pLibInfo = pTypeLibImpl;
3014 cx.length = dwTLBLength;
3017 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
3018 TRACE_(typelib)("header:\n");
3019 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
3020 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
3021 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
3024 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
3026 /* there is a small amount of information here until the next important
3028 * the segment directory . Try to calculate the amount of data */
3029 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
3031 /* now read the segment directory */
3032 TRACE("read segment directory (at %d)\n",lPSegDir);
3033 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
3034 cx.pTblDir = &tlbSegDir;
3036 /* just check two entries */
3037 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
3039 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
3040 heap_free(pTypeLibImpl);
3044 /* now fill our internal data */
3045 /* TLIBATTR fields */
3046 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
3048 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
3049 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
3050 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
3051 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
3052 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
3054 pTypeLibImpl->lcid = tlbHeader.lcid;
3056 /* name, eventually add to a hash table */
3057 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
3060 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
3061 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
3063 if( tlbHeader.varflags & HELPDLLFLAG)
3066 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3067 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3070 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3073 if(tlbHeader.CustomDataOffset >= 0)
3075 MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->custdata_list);
3078 /* fill in type descriptions */
3079 if(tlbSegDir.pTypdescTab.length > 0)
3081 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3083 pTypeLibImpl->ctTypeDesc = cTD;
3084 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3085 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3088 /* FIXME: add several sanity checks here */
3089 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3090 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3092 /* FIXME: check safearray */
3094 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3096 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3098 else if(td[0] == VT_CARRAY)
3100 /* array descr table here */
3101 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3103 else if(td[0] == VT_USERDEFINED)
3105 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3107 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3110 /* second time around to fill the array subscript info */
3113 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3114 if(tlbSegDir.pArrayDescriptions.offset>0)
3116 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3117 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3120 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3122 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3124 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3126 for(j = 0; j<td[2]; j++)
3128 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3129 sizeof(INT), &cx, DO_NOT_SEEK);
3130 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3131 sizeof(INT), &cx, DO_NOT_SEEK);
3136 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3137 ERR("didn't find array description data\n");
3142 /* imported type libs */
3143 if(tlbSegDir.pImpFiles.offset>0)
3146 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3149 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3153 pImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3154 pImpLib->offset = offset - tlbSegDir.pImpFiles.offset;
3155 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3157 MSFT_ReadLEDWords(&pImpLib->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3158 MSFT_ReadLEWords(&pImpLib->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3159 MSFT_ReadLEWords(&pImpLib->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3160 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3163 name = heap_alloc_zero(size+1);
3164 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3165 pImpLib->name = TLB_MultiByteToBSTR(name);
3168 MSFT_ReadGuid(&pImpLib->guid, oGuid, &cx);
3169 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3171 list_add_tail(&pTypeLibImpl->implib_list, &pImpLib->entry);
3175 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3176 if(pTypeLibImpl->dispatch_href != -1)
3177 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3180 if(tlbHeader.nrtypeinfos >= 0 )
3182 ITypeInfoImpl **ppTI;
3185 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3187 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3189 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3192 (pTypeLibImpl->TypeInfoCount)++;
3196 TRACE("(%p)\n", pTypeLibImpl);
3197 return (ITypeLib2*) pTypeLibImpl;
3201 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3207 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3208 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3212 guid->Data4[0] = s >> 8;
3213 guid->Data4[1] = s & 0xff;
3216 for(i = 0; i < 6; i++) {
3217 memcpy(b, str + 24 + 2 * i, 2);
3218 guid->Data4[i + 2] = strtol(b, NULL, 16);
3223 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3229 bytelen = *(const WORD*)ptr;
3230 if(bytelen == 0xffff) return 2;
3231 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3232 *pBstr = SysAllocStringLen(NULL, len);
3234 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3238 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3243 bytelen = *(const WORD*)ptr;
3244 if(bytelen == 0xffff) return 2;
3245 *str = heap_alloc(bytelen + 1);
3246 memcpy(*str, ptr + 2, bytelen);
3247 (*str)[bytelen] = '\0';
3251 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3253 char *ptr = pLibBlk;
3256 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3257 FIXME("libblk magic = %04x\n", w);
3262 if((w = *(WORD*)ptr) != 0xffff) {
3263 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3268 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3270 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3272 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3275 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3278 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3279 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3281 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3284 ptr += 4; /* skip res12 */
3286 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3289 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3292 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3295 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3296 ptr += sizeof(GUID);
3298 return ptr - (char*)pLibBlk;
3301 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3306 } sltg_ref_lookup_t;
3308 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3309 HREFTYPE *typelib_ref)
3311 if(table && typeinfo_ref < table->num)
3313 *typelib_ref = table->refs[typeinfo_ref];
3317 ERR_(typelib)("Unable to find reference\n");
3322 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3327 if((*pType & 0xe00) == 0xe00) {
3329 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3330 pTD = pTD->u.lptdesc;
3332 switch(*pType & 0x3f) {
3335 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3336 pTD = pTD->u.lptdesc;
3339 case VT_USERDEFINED:
3340 pTD->vt = VT_USERDEFINED;
3341 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3347 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3350 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3352 pTD->vt = VT_CARRAY;
3353 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3354 pTD->u.lpadesc->cDims = pSA->cDims;
3355 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3356 pSA->cDims * sizeof(SAFEARRAYBOUND));
3358 pTD = &pTD->u.lpadesc->tdescElem;
3364 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3368 pTD->vt = VT_SAFEARRAY;
3369 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3370 pTD = pTD->u.lptdesc;
3374 pTD->vt = *pType & 0x3f;
3383 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3384 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3386 /* Handle [in/out] first */
3387 if((*pType & 0xc000) == 0xc000)
3388 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3389 else if(*pType & 0x8000)
3390 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3391 else if(*pType & 0x4000)
3392 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3394 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3397 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3400 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3402 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3406 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3411 TLBRefType *ref_type;
3412 sltg_ref_lookup_t *table;
3413 HREFTYPE typelib_ref;
3415 if(pRef->magic != SLTG_REF_MAGIC) {
3416 FIXME("Ref magic = %x\n", pRef->magic);
3419 name = ( (char*)pRef->names + pRef->number);
3421 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3422 table->num = pRef->number >> 3;
3424 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3426 /* We don't want the first href to be 0 */
3427 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3429 for(ref = 0; ref < pRef->number >> 3; ref++) {
3431 unsigned int lib_offs, type_num;
3433 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3435 name += SLTG_ReadStringA(name, &refname);
3436 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3437 FIXME_(typelib)("Can't sscanf ref\n");
3438 if(lib_offs != 0xffff) {
3441 LIST_FOR_EACH_ENTRY(import, &pTL->implib_list, TLBImpLib, entry)
3442 if(import->offset == lib_offs)
3445 if(&import->entry == &pTL->implib_list) {
3446 char fname[MAX_PATH+1];
3449 import = heap_alloc_zero(sizeof(*import));
3450 import->offset = lib_offs;
3451 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3453 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3454 &import->wVersionMajor,
3455 &import->wVersionMinor,
3456 &import->lcid, fname) != 4) {
3457 FIXME_(typelib)("can't sscanf ref %s\n",
3458 pNameTable + lib_offs + 40);
3460 len = strlen(fname);
3461 if(fname[len-1] != '#')
3462 FIXME("fname = %s\n", fname);
3463 fname[len-1] = '\0';
3464 import->name = TLB_MultiByteToBSTR(fname);
3465 list_add_tail(&pTL->implib_list, &import->entry);
3467 ref_type->pImpTLInfo = import;
3469 /* Store a reference to IDispatch */
3470 if(pTL->dispatch_href == -1 && IsEqualGUID(&import->guid, &IID_StdOle) && type_num == 4)
3471 pTL->dispatch_href = typelib_ref;
3473 } else { /* internal ref */
3474 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3476 ref_type->reference = typelib_ref;
3477 ref_type->index = type_num;
3480 list_add_tail(&pTL->ref_list, &ref_type->entry);
3482 table->refs[ref] = typelib_ref;
3485 if((BYTE)*name != SLTG_REF_MAGIC)
3486 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3487 dump_TLBRefType(pTL);
3491 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3492 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3494 SLTG_ImplInfo *info;
3495 TLBImplType *pImplType;
3496 /* I don't really get this structure, usually it's 0x16 bytes
3497 long, but iuser.tlb contains some that are 0x18 bytes long.
3498 That's ok because we can use the next ptr to jump to the next
3499 one. But how do we know the length of the last one? The WORD
3500 at offs 0x8 might be the clue. For now I'm just assuming that
3501 the last one is the regular 0x16 bytes. */
3503 info = (SLTG_ImplInfo*)pBlk;
3505 pTI->TypeAttr.cImplTypes++;
3506 if(info->next == 0xffff)
3508 info = (SLTG_ImplInfo*)(pBlk + info->next);
3511 info = (SLTG_ImplInfo*)pBlk;
3512 pTI->impltypes = TLBImplType_Constructor(pTI->TypeAttr.cImplTypes);
3513 pImplType = pTI->impltypes;
3515 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3516 pImplType->implflags = info->impltypeflags;
3519 if(info->next == 0xffff)
3522 FIXME_(typelib)("Interface inheriting more than one interface\n");
3523 info = (SLTG_ImplInfo*)(pBlk + info->next);
3525 info++; /* see comment at top of function */
3529 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3530 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3532 TLBVarDesc *pVarDesc;
3533 BSTR bstrPrevName = NULL;
3534 SLTG_Variable *pItem;
3538 pVarDesc = pTI->vardescs = TLBVarDesc_Constructor(cVars);
3540 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3541 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3543 pVarDesc->vardesc.memid = pItem->memid;
3545 if (pItem->magic != SLTG_VAR_MAGIC &&
3546 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3547 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3551 if (pItem->name == 0xfffe)
3552 pVarDesc->Name = SysAllocString(bstrPrevName);
3554 pVarDesc->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3556 TRACE_(typelib)("name: %s\n", debugstr_w(pVarDesc->Name));
3557 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3558 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3560 if(pItem->flags & 0x02)
3561 pType = &pItem->type;
3563 pType = (WORD*)(pBlk + pItem->type);
3565 if (pItem->flags & ~0xda)
3566 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3568 SLTG_DoElem(pType, pBlk,
3569 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3571 if (TRACE_ON(typelib)) {
3573 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3574 TRACE_(typelib)("elemdescVar: %s\n", buf);
3577 if (pItem->flags & 0x40) {
3578 TRACE_(typelib)("VAR_DISPATCH\n");
3579 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3581 else if (pItem->flags & 0x10) {
3582 TRACE_(typelib)("VAR_CONST\n");
3583 pVarDesc->vardesc.varkind = VAR_CONST;
3584 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3585 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3586 if (pItem->flags & 0x08)
3587 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3589 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3595 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3597 TRACE_(typelib)("len = %u\n", len);
3598 if (len == 0xffff) {
3601 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3602 str = SysAllocStringLen(NULL, alloc_len);
3603 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3605 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3606 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3615 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3616 *(INT*)(pBlk + pItem->byte_offs);
3619 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3624 TRACE_(typelib)("VAR_PERINSTANCE\n");
3625 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3626 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3629 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3630 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3632 if (pItem->flags & 0x80)
3633 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3635 bstrPrevName = pVarDesc->Name;
3637 pTI->TypeAttr.cVars = cVars;
3640 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3641 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3643 SLTG_Function *pFunc;
3645 TLBFuncDesc *pFuncDesc;
3647 pTI->funcdescs = TLBFuncDesc_Constructor(cFuncs);
3649 pFuncDesc = pTI->funcdescs;
3650 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3651 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3656 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3657 case SLTG_FUNCTION_MAGIC:
3658 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3660 case SLTG_DISPATCH_FUNCTION_MAGIC:
3661 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3663 case SLTG_STATIC_FUNCTION_MAGIC:
3664 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3667 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3670 pFuncDesc->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3672 pFuncDesc->funcdesc.memid = pFunc->dispid;
3673 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3674 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3675 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3676 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3677 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3679 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3680 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3682 if(pFunc->retnextopt & 0x80)
3683 pType = &pFunc->rettype;
3685 pType = (WORD*)(pBlk + pFunc->rettype);
3687 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3689 pFuncDesc->funcdesc.lprgelemdescParam =
3690 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3691 pFuncDesc->pParamDesc = TLBParDesc_Constructor(pFuncDesc->funcdesc.cParams);
3693 pArg = (WORD*)(pBlk + pFunc->arg_off);
3695 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3696 char *paramName = pNameTable + *pArg;
3698 /* If arg type follows then paramName points to the 2nd
3699 letter of the name, else the next WORD is an offset to
3700 the arg type and paramName points to the first letter.
3701 So let's take one char off paramName and see if we're
3702 pointing at an alpha-numeric char. However if *pArg is
3703 0xffff or 0xfffe then the param has no name, the former
3704 meaning that the next WORD is the type, the latter
3705 meaning that the next WORD is an offset to the type. */
3710 else if(*pArg == 0xfffe) {
3714 else if(paramName[-1] && !isalnum(paramName[-1]))
3719 if(HaveOffs) { /* the next word is an offset to type */
3720 pType = (WORD*)(pBlk + *pArg);
3721 SLTG_DoElem(pType, pBlk,
3722 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3727 pArg = SLTG_DoElem(pArg, pBlk,
3728 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3731 /* Are we an optional param ? */
3732 if(pFuncDesc->funcdesc.cParams - param <=
3733 pFuncDesc->funcdesc.cParamsOpt)
3734 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3737 pFuncDesc->pParamDesc[param].Name =
3738 TLB_MultiByteToBSTR(paramName);
3740 pFuncDesc->pParamDesc[param].Name =
3741 SysAllocString(pFuncDesc->Name);
3745 pTI->TypeAttr.cFuncs = cFuncs;
3748 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3749 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3750 SLTG_TypeInfoTail *pTITail)
3753 sltg_ref_lookup_t *ref_lookup = NULL;
3755 if(pTIHeader->href_table != 0xffffffff) {
3756 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3762 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3763 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3765 heap_free(ref_lookup);
3769 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3770 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3771 const SLTG_TypeInfoTail *pTITail)
3774 sltg_ref_lookup_t *ref_lookup = NULL;
3776 if(pTIHeader->href_table != 0xffffffff) {
3777 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3783 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3784 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3787 if (pTITail->funcs_off != 0xffff)
3788 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3790 heap_free(ref_lookup);
3792 if (TRACE_ON(typelib))
3793 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3796 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3797 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3798 const SLTG_TypeInfoTail *pTITail)
3800 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3803 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3804 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3805 const SLTG_TypeInfoTail *pTITail)
3808 sltg_ref_lookup_t *ref_lookup = NULL;
3810 if (pTITail->simple_alias) {
3811 /* if simple alias, no more processing required */
3812 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3816 if(pTIHeader->href_table != 0xffffffff) {
3817 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3821 /* otherwise it is an offset to a type */
3822 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3824 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3826 heap_free(ref_lookup);
3829 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3830 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3831 const SLTG_TypeInfoTail *pTITail)
3833 sltg_ref_lookup_t *ref_lookup = NULL;
3834 if (pTIHeader->href_table != 0xffffffff)
3835 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3838 if (pTITail->vars_off != 0xffff)
3839 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3841 if (pTITail->funcs_off != 0xffff)
3842 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3844 if (pTITail->impls_off != 0xffff)
3845 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3847 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3848 * of dispinterface functions including the IDispatch ones, so
3849 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3850 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3852 heap_free(ref_lookup);
3853 if (TRACE_ON(typelib))
3854 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3857 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3858 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3859 const SLTG_TypeInfoTail *pTITail)
3861 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3864 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3865 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3866 const SLTG_TypeInfoTail *pTITail)
3868 sltg_ref_lookup_t *ref_lookup = NULL;
3869 if (pTIHeader->href_table != 0xffffffff)
3870 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3873 if (pTITail->vars_off != 0xffff)
3874 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3876 if (pTITail->funcs_off != 0xffff)
3877 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3878 heap_free(ref_lookup);
3879 if (TRACE_ON(typelib))
3883 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3884 manageable copy of it into this */
3897 } SLTG_InternalOtherTypeInfo;
3899 /****************************************************************************
3900 * ITypeLib2_Constructor_SLTG
3902 * loading a SLTG typelib from an in-memory image
3904 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3906 ITypeLibImpl *pTypeLibImpl;
3907 SLTG_Header *pHeader;
3908 SLTG_BlkEntry *pBlkEntry;
3912 LPVOID pBlk, pFirstBlk;
3913 SLTG_LibBlk *pLibBlk;
3914 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3915 char *pAfterOTIBlks = NULL;
3916 char *pNameTable, *ptr;
3919 ITypeInfoImpl **ppTypeInfoImpl;
3921 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3924 pTypeLibImpl = TypeLibImpl_Constructor();
3925 if (!pTypeLibImpl) return NULL;
3929 TRACE_(typelib)("header:\n");
3930 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3931 pHeader->nrOfFileBlks );
3932 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3933 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3934 pHeader->SLTG_magic);
3938 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3939 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3941 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3942 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3944 /* Next we have a magic block */
3945 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3947 /* Let's see if we're still in sync */
3948 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3949 sizeof(SLTG_COMPOBJ_MAGIC))) {
3950 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3953 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3954 sizeof(SLTG_DIR_MAGIC))) {
3955 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3959 pIndex = (SLTG_Index*)(pMagic+1);
3961 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3963 pFirstBlk = pPad9 + 1;
3965 /* We'll set up a ptr to the main library block, which is the last one. */
3967 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3968 pBlkEntry[order].next != 0;
3969 order = pBlkEntry[order].next - 1, i++) {
3970 pBlk = (char*)pBlk + pBlkEntry[order].len;
3974 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3976 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3981 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3983 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3986 ptr = (char*)pLibBlk + len;
3988 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3992 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3994 w = *(WORD*)(ptr + 2);
3997 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
3998 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3999 pOtherTypeInfoBlks[i].index_name[w] = '\0';
4001 w = *(WORD*)(ptr + 4 + len);
4003 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
4005 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
4006 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
4007 pOtherTypeInfoBlks[i].other_name[w] = '\0';
4009 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
4010 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
4011 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
4013 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
4014 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
4017 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
4018 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
4019 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
4020 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
4021 len += sizeof(SLTG_OtherTypeInfo);
4025 pAfterOTIBlks = ptr;
4027 /* Skip this WORD and get the next DWORD */
4028 len = *(DWORD*)(pAfterOTIBlks + 2);
4030 /* Now add this to pLibBLk look at what we're pointing at and
4031 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4032 dust and we should be pointing at the beginning of the name
4035 pNameTable = (char*)pLibBlk + len;
4037 switch(*(WORD*)pNameTable) {
4044 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
4048 pNameTable += 0x216;
4052 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
4054 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
4057 /* Hopefully we now have enough ptrs set up to actually read in
4058 some TypeInfos. It's not clear which order to do them in, so
4059 I'll just follow the links along the BlkEntry chain and read
4060 them in the order in which they are in the file */
4062 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
4063 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4065 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4066 pBlkEntry[order].next != 0;
4067 order = pBlkEntry[order].next - 1, i++) {
4069 SLTG_TypeInfoHeader *pTIHeader;
4070 SLTG_TypeInfoTail *pTITail;
4071 SLTG_MemberHeader *pMemHeader;
4073 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic, pOtherTypeInfoBlks[i].index_name)) {
4074 FIXME_(typelib)("Index strings don't match\n");
4075 heap_free(pOtherTypeInfoBlks);
4080 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4081 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4082 heap_free(pOtherTypeInfoBlks);
4085 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4086 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4087 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4089 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4090 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4091 (*ppTypeInfoImpl)->index = i;
4092 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
4093 pOtherTypeInfoBlks[i].name_offs +
4095 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4096 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
4097 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
4098 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4099 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4100 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4101 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4103 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4104 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4106 if((pTIHeader->typeflags1 & 7) != 2)
4107 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4108 if(pTIHeader->typeflags3 != 2)
4109 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4111 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4112 debugstr_w((*ppTypeInfoImpl)->Name),
4113 typekind_desc[pTIHeader->typekind],
4114 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4115 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4117 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4119 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4121 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4122 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4123 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4125 switch(pTIHeader->typekind) {
4127 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4128 pTIHeader, pTITail);
4132 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4133 pTIHeader, pTITail);
4136 case TKIND_INTERFACE:
4137 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4138 pTIHeader, pTITail);
4142 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4143 pTIHeader, pTITail);
4147 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4148 pTIHeader, pTITail);
4151 case TKIND_DISPATCH:
4152 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4153 pTIHeader, pTITail);
4157 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4158 pTIHeader, pTITail);
4162 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4167 /* could get cFuncs, cVars and cImplTypes from here
4168 but we've already set those */
4169 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4185 pBlk = (char*)pBlk + pBlkEntry[order].len;
4188 if(i != pTypeLibImpl->TypeInfoCount) {
4189 FIXME("Somehow processed %d TypeInfos\n", i);
4190 heap_free(pOtherTypeInfoBlks);
4194 heap_free(pOtherTypeInfoBlks);
4195 return (ITypeLib2*)pTypeLibImpl;
4198 /* ITypeLib::QueryInterface
4200 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4205 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4207 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4210 if(IsEqualIID(riid, &IID_IUnknown) ||
4211 IsEqualIID(riid,&IID_ITypeLib)||
4212 IsEqualIID(riid,&IID_ITypeLib2))
4219 ITypeLib2_AddRef(iface);
4220 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4223 TRACE("-- Interface: E_NOINTERFACE\n");
4224 return E_NOINTERFACE;
4229 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4231 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4232 ULONG ref = InterlockedIncrement(&This->ref);
4234 TRACE("(%p)->ref was %u\n",This, ref - 1);
4239 /* ITypeLib::Release
4241 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4243 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4244 ULONG ref = InterlockedDecrement(&This->ref);
4246 TRACE("(%p)->(%u)\n",This, ref);
4250 TLBImpLib *pImpLib, *pImpLibNext;
4251 TLBRefType *ref_type;
4255 /* remove cache entry */
4258 TRACE("removing from cache list\n");
4259 EnterCriticalSection(&cache_section);
4260 if(This->entry.next)
4261 list_remove(&This->entry);
4262 LeaveCriticalSection(&cache_section);
4263 heap_free(This->path);
4265 TRACE(" destroying ITypeLib(%p)\n",This);
4267 SysFreeString(This->Name);
4270 SysFreeString(This->DocString);
4271 This->DocString = NULL;
4273 SysFreeString(This->HelpFile);
4274 This->HelpFile = NULL;
4276 SysFreeString(This->HelpStringDll);
4277 This->HelpStringDll = NULL;
4279 TLB_FreeCustData(&This->custdata_list);
4281 for (i = 0; i < This->ctTypeDesc; i++)
4282 if (This->pTypeDesc[i].vt == VT_CARRAY)
4283 heap_free(This->pTypeDesc[i].u.lpadesc);
4285 heap_free(This->pTypeDesc);
4287 LIST_FOR_EACH_ENTRY_SAFE(pImpLib, pImpLibNext, &This->implib_list, TLBImpLib, entry)
4289 if (pImpLib->pImpTypeLib)
4290 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4291 SysFreeString(pImpLib->name);
4293 list_remove(&pImpLib->entry);
4297 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4299 list_remove(&ref_type->entry);
4300 heap_free(ref_type);
4303 for (i = 0; i < This->TypeInfoCount; ++i)
4304 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4305 heap_free(This->typeinfos);
4313 /* ITypeLib::GetTypeInfoCount
4315 * Returns the number of type descriptions in the type library
4317 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4319 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4320 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4321 return This->TypeInfoCount;
4324 /* ITypeLib::GetTypeInfo
4326 * retrieves the specified type description in the library.
4328 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4331 ITypeInfo **ppTInfo)
4333 ITypeLibImpl *This = (ITypeLibImpl*)iface;
4335 TRACE("%p %u %p\n", This, index, ppTInfo);
4338 return E_INVALIDARG;
4340 if(index >= This->TypeInfoCount)
4341 return TYPE_E_ELEMENTNOTFOUND;
4343 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4344 ITypeInfo_AddRef(*ppTInfo);
4350 /* ITypeLibs::GetTypeInfoType
4352 * Retrieves the type of a type description.
4354 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4359 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4361 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4364 return E_INVALIDARG;
4366 if(index >= This->TypeInfoCount)
4367 return TYPE_E_ELEMENTNOTFOUND;
4369 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4374 /* ITypeLib::GetTypeInfoOfGuid
4376 * Retrieves the type description that corresponds to the specified GUID.
4379 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4382 ITypeInfo **ppTInfo)
4384 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4387 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4389 for(i = 0; i < This->TypeInfoCount; ++i){
4390 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4391 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4392 ITypeInfo_AddRef(*ppTInfo);
4397 return TYPE_E_ELEMENTNOTFOUND;
4400 /* ITypeLib::GetLibAttr
4402 * Retrieves the structure that contains the library's attributes.
4405 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4409 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4411 TRACE("(%p, %p)\n", This, attr);
4413 if (!attr) return E_INVALIDARG;
4415 *attr = heap_alloc(sizeof(**attr));
4416 if (!*attr) return E_OUTOFMEMORY;
4418 **attr = This->LibAttr;
4422 /* ITypeLib::GetTypeComp
4424 * Enables a client compiler to bind to a library's types, variables,
4425 * constants, and global functions.
4428 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4430 ITypeComp **ppTComp)
4432 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4434 TRACE("(%p)->(%p)\n",This,ppTComp);
4435 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4436 ITypeComp_AddRef(*ppTComp);
4441 /* ITypeLib::GetDocumentation
4443 * Retrieves the library's documentation string, the complete Help file name
4444 * and path, and the context identifier for the library Help topic in the Help
4447 * On a successful return all non-null BSTR pointers will have been set,
4450 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4454 BSTR *pBstrDocString,
4455 DWORD *pdwHelpContext,
4456 BSTR *pBstrHelpFile)
4458 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4460 HRESULT result = E_INVALIDARG;
4465 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4467 pBstrName, pBstrDocString,
4468 pdwHelpContext, pBstrHelpFile);
4472 /* documentation for the typelib */
4477 if(!(*pBstrName = SysAllocString(This->Name)))
4485 if (This->DocString)
4487 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4490 else if (This->Name)
4492 if(!(*pBstrDocString = SysAllocString(This->Name)))
4496 *pBstrDocString = NULL;
4500 *pdwHelpContext = This->dwHelpContext;
4506 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4510 *pBstrHelpFile = NULL;
4517 /* for a typeinfo */
4518 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4520 if(SUCCEEDED(result))
4522 result = ITypeInfo_GetDocumentation(pTInfo,
4526 pdwHelpContext, pBstrHelpFile);
4528 ITypeInfo_Release(pTInfo);
4533 if (pBstrDocString) SysFreeString (*pBstrDocString);
4535 if (pBstrName) SysFreeString (*pBstrName);
4537 return STG_E_INSUFFICIENTMEMORY;
4542 * Indicates whether a passed-in string contains the name of a type or member
4543 * described in the library.
4546 static HRESULT WINAPI ITypeLib2_fnIsName(
4552 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4553 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), tic, fdc, vrc, pc;
4555 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4559 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4560 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4561 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4562 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4563 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4564 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4565 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++)
4566 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name, nNameBufLen))
4567 goto ITypeLib2_fnIsName_exit;
4569 for(vrc = 0; vrc < pTInfo->TypeAttr.cVars; ++vrc){
4570 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4571 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4577 ITypeLib2_fnIsName_exit:
4578 TRACE("(%p)slow! search for %s: %s found!\n", This,
4579 debugstr_w(szNameBuf), *pfName?"NOT":"");
4584 /* ITypeLib::FindName
4586 * Finds occurrences of a type description in a type library. This may be used
4587 * to quickly verify that a name exists in a type library.
4590 static HRESULT WINAPI ITypeLib2_fnFindName(
4594 ITypeInfo **ppTInfo,
4598 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4599 UINT tic, count = 0;
4602 TRACE("(%p)->(%s %u %p %p %p)\n", This, debugstr_w(name), hash, ppTInfo, memid, found);
4604 if ((!name && hash == 0) || !ppTInfo || !memid || !found)
4605 return E_INVALIDARG;
4607 len = (lstrlenW(name) + 1)*sizeof(WCHAR);
4608 for(tic = 0; tic < This->TypeInfoCount; ++tic) {
4609 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4613 if(!memcmp(name, pTInfo->Name, len)) goto ITypeLib2_fnFindName_exit;
4614 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4615 TLBFuncDesc *func = &pTInfo->funcdescs[fdc];
4618 if(!memcmp(name, func->Name, len)) goto ITypeLib2_fnFindName_exit;
4619 for(pc = 0; pc < func->funcdesc.cParams; pc++) {
4620 if(!memcmp(name, func->pParamDesc[pc].Name, len))
4621 goto ITypeLib2_fnFindName_exit;
4625 var = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->TypeAttr.cVars, name);
4627 goto ITypeLib2_fnFindName_exit;
4630 ITypeLib2_fnFindName_exit:
4631 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4632 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4635 TRACE("found %d typeinfos\n", count);
4642 /* ITypeLib::ReleaseTLibAttr
4644 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4647 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4649 TLIBATTR *pTLibAttr)
4651 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4652 TRACE("freeing (%p)\n",This);
4653 heap_free(pTLibAttr);
4657 /* ITypeLib2::GetCustData
4659 * gets the custom data
4661 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4666 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4667 TLBCustData *pCData;
4669 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
4671 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
4673 return TYPE_E_ELEMENTNOTFOUND;
4675 VariantInit(pVarVal);
4676 VariantCopy(pVarVal, &pCData->data);
4681 /* ITypeLib2::GetLibStatistics
4683 * Returns statistics about a type library that are required for efficient
4684 * sizing of hash tables.
4687 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4689 ULONG *pcUniqueNames,
4690 ULONG *pcchUniqueNames)
4692 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4694 FIXME("(%p): stub!\n", This);
4696 if(pcUniqueNames) *pcUniqueNames=1;
4697 if(pcchUniqueNames) *pcchUniqueNames=1;
4701 /* ITypeLib2::GetDocumentation2
4703 * Retrieves the library's documentation string, the complete Help file name
4704 * and path, the localization context to use, and the context ID for the
4705 * library Help topic in the Help file.
4708 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4712 BSTR *pbstrHelpString,
4713 DWORD *pdwHelpStringContext,
4714 BSTR *pbstrHelpStringDll)
4716 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4720 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4722 /* the help string should be obtained from the helpstringdll,
4723 * using the _DLLGetDocumentation function, based on the supplied
4724 * lcid. Nice to do sometime...
4728 /* documentation for the typelib */
4730 *pbstrHelpString=SysAllocString(This->DocString);
4731 if(pdwHelpStringContext)
4732 *pdwHelpStringContext=This->dwHelpContext;
4733 if(pbstrHelpStringDll)
4734 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4740 /* for a typeinfo */
4741 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4743 if(SUCCEEDED(result))
4745 ITypeInfo2 * pTInfo2;
4746 result = ITypeInfo_QueryInterface(pTInfo,
4748 (LPVOID*) &pTInfo2);
4750 if(SUCCEEDED(result))
4752 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4756 pdwHelpStringContext,
4757 pbstrHelpStringDll);
4759 ITypeInfo2_Release(pTInfo2);
4762 ITypeInfo_Release(pTInfo);
4768 static HRESULT TLB_copy_all_custdata(struct list *custdata_list, CUSTDATA *pCustData)
4770 TLBCustData *pCData;
4774 ct = list_count(custdata_list);
4776 pCustData->prgCustData = heap_alloc_zero(ct * sizeof(CUSTDATAITEM));
4777 if(!pCustData->prgCustData)
4778 return E_OUTOFMEMORY;
4780 pCustData->cCustData = ct;
4782 cdi = pCustData->prgCustData;
4783 LIST_FOR_EACH_ENTRY(pCData, custdata_list, TLBCustData, entry){
4784 cdi->guid = pCData->guid;
4785 VariantCopy(&cdi->varValue, &pCData->data);
4793 /* ITypeLib2::GetAllCustData
4795 * Gets all custom data items for the library.
4798 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4800 CUSTDATA *pCustData)
4802 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4803 TRACE("%p %p\n", iface, pCustData);
4804 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
4807 static const ITypeLib2Vtbl tlbvt = {
4808 ITypeLib2_fnQueryInterface,
4810 ITypeLib2_fnRelease,
4811 ITypeLib2_fnGetTypeInfoCount,
4812 ITypeLib2_fnGetTypeInfo,
4813 ITypeLib2_fnGetTypeInfoType,
4814 ITypeLib2_fnGetTypeInfoOfGuid,
4815 ITypeLib2_fnGetLibAttr,
4816 ITypeLib2_fnGetTypeComp,
4817 ITypeLib2_fnGetDocumentation,
4819 ITypeLib2_fnFindName,
4820 ITypeLib2_fnReleaseTLibAttr,
4822 ITypeLib2_fnGetCustData,
4823 ITypeLib2_fnGetLibStatistics,
4824 ITypeLib2_fnGetDocumentation2,
4825 ITypeLib2_fnGetAllCustData
4829 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4831 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4833 return ITypeLib2_QueryInterface((ITypeLib2 *)This, riid, ppv);
4836 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4838 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4840 return ITypeLib2_AddRef((ITypeLib2 *)This);
4843 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4845 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4847 return ITypeLib2_Release((ITypeLib2 *)This);
4850 static HRESULT WINAPI ITypeLibComp_fnBind(
4855 ITypeInfo ** ppTInfo,
4856 DESCKIND * pDescKind,
4859 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4860 int typemismatch=0, i;
4862 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4864 *pDescKind = DESCKIND_NONE;
4865 pBindPtr->lptcomp = NULL;
4868 for(i = 0; i < This->TypeInfoCount; ++i){
4869 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4870 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4872 /* FIXME: check wFlags here? */
4873 /* FIXME: we should use a hash table to look this info up using lHash
4874 * instead of an O(n) search */
4875 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4876 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4878 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4880 *pDescKind = DESCKIND_TYPECOMP;
4881 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4882 ITypeComp_AddRef(pBindPtr->lptcomp);
4883 TRACE("module or enum: %s\n", debugstr_w(szName));
4888 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4889 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4891 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4894 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4895 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4897 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4900 else if (hr == TYPE_E_TYPEMISMATCH)
4904 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4905 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4907 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4909 ITypeInfo *subtypeinfo;
4911 DESCKIND subdesckind;
4913 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4914 &subtypeinfo, &subdesckind, &subbindptr);
4915 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4917 TYPEDESC tdesc_appobject;
4918 const VARDESC vardesc_appobject =
4921 NULL, /* lpstrSchema */
4936 VAR_STATIC /* varkind */
4939 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4940 tdesc_appobject.vt = VT_USERDEFINED;
4942 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4944 /* cleanup things filled in by Bind call so we can put our
4945 * application object data in there instead */
4946 switch (subdesckind)
4948 case DESCKIND_FUNCDESC:
4949 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4951 case DESCKIND_VARDESC:
4952 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4957 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4959 if (pTypeInfo->hreftype == -1)
4960 FIXME("no hreftype for interface %p\n", pTypeInfo);
4962 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4966 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4967 *ppTInfo = (ITypeInfo *)pTypeInfo;
4968 ITypeInfo_AddRef(*ppTInfo);
4971 else if (hr == TYPE_E_TYPEMISMATCH)
4978 TRACE("type mismatch %s\n", debugstr_w(szName));
4979 return TYPE_E_TYPEMISMATCH;
4983 TRACE("name not found %s\n", debugstr_w(szName));
4988 static HRESULT WINAPI ITypeLibComp_fnBindType(
4992 ITypeInfo ** ppTInfo,
4993 ITypeComp ** ppTComp)
4995 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4998 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5000 if(!szName || !ppTInfo || !ppTComp)
5001 return E_INVALIDARG;
5003 for(i = 0; i < This->TypeInfoCount; ++i)
5005 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
5006 /* FIXME: should use lHash to do the search */
5007 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
5009 TRACE("returning %p\n", pTypeInfo);
5010 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
5011 ITypeInfo_AddRef(*ppTInfo);
5012 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
5013 ITypeComp_AddRef(*ppTComp);
5018 TRACE("not found\n");
5024 static const ITypeCompVtbl tlbtcvt =
5027 ITypeLibComp_fnQueryInterface,
5028 ITypeLibComp_fnAddRef,
5029 ITypeLibComp_fnRelease,
5031 ITypeLibComp_fnBind,
5032 ITypeLibComp_fnBindType
5035 /*================== ITypeInfo(2) Methods ===================================*/
5036 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
5038 ITypeInfoImpl *pTypeInfoImpl;
5040 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
5043 pTypeInfoImpl->lpVtbl = &tinfvt;
5044 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
5045 pTypeInfoImpl->ref = 0;
5046 pTypeInfoImpl->hreftype = -1;
5047 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
5048 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
5049 list_init(&pTypeInfoImpl->custdata_list);
5051 TRACE("(%p)\n", pTypeInfoImpl);
5052 return pTypeInfoImpl;
5055 /* ITypeInfo::QueryInterface
5057 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
5062 ITypeLibImpl *This = (ITypeLibImpl *)iface;
5064 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
5067 if(IsEqualIID(riid, &IID_IUnknown) ||
5068 IsEqualIID(riid,&IID_ITypeInfo)||
5069 IsEqualIID(riid,&IID_ITypeInfo2))
5073 ITypeInfo2_AddRef(iface);
5074 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5077 TRACE("-- Interface: E_NOINTERFACE\n");
5078 return E_NOINTERFACE;
5081 /* ITypeInfo::AddRef
5083 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5085 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5086 ULONG ref = InterlockedIncrement(&This->ref);
5088 TRACE("(%p)->ref is %u\n",This, ref);
5090 if (ref == 1 /* incremented from 0 */)
5091 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
5096 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5100 TRACE("destroying ITypeInfo(%p)\n",This);
5102 SysFreeString(This->Name);
5105 SysFreeString(This->DocString);
5106 This->DocString = NULL;
5108 SysFreeString(This->DllName);
5109 This->DllName = NULL;
5111 for (i = 0; i < This->TypeAttr.cFuncs; ++i)
5113 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5114 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5116 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5117 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5119 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5120 heap_free(elemdesc->u.paramdesc.pparamdescex);
5122 TLB_FreeCustData(&pFInfo->pParamDesc[j].custdata_list);
5123 SysFreeString(pFInfo->pParamDesc[j].Name);
5125 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5126 heap_free(pFInfo->pParamDesc);
5127 TLB_FreeCustData(&pFInfo->custdata_list);
5128 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5129 SysFreeString(pFInfo->Entry);
5130 SysFreeString(pFInfo->HelpString);
5131 SysFreeString(pFInfo->Name);
5133 heap_free(This->funcdescs);
5135 for(i = 0; i < This->TypeAttr.cVars; ++i)
5137 TLBVarDesc *pVInfo = &This->vardescs[i];
5138 if (pVInfo->vardesc.varkind == VAR_CONST)
5140 VariantClear(pVInfo->vardesc.u.lpvarValue);
5141 heap_free(pVInfo->vardesc.u.lpvarValue);
5143 TLB_FreeCustData(&pVInfo->custdata_list);
5144 SysFreeString(pVInfo->Name);
5145 SysFreeString(pVInfo->HelpString);
5147 heap_free(This->vardescs);
5149 if(This->impltypes){
5150 for (i = 0; i < This->TypeAttr.cImplTypes; ++i){
5151 TLBImplType *pImpl = &This->impltypes[i];
5152 TLB_FreeCustData(&pImpl->custdata_list);
5154 heap_free(This->impltypes);
5157 TLB_FreeCustData(&This->custdata_list);
5162 /* ITypeInfo::Release
5164 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5166 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5167 ULONG ref = InterlockedDecrement(&This->ref);
5169 TRACE("(%p)->(%u)\n",This, ref);
5173 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5174 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5175 if (not_attached_to_typelib)
5177 /* otherwise This will be freed when typelib is freed */
5183 /* ITypeInfo::GetTypeAttr
5185 * Retrieves a TYPEATTR structure that contains the attributes of the type
5189 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5190 LPTYPEATTR *ppTypeAttr)
5192 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5195 TRACE("(%p)\n",This);
5197 size = sizeof(**ppTypeAttr);
5198 if (This->TypeAttr.typekind == TKIND_ALIAS)
5199 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5201 *ppTypeAttr = heap_alloc(size);
5203 return E_OUTOFMEMORY;
5205 **ppTypeAttr = This->TypeAttr;
5207 if (This->TypeAttr.typekind == TKIND_ALIAS)
5208 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5209 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5211 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5212 /* This should include all the inherited funcs */
5213 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5214 /* This is always the size of IDispatch's vtbl */
5215 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5216 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5221 /* ITypeInfo::GetTypeComp
5223 * Retrieves the ITypeComp interface for the type description, which enables a
5224 * client compiler to bind to the type description's members.
5227 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5228 ITypeComp * *ppTComp)
5230 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5232 TRACE("(%p)->(%p)\n", This, ppTComp);
5234 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5235 ITypeComp_AddRef(*ppTComp);
5239 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5241 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5242 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5243 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5247 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5250 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5251 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5253 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5254 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5255 *buffer += sizeof(PARAMDESCEX);
5256 *pparamdescex_dest = *pparamdescex_src;
5257 VariantInit(&pparamdescex_dest->varDefaultValue);
5258 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5259 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5262 dest->u.paramdesc.pparamdescex = NULL;
5266 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5268 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5269 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5272 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5276 SIZE_T size = sizeof(*src);
5280 size += sizeof(*src->lprgscode) * src->cScodes;
5281 size += TLB_SizeElemDesc(&src->elemdescFunc);
5282 for (i = 0; i < src->cParams; i++)
5284 size += sizeof(ELEMDESC);
5285 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5288 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5289 if (!dest) return E_OUTOFMEMORY;
5292 if (dispinterface) /* overwrite funckind */
5293 dest->funckind = FUNC_DISPATCH;
5294 buffer = (char *)(dest + 1);
5296 dest->lprgscode = (SCODE *)buffer;
5297 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5298 buffer += sizeof(*src->lprgscode) * src->cScodes;
5300 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5303 SysFreeString((BSTR)dest);
5307 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5308 buffer += sizeof(ELEMDESC) * src->cParams;
5309 for (i = 0; i < src->cParams; i++)
5311 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5317 /* undo the above actions */
5318 for (i = i - 1; i >= 0; i--)
5319 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5320 TLB_FreeElemDesc(&dest->elemdescFunc);
5321 SysFreeString((BSTR)dest);
5325 /* special treatment for dispinterfaces: this makes functions appear
5326 * to return their [retval] value when it is really returning an
5328 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5330 if (dest->cParams &&
5331 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5333 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5334 if (elemdesc->tdesc.vt != VT_PTR)
5336 ERR("elemdesc should have started with VT_PTR instead of:\n");
5338 dump_ELEMDESC(elemdesc);
5339 return E_UNEXPECTED;
5342 /* copy last parameter to the return value. we are using a flat
5343 * buffer so there is no danger of leaking memory in
5345 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5347 /* remove the last parameter */
5351 /* otherwise this function is made to appear to have no return
5353 dest->elemdescFunc.tdesc.vt = VT_VOID;
5361 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5363 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5365 if (index >= This->TypeAttr.cFuncs)
5366 return TYPE_E_ELEMENTNOTFOUND;
5368 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5372 /* internal function to make the inherited interfaces' methods appear
5373 * part of the interface */
5374 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5375 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5377 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5379 UINT implemented_funcs = 0;
5384 *hrefoffset = DISPATCH_HREF_OFFSET;
5388 ITypeInfo *pSubTypeInfo;
5391 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5395 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5398 &sub_funcs, hrefoffset);
5399 implemented_funcs += sub_funcs;
5400 ITypeInfo_Release(pSubTypeInfo);
5403 *hrefoffset += DISPATCH_HREF_OFFSET;
5407 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5411 if (index < implemented_funcs)
5412 return E_INVALIDARG;
5413 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5417 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5419 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5422 switch (pTypeDesc->vt)
5424 case VT_USERDEFINED:
5425 pTypeDesc->u.hreftype += hrefoffset;
5429 pTypeDesc = pTypeDesc->u.lptdesc;
5432 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5440 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5443 for (i = 0; i < pFuncDesc->cParams; i++)
5444 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5445 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5448 /* ITypeInfo::GetFuncDesc
5450 * Retrieves the FUNCDESC structure that contains information about a
5451 * specified function.
5454 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5455 LPFUNCDESC *ppFuncDesc)
5457 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5458 const FUNCDESC *internal_funcdesc;
5460 UINT hrefoffset = 0;
5462 TRACE("(%p) index %d\n", This, index);
5464 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5465 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5466 &internal_funcdesc, NULL,
5469 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5470 &internal_funcdesc);
5473 WARN("description for function %d not found\n", index);
5477 hr = TLB_AllocAndInitFuncDesc(
5480 This->TypeAttr.typekind == TKIND_DISPATCH);
5482 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5483 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5485 TRACE("-- 0x%08x\n", hr);
5489 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5493 SIZE_T size = sizeof(*src);
5496 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5497 if (src->varkind == VAR_CONST)
5498 size += sizeof(VARIANT);
5499 size += TLB_SizeElemDesc(&src->elemdescVar);
5501 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5502 if (!dest) return E_OUTOFMEMORY;
5505 buffer = (char *)(dest + 1);
5506 if (src->lpstrSchema)
5509 dest->lpstrSchema = (LPOLESTR)buffer;
5510 len = strlenW(src->lpstrSchema);
5511 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5512 buffer += (len + 1) * sizeof(WCHAR);
5515 if (src->varkind == VAR_CONST)
5519 dest->u.lpvarValue = (VARIANT *)buffer;
5520 *dest->u.lpvarValue = *src->u.lpvarValue;
5521 buffer += sizeof(VARIANT);
5522 VariantInit(dest->u.lpvarValue);
5523 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5526 SysFreeString((BSTR)dest);
5530 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5533 if (src->varkind == VAR_CONST)
5534 VariantClear(dest->u.lpvarValue);
5535 SysFreeString((BSTR)dest);
5542 /* ITypeInfo::GetVarDesc
5544 * Retrieves a VARDESC structure that describes the specified variable.
5547 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5548 LPVARDESC *ppVarDesc)
5550 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5551 const TLBVarDesc *pVDesc = &This->vardescs[index];
5553 TRACE("(%p) index %d\n", This, index);
5555 if(index >= This->TypeAttr.cVars)
5556 return TYPE_E_ELEMENTNOTFOUND;
5558 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5561 /* ITypeInfo_GetNames
5563 * Retrieves the variable with the specified member ID (or the name of the
5564 * property or method and its parameters) that correspond to the specified
5567 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5568 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5570 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5571 const TLBFuncDesc *pFDesc;
5572 const TLBVarDesc *pVDesc;
5574 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5575 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5578 /* function found, now return function and parameter names */
5579 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5582 *rgBstrNames=SysAllocString(pFDesc->Name);
5584 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5590 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
5593 *rgBstrNames=SysAllocString(pVDesc->Name);
5598 if(This->impltypes &&
5599 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5600 /* recursive search */
5603 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5604 if(SUCCEEDED(result))
5606 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5607 ITypeInfo_Release(pTInfo);
5610 WARN("Could not search inherited interface!\n");
5614 WARN("no names found\n");
5617 return TYPE_E_ELEMENTNOTFOUND;
5624 /* ITypeInfo::GetRefTypeOfImplType
5626 * If a type description describes a COM class, it retrieves the type
5627 * description of the implemented interface types. For an interface,
5628 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5632 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5637 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5640 TRACE("(%p) index %d\n", This, index);
5641 if (TRACE_ON(ole)) dump_TypeInfo(This);
5645 /* only valid on dual interfaces;
5646 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5648 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5650 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5656 hr = TYPE_E_ELEMENTNOTFOUND;
5659 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5661 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5662 *pRefType = This->pTypeLib->dispatch_href;
5666 if(index >= This->TypeAttr.cImplTypes)
5667 hr = TYPE_E_ELEMENTNOTFOUND;
5669 *pRefType = This->impltypes[index].hRef;
5675 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5677 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5683 /* ITypeInfo::GetImplTypeFlags
5685 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5686 * or base interface in a type description.
5688 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5689 UINT index, INT *pImplTypeFlags)
5691 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5693 TRACE("(%p) index %d\n", This, index);
5695 if(This->TypeAttr.typekind == TKIND_DISPATCH && index == 0){
5696 *pImplTypeFlags = 0;
5700 if(index >= This->TypeAttr.cImplTypes)
5701 return TYPE_E_ELEMENTNOTFOUND;
5703 *pImplTypeFlags = This->impltypes[index].implflags;
5709 * Maps between member names and member IDs, and parameter names and
5712 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5713 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5715 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5716 const TLBVarDesc *pVDesc;
5720 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5723 /* init out parameters in case of failure */
5724 for (i = 0; i < cNames; i++)
5725 pMemId[i] = MEMBERID_NIL;
5727 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
5729 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
5730 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5731 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5732 for(i=1; i < cNames; i++){
5733 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5734 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5736 if( j<pFDesc->funcdesc.cParams)
5739 ret=DISP_E_UNKNOWNNAME;
5741 TRACE("-- 0x%08x\n", ret);
5745 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, *rgszNames);
5748 *pMemId = pVDesc->vardesc.memid;
5751 /* not found, see if it can be found in an inherited interface */
5752 if(This->impltypes) {
5753 /* recursive search */
5755 ret = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
5757 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5758 ITypeInfo_Release(pTInfo);
5761 WARN("Could not search inherited interface!\n");
5763 WARN("no names found\n");
5764 return DISP_E_UNKNOWNNAME;
5770 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5771 __ASM_GLOBAL_FUNC( call_method,
5773 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5774 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5775 "movl %esp,%ebp\n\t"
5776 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5778 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5780 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5781 "movl 12(%ebp),%edx\n\t"
5782 "movl %esp,%edi\n\t"
5785 "subl %edx,%edi\n\t"
5786 "andl $~15,%edi\n\t"
5787 "movl %edi,%esp\n\t"
5788 "movl 12(%ebp),%ecx\n\t"
5789 "movl 16(%ebp),%esi\n\t"
5792 "1:\tcall *8(%ebp)\n\t"
5793 "subl %esp,%edi\n\t"
5794 "movl 20(%ebp),%ecx\n\t"
5795 "movl %edi,(%ecx)\n\t"
5796 "leal -8(%ebp),%esp\n\t"
5798 __ASM_CFI(".cfi_same_value %edi\n\t")
5800 __ASM_CFI(".cfi_same_value %esi\n\t")
5802 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5803 __ASM_CFI(".cfi_same_value %ebp\n\t")
5806 /* same function but returning floating point */
5807 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5809 /* ITypeInfo::Invoke
5811 * Invokes a method, or accesses a property of an object, that implements the
5812 * interface described by the type description.
5815 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5819 if (TRACE_ON(ole)) {
5821 TRACE("Calling %p(",func);
5822 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5823 if (nrargs > 30) TRACE("...");
5830 res = call_method( func, nrargs, args, &stack_offset );
5833 FIXME("unsupported calling convention %d\n",callconv);
5837 TRACE("returns %08x\n",res);
5841 #elif defined(__x86_64__)
5843 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5844 __ASM_GLOBAL_FUNC( call_method,
5846 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5847 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5848 "movq %rsp,%rbp\n\t"
5849 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5851 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5853 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5854 "movq %rcx,%rax\n\t"
5857 "cmovgq %rdx,%rcx\n\t"
5858 "leaq 0(,%rcx,8),%rdx\n\t"
5859 "subq %rdx,%rsp\n\t"
5860 "andq $~15,%rsp\n\t"
5861 "movq %rsp,%rdi\n\t"
5864 "movq 0(%rsp),%rcx\n\t"
5865 "movq 8(%rsp),%rdx\n\t"
5866 "movq 16(%rsp),%r8\n\t"
5867 "movq 24(%rsp),%r9\n\t"
5868 "movq %rcx,%xmm0\n\t"
5869 "movq %rdx,%xmm1\n\t"
5870 "movq %r8,%xmm2\n\t"
5871 "movq %r9,%xmm3\n\t"
5873 "leaq -16(%rbp),%rsp\n\t"
5875 __ASM_CFI(".cfi_same_value %rdi\n\t")
5877 __ASM_CFI(".cfi_same_value %rsi\n\t")
5878 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5880 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5881 __ASM_CFI(".cfi_same_value %rbp\n\t")
5884 /* same function but returning floating point */
5885 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5887 #endif /* __x86_64__ */
5889 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5892 ITypeInfo *tinfo2 = NULL;
5893 TYPEATTR *tattr = NULL;
5895 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5898 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5900 tdesc->u.hreftype, hr);
5903 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5906 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5907 ITypeInfo_Release(tinfo2);
5911 switch (tattr->typekind)
5918 tdesc = &tattr->tdescAlias;
5919 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5922 case TKIND_INTERFACE:
5923 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5929 case TKIND_DISPATCH:
5938 FIXME("TKIND_RECORD unhandled.\n");
5943 FIXME("TKIND_UNION unhandled.\n");
5948 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5952 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5953 ITypeInfo_Release(tinfo2);
5957 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5961 /* enforce only one level of pointer indirection */
5962 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5964 tdesc = tdesc->u.lptdesc;
5966 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5967 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5968 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5969 if ((tdesc->vt == VT_USERDEFINED) ||
5970 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5972 VARTYPE vt_userdefined = 0;
5973 const TYPEDESC *tdesc_userdefined = tdesc;
5974 if (tdesc->vt == VT_PTR)
5976 vt_userdefined = VT_BYREF;
5977 tdesc_userdefined = tdesc->u.lptdesc;
5979 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5981 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5982 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5984 *vt |= vt_userdefined;
5996 case VT_USERDEFINED:
5997 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
6004 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
6005 hr = DISP_E_BADVARTYPE;
6009 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
6024 static HRESULT get_iface_guid(ITypeInfo *tinfo, const TYPEDESC *tdesc, GUID *guid)
6030 hres = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
6034 hres = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
6036 ITypeInfo_Release(tinfo2);
6040 switch(tattr->typekind) {
6042 hres = get_iface_guid(tinfo2, &tattr->tdescAlias, guid);
6045 case TKIND_INTERFACE:
6046 case TKIND_DISPATCH:
6047 *guid = tattr->guid;
6051 ERR("Unexpected typekind %d\n", tattr->typekind);
6052 hres = E_UNEXPECTED;
6055 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
6056 ITypeInfo_Release(tinfo2);
6060 /***********************************************************************
6061 * DispCallFunc (OLEAUT32.@)
6063 * Invokes a function of the specified calling convention, passing the
6064 * specified arguments and returns the result.
6067 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6068 * oVft [I] The offset in the vtable. See notes.
6069 * cc [I] Calling convention of the function to call.
6070 * vtReturn [I] The return type of the function.
6071 * cActuals [I] Number of parameters.
6072 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6073 * prgpvarg [I] The arguments to pass.
6074 * pvargResult [O] The return value of the function. Can be NULL.
6078 * Failure: HRESULT code.
6081 * The HRESULT return value of this function is not affected by the return
6082 * value of the user supplied function, which is returned in pvargResult.
6084 * If pvInstance is NULL then a non-object function is to be called and oVft
6085 * is the address of the function to call.
6087 * The cc parameter can be one of the following values:
6100 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6101 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6104 int argspos, stack_offset;
6109 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6110 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6111 pvargResult, V_VT(pvargResult));
6113 if (cc != CC_STDCALL && cc != CC_CDECL)
6115 FIXME("unsupported calling convention %d\n",cc);
6116 return E_INVALIDARG;
6119 /* maximum size for an argument is sizeof(VARIANT) */
6120 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6122 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6126 const FARPROC *vtable = *(FARPROC **)pvInstance;
6127 func = vtable[oVft/sizeof(void *)];
6128 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6130 else func = (void *)oVft;
6132 for (i = 0; i < cActuals; i++)
6134 VARIANT *arg = prgpvarg[i];
6145 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6146 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6150 memcpy( &args[argspos], arg, sizeof(*arg) );
6151 argspos += sizeof(*arg) / sizeof(DWORD);
6153 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6154 args[argspos++] = V_BOOL(arg);
6157 args[argspos++] = V_UI4(arg);
6160 TRACE("arg %u: type %d\n",i,prgvt[i]);
6167 call_method( func, argspos - 1, args + 1, &stack_offset );
6170 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6174 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6178 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6179 call_method( func, argspos, args, &stack_offset );
6184 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6187 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6191 if (stack_offset && cc == CC_STDCALL)
6193 WARN( "stack pointer off by %d\n", stack_offset );
6194 return DISP_E_BADCALLEE;
6196 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6197 TRACE("retval: "); dump_Variant(pvargResult);
6200 #elif defined(__x86_64__)
6206 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6207 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6208 pvargResult, V_VT(pvargResult));
6210 if (cc != CC_STDCALL && cc != CC_CDECL)
6212 FIXME("unsupported calling convention %d\n",cc);
6213 return E_INVALIDARG;
6216 /* maximum size for an argument is sizeof(DWORD_PTR) */
6217 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6219 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6223 const FARPROC *vtable = *(FARPROC **)pvInstance;
6224 func = vtable[oVft/sizeof(void *)];
6225 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6227 else func = (void *)oVft;
6229 for (i = 0; i < cActuals; i++)
6231 VARIANT *arg = prgpvarg[i];
6237 args[argspos++] = (ULONG_PTR)arg;
6239 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6240 args[argspos++] = V_BOOL(arg);
6243 args[argspos++] = V_UI8(arg);
6246 TRACE("arg %u: type %d\n",i,prgvt[i]);
6253 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6257 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6261 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6262 call_method( func, argspos, args );
6265 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6269 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6270 TRACE("retval: "); dump_Variant(pvargResult);
6274 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6275 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6280 static inline BOOL func_restricted( const FUNCDESC *desc )
6282 return (desc->wFuncFlags & FUNCFLAG_FRESTRICTED) && (desc->memid >= 0);
6285 #define INVBUF_ELEMENT_SIZE \
6286 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6287 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6288 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6289 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6290 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6291 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6292 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6293 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6295 static HRESULT WINAPI ITypeInfo_fnInvoke(
6300 DISPPARAMS *pDispParams,
6301 VARIANT *pVarResult,
6302 EXCEPINFO *pExcepInfo,
6305 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6307 unsigned int var_index;
6310 const TLBFuncDesc *pFuncInfo;
6313 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6314 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6317 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6318 return DISP_E_MEMBERNOTFOUND;
6322 ERR("NULL pDispParams not allowed\n");
6323 return E_INVALIDARG;
6326 dump_DispParms(pDispParams);
6328 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6330 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6331 pDispParams->cNamedArgs, pDispParams->cArgs);
6332 return E_INVALIDARG;
6335 /* we do this instead of using GetFuncDesc since it will return a fake
6336 * FUNCDESC for dispinterfaces and we want the real function description */
6337 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6338 pFuncInfo = &This->funcdescs[fdc];
6339 if ((memid == pFuncInfo->funcdesc.memid) &&
6340 (wFlags & pFuncInfo->funcdesc.invkind) &&
6341 !func_restricted( &pFuncInfo->funcdesc ))
6345 if (fdc < This->TypeAttr.cFuncs) {
6346 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6350 TRACE("invoking:\n");
6351 dump_TLBFuncDescOne(pFuncInfo);
6354 switch (func_desc->funckind) {
6355 case FUNC_PUREVIRTUAL:
6356 case FUNC_VIRTUAL: {
6357 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6359 VARIANT retval; /* pointer for storing byref retvals in */
6360 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6361 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6362 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6363 UINT cNamedArgs = pDispParams->cNamedArgs;
6364 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6365 UINT vargs_converted=0;
6369 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6371 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6373 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6374 hres = DISP_E_PARAMNOTFOUND;
6379 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6381 ERR("functions with the vararg attribute do not support named arguments\n");
6382 hres = DISP_E_NONAMEDARGS;
6386 for (i = 0; i < func_desc->cParams; i++)
6388 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6389 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6394 TRACE("changing args\n");
6395 for (i = 0; i < func_desc->cParams; i++)
6397 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6398 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6399 VARIANTARG *src_arg;
6401 if (wParamFlags & PARAMFLAG_FLCID)
6404 arg = prgpvarg[i] = &rgvarg[i];
6406 V_I4(arg) = This->pTypeLib->lcid;
6415 for (j = 0; j < cNamedArgs; j++)
6416 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6418 src_arg = &pDispParams->rgvarg[j];
6423 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6425 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6429 if (wParamFlags & PARAMFLAG_FRETVAL)
6431 /* under most conditions the caller is not allowed to
6432 * pass in a dispparam arg in the index of what would be
6433 * the retval parameter. however, there is an exception
6434 * where the extra parameter is used in an extra
6435 * IDispatch::Invoke below */
6436 if ((i < pDispParams->cArgs) &&
6437 ((func_desc->cParams != 1) || !pVarResult ||
6438 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6440 hres = DISP_E_BADPARAMCOUNT;
6444 /* note: this check is placed so that if the caller passes
6445 * in a VARIANTARG for the retval we just ignore it, like
6447 if (i == func_desc->cParams - 1)
6450 arg = prgpvarg[i] = &rgvarg[i];
6451 memset(arg, 0, sizeof(*arg));
6452 V_VT(arg) = rgvt[i];
6453 memset(&retval, 0, sizeof(retval));
6454 V_BYREF(arg) = &retval;
6458 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6459 hres = E_UNEXPECTED;
6465 dump_Variant(src_arg);
6467 if(rgvt[i]!=V_VT(src_arg))
6469 if (rgvt[i] == VT_VARIANT)
6470 hres = VariantCopy(&rgvarg[i], src_arg);
6471 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6473 if (rgvt[i] == V_VT(src_arg))
6474 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6477 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6478 if (wParamFlags & PARAMFLAG_FIN)
6479 hres = VariantCopy(&missing_arg[i], src_arg);
6480 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6482 V_VT(&rgvarg[i]) = rgvt[i];
6484 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6487 SAFEARRAYBOUND bound;
6491 bound.cElements = pDispParams->cArgs-i;
6492 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6494 ERR("SafeArrayCreate failed\n");
6497 hres = SafeArrayAccessData(a, (LPVOID)&v);
6500 ERR("SafeArrayAccessData failed with %x\n", hres);
6501 SafeArrayDestroy(a);
6504 for (j = 0; j < bound.cElements; j++)
6505 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6506 hres = SafeArrayUnaccessData(a);
6509 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6510 SafeArrayDestroy(a);
6513 V_ARRAY(&rgvarg[i]) = a;
6514 V_VT(&rgvarg[i]) = rgvt[i];
6516 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6518 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6519 if (wParamFlags & PARAMFLAG_FIN)
6520 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6522 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6523 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6524 V_VT(&rgvarg[i]) = rgvt[i];
6526 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6528 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6529 V_VT(&rgvarg[i]) = rgvt[i];
6533 /* FIXME: this doesn't work for VT_BYREF arguments if
6534 * they are not the same type as in the paramdesc */
6535 V_VT(&rgvarg[i]) = V_VT(src_arg);
6536 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6537 V_VT(&rgvarg[i]) = rgvt[i];
6542 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6543 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6544 debugstr_VT(src_arg), debugstr_VF(src_arg));
6547 prgpvarg[i] = &rgvarg[i];
6551 prgpvarg[i] = src_arg;
6554 if((tdesc->vt == VT_USERDEFINED || (tdesc->vt == VT_PTR && tdesc->u.lptdesc->vt == VT_USERDEFINED))
6555 && (V_VT(prgpvarg[i]) == VT_DISPATCH || V_VT(prgpvarg[i]) == VT_UNKNOWN)
6556 && V_UNKNOWN(prgpvarg[i])) {
6557 IUnknown *userdefined_iface;
6560 hres = get_iface_guid((ITypeInfo*)iface, tdesc->vt == VT_PTR ? tdesc->u.lptdesc : tdesc, &guid);
6564 hres = IUnknown_QueryInterface(V_UNKNOWN(prgpvarg[i]), &guid, (void**)&userdefined_iface);
6566 ERR("argument does not support %s interface\n", debugstr_guid(&guid));
6570 IUnknown_Release(V_UNKNOWN(prgpvarg[i]));
6571 V_UNKNOWN(prgpvarg[i]) = userdefined_iface;
6574 else if (wParamFlags & PARAMFLAG_FOPT)
6577 arg = prgpvarg[i] = &rgvarg[i];
6578 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6580 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6586 VARIANTARG *missing_arg;
6587 /* if the function wants a pointer to a variant then
6588 * set that up, otherwise just pass the VT_ERROR in
6589 * the argument by value */
6590 if (rgvt[i] & VT_BYREF)
6592 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6593 V_VT(arg) = VT_VARIANT | VT_BYREF;
6594 V_VARIANTREF(arg) = missing_arg;
6598 V_VT(missing_arg) = VT_ERROR;
6599 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6604 hres = DISP_E_BADPARAMCOUNT;
6608 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6610 /* VT_VOID is a special case for return types, so it is not
6611 * handled in the general function */
6612 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6613 V_VT(&varresult) = VT_EMPTY;
6616 V_VT(&varresult) = 0;
6617 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6618 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6621 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6622 V_VT(&varresult), func_desc->cParams, rgvt,
6623 prgpvarg, &varresult);
6625 vargs_converted = 0;
6627 for (i = 0; i < func_desc->cParams; i++)
6629 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6630 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6632 if (wParamFlags & PARAMFLAG_FLCID)
6634 else if (wParamFlags & PARAMFLAG_FRETVAL)
6638 TRACE("[retval] value: ");
6639 dump_Variant(prgpvarg[i]);
6644 VariantInit(pVarResult);
6645 /* deref return value */
6646 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6649 VARIANT_ClearInd(prgpvarg[i]);
6651 else if (vargs_converted < pDispParams->cArgs)
6653 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6654 if (wParamFlags & PARAMFLAG_FOUT)
6656 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6658 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6662 ERR("failed to convert param %d to vt %d\n", i,
6663 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6668 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6669 func_desc->cParamsOpt < 0 &&
6670 i == func_desc->cParams-1)
6672 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6675 hres = SafeArrayGetUBound(a, 1, &ubound);
6678 ERR("SafeArrayGetUBound failed with %x\n", hres);
6681 hres = SafeArrayAccessData(a, (LPVOID)&v);
6684 ERR("SafeArrayAccessData failed with %x\n", hres);
6687 for (j = 0; j <= ubound; j++)
6688 VariantClear(&v[j]);
6689 hres = SafeArrayUnaccessData(a);
6692 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6696 VariantClear(&rgvarg[i]);
6699 else if (wParamFlags & PARAMFLAG_FOPT)
6701 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6702 VariantClear(&rgvarg[i]);
6705 VariantClear(&missing_arg[i]);
6708 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6710 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6711 hres = DISP_E_EXCEPTION;
6714 IErrorInfo *pErrorInfo;
6715 pExcepInfo->scode = V_ERROR(&varresult);
6716 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6718 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6719 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6720 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6721 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6723 IErrorInfo_Release(pErrorInfo);
6727 if (V_VT(&varresult) != VT_ERROR)
6729 TRACE("varresult value: ");
6730 dump_Variant(&varresult);
6734 VariantClear(pVarResult);
6735 *pVarResult = varresult;
6738 VariantClear(&varresult);
6741 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6742 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6743 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6744 (pDispParams->cArgs != 0))
6746 if (V_VT(pVarResult) == VT_DISPATCH)
6748 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6749 /* Note: not VariantClear; we still need the dispatch
6750 * pointer to be valid */
6751 VariantInit(pVarResult);
6752 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6753 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6754 pDispParams, pVarResult, pExcepInfo, pArgErr);
6755 IDispatch_Release(pDispatch);
6759 VariantClear(pVarResult);
6760 hres = DISP_E_NOTACOLLECTION;
6768 case FUNC_DISPATCH: {
6771 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6772 if (SUCCEEDED(hres)) {
6773 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6774 hres = IDispatch_Invoke(
6775 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6776 pVarResult,pExcepInfo,pArgErr
6779 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6780 IDispatch_Release(disp);
6782 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6786 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6791 TRACE("-- 0x%08x\n", hres);
6794 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6797 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6798 if(FAILED(hres)) return hres;
6800 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6801 dump_VARDESC(var_desc);
6802 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6806 /* not found, look for it in inherited interfaces */
6807 ITypeInfo2_GetTypeKind(iface, &type_kind);
6808 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6809 if(This->impltypes) {
6810 /* recursive search */
6812 hres = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6813 if(SUCCEEDED(hres)){
6814 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6815 ITypeInfo_Release(pTInfo);
6818 WARN("Could not search inherited interface!\n");
6821 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6822 return DISP_E_MEMBERNOTFOUND;
6825 /* ITypeInfo::GetDocumentation
6827 * Retrieves the documentation string, the complete Help file name and path,
6828 * and the context ID for the Help topic for a specified type description.
6830 * (Can be tested by the Visual Basic Editor in Word for instance.)
6832 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6833 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6834 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6836 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6837 const TLBFuncDesc *pFDesc;
6838 const TLBVarDesc *pVDesc;
6839 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6840 " HelpContext(%p) HelpFile(%p)\n",
6841 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6842 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6844 *pBstrName=SysAllocString(This->Name);
6846 *pBstrDocString=SysAllocString(This->DocString);
6848 *pdwHelpContext=This->dwHelpContext;
6850 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6852 }else {/* for a member */
6853 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6856 *pBstrName = SysAllocString(pFDesc->Name);
6858 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6860 *pdwHelpContext=pFDesc->helpcontext;
6863 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
6866 *pBstrName = SysAllocString(pVDesc->Name);
6868 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6870 *pdwHelpContext=pVDesc->HelpContext;
6875 if(This->impltypes &&
6876 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6877 /* recursive search */
6880 result = ITypeInfo2_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6881 if(SUCCEEDED(result)) {
6882 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6883 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6884 ITypeInfo_Release(pTInfo);
6887 WARN("Could not search inherited interface!\n");
6890 WARN("member %d not found\n", memid);
6891 return TYPE_E_ELEMENTNOTFOUND;
6894 /* ITypeInfo::GetDllEntry
6896 * Retrieves a description or specification of an entry point for a function
6899 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6900 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6903 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6904 const TLBFuncDesc *pFDesc;
6906 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6908 if (pBstrDllName) *pBstrDllName = NULL;
6909 if (pBstrName) *pBstrName = NULL;
6910 if (pwOrdinal) *pwOrdinal = 0;
6912 if (This->TypeAttr.typekind != TKIND_MODULE)
6913 return TYPE_E_BADMODULEKIND;
6915 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6917 dump_TypeInfo(This);
6919 dump_TLBFuncDescOne(pFDesc);
6922 *pBstrDllName = SysAllocString(This->DllName);
6924 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6926 *pBstrName = SysAllocString(pFDesc->Entry);
6934 *pwOrdinal = LOWORD(pFDesc->Entry);
6937 return TYPE_E_ELEMENTNOTFOUND;
6940 /* internal function to make the inherited interfaces' methods appear
6941 * part of the interface */
6942 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6943 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6945 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6948 TRACE("%p, 0x%x\n", iface, *hRefType);
6950 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
6952 ITypeInfo *pSubTypeInfo;
6954 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6958 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6960 ITypeInfo_Release(pSubTypeInfo);
6964 *hRefType -= DISPATCH_HREF_OFFSET;
6966 if (!(*hRefType & DISPATCH_HREF_MASK))
6967 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6972 /* ITypeInfo::GetRefTypeInfo
6974 * If a type description references other type descriptions, it retrieves
6975 * the referenced type descriptions.
6977 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6980 ITypeInfo **ppTInfo)
6982 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6983 HRESULT result = E_FAIL;
6985 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6987 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6988 ITypeInfo_AddRef(*ppTInfo);
6991 else if (hRefType == -1 &&
6992 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6993 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6995 /* when we meet a DUAL dispinterface, we must create the interface
6998 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
7001 /* the interface version contains the same information as the dispinterface
7002 * copy the contents of the structs.
7004 *pTypeInfoImpl = *This;
7005 pTypeInfoImpl->ref = 0;
7007 /* change the type to interface */
7008 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
7010 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
7012 /* the AddRef implicitly adds a reference to the parent typelib, which
7013 * stops the copied data from being destroyed until the new typeinfo's
7014 * refcount goes to zero, but we need to signal to the new instance to
7015 * not free its data structures when it is destroyed */
7016 pTypeInfoImpl->not_attached_to_typelib = TRUE;
7018 ITypeInfo_AddRef(*ppTInfo);
7022 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
7023 (This->TypeAttr.typekind == TKIND_DISPATCH))
7025 HREFTYPE href_dispatch = hRefType;
7026 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
7028 TLBRefType *ref_type;
7029 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
7031 if(ref_type->reference == hRefType)
7034 if(&ref_type->entry == &This->pTypeLib->ref_list)
7036 FIXME("Can't find pRefType for ref %x\n", hRefType);
7039 if(hRefType != -1) {
7040 ITypeLib *pTLib = NULL;
7042 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
7044 result = ITypeInfo2_GetContainingTypeLib(iface, &pTLib, &Index);
7046 if(ref_type->pImpTLInfo->pImpTypeLib) {
7047 TRACE("typeinfo in imported typelib that is already loaded\n");
7048 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
7049 ITypeLib_AddRef(pTLib);
7052 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7053 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
7054 ref_type->pImpTLInfo->wVersionMajor,
7055 ref_type->pImpTLInfo->wVersionMinor,
7056 ref_type->pImpTLInfo->lcid,
7059 if(FAILED(result)) {
7060 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
7061 result=LoadTypeLib(libnam, &pTLib);
7062 SysFreeString(libnam);
7064 if(SUCCEEDED(result)) {
7065 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
7066 ITypeLib_AddRef(pTLib);
7070 if(SUCCEEDED(result)) {
7071 if(ref_type->index == TLB_REF_USE_GUID)
7072 result = ITypeLib_GetTypeInfoOfGuid(pTLib, &ref_type->guid, ppTInfo);
7074 result = ITypeLib_GetTypeInfo(pTLib, ref_type->index, ppTInfo);
7077 ITypeLib_Release(pTLib);
7082 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
7083 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
7087 /* ITypeInfo::AddressOfMember
7089 * Retrieves the addresses of static functions or variables, such as those
7092 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
7093 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
7095 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7101 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
7103 hr = ITypeInfo2_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
7107 module = LoadLibraryW(dll);
7110 ERR("couldn't load %s\n", debugstr_w(dll));
7112 SysFreeString(entry);
7113 return STG_E_FILENOTFOUND;
7115 /* FIXME: store library somewhere where we can free it */
7120 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
7121 entryA = heap_alloc(len);
7122 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
7124 *ppv = GetProcAddress(module, entryA);
7126 ERR("function not found %s\n", debugstr_a(entryA));
7132 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7134 ERR("function not found %d\n", ordinal);
7138 SysFreeString(entry);
7141 return TYPE_E_DLLFUNCTIONNOTFOUND;
7146 /* ITypeInfo::CreateInstance
7148 * Creates a new instance of a type that describes a component object class
7151 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7152 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7154 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7158 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7164 WARN("Not able to aggregate\n");
7165 return CLASS_E_NOAGGREGATION;
7168 hr = ITypeInfo2_GetTypeAttr(iface, &pTA);
7169 if(FAILED(hr)) return hr;
7171 if(pTA->typekind != TKIND_COCLASS)
7173 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7179 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7182 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7183 TRACE("GetActiveObject rets %08x\n", hr);
7186 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7187 IUnknown_Release(pUnk);
7192 hr = CoCreateInstance(&pTA->guid, NULL,
7193 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7197 ITypeInfo2_ReleaseTypeAttr(iface, pTA);
7201 /* ITypeInfo::GetMops
7203 * Retrieves marshalling information.
7205 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7208 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7209 FIXME("(%p %d) stub!\n", This, memid);
7214 /* ITypeInfo::GetContainingTypeLib
7216 * Retrieves the containing type library and the index of the type description
7217 * within that type library.
7219 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7220 ITypeLib * *ppTLib, UINT *pIndex)
7222 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7224 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7226 *pIndex=This->index;
7227 TRACE("returning pIndex=%d\n", *pIndex);
7231 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7232 ITypeLib_AddRef(*ppTLib);
7233 TRACE("returning ppTLib=%p\n", *ppTLib);
7239 /* ITypeInfo::ReleaseTypeAttr
7241 * Releases a TYPEATTR previously returned by GetTypeAttr.
7244 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7245 TYPEATTR* pTypeAttr)
7247 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7248 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7249 heap_free(pTypeAttr);
7252 /* ITypeInfo::ReleaseFuncDesc
7254 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7256 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7258 FUNCDESC *pFuncDesc)
7260 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7263 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7265 for (i = 0; i < pFuncDesc->cParams; i++)
7266 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7267 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7269 SysFreeString((BSTR)pFuncDesc);
7272 /* ITypeInfo::ReleaseVarDesc
7274 * Releases a VARDESC previously returned by GetVarDesc.
7276 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7279 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7280 TRACE("(%p)->(%p)\n", This, pVarDesc);
7282 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7283 if (pVarDesc->varkind == VAR_CONST)
7284 VariantClear(pVarDesc->u.lpvarValue);
7285 SysFreeString((BSTR)pVarDesc);
7288 /* ITypeInfo2::GetTypeKind
7290 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7293 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7294 TYPEKIND *pTypeKind)
7296 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7297 *pTypeKind=This->TypeAttr.typekind;
7298 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7302 /* ITypeInfo2::GetTypeFlags
7304 * Returns the type flags without any allocations. This returns a DWORD type
7305 * flag, which expands the type flags without growing the TYPEATTR (type
7309 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7311 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7312 *pTypeFlags=This->TypeAttr.wTypeFlags;
7313 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7317 /* ITypeInfo2::GetFuncIndexOfMemId
7318 * Binds to a specific member based on a known DISPID, where the member name
7319 * is not known (for example, when binding to a default member).
7322 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7323 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7325 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7329 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7330 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7331 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7334 if(fdc < This->TypeAttr.cFuncs) {
7338 result = TYPE_E_ELEMENTNOTFOUND;
7340 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7341 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7345 /* TypeInfo2::GetVarIndexOfMemId
7347 * Binds to a specific member based on a known DISPID, where the member name
7348 * is not known (for example, when binding to a default member).
7351 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7352 MEMBERID memid, UINT *pVarIndex)
7354 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7355 TLBVarDesc *pVarInfo;
7357 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7359 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7361 return TYPE_E_ELEMENTNOTFOUND;
7363 *pVarIndex = (pVarInfo - This->vardescs);
7368 /* ITypeInfo2::GetCustData
7370 * Gets the custom data
7372 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7377 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7378 TLBCustData *pCData;
7380 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7382 pCData = TLB_get_custdata_by_guid(&This->custdata_list, guid);
7384 VariantInit( pVarVal);
7386 VariantCopy( pVarVal, &pCData->data);
7388 VariantClear( pVarVal );
7392 /* ITypeInfo2::GetFuncCustData
7394 * Gets the custom data
7396 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7402 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7403 TLBCustData *pCData;
7404 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7406 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7408 if(index >= This->TypeAttr.cFuncs)
7409 return TYPE_E_ELEMENTNOTFOUND;
7411 pCData = TLB_get_custdata_by_guid(&pFDesc->custdata_list, guid);
7413 return TYPE_E_ELEMENTNOTFOUND;
7415 VariantInit(pVarVal);
7416 VariantCopy(pVarVal, &pCData->data);
7421 /* ITypeInfo2::GetParamCustData
7423 * Gets the custom data
7425 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7432 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7433 TLBCustData *pCData;
7434 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7436 TRACE("%p %u %u %s %p\n", This, indexFunc, indexParam,
7437 debugstr_guid(guid), pVarVal);
7439 if(indexFunc >= This->TypeAttr.cFuncs)
7440 return TYPE_E_ELEMENTNOTFOUND;
7442 if(indexParam >= pFDesc->funcdesc.cParams)
7443 return TYPE_E_ELEMENTNOTFOUND;
7445 pCData = TLB_get_custdata_by_guid(&pFDesc->pParamDesc[indexParam].custdata_list, guid);
7447 return TYPE_E_ELEMENTNOTFOUND;
7449 VariantInit(pVarVal);
7450 VariantCopy(pVarVal, &pCData->data);
7455 /* ITypeInfo2::GetVarCustData
7457 * Gets the custom data
7459 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7465 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7466 TLBCustData *pCData;
7467 TLBVarDesc *pVDesc = &This->vardescs[index];
7469 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7471 if(index >= This->TypeAttr.cVars)
7472 return TYPE_E_ELEMENTNOTFOUND;
7474 pCData = TLB_get_custdata_by_guid(&pVDesc->custdata_list, guid);
7476 return TYPE_E_ELEMENTNOTFOUND;
7478 VariantInit(pVarVal);
7479 VariantCopy(pVarVal, &pCData->data);
7484 /* ITypeInfo2::GetImplCustData
7486 * Gets the custom data
7488 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7494 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7495 TLBCustData *pCData;
7496 TLBImplType *pRDesc = &This->impltypes[index];
7498 TRACE("%p %u %s %p\n", This, index, debugstr_guid(guid), pVarVal);
7500 if(index >= This->TypeAttr.cImplTypes)
7501 return TYPE_E_ELEMENTNOTFOUND;
7503 pCData = TLB_get_custdata_by_guid(&pRDesc->custdata_list, guid);
7505 return TYPE_E_ELEMENTNOTFOUND;
7507 VariantInit(pVarVal);
7508 VariantCopy(pVarVal, &pCData->data);
7513 /* ITypeInfo2::GetDocumentation2
7515 * Retrieves the documentation string, the complete Help file name and path,
7516 * the localization context to use, and the context ID for the library Help
7517 * topic in the Help file.
7520 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7524 BSTR *pbstrHelpString,
7525 DWORD *pdwHelpStringContext,
7526 BSTR *pbstrHelpStringDll)
7528 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7529 const TLBFuncDesc *pFDesc;
7530 const TLBVarDesc *pVDesc;
7531 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7532 "HelpStringContext(%p) HelpStringDll(%p)\n",
7533 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7534 pbstrHelpStringDll );
7535 /* the help string should be obtained from the helpstringdll,
7536 * using the _DLLGetDocumentation function, based on the supplied
7537 * lcid. Nice to do sometime...
7539 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7541 *pbstrHelpString=SysAllocString(This->Name);
7542 if(pdwHelpStringContext)
7543 *pdwHelpStringContext=This->dwHelpStringContext;
7544 if(pbstrHelpStringDll)
7545 *pbstrHelpStringDll=
7546 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7548 }else {/* for a member */
7549 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7552 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7553 if(pdwHelpStringContext)
7554 *pdwHelpStringContext=pFDesc->HelpStringContext;
7555 if(pbstrHelpStringDll)
7556 *pbstrHelpStringDll=
7557 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7560 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7563 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7564 if(pdwHelpStringContext)
7565 *pdwHelpStringContext=pVDesc->HelpStringContext;
7566 if(pbstrHelpStringDll)
7567 *pbstrHelpStringDll=
7568 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7572 return TYPE_E_ELEMENTNOTFOUND;
7575 /* ITypeInfo2::GetAllCustData
7577 * Gets all custom data items for the Type info.
7580 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7582 CUSTDATA *pCustData)
7584 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7586 TRACE("%p %p\n", This, pCustData);
7588 return TLB_copy_all_custdata(&This->custdata_list, pCustData);
7591 /* ITypeInfo2::GetAllFuncCustData
7593 * Gets all custom data items for the specified Function
7596 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7599 CUSTDATA *pCustData)
7601 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7602 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7604 TRACE("%p %u %p\n", This, index, pCustData);
7606 if(index >= This->TypeAttr.cFuncs)
7607 return TYPE_E_ELEMENTNOTFOUND;
7609 return TLB_copy_all_custdata(&pFDesc->custdata_list, pCustData);
7612 /* ITypeInfo2::GetAllParamCustData
7614 * Gets all custom data items for the Functions
7617 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7618 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7620 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7621 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7623 TRACE("%p %u %u %p\n", This, indexFunc, indexParam, pCustData);
7625 if(indexFunc >= This->TypeAttr.cFuncs)
7626 return TYPE_E_ELEMENTNOTFOUND;
7628 if(indexParam >= pFDesc->funcdesc.cParams)
7629 return TYPE_E_ELEMENTNOTFOUND;
7631 return TLB_copy_all_custdata(&pFDesc->pParamDesc[indexParam].custdata_list, pCustData);
7634 /* ITypeInfo2::GetAllVarCustData
7636 * Gets all custom data items for the specified Variable
7639 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7640 UINT index, CUSTDATA *pCustData)
7642 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7643 TLBVarDesc * pVDesc = &This->vardescs[index];
7645 TRACE("%p %u %p\n", This, index, pCustData);
7647 if(index >= This->TypeAttr.cVars)
7648 return TYPE_E_ELEMENTNOTFOUND;
7650 return TLB_copy_all_custdata(&pVDesc->custdata_list, pCustData);
7653 /* ITypeInfo2::GetAllImplCustData
7655 * Gets all custom data items for the specified implementation type
7658 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7661 CUSTDATA *pCustData)
7663 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7664 TLBImplType *pRDesc = &This->impltypes[index];
7666 TRACE("%p %u %p\n", This, index, pCustData);
7668 if(index >= This->TypeAttr.cImplTypes)
7669 return TYPE_E_ELEMENTNOTFOUND;
7671 return TLB_copy_all_custdata(&pRDesc->custdata_list, pCustData);
7674 static const ITypeInfo2Vtbl tinfvt =
7677 ITypeInfo_fnQueryInterface,
7679 ITypeInfo_fnRelease,
7681 ITypeInfo_fnGetTypeAttr,
7682 ITypeInfo_fnGetTypeComp,
7683 ITypeInfo_fnGetFuncDesc,
7684 ITypeInfo_fnGetVarDesc,
7685 ITypeInfo_fnGetNames,
7686 ITypeInfo_fnGetRefTypeOfImplType,
7687 ITypeInfo_fnGetImplTypeFlags,
7688 ITypeInfo_fnGetIDsOfNames,
7690 ITypeInfo_fnGetDocumentation,
7691 ITypeInfo_fnGetDllEntry,
7692 ITypeInfo_fnGetRefTypeInfo,
7693 ITypeInfo_fnAddressOfMember,
7694 ITypeInfo_fnCreateInstance,
7695 ITypeInfo_fnGetMops,
7696 ITypeInfo_fnGetContainingTypeLib,
7697 ITypeInfo_fnReleaseTypeAttr,
7698 ITypeInfo_fnReleaseFuncDesc,
7699 ITypeInfo_fnReleaseVarDesc,
7701 ITypeInfo2_fnGetTypeKind,
7702 ITypeInfo2_fnGetTypeFlags,
7703 ITypeInfo2_fnGetFuncIndexOfMemId,
7704 ITypeInfo2_fnGetVarIndexOfMemId,
7705 ITypeInfo2_fnGetCustData,
7706 ITypeInfo2_fnGetFuncCustData,
7707 ITypeInfo2_fnGetParamCustData,
7708 ITypeInfo2_fnGetVarCustData,
7709 ITypeInfo2_fnGetImplTypeCustData,
7710 ITypeInfo2_fnGetDocumentation2,
7711 ITypeInfo2_fnGetAllCustData,
7712 ITypeInfo2_fnGetAllFuncCustData,
7713 ITypeInfo2_fnGetAllParamCustData,
7714 ITypeInfo2_fnGetAllVarCustData,
7715 ITypeInfo2_fnGetAllImplTypeCustData,
7718 /******************************************************************************
7719 * CreateDispTypeInfo [OLEAUT32.31]
7721 * Build type information for an object so it can be called through an
7722 * IDispatch interface.
7725 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7726 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7729 * This call allows an objects methods to be accessed through IDispatch, by
7730 * building an ITypeInfo object that IDispatch can use to call through.
7732 HRESULT WINAPI CreateDispTypeInfo(
7733 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7734 LCID lcid, /* [I] Locale Id */
7735 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7737 ITypeInfoImpl *pTIClass, *pTIIface;
7738 ITypeLibImpl *pTypeLibImpl;
7739 unsigned int param, func;
7740 TLBFuncDesc *pFuncDesc;
7744 pTypeLibImpl = TypeLibImpl_Constructor();
7745 if (!pTypeLibImpl) return E_FAIL;
7747 pTypeLibImpl->TypeInfoCount = 2;
7748 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
7750 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
7751 pTIIface->pTypeLib = pTypeLibImpl;
7752 pTIIface->index = 0;
7753 pTIIface->Name = NULL;
7754 pTIIface->dwHelpContext = -1;
7755 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7756 pTIIface->TypeAttr.lcid = lcid;
7757 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7758 pTIIface->TypeAttr.wMajorVerNum = 0;
7759 pTIIface->TypeAttr.wMinorVerNum = 0;
7760 pTIIface->TypeAttr.cbAlignment = 2;
7761 pTIIface->TypeAttr.cbSizeInstance = -1;
7762 pTIIface->TypeAttr.cbSizeVft = -1;
7763 pTIIface->TypeAttr.cFuncs = 0;
7764 pTIIface->TypeAttr.cImplTypes = 0;
7765 pTIIface->TypeAttr.cVars = 0;
7766 pTIIface->TypeAttr.wTypeFlags = 0;
7768 pTIIface->funcdescs = TLBFuncDesc_Constructor(pidata->cMembers);
7769 pFuncDesc = pTIIface->funcdescs;
7770 for(func = 0; func < pidata->cMembers; func++) {
7771 METHODDATA *md = pidata->pmethdata + func;
7772 pFuncDesc->Name = SysAllocString(md->szName);
7773 pFuncDesc->funcdesc.memid = md->dispid;
7774 pFuncDesc->funcdesc.lprgscode = NULL;
7775 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
7776 pFuncDesc->funcdesc.invkind = md->wFlags;
7777 pFuncDesc->funcdesc.callconv = md->cc;
7778 pFuncDesc->funcdesc.cParams = md->cArgs;
7779 pFuncDesc->funcdesc.cParamsOpt = 0;
7780 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
7781 pFuncDesc->funcdesc.cScodes = 0;
7782 pFuncDesc->funcdesc.wFuncFlags = 0;
7783 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7784 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7785 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7786 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7787 md->cArgs * sizeof(ELEMDESC));
7788 pFuncDesc->pParamDesc = TLBParDesc_Constructor(md->cArgs);
7789 for(param = 0; param < md->cArgs; param++) {
7790 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7791 pFuncDesc->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7793 pFuncDesc->helpcontext = 0;
7794 pFuncDesc->HelpStringContext = 0;
7795 pFuncDesc->HelpString = NULL;
7796 pFuncDesc->Entry = NULL;
7797 list_init(&pFuncDesc->custdata_list);
7798 pTIIface->TypeAttr.cFuncs++;
7802 dump_TypeInfo(pTIIface);
7804 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
7805 pTIClass->pTypeLib = pTypeLibImpl;
7806 pTIClass->index = 1;
7807 pTIClass->Name = NULL;
7808 pTIClass->dwHelpContext = -1;
7809 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7810 pTIClass->TypeAttr.lcid = lcid;
7811 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7812 pTIClass->TypeAttr.wMajorVerNum = 0;
7813 pTIClass->TypeAttr.wMinorVerNum = 0;
7814 pTIClass->TypeAttr.cbAlignment = 2;
7815 pTIClass->TypeAttr.cbSizeInstance = -1;
7816 pTIClass->TypeAttr.cbSizeVft = -1;
7817 pTIClass->TypeAttr.cFuncs = 0;
7818 pTIClass->TypeAttr.cImplTypes = 1;
7819 pTIClass->TypeAttr.cVars = 0;
7820 pTIClass->TypeAttr.wTypeFlags = 0;
7822 pTIClass->impltypes = TLBImplType_Constructor(1);
7824 ref = heap_alloc_zero(sizeof(*ref));
7825 ref->pImpTLInfo = TLB_REF_INTERNAL;
7826 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7828 dump_TypeInfo(pTIClass);
7830 *pptinfo = (ITypeInfo*)pTIClass;
7832 ITypeInfo_AddRef(*pptinfo);
7833 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7839 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7841 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7843 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7846 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7848 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7850 return ITypeInfo_AddRef((ITypeInfo *)This);
7853 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7855 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7857 return ITypeInfo_Release((ITypeInfo *)This);
7860 static HRESULT WINAPI ITypeComp_fnBind(
7865 ITypeInfo ** ppTInfo,
7866 DESCKIND * pDescKind,
7869 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7870 const TLBFuncDesc *pFDesc;
7871 const TLBVarDesc *pVDesc;
7872 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7875 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7877 *pDescKind = DESCKIND_NONE;
7878 pBindPtr->lpfuncdesc = NULL;
7881 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7882 pFDesc = &This->funcdescs[fdc];
7883 if (!strcmpiW(pFDesc->Name, szName)) {
7884 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7887 /* name found, but wrong flags */
7888 hr = TYPE_E_TYPEMISMATCH;
7892 if (fdc < This->TypeAttr.cFuncs)
7894 HRESULT hr = TLB_AllocAndInitFuncDesc(
7896 &pBindPtr->lpfuncdesc,
7897 This->TypeAttr.typekind == TKIND_DISPATCH);
7900 *pDescKind = DESCKIND_FUNCDESC;
7901 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7902 ITypeInfo_AddRef(*ppTInfo);
7905 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, szName);
7907 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7910 *pDescKind = DESCKIND_VARDESC;
7911 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7912 ITypeInfo_AddRef(*ppTInfo);
7916 /* FIXME: search each inherited interface, not just the first */
7917 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
7918 /* recursive search */
7922 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypes[0].hRef, &pTInfo);
7925 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7926 ITypeInfo_Release(pTInfo);
7930 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7931 ITypeComp_Release(pTComp);
7934 WARN("Could not search inherited interface!\n");
7936 if (hr == DISP_E_MEMBERNOTFOUND)
7938 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7942 static HRESULT WINAPI ITypeComp_fnBindType(
7946 ITypeInfo ** ppTInfo,
7947 ITypeComp ** ppTComp)
7949 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7951 /* strange behaviour (does nothing) but like the
7954 if (!ppTInfo || !ppTComp)
7963 static const ITypeCompVtbl tcompvt =
7966 ITypeComp_fnQueryInterface,
7968 ITypeComp_fnRelease,
7971 ITypeComp_fnBindType