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 IUnknown_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
960 struct tagTLBCustData* next;
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 */
980 struct tagTLBImpLib * next;
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 int ctCustData; /* number of items in cust data list */
1003 TLBCustData * pCustData; /* linked list to cust data */
1004 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
1005 int ctTypeDesc; /* number of items in type desc array */
1006 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1007 library. Only used while reading MSFT
1009 struct list ref_list; /* list of ref types in this typelib */
1010 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1013 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1014 struct tagITypeLibImpl *next, *prev;
1019 static const ITypeLib2Vtbl tlbvt;
1020 static const ITypeCompVtbl tlbtcvt;
1022 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1024 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1027 /* ITypeLib methods */
1028 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1029 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1031 /*======================= ITypeInfo implementation =======================*/
1033 /* data for referenced types */
1034 typedef struct tagTLBRefType
1036 INT index; /* Type index for internal ref or for external ref
1037 it the format is SLTG. -2 indicates to
1040 GUID guid; /* guid of the referenced type */
1041 /* if index == TLB_REF_USE_GUID */
1043 HREFTYPE reference; /* The href of this ref */
1044 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1045 TLB_REF_INTERNAL for internal refs
1046 TLB_REF_NOT_FOUND for broken refs */
1051 #define TLB_REF_USE_GUID -2
1053 #define TLB_REF_INTERNAL (void*)-2
1054 #define TLB_REF_NOT_FOUND (void*)-1
1056 /* internal Parameter data */
1057 typedef struct tagTLBParDesc
1061 TLBCustData * pCustData; /* linked list to cust data */
1064 /* internal Function data */
1065 typedef struct tagTLBFuncDesc
1067 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1068 BSTR Name; /* the name of this function */
1069 TLBParDesc *pParamDesc; /* array with param names and custom data */
1071 int HelpStringContext;
1073 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1075 TLBCustData * pCustData; /* linked list to cust data; */
1078 /* internal Variable data */
1079 typedef struct tagTLBVarDesc
1081 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1082 BSTR Name; /* the name of this variable */
1084 int HelpStringContext;
1087 TLBCustData * pCustData;/* linked list to cust data; */
1090 /* internal implemented interface data */
1091 typedef struct tagTLBImplType
1093 HREFTYPE hRef; /* hRef of interface */
1094 int implflags; /* IMPLFLAG_*s */
1096 TLBCustData * pCustData;/* linked list to custom data; */
1099 /* internal TypeInfo data */
1100 typedef struct tagITypeInfoImpl
1102 const ITypeInfo2Vtbl *lpVtbl;
1103 const ITypeCompVtbl *lpVtblTypeComp;
1105 BOOL not_attached_to_typelib;
1106 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1107 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1108 int index; /* index in this typelib; */
1109 HREFTYPE hreftype; /* hreftype for app object binding */
1110 /* type libs seem to store the doc strings in ascii
1111 * so why should we do it in unicode?
1116 DWORD dwHelpContext;
1117 DWORD dwHelpStringContext;
1120 TLBFuncDesc *funcdescs;
1123 TLBVarDesc *vardescs;
1125 /* Implemented Interfaces */
1126 TLBImplType *impltypes;
1129 TLBCustData * pCustData; /* linked list to cust data; */
1132 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1134 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1137 static const ITypeInfo2Vtbl tinfvt;
1138 static const ITypeCompVtbl tcompvt;
1140 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1141 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1143 typedef struct tagTLBContext
1145 unsigned int oStart; /* start of TLB in file */
1146 unsigned int pos; /* current pos */
1147 unsigned int length; /* total length */
1148 void *mapping; /* memory mapping */
1149 MSFT_SegDir * pTblDir;
1150 ITypeLibImpl* pLibInfo;
1154 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1159 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1160 if (pTD->vt & VT_RESERVED)
1161 szVarType += strlen(strcpy(szVarType, "reserved | "));
1162 if (pTD->vt & VT_BYREF)
1163 szVarType += strlen(strcpy(szVarType, "ref to "));
1164 if (pTD->vt & VT_ARRAY)
1165 szVarType += strlen(strcpy(szVarType, "array of "));
1166 if (pTD->vt & VT_VECTOR)
1167 szVarType += strlen(strcpy(szVarType, "vector of "));
1168 switch(pTD->vt & VT_TYPEMASK) {
1169 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1170 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1171 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1172 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1173 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1174 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1175 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1176 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1177 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1178 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1179 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1180 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1181 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1182 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1183 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1184 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1185 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1186 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1187 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1188 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1189 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1190 pTD->u.hreftype); break;
1191 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1192 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1193 case VT_PTR: sprintf(szVarType, "ptr to ");
1194 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1196 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1197 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1199 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1200 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1201 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1204 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1208 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1210 USHORT flags = edesc->u.paramdesc.wParamFlags;
1211 dump_TypeDesc(&edesc->tdesc,buf);
1212 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1213 MESSAGE("\t\tu.paramdesc.wParamFlags");
1214 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1215 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1216 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1217 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1218 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1219 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1220 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1221 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1222 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1224 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1226 MESSAGE("memid is %08x\n",funcdesc->memid);
1227 for (i=0;i<funcdesc->cParams;i++) {
1228 MESSAGE("Param %d:\n",i);
1229 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1231 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1232 switch (funcdesc->funckind) {
1233 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1234 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1235 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1236 case FUNC_STATIC: MESSAGE("static");break;
1237 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1238 default: MESSAGE("unknown");break;
1240 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1241 switch (funcdesc->invkind) {
1242 case INVOKE_FUNC: MESSAGE("func");break;
1243 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1244 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1245 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1247 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1248 switch (funcdesc->callconv) {
1249 case CC_CDECL: MESSAGE("cdecl");break;
1250 case CC_PASCAL: MESSAGE("pascal");break;
1251 case CC_STDCALL: MESSAGE("stdcall");break;
1252 case CC_SYSCALL: MESSAGE("syscall");break;
1255 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1256 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1257 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1259 MESSAGE("\telemdescFunc (return value type):\n");
1260 dump_ELEMDESC(&funcdesc->elemdescFunc);
1263 static const char * const typekind_desc[] =
1276 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1279 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1280 for (i=0;i<pfd->funcdesc.cParams;i++)
1281 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1284 dump_FUNCDESC(&(pfd->funcdesc));
1286 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1287 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1289 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1293 dump_TLBFuncDescOne(pfd);
1298 static void dump_TLBVarDesc(const TLBVarDesc * pvd, UINT n)
1302 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1308 static void dump_TLBImpLib(const TLBImpLib *import)
1310 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1311 debugstr_w(import->name));
1312 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1313 import->wVersionMinor, import->lcid, import->offset);
1316 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1320 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1322 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1323 if(ref->index == -1)
1324 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1326 TRACE_(typelib)("type no: %d\n", ref->index);
1328 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1330 TRACE_(typelib)("in lib\n");
1331 dump_TLBImpLib(ref->pImpTLInfo);
1336 static void dump_TLBImplType(const TLBImplType * impl, UINT n)
1341 TRACE_(typelib)("implementing/inheriting interface hRef = %x implflags %x\n",
1342 impl->hRef, impl->implflags);
1348 static void dump_Variant(const VARIANT * pvar)
1352 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1356 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1357 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1359 TRACE(",%p", V_BYREF(pvar));
1361 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1363 TRACE(",%p", V_ARRAY(pvar));
1365 else switch (V_TYPE(pvar))
1367 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1368 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1369 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1370 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1372 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1374 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1375 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1376 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1377 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1378 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1379 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1380 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1381 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1382 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1383 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1384 V_CY(pvar).s.Lo); break;
1386 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1387 TRACE(",<invalid>");
1389 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1390 st.wHour, st.wMinute, st.wSecond);
1394 case VT_USERDEFINED:
1396 case VT_NULL: break;
1397 default: TRACE(",?"); break;
1403 static void dump_DispParms(const DISPPARAMS * pdp)
1407 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1409 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1411 TRACE("named args:\n");
1412 for (index = 0; index < pdp->cNamedArgs; index++)
1413 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1416 if (pdp->cArgs && pdp->rgvarg)
1419 for (index = 0; index < pdp->cArgs; index++)
1420 dump_Variant( &pdp->rgvarg[index] );
1424 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1426 TRACE("%p ref=%u\n", pty, pty->ref);
1427 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1428 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1429 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1430 TRACE("fct:%u var:%u impl:%u\n",
1431 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1432 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1433 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1434 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1436 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1437 dump_TLBVarDesc(pty->vardescs, pty->TypeAttr.cVars);
1438 dump_TLBImplType(pty->impltypes, pty->TypeAttr.cImplTypes);
1441 static void dump_VARDESC(const VARDESC *v)
1443 MESSAGE("memid %d\n",v->memid);
1444 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1445 MESSAGE("oInst %d\n",v->u.oInst);
1446 dump_ELEMDESC(&(v->elemdescVar));
1447 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1448 MESSAGE("varkind %d\n",v->varkind);
1451 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1453 /* VT_LPWSTR is largest type that, may appear in type description */
1454 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1455 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1456 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1457 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1458 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1459 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1460 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1461 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1464 static void TLB_abort(void)
1469 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1471 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1472 if (!ret) ERR("cannot allocate memory\n");
1476 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1478 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1479 if (!ret) ERR("cannot allocate memory\n");
1483 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1485 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1488 void heap_free(void *ptr)
1490 HeapFree(GetProcessHeap(), 0, ptr);
1493 /* returns the size required for a deep copy of a typedesc into a
1495 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1499 if (alloc_initial_space)
1500 size += sizeof(TYPEDESC);
1506 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1509 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1510 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1516 /* deep copy a typedesc into a flat buffer */
1517 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1522 buffer = (char *)buffer + sizeof(TYPEDESC);
1531 dest->u.lptdesc = buffer;
1532 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1535 dest->u.lpadesc = buffer;
1536 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1537 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1538 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1544 /* free custom data allocated by MSFT_CustData */
1545 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1547 TLBCustData *pCustDataNext;
1548 for (; pCustData; pCustData = pCustDataNext)
1550 VariantClear(&pCustData->data);
1552 pCustDataNext = pCustData->next;
1553 heap_free(pCustData);
1557 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1562 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1563 ret = SysAllocStringLen(NULL, len - 1);
1564 if (!ret) return ret;
1565 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1569 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1570 UINT n, MEMBERID memid)
1573 if(funcdescs->funcdesc.memid == memid)
1581 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1582 UINT n, const OLECHAR *name)
1585 if(!lstrcmpiW(funcdescs->Name, name))
1593 static inline TLBVarDesc *TLB_get_vardesc_by_memberid(TLBVarDesc *vardescs,
1594 UINT n, MEMBERID memid)
1597 if(vardescs->vardesc.memid == memid)
1605 static inline TLBVarDesc *TLB_get_vardesc_by_name(TLBVarDesc *vardescs,
1606 UINT n, const OLECHAR *name)
1609 if(!lstrcmpiW(vardescs->Name, name))
1617 /**********************************************************************
1619 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1621 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1626 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1628 if (where != DO_NOT_SEEK)
1630 where += pcx->oStart;
1631 if (where > pcx->length)
1634 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1642 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1644 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1645 pcx->pos, count, pcx->oStart, pcx->length, where);
1647 MSFT_Seek(pcx, where);
1648 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1649 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1654 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1659 ret = MSFT_Read(buffer, count, pcx, where);
1660 FromLEDWords(buffer, ret);
1665 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1670 ret = MSFT_Read(buffer, count, pcx, where);
1671 FromLEWords(buffer, ret);
1676 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1678 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1679 memset(pGuid,0, sizeof(GUID));
1682 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1683 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1684 pGuid->Data2 = FromLEWord(pGuid->Data2);
1685 pGuid->Data3 = FromLEWord(pGuid->Data3);
1686 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1689 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1691 MSFT_NameIntro niName;
1695 ERR_(typelib)("bad offset %d\n", offset);
1699 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1700 pcx->pTblDir->pNametab.offset+offset);
1702 return niName.hreftype;
1705 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1708 MSFT_NameIntro niName;
1710 BSTR bstrName = NULL;
1714 ERR_(typelib)("bad offset %d\n", offset);
1717 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1718 pcx->pTblDir->pNametab.offset+offset);
1719 niName.namelen &= 0xFF; /* FIXME: correct ? */
1720 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1721 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1722 name[niName.namelen & 0xff]='\0';
1724 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1727 /* no invalid characters in string */
1730 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1732 /* don't check for invalid character since this has been done previously */
1733 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1737 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1741 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1748 if(offset<0) return NULL;
1749 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1750 if(length <= 0) return 0;
1751 string = heap_alloc_zero(length +1);
1752 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1753 string[length]='\0';
1755 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1756 string, -1, NULL, 0);
1758 /* no invalid characters in string */
1761 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1763 /* don't check for invalid character since this has been done previously */
1764 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1768 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1772 * read a value and fill a VARIANT structure
1774 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1778 TRACE_(typelib)("\n");
1780 if(offset <0) { /* data are packed in here */
1781 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1782 V_I4(pVar) = offset & 0x3ffffff;
1785 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1786 pcx->pTblDir->pCustData.offset + offset );
1787 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1788 switch (V_VT(pVar)){
1789 case VT_EMPTY: /* FIXME: is this right? */
1790 case VT_NULL: /* FIXME: is this right? */
1791 case VT_I2 : /* this should not happen */
1802 case VT_VOID : /* FIXME: is this right? */
1810 case VT_DECIMAL : /* FIXME: is this right? */
1813 /* pointer types with known behaviour */
1816 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1819 DWORD origPos = MSFT_Tell(pcx), nullPos;
1822 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1824 nullPos = MSFT_Tell(pcx);
1825 size = nullPos - origPos;
1826 MSFT_Seek(pcx, origPos);
1828 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1829 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1830 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1831 /* FIXME: do we need a AtoW conversion here? */
1832 V_UNION(pVar, bstrVal[size])='\0';
1833 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1837 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1844 case VT_USERDEFINED :
1850 case VT_STREAMED_OBJECT :
1851 case VT_STORED_OBJECT :
1852 case VT_BLOB_OBJECT :
1857 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1861 if(size>0) /* (big|small) endian correct? */
1862 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1866 * create a linked list with custom data
1868 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1874 TRACE_(typelib)("\n");
1878 pNew=heap_alloc_zero(sizeof(TLBCustData));
1879 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1880 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1881 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1882 /* add new custom data at head of the list */
1883 pNew->next=*ppCustData;
1885 offset = entry.next;
1890 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1894 pTd->vt=type & VT_TYPEMASK;
1896 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1898 if(pTd->vt == VT_USERDEFINED)
1899 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1901 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1904 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1906 /* resolve referenced type if any */
1909 switch (lpTypeDesc->vt)
1912 lpTypeDesc = lpTypeDesc->u.lptdesc;
1916 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1919 case VT_USERDEFINED:
1920 MSFT_DoRefType(pcx, pTI->pTypeLib,
1921 lpTypeDesc->u.hreftype);
1933 MSFT_DoFuncs(TLBContext* pcx,
1938 TLBFuncDesc** pptfd)
1941 * member information is stored in a data structure at offset
1942 * indicated by the memoffset field of the typeinfo structure
1943 * There are several distinctive parts.
1944 * The first part starts with a field that holds the total length
1945 * of this (first) part excluding this field. Then follow the records,
1946 * for each member there is one record.
1948 * The first entry is always the length of the record (including this
1950 * The rest of the record depends on the type of the member. If there is
1951 * a field indicating the member type (function, variable, interface, etc)
1952 * I have not found it yet. At this time we depend on the information
1953 * in the type info and the usual order how things are stored.
1955 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1958 * Third is an equal sized array with file offsets to the name entry
1961 * The fourth and last (?) part is an array with offsets to the records
1962 * in the first part of this file segment.
1965 int infolen, nameoffset, reclength, i;
1966 int recoffset = offset + sizeof(INT);
1968 char *recbuf = heap_alloc(0xffff);
1969 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
1970 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
1972 TRACE_(typelib)("\n");
1974 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1976 *pptfd = heap_alloc_zero(sizeof(TLBFuncDesc) * cFuncs);
1978 for ( i = 0; i < cFuncs ; i++ )
1982 /* name, eventually add to a hash table */
1983 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1984 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1986 /* nameoffset is sometimes -1 on the second half of a propget/propput
1987 * pair of functions */
1988 if ((nameoffset == -1) && (i > 0))
1989 ptfd->Name = SysAllocString(ptfd_prev->Name);
1991 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
1993 /* read the function information record */
1994 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
1996 reclength &= 0xffff;
1998 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
2000 /* size without argument data */
2001 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
2003 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
2004 ptfd->helpcontext = pFuncRec->HelpContext;
2006 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
2007 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
2009 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
2011 if (pFuncRec->FKCCIC & 0x2000 )
2013 if (!IS_INTRESOURCE(pFuncRec->oEntry))
2014 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
2015 ptfd->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
2018 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
2021 ptfd->Entry = (BSTR)-1;
2023 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
2024 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2026 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2027 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->pCustData);
2029 /* fill the FuncDesc Structure */
2030 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2031 offset + infolen + ( i + 1) * sizeof(INT));
2033 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2034 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2035 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2036 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2037 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2038 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2039 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2043 &ptfd->funcdesc.elemdescFunc.tdesc,
2045 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2047 /* do the parameters/arguments */
2048 if(pFuncRec->nrargs)
2051 MSFT_ParameterInfo paraminfo;
2053 ptfd->funcdesc.lprgelemdescParam =
2054 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2057 heap_alloc_zero(pFuncRec->nrargs * sizeof(TLBParDesc));
2059 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
2060 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2062 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2064 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2071 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2074 if (paraminfo.oName == -1)
2075 /* this occurs for [propput] or [propget] methods, so
2076 * we should just set the name of the parameter to the
2077 * name of the method. */
2078 ptfd->pParamDesc[j].Name = SysAllocString(ptfd->Name);
2080 ptfd->pParamDesc[j].Name =
2081 MSFT_ReadName( pcx, paraminfo.oName );
2082 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(ptfd->pParamDesc[j].Name));
2084 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2087 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2088 (pFuncRec->FKCCIC & 0x1000) )
2090 INT* pInt = (INT *)((char *)pFuncRec +
2092 (pFuncRec->nrargs * 4) * sizeof(INT) );
2094 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2096 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2097 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2099 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2103 elemdesc->u.paramdesc.pparamdescex = NULL;
2106 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2107 j*sizeof(pFuncRec->oArgCustData[0])) &&
2108 pFuncRec->FKCCIC & 0x80 )
2111 pFuncRec->oArgCustData[j],
2112 &ptfd->pParamDesc[j].pCustData);
2115 /* SEEK value = jump to offset,
2116 * from there jump to the end of record,
2117 * go back by (j-1) arguments
2119 MSFT_ReadLEDWords( ¶minfo ,
2120 sizeof(MSFT_ParameterInfo), pcx,
2121 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2122 * sizeof(MSFT_ParameterInfo)));
2126 /* scode is not used: archaic win16 stuff FIXME: right? */
2127 ptfd->funcdesc.cScodes = 0 ;
2128 ptfd->funcdesc.lprgscode = NULL ;
2132 recoffset += reclength;
2137 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2138 int cVars, int offset, TLBVarDesc ** pptvd)
2140 int infolen, nameoffset, reclength;
2142 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2147 TRACE_(typelib)("\n");
2149 ptvd = *pptvd = heap_alloc_zero(sizeof(TLBVarDesc) * cVars);
2150 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2151 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2152 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2153 recoffset += offset+sizeof(INT);
2154 for(i=0;i<cVars;i++, ++ptvd){
2155 /* name, eventually add to a hash table */
2156 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2157 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2158 ptvd->Name=MSFT_ReadName(pcx, nameoffset);
2159 /* read the variable information record */
2160 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2162 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2165 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2166 ptvd->HelpContext = pVarRec->HelpContext;
2168 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2169 ptvd->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2171 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2172 ptvd->HelpStringContext = pVarRec->HelpStringContext;
2174 /* fill the VarDesc Structure */
2175 MSFT_ReadLEDWords(&ptvd->vardesc.memid, sizeof(INT), pcx,
2176 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2177 ptvd->vardesc.varkind = pVarRec->VarKind;
2178 ptvd->vardesc.wVarFlags = pVarRec->Flags;
2179 MSFT_GetTdesc(pcx, pVarRec->DataType,
2180 &ptvd->vardesc.elemdescVar.tdesc, pTI);
2181 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2182 if(pVarRec->VarKind == VAR_CONST ){
2183 ptvd->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2184 MSFT_ReadValue(ptvd->vardesc.u.lpvarValue,
2185 pVarRec->OffsValue, pcx);
2187 ptvd->vardesc.u.oInst=pVarRec->OffsValue;
2188 MSFT_ResolveReferencedTypes(pcx, pTI, &ptvd->vardesc.elemdescVar.tdesc);
2189 recoffset += reclength;
2192 /* fill in data for a hreftype (offset). When the referenced type is contained
2193 * in the typelib, it's just an (file) offset in the type info base dir.
2194 * If comes from import, it's an offset+1 in the ImpInfo table
2196 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2201 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2203 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2205 if(ref->reference == offset) return;
2208 ref = heap_alloc_zero(sizeof(TLBRefType));
2209 list_add_tail(&pTL->ref_list, &ref->entry);
2211 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2212 /* external typelib */
2213 MSFT_ImpInfo impinfo;
2214 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2216 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2218 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2219 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2220 while (pImpLib){ /* search the known offsets of all import libraries */
2221 if(pImpLib->offset==impinfo.oImpFile) break;
2222 pImpLib=pImpLib->next;
2225 ref->reference = offset;
2226 ref->pImpTLInfo = pImpLib;
2227 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2228 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2229 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2230 ref->index = TLB_REF_USE_GUID;
2232 ref->index = impinfo.oGuid;
2234 ERR("Cannot find a reference\n");
2235 ref->reference = -1;
2236 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2239 /* in this typelib */
2240 ref->index = MSFT_HREFTYPE_INDEX(offset);
2241 ref->reference = offset;
2242 ref->pImpTLInfo = TLB_REF_INTERNAL;
2246 /* process Implemented Interfaces of a com class */
2247 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2251 MSFT_RefRecord refrec;
2254 TRACE_(typelib)("\n");
2256 pTI->impltypes = heap_alloc_zero(count * sizeof(TLBImplType));
2257 pImpl = pTI->impltypes;
2258 for(i=0;i<count;i++){
2259 if(offset<0) break; /* paranoia */
2260 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2261 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2262 pImpl->hRef = refrec.reftype;
2263 pImpl->implflags=refrec.flags;
2265 MSFT_CustData(pcx, refrec.oCustData, &pImpl->pCustData);
2266 offset=refrec.onext;
2271 * process a typeinfo record
2273 static ITypeInfoImpl * MSFT_DoTypeInfo(
2276 ITypeLibImpl * pLibInfo)
2278 MSFT_TypeInfoBase tiBase;
2279 ITypeInfoImpl *ptiRet;
2281 TRACE_(typelib)("count=%u\n", count);
2283 ptiRet = ITypeInfoImpl_Constructor();
2284 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2285 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2287 /* this is where we are coming from */
2288 ptiRet->pTypeLib = pLibInfo;
2289 ptiRet->index=count;
2290 /* fill in the typeattr fields */
2292 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2293 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2294 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2295 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2296 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2297 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2298 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2299 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2300 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2301 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2302 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2303 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2304 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2305 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2306 MSFT_GetTdesc(pcx, tiBase.datatype1,
2307 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2310 /* IDLDESC idldescType; *//* never saw this one != zero */
2312 /* name, eventually add to a hash table */
2313 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2314 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2315 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2317 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2318 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2319 ptiRet->dwHelpContext=tiBase.helpcontext;
2321 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2322 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2324 /* note: InfoType's Help file and HelpStringDll come from the containing
2325 * library. Further HelpString and Docstring appear to be the same thing :(
2328 if(ptiRet->TypeAttr.cFuncs >0 )
2329 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2330 ptiRet->TypeAttr.cVars,
2331 tiBase.memoffset, &ptiRet->funcdescs);
2333 if(ptiRet->TypeAttr.cVars >0 )
2334 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2335 ptiRet->TypeAttr.cVars,
2336 tiBase.memoffset, &ptiRet->vardescs);
2337 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2338 switch(ptiRet->TypeAttr.typekind)
2341 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2344 case TKIND_DISPATCH:
2345 /* This is not -1 when the interface is a non-base dual interface or
2346 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2347 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2351 if (tiBase.datatype1 != -1)
2353 ptiRet->impltypes = heap_alloc_zero(sizeof(TLBImplType));
2354 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2355 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2359 ptiRet->impltypes = heap_alloc_zero(sizeof(TLBImplType));
2360 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2361 ptiRet->impltypes[0].hRef = tiBase.datatype1;
2366 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2368 TRACE_(typelib)("%s guid: %s kind:%s\n",
2369 debugstr_w(ptiRet->Name),
2370 debugstr_guid(&ptiRet->TypeAttr.guid),
2371 typekind_desc[ptiRet->TypeAttr.typekind]);
2372 if (TRACE_ON(typelib))
2373 dump_TypeInfo(ptiRet);
2378 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2379 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2380 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2383 static ITypeLibImpl *tlb_cache_first;
2384 static CRITICAL_SECTION cache_section;
2385 static CRITICAL_SECTION_DEBUG cache_section_debug =
2387 0, 0, &cache_section,
2388 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2389 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2391 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2394 typedef struct TLB_PEFile
2396 const IUnknownVtbl *lpvtbl;
2399 HRSRC typelib_resource;
2400 HGLOBAL typelib_global;
2401 LPVOID typelib_base;
2404 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2406 if (IsEqualIID(riid, &IID_IUnknown))
2409 IUnknown_AddRef(iface);
2413 return E_NOINTERFACE;
2416 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2418 TLB_PEFile *This = (TLB_PEFile *)iface;
2419 return InterlockedIncrement(&This->refs);
2422 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2424 TLB_PEFile *This = (TLB_PEFile *)iface;
2425 ULONG refs = InterlockedDecrement(&This->refs);
2428 if (This->typelib_global)
2429 FreeResource(This->typelib_global);
2431 FreeLibrary(This->dll);
2437 static const IUnknownVtbl TLB_PEFile_Vtable =
2439 TLB_PEFile_QueryInterface,
2444 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2448 This = heap_alloc(sizeof(TLB_PEFile));
2450 return E_OUTOFMEMORY;
2452 This->lpvtbl = &TLB_PEFile_Vtable;
2455 This->typelib_resource = NULL;
2456 This->typelib_global = NULL;
2457 This->typelib_base = NULL;
2459 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2460 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2464 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2465 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2466 if (This->typelib_resource)
2468 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2469 if (This->typelib_global)
2471 This->typelib_base = LockResource(This->typelib_global);
2473 if (This->typelib_base)
2475 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2476 *ppBase = This->typelib_base;
2477 *ppFile = (IUnknown *)&This->lpvtbl;
2484 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2485 return TYPE_E_CANTLOADLIBRARY;
2488 typedef struct TLB_NEFile
2490 const IUnknownVtbl *lpvtbl;
2492 LPVOID typelib_base;
2495 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2497 if (IsEqualIID(riid, &IID_IUnknown))
2500 IUnknown_AddRef(iface);
2504 return E_NOINTERFACE;
2507 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2509 TLB_NEFile *This = (TLB_NEFile *)iface;
2510 return InterlockedIncrement(&This->refs);
2513 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2515 TLB_NEFile *This = (TLB_NEFile *)iface;
2516 ULONG refs = InterlockedDecrement(&This->refs);
2519 heap_free(This->typelib_base);
2525 static const IUnknownVtbl TLB_NEFile_Vtable =
2527 TLB_NEFile_QueryInterface,
2532 /***********************************************************************
2533 * read_xx_header [internal]
2535 static int read_xx_header( HFILE lzfd )
2537 IMAGE_DOS_HEADER mzh;
2540 LZSeek( lzfd, 0, SEEK_SET );
2541 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2543 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2546 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2547 if ( 2 != LZRead( lzfd, magic, 2 ) )
2550 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2552 if ( magic[0] == 'N' && magic[1] == 'E' )
2553 return IMAGE_OS2_SIGNATURE;
2554 if ( magic[0] == 'P' && magic[1] == 'E' )
2555 return IMAGE_NT_SIGNATURE;
2558 WARN("Can't handle %s files.\n", magic );
2563 /***********************************************************************
2564 * find_ne_resource [internal]
2566 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2567 DWORD *resLen, DWORD *resOff )
2569 IMAGE_OS2_HEADER nehd;
2570 NE_TYPEINFO *typeInfo;
2571 NE_NAMEINFO *nameInfo;
2577 /* Read in NE header */
2578 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2579 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2581 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2584 TRACE("No resources in NE dll\n" );
2588 /* Read in resource table */
2589 resTab = heap_alloc( resTabSize );
2590 if ( !resTab ) return FALSE;
2592 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2593 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2595 heap_free( resTab );
2600 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2602 if (!IS_INTRESOURCE(typeid)) /* named type */
2604 BYTE len = strlen( typeid );
2605 while (typeInfo->type_id)
2607 if (!(typeInfo->type_id & 0x8000))
2609 BYTE *p = resTab + typeInfo->type_id;
2610 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2612 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2613 typeInfo->count * sizeof(NE_NAMEINFO));
2616 else /* numeric type id */
2618 WORD id = LOWORD(typeid) | 0x8000;
2619 while (typeInfo->type_id)
2621 if (typeInfo->type_id == id) goto found_type;
2622 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2623 typeInfo->count * sizeof(NE_NAMEINFO));
2626 TRACE("No typeid entry found for %p\n", typeid );
2627 heap_free( resTab );
2631 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2633 if (!IS_INTRESOURCE(resid)) /* named resource */
2635 BYTE len = strlen( resid );
2636 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2638 BYTE *p = resTab + nameInfo->id;
2639 if (nameInfo->id & 0x8000) continue;
2640 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2643 else /* numeric resource id */
2645 WORD id = LOWORD(resid) | 0x8000;
2646 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2647 if (nameInfo->id == id) goto found_name;
2649 TRACE("No resid entry found for %p\n", typeid );
2650 heap_free( resTab );
2654 /* Return resource data */
2655 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2656 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2658 heap_free( resTab );
2662 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2666 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2669 This = heap_alloc(sizeof(TLB_NEFile));
2670 if (!This) return E_OUTOFMEMORY;
2672 This->lpvtbl = &TLB_NEFile_Vtable;
2674 This->typelib_base = NULL;
2676 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2677 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2679 DWORD reslen, offset;
2680 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2682 This->typelib_base = heap_alloc(reslen);
2683 if( !This->typelib_base )
2687 LZSeek( lzfd, offset, SEEK_SET );
2688 reslen = LZRead( lzfd, This->typelib_base, reslen );
2690 *ppBase = This->typelib_base;
2691 *pdwTLBLength = reslen;
2692 *ppFile = (IUnknown *)&This->lpvtbl;
2698 if( lzfd >= 0) LZClose( lzfd );
2699 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2703 typedef struct TLB_Mapping
2705 const IUnknownVtbl *lpvtbl;
2709 LPVOID typelib_base;
2712 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2714 if (IsEqualIID(riid, &IID_IUnknown))
2717 IUnknown_AddRef(iface);
2721 return E_NOINTERFACE;
2724 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2726 TLB_Mapping *This = (TLB_Mapping *)iface;
2727 return InterlockedIncrement(&This->refs);
2730 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2732 TLB_Mapping *This = (TLB_Mapping *)iface;
2733 ULONG refs = InterlockedDecrement(&This->refs);
2736 if (This->typelib_base)
2737 UnmapViewOfFile(This->typelib_base);
2739 CloseHandle(This->mapping);
2740 if (This->file != INVALID_HANDLE_VALUE)
2741 CloseHandle(This->file);
2747 static const IUnknownVtbl TLB_Mapping_Vtable =
2749 TLB_Mapping_QueryInterface,
2754 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2758 This = heap_alloc(sizeof(TLB_Mapping));
2760 return E_OUTOFMEMORY;
2762 This->lpvtbl = &TLB_Mapping_Vtable;
2764 This->file = INVALID_HANDLE_VALUE;
2765 This->mapping = NULL;
2766 This->typelib_base = NULL;
2768 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2769 if (INVALID_HANDLE_VALUE != This->file)
2771 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2774 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2775 if(This->typelib_base)
2777 /* retrieve file size */
2778 *pdwTLBLength = GetFileSize(This->file, NULL);
2779 *ppBase = This->typelib_base;
2780 *ppFile = (IUnknown *)&This->lpvtbl;
2786 IUnknown_Release((IUnknown *)&This->lpvtbl);
2787 return TYPE_E_CANTLOADLIBRARY;
2790 /****************************************************************************
2793 * find the type of the typelib file and map the typelib resource into
2797 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2798 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2800 ITypeLibImpl *entry;
2803 LPWSTR index_str, file = (LPWSTR)pszFileName;
2804 LPVOID pBase = NULL;
2805 DWORD dwTLBLength = 0;
2806 IUnknown *pFile = NULL;
2810 index_str = strrchrW(pszFileName, '\\');
2811 if(index_str && *++index_str != '\0')
2814 LONG idx = strtolW(index_str, &end_ptr, 10);
2815 if(*end_ptr == '\0')
2817 int str_len = index_str - pszFileName - 1;
2819 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2820 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2825 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2827 if(strchrW(file, '\\'))
2829 lstrcpyW(pszPath, file);
2833 int len = GetSystemDirectoryW(pszPath, cchPath);
2834 pszPath[len] = '\\';
2835 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2839 if(file != pszFileName) heap_free(file);
2841 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2843 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2844 EnterCriticalSection(&cache_section);
2845 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2847 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2849 TRACE("cache hit\n");
2850 *ppTypeLib = (ITypeLib2*)entry;
2851 ITypeLib_AddRef(*ppTypeLib);
2852 LeaveCriticalSection(&cache_section);
2856 LeaveCriticalSection(&cache_section);
2858 /* now actually load and parse the typelib */
2860 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2861 if (ret == TYPE_E_CANTLOADLIBRARY)
2862 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2863 if (ret == TYPE_E_CANTLOADLIBRARY)
2864 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2867 if (dwTLBLength >= 4)
2869 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2870 if (dwSignature == MSFT_SIGNATURE)
2871 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2872 else if (dwSignature == SLTG_SIGNATURE)
2873 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2876 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2877 ret = TYPE_E_CANTLOADLIBRARY;
2881 ret = TYPE_E_CANTLOADLIBRARY;
2882 IUnknown_Release(pFile);
2886 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2888 TRACE("adding to cache\n");
2889 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2890 lstrcpyW(impl->path, pszPath);
2891 /* We should really canonicalise the path here. */
2892 impl->index = index;
2894 /* FIXME: check if it has added already in the meantime */
2895 EnterCriticalSection(&cache_section);
2896 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2898 tlb_cache_first = impl;
2899 LeaveCriticalSection(&cache_section);
2902 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2907 /*================== ITypeLib(2) Methods ===================================*/
2909 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2911 ITypeLibImpl* pTypeLibImpl;
2913 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2914 if (!pTypeLibImpl) return NULL;
2916 pTypeLibImpl->lpVtbl = &tlbvt;
2917 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2918 pTypeLibImpl->ref = 1;
2920 list_init(&pTypeLibImpl->ref_list);
2921 pTypeLibImpl->dispatch_href = -1;
2923 return pTypeLibImpl;
2926 /****************************************************************************
2927 * ITypeLib2_Constructor_MSFT
2929 * loading an MSFT typelib from an in-memory image
2931 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2935 MSFT_Header tlbHeader;
2936 MSFT_SegDir tlbSegDir;
2937 ITypeLibImpl * pTypeLibImpl;
2939 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2941 pTypeLibImpl = TypeLibImpl_Constructor();
2942 if (!pTypeLibImpl) return NULL;
2944 /* get pointer to beginning of typelib data */
2948 cx.pLibInfo = pTypeLibImpl;
2949 cx.length = dwTLBLength;
2952 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2953 TRACE_(typelib)("header:\n");
2954 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2955 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2956 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2959 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2961 /* there is a small amount of information here until the next important
2963 * the segment directory . Try to calculate the amount of data */
2964 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2966 /* now read the segment directory */
2967 TRACE("read segment directory (at %d)\n",lPSegDir);
2968 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2969 cx.pTblDir = &tlbSegDir;
2971 /* just check two entries */
2972 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2974 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
2975 heap_free(pTypeLibImpl);
2979 /* now fill our internal data */
2980 /* TLIBATTR fields */
2981 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2983 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2984 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2985 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2986 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2987 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2989 pTypeLibImpl->lcid = tlbHeader.lcid;
2991 /* name, eventually add to a hash table */
2992 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2995 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2996 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2998 if( tlbHeader.varflags & HELPDLLFLAG)
3001 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
3002 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
3005 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
3008 if(tlbHeader.CustomDataOffset >= 0)
3010 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
3013 /* fill in type descriptions */
3014 if(tlbSegDir.pTypdescTab.length > 0)
3016 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
3018 pTypeLibImpl->ctTypeDesc = cTD;
3019 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
3020 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
3023 /* FIXME: add several sanity checks here */
3024 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
3025 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3027 /* FIXME: check safearray */
3029 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3031 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3033 else if(td[0] == VT_CARRAY)
3035 /* array descr table here */
3036 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3038 else if(td[0] == VT_USERDEFINED)
3040 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3042 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3045 /* second time around to fill the array subscript info */
3048 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3049 if(tlbSegDir.pArrayDescriptions.offset>0)
3051 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3052 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3055 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3057 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3059 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3061 for(j = 0; j<td[2]; j++)
3063 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3064 sizeof(INT), &cx, DO_NOT_SEEK);
3065 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3066 sizeof(INT), &cx, DO_NOT_SEEK);
3071 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3072 ERR("didn't find array description data\n");
3077 /* imported type libs */
3078 if(tlbSegDir.pImpFiles.offset>0)
3080 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
3081 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3084 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3088 *ppImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3089 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
3090 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3092 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3093 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3094 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3095 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3098 name = heap_alloc_zero(size+1);
3099 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3100 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3103 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3104 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3106 ppImpLib = &(*ppImpLib)->next;
3110 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3111 if(pTypeLibImpl->dispatch_href != -1)
3112 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3115 if(tlbHeader.nrtypeinfos >= 0 )
3117 ITypeInfoImpl **ppTI;
3120 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3122 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3124 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3127 (pTypeLibImpl->TypeInfoCount)++;
3131 TRACE("(%p)\n", pTypeLibImpl);
3132 return (ITypeLib2*) pTypeLibImpl;
3136 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3142 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3143 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3147 guid->Data4[0] = s >> 8;
3148 guid->Data4[1] = s & 0xff;
3151 for(i = 0; i < 6; i++) {
3152 memcpy(b, str + 24 + 2 * i, 2);
3153 guid->Data4[i + 2] = strtol(b, NULL, 16);
3158 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3164 bytelen = *(const WORD*)ptr;
3165 if(bytelen == 0xffff) return 2;
3166 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3167 *pBstr = SysAllocStringLen(NULL, len);
3169 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3173 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3178 bytelen = *(const WORD*)ptr;
3179 if(bytelen == 0xffff) return 2;
3180 *str = heap_alloc(bytelen + 1);
3181 memcpy(*str, ptr + 2, bytelen);
3182 (*str)[bytelen] = '\0';
3186 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3188 char *ptr = pLibBlk;
3191 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3192 FIXME("libblk magic = %04x\n", w);
3197 if((w = *(WORD*)ptr) != 0xffff) {
3198 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3203 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3205 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3207 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3210 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3213 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3214 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3216 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3219 ptr += 4; /* skip res12 */
3221 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3224 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3227 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3230 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3231 ptr += sizeof(GUID);
3233 return ptr - (char*)pLibBlk;
3236 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3241 } sltg_ref_lookup_t;
3243 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3244 HREFTYPE *typelib_ref)
3246 if(table && typeinfo_ref < table->num)
3248 *typelib_ref = table->refs[typeinfo_ref];
3252 ERR_(typelib)("Unable to find reference\n");
3257 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3262 if((*pType & 0xe00) == 0xe00) {
3264 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3265 pTD = pTD->u.lptdesc;
3267 switch(*pType & 0x3f) {
3270 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3271 pTD = pTD->u.lptdesc;
3274 case VT_USERDEFINED:
3275 pTD->vt = VT_USERDEFINED;
3276 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3282 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3285 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3287 pTD->vt = VT_CARRAY;
3288 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3289 pTD->u.lpadesc->cDims = pSA->cDims;
3290 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3291 pSA->cDims * sizeof(SAFEARRAYBOUND));
3293 pTD = &pTD->u.lpadesc->tdescElem;
3299 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3303 pTD->vt = VT_SAFEARRAY;
3304 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3305 pTD = pTD->u.lptdesc;
3309 pTD->vt = *pType & 0x3f;
3318 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3319 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3321 /* Handle [in/out] first */
3322 if((*pType & 0xc000) == 0xc000)
3323 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3324 else if(*pType & 0x8000)
3325 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3326 else if(*pType & 0x4000)
3327 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3329 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3332 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3335 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3337 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3341 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3346 TLBRefType *ref_type;
3347 sltg_ref_lookup_t *table;
3348 HREFTYPE typelib_ref;
3350 if(pRef->magic != SLTG_REF_MAGIC) {
3351 FIXME("Ref magic = %x\n", pRef->magic);
3354 name = ( (char*)pRef->names + pRef->number);
3356 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3357 table->num = pRef->number >> 3;
3359 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3361 /* We don't want the first href to be 0 */
3362 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3364 for(ref = 0; ref < pRef->number >> 3; ref++) {
3366 unsigned int lib_offs, type_num;
3368 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3370 name += SLTG_ReadStringA(name, &refname);
3371 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3372 FIXME_(typelib)("Can't sscanf ref\n");
3373 if(lib_offs != 0xffff) {
3374 TLBImpLib **import = &pTL->pImpLibs;
3377 if((*import)->offset == lib_offs)
3379 import = &(*import)->next;
3382 char fname[MAX_PATH+1];
3385 *import = heap_alloc_zero(sizeof(**import));
3386 (*import)->offset = lib_offs;
3387 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3389 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3390 &(*import)->wVersionMajor,
3391 &(*import)->wVersionMinor,
3392 &(*import)->lcid, fname) != 4) {
3393 FIXME_(typelib)("can't sscanf ref %s\n",
3394 pNameTable + lib_offs + 40);
3396 len = strlen(fname);
3397 if(fname[len-1] != '#')
3398 FIXME("fname = %s\n", fname);
3399 fname[len-1] = '\0';
3400 (*import)->name = TLB_MultiByteToBSTR(fname);
3402 ref_type->pImpTLInfo = *import;
3404 /* Store a reference to IDispatch */
3405 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3406 pTL->dispatch_href = typelib_ref;
3408 } else { /* internal ref */
3409 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3411 ref_type->reference = typelib_ref;
3412 ref_type->index = type_num;
3415 list_add_tail(&pTL->ref_list, &ref_type->entry);
3417 table->refs[ref] = typelib_ref;
3420 if((BYTE)*name != SLTG_REF_MAGIC)
3421 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3422 dump_TLBRefType(pTL);
3426 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3427 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3429 SLTG_ImplInfo *info;
3430 TLBImplType *pImplType;
3431 /* I don't really get this structure, usually it's 0x16 bytes
3432 long, but iuser.tlb contains some that are 0x18 bytes long.
3433 That's ok because we can use the next ptr to jump to the next
3434 one. But how do we know the length of the last one? The WORD
3435 at offs 0x8 might be the clue. For now I'm just assuming that
3436 the last one is the regular 0x16 bytes. */
3438 info = (SLTG_ImplInfo*)pBlk;
3440 pTI->TypeAttr.cImplTypes++;
3441 if(info->next == 0xffff)
3443 info = (SLTG_ImplInfo*)(pBlk + info->next);
3446 info = (SLTG_ImplInfo*)pBlk;
3447 pTI->impltypes = heap_alloc_zero(pTI->TypeAttr.cImplTypes * sizeof(TLBImplType));
3448 pImplType = pTI->impltypes;
3450 sltg_get_typelib_ref(ref_lookup, info->ref, &pImplType->hRef);
3451 pImplType->implflags = info->impltypeflags;
3454 if(info->next == 0xffff)
3457 FIXME_(typelib)("Interface inheriting more than one interface\n");
3458 info = (SLTG_ImplInfo*)(pBlk + info->next);
3460 info++; /* see comment at top of function */
3464 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3465 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3467 TLBVarDesc *pVarDesc;
3468 BSTR bstrPrevName = NULL;
3469 SLTG_Variable *pItem;
3473 pVarDesc = pTI->vardescs = heap_alloc_zero(sizeof(TLBVarDesc) * cVars);
3475 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3476 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++, ++pVarDesc) {
3478 pVarDesc->vardesc.memid = pItem->memid;
3480 if (pItem->magic != SLTG_VAR_MAGIC &&
3481 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3482 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3486 if (pItem->name == 0xfffe)
3487 pVarDesc->Name = SysAllocString(bstrPrevName);
3489 pVarDesc->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3491 TRACE_(typelib)("name: %s\n", debugstr_w(pVarDesc->Name));
3492 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3493 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3495 if(pItem->flags & 0x02)
3496 pType = &pItem->type;
3498 pType = (WORD*)(pBlk + pItem->type);
3500 if (pItem->flags & ~0xda)
3501 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3503 SLTG_DoElem(pType, pBlk,
3504 &pVarDesc->vardesc.elemdescVar, ref_lookup);
3506 if (TRACE_ON(typelib)) {
3508 dump_TypeDesc(&pVarDesc->vardesc.elemdescVar.tdesc, buf);
3509 TRACE_(typelib)("elemdescVar: %s\n", buf);
3512 if (pItem->flags & 0x40) {
3513 TRACE_(typelib)("VAR_DISPATCH\n");
3514 pVarDesc->vardesc.varkind = VAR_DISPATCH;
3516 else if (pItem->flags & 0x10) {
3517 TRACE_(typelib)("VAR_CONST\n");
3518 pVarDesc->vardesc.varkind = VAR_CONST;
3519 pVarDesc->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3520 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_INT;
3521 if (pItem->flags & 0x08)
3522 V_INT(pVarDesc->vardesc.u.lpvarValue) = pItem->byte_offs;
3524 switch (pVarDesc->vardesc.elemdescVar.tdesc.vt)
3530 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3532 TRACE_(typelib)("len = %u\n", len);
3533 if (len == 0xffff) {
3536 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3537 str = SysAllocStringLen(NULL, alloc_len);
3538 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3540 V_VT(pVarDesc->vardesc.u.lpvarValue) = VT_BSTR;
3541 V_BSTR(pVarDesc->vardesc.u.lpvarValue) = str;
3550 V_INT(pVarDesc->vardesc.u.lpvarValue) =
3551 *(INT*)(pBlk + pItem->byte_offs);
3554 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", pVarDesc->vardesc.elemdescVar.tdesc.vt);
3559 TRACE_(typelib)("VAR_PERINSTANCE\n");
3560 pVarDesc->vardesc.u.oInst = pItem->byte_offs;
3561 pVarDesc->vardesc.varkind = VAR_PERINSTANCE;
3564 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3565 pVarDesc->vardesc.wVarFlags = pItem->varflags;
3567 if (pItem->flags & 0x80)
3568 pVarDesc->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3570 bstrPrevName = pVarDesc->Name;
3572 pTI->TypeAttr.cVars = cVars;
3575 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3576 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3578 SLTG_Function *pFunc;
3580 TLBFuncDesc *pFuncDesc;
3582 pTI->funcdescs = heap_alloc_zero(cFuncs * sizeof(TLBFuncDesc));
3584 pFuncDesc = pTI->funcdescs;
3585 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3586 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3591 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3592 case SLTG_FUNCTION_MAGIC:
3593 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3595 case SLTG_DISPATCH_FUNCTION_MAGIC:
3596 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3598 case SLTG_STATIC_FUNCTION_MAGIC:
3599 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3602 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3605 pFuncDesc->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3607 pFuncDesc->funcdesc.memid = pFunc->dispid;
3608 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3609 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3610 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3611 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3612 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3614 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3615 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3617 if(pFunc->retnextopt & 0x80)
3618 pType = &pFunc->rettype;
3620 pType = (WORD*)(pBlk + pFunc->rettype);
3622 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3624 pFuncDesc->funcdesc.lprgelemdescParam =
3625 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3626 pFuncDesc->pParamDesc =
3627 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(TLBParDesc));
3629 pArg = (WORD*)(pBlk + pFunc->arg_off);
3631 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3632 char *paramName = pNameTable + *pArg;
3634 /* If arg type follows then paramName points to the 2nd
3635 letter of the name, else the next WORD is an offset to
3636 the arg type and paramName points to the first letter.
3637 So let's take one char off paramName and see if we're
3638 pointing at an alpha-numeric char. However if *pArg is
3639 0xffff or 0xfffe then the param has no name, the former
3640 meaning that the next WORD is the type, the latter
3641 meaning that the next WORD is an offset to the type. */
3646 else if(*pArg == 0xfffe) {
3650 else if(paramName[-1] && !isalnum(paramName[-1]))
3655 if(HaveOffs) { /* the next word is an offset to type */
3656 pType = (WORD*)(pBlk + *pArg);
3657 SLTG_DoElem(pType, pBlk,
3658 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3663 pArg = SLTG_DoElem(pArg, pBlk,
3664 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3667 /* Are we an optional param ? */
3668 if(pFuncDesc->funcdesc.cParams - param <=
3669 pFuncDesc->funcdesc.cParamsOpt)
3670 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3673 pFuncDesc->pParamDesc[param].Name =
3674 TLB_MultiByteToBSTR(paramName);
3676 pFuncDesc->pParamDesc[param].Name =
3677 SysAllocString(pFuncDesc->Name);
3681 pTI->TypeAttr.cFuncs = cFuncs;
3684 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3685 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3686 SLTG_TypeInfoTail *pTITail)
3689 sltg_ref_lookup_t *ref_lookup = NULL;
3691 if(pTIHeader->href_table != 0xffffffff) {
3692 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3698 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3699 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3701 heap_free(ref_lookup);
3705 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3706 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3707 const SLTG_TypeInfoTail *pTITail)
3710 sltg_ref_lookup_t *ref_lookup = NULL;
3712 if(pTIHeader->href_table != 0xffffffff) {
3713 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3719 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3720 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3723 if (pTITail->funcs_off != 0xffff)
3724 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3726 heap_free(ref_lookup);
3728 if (TRACE_ON(typelib))
3729 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3732 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3733 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3734 const SLTG_TypeInfoTail *pTITail)
3736 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3739 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3740 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3741 const SLTG_TypeInfoTail *pTITail)
3744 sltg_ref_lookup_t *ref_lookup = NULL;
3746 if (pTITail->simple_alias) {
3747 /* if simple alias, no more processing required */
3748 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3752 if(pTIHeader->href_table != 0xffffffff) {
3753 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3757 /* otherwise it is an offset to a type */
3758 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3760 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3762 heap_free(ref_lookup);
3765 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3766 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3767 const SLTG_TypeInfoTail *pTITail)
3769 sltg_ref_lookup_t *ref_lookup = NULL;
3770 if (pTIHeader->href_table != 0xffffffff)
3771 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3774 if (pTITail->vars_off != 0xffff)
3775 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3777 if (pTITail->funcs_off != 0xffff)
3778 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3780 if (pTITail->impls_off != 0xffff)
3781 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3783 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3784 * of dispinterface functions including the IDispatch ones, so
3785 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3786 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3788 heap_free(ref_lookup);
3789 if (TRACE_ON(typelib))
3790 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3793 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3794 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3795 const SLTG_TypeInfoTail *pTITail)
3797 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3800 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3801 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3802 const SLTG_TypeInfoTail *pTITail)
3804 sltg_ref_lookup_t *ref_lookup = NULL;
3805 if (pTIHeader->href_table != 0xffffffff)
3806 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3809 if (pTITail->vars_off != 0xffff)
3810 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3812 if (pTITail->funcs_off != 0xffff)
3813 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3814 heap_free(ref_lookup);
3815 if (TRACE_ON(typelib))
3819 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3820 managable copy of it into this */
3833 } SLTG_InternalOtherTypeInfo;
3835 /****************************************************************************
3836 * ITypeLib2_Constructor_SLTG
3838 * loading a SLTG typelib from an in-memory image
3840 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3842 ITypeLibImpl *pTypeLibImpl;
3843 SLTG_Header *pHeader;
3844 SLTG_BlkEntry *pBlkEntry;
3848 LPVOID pBlk, pFirstBlk;
3849 SLTG_LibBlk *pLibBlk;
3850 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3851 char *pAfterOTIBlks = NULL;
3852 char *pNameTable, *ptr;
3855 ITypeInfoImpl **ppTypeInfoImpl;
3857 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3860 pTypeLibImpl = TypeLibImpl_Constructor();
3861 if (!pTypeLibImpl) return NULL;
3865 TRACE_(typelib)("header:\n");
3866 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3867 pHeader->nrOfFileBlks );
3868 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3869 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3870 pHeader->SLTG_magic);
3874 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3875 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3877 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3878 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3880 /* Next we have a magic block */
3881 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3883 /* Let's see if we're still in sync */
3884 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3885 sizeof(SLTG_COMPOBJ_MAGIC))) {
3886 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3889 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3890 sizeof(SLTG_DIR_MAGIC))) {
3891 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3895 pIndex = (SLTG_Index*)(pMagic+1);
3897 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3899 pFirstBlk = pPad9 + 1;
3901 /* We'll set up a ptr to the main library block, which is the last one. */
3903 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3904 pBlkEntry[order].next != 0;
3905 order = pBlkEntry[order].next - 1, i++) {
3906 pBlk = (char*)pBlk + pBlkEntry[order].len;
3910 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3912 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3917 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3919 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3922 ptr = (char*)pLibBlk + len;
3924 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3928 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3930 w = *(WORD*)(ptr + 2);
3933 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
3934 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3935 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3937 w = *(WORD*)(ptr + 4 + len);
3939 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3941 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
3942 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3943 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3945 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3946 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3947 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3949 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
3950 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3953 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3954 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3955 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3956 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3957 len += sizeof(SLTG_OtherTypeInfo);
3961 pAfterOTIBlks = ptr;
3963 /* Skip this WORD and get the next DWORD */
3964 len = *(DWORD*)(pAfterOTIBlks + 2);
3966 /* Now add this to pLibBLk look at what we're pointing at and
3967 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3968 dust and we should be pointing at the beginning of the name
3971 pNameTable = (char*)pLibBlk + len;
3973 switch(*(WORD*)pNameTable) {
3980 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3984 pNameTable += 0x216;
3988 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3990 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3993 /* Hopefully we now have enough ptrs set up to actually read in
3994 some TypeInfos. It's not clear which order to do them in, so
3995 I'll just follow the links along the BlkEntry chain and read
3996 them in the order in which they are in the file */
3998 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
3999 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
4001 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
4002 pBlkEntry[order].next != 0;
4003 order = pBlkEntry[order].next - 1, i++) {
4005 SLTG_TypeInfoHeader *pTIHeader;
4006 SLTG_TypeInfoTail *pTITail;
4007 SLTG_MemberHeader *pMemHeader;
4009 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
4010 pOtherTypeInfoBlks[i].index_name)) {
4011 FIXME_(typelib)("Index strings don't match\n");
4016 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
4017 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
4020 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4021 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4022 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
4024 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
4025 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
4026 (*ppTypeInfoImpl)->index = i;
4027 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
4028 pOtherTypeInfoBlks[i].name_offs +
4030 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
4031 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
4032 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
4033 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4034 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4035 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4036 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4038 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4039 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4041 if((pTIHeader->typeflags1 & 7) != 2)
4042 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4043 if(pTIHeader->typeflags3 != 2)
4044 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4046 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4047 debugstr_w((*ppTypeInfoImpl)->Name),
4048 typekind_desc[pTIHeader->typekind],
4049 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4050 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4052 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4054 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4056 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4057 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4058 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4060 switch(pTIHeader->typekind) {
4062 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4063 pTIHeader, pTITail);
4067 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4068 pTIHeader, pTITail);
4071 case TKIND_INTERFACE:
4072 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4073 pTIHeader, pTITail);
4077 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4078 pTIHeader, pTITail);
4082 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4083 pTIHeader, pTITail);
4086 case TKIND_DISPATCH:
4087 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4088 pTIHeader, pTITail);
4092 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4093 pTIHeader, pTITail);
4097 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4102 /* could get cFuncs, cVars and cImplTypes from here
4103 but we've already set those */
4104 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4120 pBlk = (char*)pBlk + pBlkEntry[order].len;
4123 if(i != pTypeLibImpl->TypeInfoCount) {
4124 FIXME("Somehow processed %d TypeInfos\n", i);
4128 heap_free(pOtherTypeInfoBlks);
4129 return (ITypeLib2*)pTypeLibImpl;
4132 /* ITypeLib::QueryInterface
4134 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4139 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4141 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4144 if(IsEqualIID(riid, &IID_IUnknown) ||
4145 IsEqualIID(riid,&IID_ITypeLib)||
4146 IsEqualIID(riid,&IID_ITypeLib2))
4153 ITypeLib2_AddRef(iface);
4154 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4157 TRACE("-- Interface: E_NOINTERFACE\n");
4158 return E_NOINTERFACE;
4163 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4165 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4166 ULONG ref = InterlockedIncrement(&This->ref);
4168 TRACE("(%p)->ref was %u\n",This, ref - 1);
4173 /* ITypeLib::Release
4175 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4177 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4178 ULONG ref = InterlockedDecrement(&This->ref);
4180 TRACE("(%p)->(%u)\n",This, ref);
4184 TLBImpLib *pImpLib, *pImpLibNext;
4185 TLBCustData *pCustData, *pCustDataNext;
4186 TLBRefType *ref_type;
4190 /* remove cache entry */
4193 TRACE("removing from cache list\n");
4194 EnterCriticalSection(&cache_section);
4195 if (This->next) This->next->prev = This->prev;
4196 if (This->prev) This->prev->next = This->next;
4197 else tlb_cache_first = This->next;
4198 LeaveCriticalSection(&cache_section);
4199 heap_free(This->path);
4201 TRACE(" destroying ITypeLib(%p)\n",This);
4203 SysFreeString(This->Name);
4206 SysFreeString(This->DocString);
4207 This->DocString = NULL;
4209 SysFreeString(This->HelpFile);
4210 This->HelpFile = NULL;
4212 SysFreeString(This->HelpStringDll);
4213 This->HelpStringDll = NULL;
4215 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4217 VariantClear(&pCustData->data);
4219 pCustDataNext = pCustData->next;
4220 heap_free(pCustData);
4223 for (i = 0; i < This->ctTypeDesc; i++)
4224 if (This->pTypeDesc[i].vt == VT_CARRAY)
4225 heap_free(This->pTypeDesc[i].u.lpadesc);
4227 heap_free(This->pTypeDesc);
4229 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4231 if (pImpLib->pImpTypeLib)
4232 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4233 SysFreeString(pImpLib->name);
4235 pImpLibNext = pImpLib->next;
4239 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4241 list_remove(&ref_type->entry);
4242 heap_free(ref_type);
4245 for (i = 0; i < This->TypeInfoCount; ++i)
4246 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4247 heap_free(This->typeinfos);
4255 /* ITypeLib::GetTypeInfoCount
4257 * Returns the number of type descriptions in the type library
4259 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4261 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4262 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4263 return This->TypeInfoCount;
4266 /* ITypeLib::GetTypeInfo
4268 * retrieves the specified type description in the library.
4270 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4273 ITypeInfo **ppTInfo)
4275 ITypeLibImpl *This = (ITypeLibImpl*)iface;
4277 TRACE("%p %u %p\n", This, index, ppTInfo);
4280 return E_INVALIDARG;
4282 if(index >= This->TypeInfoCount)
4283 return TYPE_E_ELEMENTNOTFOUND;
4285 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4286 ITypeInfo_AddRef(*ppTInfo);
4292 /* ITypeLibs::GetTypeInfoType
4294 * Retrieves the type of a type description.
4296 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4301 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4303 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4306 return E_INVALIDARG;
4308 if(index >= This->TypeInfoCount)
4309 return TYPE_E_ELEMENTNOTFOUND;
4311 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4316 /* ITypeLib::GetTypeInfoOfGuid
4318 * Retrieves the type description that corresponds to the specified GUID.
4321 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4324 ITypeInfo **ppTInfo)
4326 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4329 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4331 for(i = 0; i < This->TypeInfoCount; ++i){
4332 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4333 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4334 ITypeInfo_AddRef(*ppTInfo);
4339 return TYPE_E_ELEMENTNOTFOUND;
4342 /* ITypeLib::GetLibAttr
4344 * Retrieves the structure that contains the library's attributes.
4347 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4351 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4353 TRACE("(%p, %p)\n", This, attr);
4355 if (!attr) return E_INVALIDARG;
4357 *attr = heap_alloc(sizeof(**attr));
4358 if (!*attr) return E_OUTOFMEMORY;
4360 **attr = This->LibAttr;
4364 /* ITypeLib::GetTypeComp
4366 * Enables a client compiler to bind to a library's types, variables,
4367 * constants, and global functions.
4370 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4372 ITypeComp **ppTComp)
4374 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4376 TRACE("(%p)->(%p)\n",This,ppTComp);
4377 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4378 ITypeComp_AddRef(*ppTComp);
4383 /* ITypeLib::GetDocumentation
4385 * Retrieves the library's documentation string, the complete Help file name
4386 * and path, and the context identifier for the library Help topic in the Help
4389 * On a successful return all non-null BSTR pointers will have been set,
4392 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4396 BSTR *pBstrDocString,
4397 DWORD *pdwHelpContext,
4398 BSTR *pBstrHelpFile)
4400 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4402 HRESULT result = E_INVALIDARG;
4407 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4409 pBstrName, pBstrDocString,
4410 pdwHelpContext, pBstrHelpFile);
4414 /* documentation for the typelib */
4419 if(!(*pBstrName = SysAllocString(This->Name)))
4427 if (This->DocString)
4429 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4432 else if (This->Name)
4434 if(!(*pBstrDocString = SysAllocString(This->Name)))
4438 *pBstrDocString = NULL;
4442 *pdwHelpContext = This->dwHelpContext;
4448 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4452 *pBstrHelpFile = NULL;
4459 /* for a typeinfo */
4460 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4462 if(SUCCEEDED(result))
4464 result = ITypeInfo_GetDocumentation(pTInfo,
4468 pdwHelpContext, pBstrHelpFile);
4470 ITypeInfo_Release(pTInfo);
4475 if (pBstrDocString) SysFreeString (*pBstrDocString);
4477 if (pBstrName) SysFreeString (*pBstrName);
4479 return STG_E_INSUFFICIENTMEMORY;
4484 * Indicates whether a passed-in string contains the name of a type or member
4485 * described in the library.
4488 static HRESULT WINAPI ITypeLib2_fnIsName(
4494 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4495 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), tic, fdc, vrc, pc;
4497 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4501 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4502 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4503 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4504 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4505 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4506 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4507 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++)
4508 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name, nNameBufLen))
4509 goto ITypeLib2_fnIsName_exit;
4511 for(vrc = 0; vrc < pTInfo->TypeAttr.cVars; ++vrc){
4512 TLBVarDesc *pVInfo = &pTInfo->vardescs[vrc];
4513 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4519 ITypeLib2_fnIsName_exit:
4520 TRACE("(%p)slow! search for %s: %s found!\n", This,
4521 debugstr_w(szNameBuf), *pfName?"NOT":"");
4526 /* ITypeLib::FindName
4528 * Finds occurrences of a type description in a type library. This may be used
4529 * to quickly verify that a name exists in a type library.
4532 static HRESULT WINAPI ITypeLib2_fnFindName(
4536 ITypeInfo **ppTInfo,
4540 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4542 UINT tic, fdc, pc, count = 0;
4543 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4545 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4546 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4547 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4548 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4549 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4550 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4551 for(pc = 0;pc < pFInfo->funcdesc.cParams; pc++) {
4552 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name,nNameBufLen))
4553 goto ITypeLib2_fnFindName_exit;
4557 pVInfo = TLB_get_vardesc_by_name(pTInfo->vardescs, pTInfo->TypeAttr.cVars, szNameBuf);
4559 goto ITypeLib2_fnFindName_exit;
4562 ITypeLib2_fnFindName_exit:
4563 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4564 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4567 TRACE("(%p)slow! search for %d with %s: found %d TypeInfos!\n",
4568 This, *pcFound, debugstr_w(szNameBuf), count);
4575 /* ITypeLib::ReleaseTLibAttr
4577 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4580 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4582 TLIBATTR *pTLibAttr)
4584 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4585 TRACE("freeing (%p)\n",This);
4586 heap_free(pTLibAttr);
4590 /* ITypeLib2::GetCustData
4592 * gets the custom data
4594 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4599 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4600 TLBCustData *pCData;
4602 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4604 if( IsEqualIID(guid, &pCData->guid)) break;
4607 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4611 VariantInit( pVarVal);
4612 VariantCopy( pVarVal, &pCData->data);
4615 return E_INVALIDARG; /* FIXME: correct? */
4618 /* ITypeLib2::GetLibStatistics
4620 * Returns statistics about a type library that are required for efficient
4621 * sizing of hash tables.
4624 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4626 ULONG *pcUniqueNames,
4627 ULONG *pcchUniqueNames)
4629 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4631 FIXME("(%p): stub!\n", This);
4633 if(pcUniqueNames) *pcUniqueNames=1;
4634 if(pcchUniqueNames) *pcchUniqueNames=1;
4638 /* ITypeLib2::GetDocumentation2
4640 * Retrieves the library's documentation string, the complete Help file name
4641 * and path, the localization context to use, and the context ID for the
4642 * library Help topic in the Help file.
4645 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4649 BSTR *pbstrHelpString,
4650 DWORD *pdwHelpStringContext,
4651 BSTR *pbstrHelpStringDll)
4653 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4657 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4659 /* the help string should be obtained from the helpstringdll,
4660 * using the _DLLGetDocumentation function, based on the supplied
4661 * lcid. Nice to do sometime...
4665 /* documentation for the typelib */
4667 *pbstrHelpString=SysAllocString(This->DocString);
4668 if(pdwHelpStringContext)
4669 *pdwHelpStringContext=This->dwHelpContext;
4670 if(pbstrHelpStringDll)
4671 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4677 /* for a typeinfo */
4678 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4680 if(SUCCEEDED(result))
4682 ITypeInfo2 * pTInfo2;
4683 result = ITypeInfo_QueryInterface(pTInfo,
4685 (LPVOID*) &pTInfo2);
4687 if(SUCCEEDED(result))
4689 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4693 pdwHelpStringContext,
4694 pbstrHelpStringDll);
4696 ITypeInfo2_Release(pTInfo2);
4699 ITypeInfo_Release(pTInfo);
4705 /* ITypeLib2::GetAllCustData
4707 * Gets all custom data items for the library.
4710 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4712 CUSTDATA *pCustData)
4714 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4715 TLBCustData *pCData;
4717 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4718 pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
4719 if(pCustData->prgCustData ){
4720 pCustData->cCustData=This->ctCustData;
4721 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4722 pCustData->prgCustData[i].guid=pCData->guid;
4723 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4726 ERR(" OUT OF MEMORY!\n");
4727 return E_OUTOFMEMORY;
4732 static const ITypeLib2Vtbl tlbvt = {
4733 ITypeLib2_fnQueryInterface,
4735 ITypeLib2_fnRelease,
4736 ITypeLib2_fnGetTypeInfoCount,
4737 ITypeLib2_fnGetTypeInfo,
4738 ITypeLib2_fnGetTypeInfoType,
4739 ITypeLib2_fnGetTypeInfoOfGuid,
4740 ITypeLib2_fnGetLibAttr,
4741 ITypeLib2_fnGetTypeComp,
4742 ITypeLib2_fnGetDocumentation,
4744 ITypeLib2_fnFindName,
4745 ITypeLib2_fnReleaseTLibAttr,
4747 ITypeLib2_fnGetCustData,
4748 ITypeLib2_fnGetLibStatistics,
4749 ITypeLib2_fnGetDocumentation2,
4750 ITypeLib2_fnGetAllCustData
4754 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4756 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4758 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4761 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4763 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4765 return ITypeLib2_AddRef((ITypeLib2 *)This);
4768 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4770 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4772 return ITypeLib2_Release((ITypeLib2 *)This);
4775 static HRESULT WINAPI ITypeLibComp_fnBind(
4780 ITypeInfo ** ppTInfo,
4781 DESCKIND * pDescKind,
4784 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4785 int typemismatch=0, i;
4787 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4789 *pDescKind = DESCKIND_NONE;
4790 pBindPtr->lptcomp = NULL;
4793 for(i = 0; i < This->TypeInfoCount; ++i){
4794 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4795 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4797 /* FIXME: check wFlags here? */
4798 /* FIXME: we should use a hash table to look this info up using lHash
4799 * instead of an O(n) search */
4800 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4801 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4803 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4805 *pDescKind = DESCKIND_TYPECOMP;
4806 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4807 ITypeComp_AddRef(pBindPtr->lptcomp);
4808 TRACE("module or enum: %s\n", debugstr_w(szName));
4813 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4814 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4816 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4819 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4820 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4822 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4825 else if (hr == TYPE_E_TYPEMISMATCH)
4829 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4830 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4832 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4834 ITypeInfo *subtypeinfo;
4836 DESCKIND subdesckind;
4838 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4839 &subtypeinfo, &subdesckind, &subbindptr);
4840 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4842 TYPEDESC tdesc_appobject;
4843 const VARDESC vardesc_appobject =
4846 NULL, /* lpstrSchema */
4861 VAR_STATIC /* varkind */
4864 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4865 tdesc_appobject.vt = VT_USERDEFINED;
4867 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4869 /* cleanup things filled in by Bind call so we can put our
4870 * application object data in there instead */
4871 switch (subdesckind)
4873 case DESCKIND_FUNCDESC:
4874 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4876 case DESCKIND_VARDESC:
4877 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4882 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4884 if (pTypeInfo->hreftype == -1)
4885 FIXME("no hreftype for interface %p\n", pTypeInfo);
4887 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4891 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4892 *ppTInfo = (ITypeInfo *)pTypeInfo;
4893 ITypeInfo_AddRef(*ppTInfo);
4896 else if (hr == TYPE_E_TYPEMISMATCH)
4903 TRACE("type mismatch %s\n", debugstr_w(szName));
4904 return TYPE_E_TYPEMISMATCH;
4908 TRACE("name not found %s\n", debugstr_w(szName));
4913 static HRESULT WINAPI ITypeLibComp_fnBindType(
4917 ITypeInfo ** ppTInfo,
4918 ITypeComp ** ppTComp)
4920 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4923 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4925 if(!szName || !ppTInfo || !ppTComp)
4926 return E_INVALIDARG;
4928 for(i = 0; i < This->TypeInfoCount; ++i)
4930 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4931 /* FIXME: should use lHash to do the search */
4932 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
4934 TRACE("returning %p\n", pTypeInfo);
4935 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4936 ITypeInfo_AddRef(*ppTInfo);
4937 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4938 ITypeComp_AddRef(*ppTComp);
4943 TRACE("not found\n");
4949 static const ITypeCompVtbl tlbtcvt =
4952 ITypeLibComp_fnQueryInterface,
4953 ITypeLibComp_fnAddRef,
4954 ITypeLibComp_fnRelease,
4956 ITypeLibComp_fnBind,
4957 ITypeLibComp_fnBindType
4960 /*================== ITypeInfo(2) Methods ===================================*/
4961 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
4963 ITypeInfoImpl *pTypeInfoImpl;
4965 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
4968 pTypeInfoImpl->lpVtbl = &tinfvt;
4969 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4970 pTypeInfoImpl->ref = 0;
4971 pTypeInfoImpl->hreftype = -1;
4972 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4973 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4975 TRACE("(%p)\n", pTypeInfoImpl);
4976 return pTypeInfoImpl;
4979 /* ITypeInfo::QueryInterface
4981 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4986 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4988 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4991 if(IsEqualIID(riid, &IID_IUnknown) ||
4992 IsEqualIID(riid,&IID_ITypeInfo)||
4993 IsEqualIID(riid,&IID_ITypeInfo2))
4997 ITypeInfo_AddRef(iface);
4998 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
5001 TRACE("-- Interface: E_NOINTERFACE\n");
5002 return E_NOINTERFACE;
5005 /* ITypeInfo::AddRef
5007 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5009 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5010 ULONG ref = InterlockedIncrement(&This->ref);
5012 TRACE("(%p)->ref is %u\n",This, ref);
5014 if (ref == 1 /* incremented from 0 */)
5015 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
5020 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5024 TRACE("destroying ITypeInfo(%p)\n",This);
5026 SysFreeString(This->Name);
5029 SysFreeString(This->DocString);
5030 This->DocString = NULL;
5032 SysFreeString(This->DllName);
5033 This->DllName = NULL;
5035 for (i = 0; i < This->TypeAttr.cFuncs; ++i)
5037 TLBFuncDesc *pFInfo = &This->funcdescs[i];
5038 for(j = 0; j < pFInfo->funcdesc.cParams; j++)
5040 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[j];
5041 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5043 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5044 heap_free(elemdesc->u.paramdesc.pparamdescex);
5046 TLB_FreeCustData(pFInfo->pParamDesc[j].pCustData);
5047 SysFreeString(pFInfo->pParamDesc[j].Name);
5049 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5050 heap_free(pFInfo->pParamDesc);
5051 TLB_FreeCustData(pFInfo->pCustData);
5052 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5053 SysFreeString(pFInfo->Entry);
5054 SysFreeString(pFInfo->HelpString);
5055 SysFreeString(pFInfo->Name);
5057 heap_free(This->funcdescs);
5059 for(i = 0; i < This->TypeAttr.cVars; ++i)
5061 TLBVarDesc *pVInfo = &This->vardescs[i];
5062 if (pVInfo->vardesc.varkind == VAR_CONST)
5064 VariantClear(pVInfo->vardesc.u.lpvarValue);
5065 heap_free(pVInfo->vardesc.u.lpvarValue);
5067 TLB_FreeCustData(pVInfo->pCustData);
5068 SysFreeString(pVInfo->Name);
5069 SysFreeString(pVInfo->HelpString);
5071 heap_free(This->vardescs);
5073 if(This->impltypes){
5074 for (i = 0; i < This->TypeAttr.cImplTypes; ++i){
5075 TLBImplType *pImpl = &This->impltypes[i];
5076 TLB_FreeCustData(pImpl->pCustData);
5078 heap_free(This->impltypes);
5081 TLB_FreeCustData(This->pCustData);
5086 /* ITypeInfo::Release
5088 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5090 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5091 ULONG ref = InterlockedDecrement(&This->ref);
5093 TRACE("(%p)->(%u)\n",This, ref);
5097 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5098 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5099 if (not_attached_to_typelib)
5101 /* otherwise This will be freed when typelib is freed */
5107 /* ITypeInfo::GetTypeAttr
5109 * Retrieves a TYPEATTR structure that contains the attributes of the type
5113 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5114 LPTYPEATTR *ppTypeAttr)
5116 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5119 TRACE("(%p)\n",This);
5121 size = sizeof(**ppTypeAttr);
5122 if (This->TypeAttr.typekind == TKIND_ALIAS)
5123 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5125 *ppTypeAttr = heap_alloc(size);
5127 return E_OUTOFMEMORY;
5129 **ppTypeAttr = This->TypeAttr;
5131 if (This->TypeAttr.typekind == TKIND_ALIAS)
5132 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5133 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5135 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5136 /* This should include all the inherited funcs */
5137 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5138 /* This is always the size of IDispatch's vtbl */
5139 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5140 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5145 /* ITypeInfo::GetTypeComp
5147 * Retrieves the ITypeComp interface for the type description, which enables a
5148 * client compiler to bind to the type description's members.
5151 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5152 ITypeComp * *ppTComp)
5154 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5156 TRACE("(%p)->(%p)\n", This, ppTComp);
5158 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5159 ITypeComp_AddRef(*ppTComp);
5163 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5165 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5166 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5167 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5171 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5174 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5175 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5177 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5178 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5179 *buffer += sizeof(PARAMDESCEX);
5180 *pparamdescex_dest = *pparamdescex_src;
5181 VariantInit(&pparamdescex_dest->varDefaultValue);
5182 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5183 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5186 dest->u.paramdesc.pparamdescex = NULL;
5190 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5192 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5193 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5196 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5200 SIZE_T size = sizeof(*src);
5204 size += sizeof(*src->lprgscode) * src->cScodes;
5205 size += TLB_SizeElemDesc(&src->elemdescFunc);
5206 for (i = 0; i < src->cParams; i++)
5208 size += sizeof(ELEMDESC);
5209 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5212 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5213 if (!dest) return E_OUTOFMEMORY;
5216 if (dispinterface) /* overwrite funckind */
5217 dest->funckind = FUNC_DISPATCH;
5218 buffer = (char *)(dest + 1);
5220 dest->lprgscode = (SCODE *)buffer;
5221 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5222 buffer += sizeof(*src->lprgscode) * src->cScodes;
5224 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5227 SysFreeString((BSTR)dest);
5231 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5232 buffer += sizeof(ELEMDESC) * src->cParams;
5233 for (i = 0; i < src->cParams; i++)
5235 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5241 /* undo the above actions */
5242 for (i = i - 1; i >= 0; i--)
5243 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5244 TLB_FreeElemDesc(&dest->elemdescFunc);
5245 SysFreeString((BSTR)dest);
5249 /* special treatment for dispinterfaces: this makes functions appear
5250 * to return their [retval] value when it is really returning an
5252 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5254 if (dest->cParams &&
5255 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5257 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5258 if (elemdesc->tdesc.vt != VT_PTR)
5260 ERR("elemdesc should have started with VT_PTR instead of:\n");
5262 dump_ELEMDESC(elemdesc);
5263 return E_UNEXPECTED;
5266 /* copy last parameter to the return value. we are using a flat
5267 * buffer so there is no danger of leaking memory in
5269 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5271 /* remove the last parameter */
5275 /* otherwise this function is made to appear to have no return
5277 dest->elemdescFunc.tdesc.vt = VT_VOID;
5285 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5287 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5289 if (index >= This->TypeAttr.cFuncs)
5290 return TYPE_E_ELEMENTNOTFOUND;
5292 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5296 /* internal function to make the inherited interfaces' methods appear
5297 * part of the interface */
5298 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5299 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5301 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5303 UINT implemented_funcs = 0;
5308 *hrefoffset = DISPATCH_HREF_OFFSET;
5312 ITypeInfo *pSubTypeInfo;
5315 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
5319 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5322 &sub_funcs, hrefoffset);
5323 implemented_funcs += sub_funcs;
5324 ITypeInfo_Release(pSubTypeInfo);
5327 *hrefoffset += DISPATCH_HREF_OFFSET;
5331 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5335 if (index < implemented_funcs)
5336 return E_INVALIDARG;
5337 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5341 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5343 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5346 switch (pTypeDesc->vt)
5348 case VT_USERDEFINED:
5349 pTypeDesc->u.hreftype += hrefoffset;
5353 pTypeDesc = pTypeDesc->u.lptdesc;
5356 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5364 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5367 for (i = 0; i < pFuncDesc->cParams; i++)
5368 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5369 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5372 /* ITypeInfo::GetFuncDesc
5374 * Retrieves the FUNCDESC structure that contains information about a
5375 * specified function.
5378 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5379 LPFUNCDESC *ppFuncDesc)
5381 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5382 const FUNCDESC *internal_funcdesc;
5384 UINT hrefoffset = 0;
5386 TRACE("(%p) index %d\n", This, index);
5388 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5389 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5390 &internal_funcdesc, NULL,
5393 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5394 &internal_funcdesc);
5397 WARN("description for function %d not found\n", index);
5401 hr = TLB_AllocAndInitFuncDesc(
5404 This->TypeAttr.typekind == TKIND_DISPATCH);
5406 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5407 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5409 TRACE("-- 0x%08x\n", hr);
5413 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5417 SIZE_T size = sizeof(*src);
5420 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5421 if (src->varkind == VAR_CONST)
5422 size += sizeof(VARIANT);
5423 size += TLB_SizeElemDesc(&src->elemdescVar);
5425 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5426 if (!dest) return E_OUTOFMEMORY;
5429 buffer = (char *)(dest + 1);
5430 if (src->lpstrSchema)
5433 dest->lpstrSchema = (LPOLESTR)buffer;
5434 len = strlenW(src->lpstrSchema);
5435 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5436 buffer += (len + 1) * sizeof(WCHAR);
5439 if (src->varkind == VAR_CONST)
5443 dest->u.lpvarValue = (VARIANT *)buffer;
5444 *dest->u.lpvarValue = *src->u.lpvarValue;
5445 buffer += sizeof(VARIANT);
5446 VariantInit(dest->u.lpvarValue);
5447 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5450 SysFreeString((BSTR)dest);
5454 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5457 if (src->varkind == VAR_CONST)
5458 VariantClear(dest->u.lpvarValue);
5459 SysFreeString((BSTR)dest);
5466 /* ITypeInfo::GetVarDesc
5468 * Retrieves a VARDESC structure that describes the specified variable.
5471 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5472 LPVARDESC *ppVarDesc)
5474 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5475 const TLBVarDesc *pVDesc = &This->vardescs[index];
5477 TRACE("(%p) index %d\n", This, index);
5479 if(index >= This->TypeAttr.cVars)
5480 return TYPE_E_ELEMENTNOTFOUND;
5482 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5485 /* ITypeInfo_GetNames
5487 * Retrieves the variable with the specified member ID (or the name of the
5488 * property or method and its parameters) that correspond to the specified
5491 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5492 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5494 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5495 const TLBFuncDesc *pFDesc;
5496 const TLBVarDesc *pVDesc;
5498 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5499 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5502 /* function found, now return function and parameter names */
5503 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5506 *rgBstrNames=SysAllocString(pFDesc->Name);
5508 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5514 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
5517 *rgBstrNames=SysAllocString(pVDesc->Name);
5522 if(This->impltypes &&
5523 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5524 /* recursive search */
5527 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef,
5529 if(SUCCEEDED(result))
5531 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5532 ITypeInfo_Release(pTInfo);
5535 WARN("Could not search inherited interface!\n");
5539 WARN("no names found\n");
5542 return TYPE_E_ELEMENTNOTFOUND;
5549 /* ITypeInfo::GetRefTypeOfImplType
5551 * If a type description describes a COM class, it retrieves the type
5552 * description of the implemented interface types. For an interface,
5553 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5557 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5562 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5565 TRACE("(%p) index %d\n", This, index);
5566 if (TRACE_ON(ole)) dump_TypeInfo(This);
5570 /* only valid on dual interfaces;
5571 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5573 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5575 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5581 hr = TYPE_E_ELEMENTNOTFOUND;
5584 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5586 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5587 *pRefType = This->pTypeLib->dispatch_href;
5591 if(index >= This->TypeAttr.cImplTypes)
5592 hr = TYPE_E_ELEMENTNOTFOUND;
5594 *pRefType = This->impltypes[index].hRef;
5600 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5602 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5608 /* ITypeInfo::GetImplTypeFlags
5610 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5611 * or base interface in a type description.
5613 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5614 UINT index, INT *pImplTypeFlags)
5616 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5618 TRACE("(%p) index %d\n", This, index);
5620 if(This->TypeAttr.typekind == TKIND_DISPATCH && index == 0){
5621 *pImplTypeFlags = 0;
5625 if(index >= This->TypeAttr.cImplTypes)
5626 return TYPE_E_ELEMENTNOTFOUND;
5628 *pImplTypeFlags = This->impltypes[index].implflags;
5634 * Maps between member names and member IDs, and parameter names and
5637 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5638 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5640 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5641 const TLBVarDesc *pVDesc;
5645 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5648 /* init out parameters in case of failure */
5649 for (i = 0; i < cNames; i++)
5650 pMemId[i] = MEMBERID_NIL;
5652 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
5654 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
5655 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5656 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5657 for(i=1; i < cNames; i++){
5658 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5659 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5661 if( j<pFDesc->funcdesc.cParams)
5664 ret=DISP_E_UNKNOWNNAME;
5666 TRACE("-- 0x%08x\n", ret);
5670 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, *rgszNames);
5673 *pMemId = pVDesc->vardesc.memid;
5676 /* not found, see if it can be found in an inherited interface */
5677 if(This->impltypes) {
5678 /* recursive search */
5680 ret=ITypeInfo_GetRefTypeInfo(iface,
5681 This->impltypes[0].hRef, &pTInfo);
5683 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5684 ITypeInfo_Release(pTInfo);
5687 WARN("Could not search inherited interface!\n");
5689 WARN("no names found\n");
5690 return DISP_E_UNKNOWNNAME;
5696 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5697 __ASM_GLOBAL_FUNC( call_method,
5699 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5700 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5701 "movl %esp,%ebp\n\t"
5702 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5704 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5706 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5707 "movl 12(%ebp),%edx\n\t"
5708 "movl %esp,%edi\n\t"
5711 "subl %edx,%edi\n\t"
5712 "andl $~15,%edi\n\t"
5713 "movl %edi,%esp\n\t"
5714 "movl 12(%ebp),%ecx\n\t"
5715 "movl 16(%ebp),%esi\n\t"
5718 "1:\tcall *8(%ebp)\n\t"
5719 "subl %esp,%edi\n\t"
5720 "movl 20(%ebp),%ecx\n\t"
5721 "movl %edi,(%ecx)\n\t"
5722 "leal -8(%ebp),%esp\n\t"
5724 __ASM_CFI(".cfi_same_value %edi\n\t")
5726 __ASM_CFI(".cfi_same_value %esi\n\t")
5728 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5729 __ASM_CFI(".cfi_same_value %ebp\n\t")
5732 /* same function but returning floating point */
5733 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5735 /* ITypeInfo::Invoke
5737 * Invokes a method, or accesses a property of an object, that implements the
5738 * interface described by the type description.
5741 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5745 if (TRACE_ON(ole)) {
5747 TRACE("Calling %p(",func);
5748 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5749 if (nrargs > 30) TRACE("...");
5756 res = call_method( func, nrargs, args, &stack_offset );
5759 FIXME("unsupported calling convention %d\n",callconv);
5763 TRACE("returns %08x\n",res);
5767 #elif defined(__x86_64__)
5769 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5770 __ASM_GLOBAL_FUNC( call_method,
5772 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5773 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5774 "movq %rsp,%rbp\n\t"
5775 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5777 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5779 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5780 "movq %rcx,%rax\n\t"
5783 "cmovgq %rdx,%rcx\n\t"
5784 "leaq 0(,%rcx,8),%rdx\n\t"
5785 "subq %rdx,%rsp\n\t"
5786 "andq $~15,%rsp\n\t"
5787 "movq %rsp,%rdi\n\t"
5790 "movq 0(%rsp),%rcx\n\t"
5791 "movq 8(%rsp),%rdx\n\t"
5792 "movq 16(%rsp),%r8\n\t"
5793 "movq 24(%rsp),%r9\n\t"
5794 "movq %rcx,%xmm0\n\t"
5795 "movq %rdx,%xmm1\n\t"
5796 "movq %r8,%xmm2\n\t"
5797 "movq %r9,%xmm3\n\t"
5799 "leaq -16(%rbp),%rsp\n\t"
5801 __ASM_CFI(".cfi_same_value %rdi\n\t")
5803 __ASM_CFI(".cfi_same_value %rsi\n\t")
5804 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5806 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5807 __ASM_CFI(".cfi_same_value %rbp\n\t")
5810 /* same function but returning floating point */
5811 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5813 #endif /* __x86_64__ */
5815 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5818 ITypeInfo *tinfo2 = NULL;
5819 TYPEATTR *tattr = NULL;
5821 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5824 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5826 tdesc->u.hreftype, hr);
5829 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5832 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5833 ITypeInfo_Release(tinfo2);
5837 switch (tattr->typekind)
5844 tdesc = &tattr->tdescAlias;
5845 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5848 case TKIND_INTERFACE:
5849 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5855 case TKIND_DISPATCH:
5864 FIXME("TKIND_RECORD unhandled.\n");
5869 FIXME("TKIND_UNION unhandled.\n");
5874 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5878 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5879 ITypeInfo_Release(tinfo2);
5883 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5887 /* enforce only one level of pointer indirection */
5888 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5890 tdesc = tdesc->u.lptdesc;
5892 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5893 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5894 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5895 if ((tdesc->vt == VT_USERDEFINED) ||
5896 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5898 VARTYPE vt_userdefined = 0;
5899 const TYPEDESC *tdesc_userdefined = tdesc;
5900 if (tdesc->vt == VT_PTR)
5902 vt_userdefined = VT_BYREF;
5903 tdesc_userdefined = tdesc->u.lptdesc;
5905 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5907 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5908 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5910 *vt |= vt_userdefined;
5922 case VT_USERDEFINED:
5923 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5930 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5931 hr = DISP_E_BADVARTYPE;
5935 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5950 /***********************************************************************
5951 * DispCallFunc (OLEAUT32.@)
5953 * Invokes a function of the specified calling convention, passing the
5954 * specified arguments and returns the result.
5957 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5958 * oVft [I] The offset in the vtable. See notes.
5959 * cc [I] Calling convention of the function to call.
5960 * vtReturn [I] The return type of the function.
5961 * cActuals [I] Number of parameters.
5962 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5963 * prgpvarg [I] The arguments to pass.
5964 * pvargResult [O] The return value of the function. Can be NULL.
5968 * Failure: HRESULT code.
5971 * The HRESULT return value of this function is not affected by the return
5972 * value of the user supplied function, which is returned in pvargResult.
5974 * If pvInstance is NULL then a non-object function is to be called and oVft
5975 * is the address of the function to call.
5977 * The cc parameter can be one of the following values:
5990 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5991 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5994 int argspos, stack_offset;
5999 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6000 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6001 pvargResult, V_VT(pvargResult));
6003 if (cc != CC_STDCALL && cc != CC_CDECL)
6005 FIXME("unsupported calling convention %d\n",cc);
6006 return E_INVALIDARG;
6009 /* maximum size for an argument is sizeof(VARIANT) */
6010 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6012 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6016 const FARPROC *vtable = *(FARPROC **)pvInstance;
6017 func = vtable[oVft/sizeof(void *)];
6018 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6020 else func = (void *)oVft;
6022 for (i = 0; i < cActuals; i++)
6024 VARIANT *arg = prgpvarg[i];
6035 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6036 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6040 memcpy( &args[argspos], arg, sizeof(*arg) );
6041 argspos += sizeof(*arg) / sizeof(DWORD);
6043 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6044 args[argspos++] = V_BOOL(arg);
6047 args[argspos++] = V_UI4(arg);
6050 TRACE("arg %u: type %d\n",i,prgvt[i]);
6057 call_method( func, argspos - 1, args + 1, &stack_offset );
6060 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6064 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6068 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6069 call_method( func, argspos, args, &stack_offset );
6074 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6077 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6081 if (stack_offset && cc == CC_STDCALL)
6083 WARN( "stack pointer off by %d\n", stack_offset );
6084 return DISP_E_BADCALLEE;
6086 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6087 TRACE("retval: "); dump_Variant(pvargResult);
6090 #elif defined(__x86_64__)
6096 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6097 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6098 pvargResult, V_VT(pvargResult));
6100 if (cc != CC_STDCALL && cc != CC_CDECL)
6102 FIXME("unsupported calling convention %d\n",cc);
6103 return E_INVALIDARG;
6106 /* maximum size for an argument is sizeof(DWORD_PTR) */
6107 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6109 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6113 const FARPROC *vtable = *(FARPROC **)pvInstance;
6114 func = vtable[oVft/sizeof(void *)];
6115 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6117 else func = (void *)oVft;
6119 for (i = 0; i < cActuals; i++)
6121 VARIANT *arg = prgpvarg[i];
6127 args[argspos++] = (ULONG_PTR)arg;
6129 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6130 args[argspos++] = V_BOOL(arg);
6133 args[argspos++] = V_UI8(arg);
6136 TRACE("arg %u: type %d\n",i,prgvt[i]);
6143 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6147 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6151 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6152 call_method( func, argspos, args );
6155 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6159 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6160 TRACE("retval: "); dump_Variant(pvargResult);
6164 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6165 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6170 #define INVBUF_ELEMENT_SIZE \
6171 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6172 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6173 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6174 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6175 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6176 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6177 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6178 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6180 static HRESULT WINAPI ITypeInfo_fnInvoke(
6185 DISPPARAMS *pDispParams,
6186 VARIANT *pVarResult,
6187 EXCEPINFO *pExcepInfo,
6190 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6192 unsigned int var_index;
6195 const TLBFuncDesc *pFuncInfo;
6198 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6199 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6202 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6203 return DISP_E_MEMBERNOTFOUND;
6207 ERR("NULL pDispParams not allowed\n");
6208 return E_INVALIDARG;
6211 dump_DispParms(pDispParams);
6213 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6215 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6216 pDispParams->cNamedArgs, pDispParams->cArgs);
6217 return E_INVALIDARG;
6220 /* we do this instead of using GetFuncDesc since it will return a fake
6221 * FUNCDESC for dispinterfaces and we want the real function description */
6222 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6223 pFuncInfo = &This->funcdescs[fdc];
6224 if ((memid == pFuncInfo->funcdesc.memid) &&
6225 (wFlags & pFuncInfo->funcdesc.invkind) &&
6226 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6230 if (fdc < This->TypeAttr.cFuncs) {
6231 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6235 TRACE("invoking:\n");
6236 dump_TLBFuncDescOne(pFuncInfo);
6239 switch (func_desc->funckind) {
6240 case FUNC_PUREVIRTUAL:
6241 case FUNC_VIRTUAL: {
6242 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6244 VARIANT retval; /* pointer for storing byref retvals in */
6245 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6246 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6247 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6248 UINT cNamedArgs = pDispParams->cNamedArgs;
6249 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6250 UINT vargs_converted=0;
6254 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6256 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6258 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6259 hres = DISP_E_PARAMNOTFOUND;
6264 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6266 ERR("functions with the vararg attribute do not support named arguments\n");
6267 hres = DISP_E_NONAMEDARGS;
6271 for (i = 0; i < func_desc->cParams; i++)
6273 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6274 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6279 TRACE("changing args\n");
6280 for (i = 0; i < func_desc->cParams; i++)
6282 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6283 VARIANTARG *src_arg;
6285 if (wParamFlags & PARAMFLAG_FLCID)
6288 arg = prgpvarg[i] = &rgvarg[i];
6290 V_I4(arg) = This->pTypeLib->lcid;
6299 for (j = 0; j < cNamedArgs; j++)
6300 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6302 src_arg = &pDispParams->rgvarg[j];
6307 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6309 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6313 if (wParamFlags & PARAMFLAG_FRETVAL)
6315 /* under most conditions the caller is not allowed to
6316 * pass in a dispparam arg in the index of what would be
6317 * the retval parameter. however, there is an exception
6318 * where the extra parameter is used in an extra
6319 * IDispatch::Invoke below */
6320 if ((i < pDispParams->cArgs) &&
6321 ((func_desc->cParams != 1) || !pVarResult ||
6322 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6324 hres = DISP_E_BADPARAMCOUNT;
6328 /* note: this check is placed so that if the caller passes
6329 * in a VARIANTARG for the retval we just ignore it, like
6331 if (i == func_desc->cParams - 1)
6334 arg = prgpvarg[i] = &rgvarg[i];
6335 memset(arg, 0, sizeof(*arg));
6336 V_VT(arg) = rgvt[i];
6337 memset(&retval, 0, sizeof(retval));
6338 V_BYREF(arg) = &retval;
6342 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6343 hres = E_UNEXPECTED;
6349 dump_Variant(src_arg);
6351 if (rgvt[i] == VT_VARIANT)
6352 hres = VariantCopy(&rgvarg[i], src_arg);
6353 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6355 if (rgvt[i] == V_VT(src_arg))
6356 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6359 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6360 if (wParamFlags & PARAMFLAG_FIN)
6361 hres = VariantCopy(&missing_arg[i], src_arg);
6362 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6364 V_VT(&rgvarg[i]) = rgvt[i];
6366 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6369 SAFEARRAYBOUND bound;
6373 bound.cElements = pDispParams->cArgs-i;
6374 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6376 ERR("SafeArrayCreate failed\n");
6379 hres = SafeArrayAccessData(a, (LPVOID)&v);
6382 ERR("SafeArrayAccessData failed with %x\n", hres);
6385 for (j = 0; j < bound.cElements; j++)
6386 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6387 hres = SafeArrayUnaccessData(a);
6390 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6393 V_ARRAY(&rgvarg[i]) = a;
6394 V_VT(&rgvarg[i]) = rgvt[i];
6396 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6398 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6399 if (wParamFlags & PARAMFLAG_FIN)
6400 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6402 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6403 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6404 V_VT(&rgvarg[i]) = rgvt[i];
6406 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6408 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6409 V_VT(&rgvarg[i]) = rgvt[i];
6413 /* FIXME: this doesn't work for VT_BYREF arguments if
6414 * they are not the same type as in the paramdesc */
6415 V_VT(&rgvarg[i]) = V_VT(src_arg);
6416 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6417 V_VT(&rgvarg[i]) = rgvt[i];
6422 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6423 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6424 debugstr_VT(src_arg), debugstr_VF(src_arg));
6427 prgpvarg[i] = &rgvarg[i];
6429 else if (wParamFlags & PARAMFLAG_FOPT)
6432 arg = prgpvarg[i] = &rgvarg[i];
6433 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6435 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6441 VARIANTARG *missing_arg;
6442 /* if the function wants a pointer to a variant then
6443 * set that up, otherwise just pass the VT_ERROR in
6444 * the argument by value */
6445 if (rgvt[i] & VT_BYREF)
6447 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6448 V_VT(arg) = VT_VARIANT | VT_BYREF;
6449 V_VARIANTREF(arg) = missing_arg;
6453 V_VT(missing_arg) = VT_ERROR;
6454 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6459 hres = DISP_E_BADPARAMCOUNT;
6463 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6465 /* VT_VOID is a special case for return types, so it is not
6466 * handled in the general function */
6467 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6468 V_VT(&varresult) = VT_EMPTY;
6471 V_VT(&varresult) = 0;
6472 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6473 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6476 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6477 V_VT(&varresult), func_desc->cParams, rgvt,
6478 prgpvarg, &varresult);
6480 vargs_converted = 0;
6482 for (i = 0; i < func_desc->cParams; i++)
6484 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6485 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6487 if (wParamFlags & PARAMFLAG_FLCID)
6489 else if (wParamFlags & PARAMFLAG_FRETVAL)
6493 TRACE("[retval] value: ");
6494 dump_Variant(prgpvarg[i]);
6499 VariantInit(pVarResult);
6500 /* deref return value */
6501 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6504 VARIANT_ClearInd(prgpvarg[i]);
6506 else if (vargs_converted < pDispParams->cArgs)
6508 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6509 if (wParamFlags & PARAMFLAG_FOUT)
6511 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6513 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6517 ERR("failed to convert param %d to vt %d\n", i,
6518 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6523 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6524 func_desc->cParamsOpt < 0 &&
6525 i == func_desc->cParams-1)
6527 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6530 hres = SafeArrayGetUBound(a, 1, &ubound);
6533 ERR("SafeArrayGetUBound failed with %x\n", hres);
6536 hres = SafeArrayAccessData(a, (LPVOID)&v);
6539 ERR("SafeArrayAccessData failed with %x\n", hres);
6542 for (j = 0; j <= ubound; j++)
6543 VariantClear(&v[j]);
6544 hres = SafeArrayUnaccessData(a);
6547 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6551 VariantClear(&rgvarg[i]);
6554 else if (wParamFlags & PARAMFLAG_FOPT)
6556 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6557 VariantClear(&rgvarg[i]);
6560 VariantClear(&missing_arg[i]);
6563 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6565 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6566 hres = DISP_E_EXCEPTION;
6569 IErrorInfo *pErrorInfo;
6570 pExcepInfo->scode = V_ERROR(&varresult);
6571 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6573 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6574 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6575 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6576 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6578 IErrorInfo_Release(pErrorInfo);
6582 if (V_VT(&varresult) != VT_ERROR)
6584 TRACE("varresult value: ");
6585 dump_Variant(&varresult);
6589 VariantClear(pVarResult);
6590 *pVarResult = varresult;
6593 VariantClear(&varresult);
6596 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6597 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6598 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6599 (pDispParams->cArgs != 0))
6601 if (V_VT(pVarResult) == VT_DISPATCH)
6603 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6604 /* Note: not VariantClear; we still need the dispatch
6605 * pointer to be valid */
6606 VariantInit(pVarResult);
6607 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6608 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6609 pDispParams, pVarResult, pExcepInfo, pArgErr);
6610 IDispatch_Release(pDispatch);
6614 VariantClear(pVarResult);
6615 hres = DISP_E_NOTACOLLECTION;
6623 case FUNC_DISPATCH: {
6626 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6627 if (SUCCEEDED(hres)) {
6628 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6629 hres = IDispatch_Invoke(
6630 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6631 pVarResult,pExcepInfo,pArgErr
6634 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6635 IDispatch_Release(disp);
6637 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6641 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6646 TRACE("-- 0x%08x\n", hres);
6649 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6652 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6653 if(FAILED(hres)) return hres;
6655 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6656 dump_VARDESC(var_desc);
6657 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6661 /* not found, look for it in inherited interfaces */
6662 ITypeInfo2_GetTypeKind(iface, &type_kind);
6663 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6664 if(This->impltypes) {
6665 /* recursive search */
6667 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pTInfo);
6668 if(SUCCEEDED(hres)){
6669 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6670 ITypeInfo_Release(pTInfo);
6673 WARN("Could not search inherited interface!\n");
6676 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6677 return DISP_E_MEMBERNOTFOUND;
6680 /* ITypeInfo::GetDocumentation
6682 * Retrieves the documentation string, the complete Help file name and path,
6683 * and the context ID for the Help topic for a specified type description.
6685 * (Can be tested by the Visual Basic Editor in Word for instance.)
6687 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6688 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6689 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6691 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6692 const TLBFuncDesc *pFDesc;
6693 const TLBVarDesc *pVDesc;
6694 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6695 " HelpContext(%p) HelpFile(%p)\n",
6696 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6697 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6699 *pBstrName=SysAllocString(This->Name);
6701 *pBstrDocString=SysAllocString(This->DocString);
6703 *pdwHelpContext=This->dwHelpContext;
6705 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6707 }else {/* for a member */
6708 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6711 *pBstrName = SysAllocString(pFDesc->Name);
6713 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6715 *pdwHelpContext=pFDesc->helpcontext;
6718 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
6721 *pBstrName = SysAllocString(pVDesc->Name);
6723 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6725 *pdwHelpContext=pVDesc->HelpContext;
6730 if(This->impltypes &&
6731 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6732 /* recursive search */
6735 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef,
6737 if(SUCCEEDED(result)) {
6738 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6739 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6740 ITypeInfo_Release(pTInfo);
6743 WARN("Could not search inherited interface!\n");
6746 WARN("member %d not found\n", memid);
6747 return TYPE_E_ELEMENTNOTFOUND;
6750 /* ITypeInfo::GetDllEntry
6752 * Retrieves a description or specification of an entry point for a function
6755 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6756 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6759 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6760 const TLBFuncDesc *pFDesc;
6762 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6764 if (pBstrDllName) *pBstrDllName = NULL;
6765 if (pBstrName) *pBstrName = NULL;
6766 if (pwOrdinal) *pwOrdinal = 0;
6768 if (This->TypeAttr.typekind != TKIND_MODULE)
6769 return TYPE_E_BADMODULEKIND;
6771 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6773 dump_TypeInfo(This);
6775 dump_TLBFuncDescOne(pFDesc);
6778 *pBstrDllName = SysAllocString(This->DllName);
6780 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6782 *pBstrName = SysAllocString(pFDesc->Entry);
6790 *pwOrdinal = LOWORD(pFDesc->Entry);
6793 return TYPE_E_ELEMENTNOTFOUND;
6796 /* internal function to make the inherited interfaces' methods appear
6797 * part of the interface */
6798 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6799 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6801 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6804 TRACE("%p, 0x%x\n", iface, *hRefType);
6806 if (This->impltypes && (*hRefType & DISPATCH_HREF_MASK))
6808 ITypeInfo *pSubTypeInfo;
6810 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypes[0].hRef, &pSubTypeInfo);
6814 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6816 ITypeInfo_Release(pSubTypeInfo);
6820 *hRefType -= DISPATCH_HREF_OFFSET;
6822 if (!(*hRefType & DISPATCH_HREF_MASK))
6823 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6828 /* ITypeInfo::GetRefTypeInfo
6830 * If a type description references other type descriptions, it retrieves
6831 * the referenced type descriptions.
6833 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6836 ITypeInfo **ppTInfo)
6838 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6839 HRESULT result = E_FAIL;
6841 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6843 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6844 ITypeInfo_AddRef(*ppTInfo);
6847 else if (hRefType == -1 &&
6848 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6849 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6851 /* when we meet a DUAL dispinterface, we must create the interface
6854 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
6857 /* the interface version contains the same information as the dispinterface
6858 * copy the contents of the structs.
6860 *pTypeInfoImpl = *This;
6861 pTypeInfoImpl->ref = 0;
6863 /* change the type to interface */
6864 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6866 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6868 /* the AddRef implicitly adds a reference to the parent typelib, which
6869 * stops the copied data from being destroyed until the new typeinfo's
6870 * refcount goes to zero, but we need to signal to the new instance to
6871 * not free its data structures when it is destroyed */
6872 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6874 ITypeInfo_AddRef(*ppTInfo);
6878 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6879 (This->TypeAttr.typekind == TKIND_DISPATCH))
6881 HREFTYPE href_dispatch = hRefType;
6882 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6884 TLBRefType *ref_type;
6885 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6887 if(ref_type->reference == hRefType)
6890 if(&ref_type->entry == &This->pTypeLib->ref_list)
6892 FIXME("Can't find pRefType for ref %x\n", hRefType);
6895 if(hRefType != -1) {
6896 ITypeLib *pTLib = NULL;
6898 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6900 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6902 if(ref_type->pImpTLInfo->pImpTypeLib) {
6903 TRACE("typeinfo in imported typelib that is already loaded\n");
6904 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6905 ITypeLib2_AddRef(pTLib);
6908 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6909 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6910 ref_type->pImpTLInfo->wVersionMajor,
6911 ref_type->pImpTLInfo->wVersionMinor,
6912 ref_type->pImpTLInfo->lcid,
6915 if(FAILED(result)) {
6916 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6917 result=LoadTypeLib(libnam, &pTLib);
6918 SysFreeString(libnam);
6920 if(SUCCEEDED(result)) {
6921 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6922 ITypeLib2_AddRef(pTLib);
6926 if(SUCCEEDED(result)) {
6927 if(ref_type->index == TLB_REF_USE_GUID)
6928 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6932 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6936 ITypeLib2_Release(pTLib);
6941 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6942 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6946 /* ITypeInfo::AddressOfMember
6948 * Retrieves the addresses of static functions or variables, such as those
6951 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6952 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6954 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6960 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6962 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6966 module = LoadLibraryW(dll);
6969 ERR("couldn't load %s\n", debugstr_w(dll));
6971 SysFreeString(entry);
6972 return STG_E_FILENOTFOUND;
6974 /* FIXME: store library somewhere where we can free it */
6979 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6980 entryA = heap_alloc(len);
6981 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6983 *ppv = GetProcAddress(module, entryA);
6985 ERR("function not found %s\n", debugstr_a(entryA));
6991 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6993 ERR("function not found %d\n", ordinal);
6997 SysFreeString(entry);
7000 return TYPE_E_DLLFUNCTIONNOTFOUND;
7005 /* ITypeInfo::CreateInstance
7007 * Creates a new instance of a type that describes a component object class
7010 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7011 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7013 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7017 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7023 WARN("Not able to aggregate\n");
7024 return CLASS_E_NOAGGREGATION;
7027 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
7028 if(FAILED(hr)) return hr;
7030 if(pTA->typekind != TKIND_COCLASS)
7032 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7038 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7041 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7042 TRACE("GetActiveObject rets %08x\n", hr);
7045 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7046 IUnknown_Release(pUnk);
7051 hr = CoCreateInstance(&pTA->guid, NULL,
7052 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7056 ITypeInfo_ReleaseTypeAttr(iface, pTA);
7060 /* ITypeInfo::GetMops
7062 * Retrieves marshalling information.
7064 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7067 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7068 FIXME("(%p %d) stub!\n", This, memid);
7073 /* ITypeInfo::GetContainingTypeLib
7075 * Retrieves the containing type library and the index of the type description
7076 * within that type library.
7078 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7079 ITypeLib * *ppTLib, UINT *pIndex)
7081 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7083 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7085 *pIndex=This->index;
7086 TRACE("returning pIndex=%d\n", *pIndex);
7090 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7091 ITypeLib2_AddRef(*ppTLib);
7092 TRACE("returning ppTLib=%p\n", *ppTLib);
7098 /* ITypeInfo::ReleaseTypeAttr
7100 * Releases a TYPEATTR previously returned by GetTypeAttr.
7103 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7104 TYPEATTR* pTypeAttr)
7106 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7107 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7108 heap_free(pTypeAttr);
7111 /* ITypeInfo::ReleaseFuncDesc
7113 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7115 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7117 FUNCDESC *pFuncDesc)
7119 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7122 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7124 for (i = 0; i < pFuncDesc->cParams; i++)
7125 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7126 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7128 SysFreeString((BSTR)pFuncDesc);
7131 /* ITypeInfo::ReleaseVarDesc
7133 * Releases a VARDESC previously returned by GetVarDesc.
7135 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7138 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7139 TRACE("(%p)->(%p)\n", This, pVarDesc);
7141 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7142 if (pVarDesc->varkind == VAR_CONST)
7143 VariantClear(pVarDesc->u.lpvarValue);
7144 SysFreeString((BSTR)pVarDesc);
7147 /* ITypeInfo2::GetTypeKind
7149 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7152 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7153 TYPEKIND *pTypeKind)
7155 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7156 *pTypeKind=This->TypeAttr.typekind;
7157 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7161 /* ITypeInfo2::GetTypeFlags
7163 * Returns the type flags without any allocations. This returns a DWORD type
7164 * flag, which expands the type flags without growing the TYPEATTR (type
7168 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7170 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7171 *pTypeFlags=This->TypeAttr.wTypeFlags;
7172 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7176 /* ITypeInfo2::GetFuncIndexOfMemId
7177 * Binds to a specific member based on a known DISPID, where the member name
7178 * is not known (for example, when binding to a default member).
7181 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7182 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7184 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7188 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7189 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7190 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7193 if(fdc < This->TypeAttr.cFuncs) {
7197 result = TYPE_E_ELEMENTNOTFOUND;
7199 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7200 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7204 /* TypeInfo2::GetVarIndexOfMemId
7206 * Binds to a specific member based on a known DISPID, where the member name
7207 * is not known (for example, when binding to a default member).
7210 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7211 MEMBERID memid, UINT *pVarIndex)
7213 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7214 TLBVarDesc *pVarInfo;
7216 TRACE("%p %d %p\n", iface, memid, pVarIndex);
7218 pVarInfo = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7220 return TYPE_E_ELEMENTNOTFOUND;
7222 *pVarIndex = (pVarInfo - This->vardescs);
7227 /* ITypeInfo2::GetCustData
7229 * Gets the custom data
7231 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7236 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7237 TLBCustData *pCData;
7239 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7240 if( IsEqualIID(guid, &pCData->guid)) break;
7242 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7244 VariantInit( pVarVal);
7246 VariantCopy( pVarVal, &pCData->data);
7248 VariantClear( pVarVal );
7252 /* ITypeInfo2::GetFuncCustData
7254 * Gets the custom data
7256 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7262 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7263 TLBCustData *pCData=NULL;
7264 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7266 if(index >= This->TypeAttr.cFuncs)
7267 return TYPE_E_ELEMENTNOTFOUND;
7269 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7270 if( IsEqualIID(guid, &pCData->guid)) break;
7272 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7275 VariantInit( pVarVal);
7276 VariantCopy( pVarVal, &pCData->data);
7279 return TYPE_E_ELEMENTNOTFOUND;
7282 /* ITypeInfo2::GetParamCustData
7284 * Gets the custom data
7286 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7293 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7294 TLBCustData *pCData;
7295 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7297 if(indexFunc >= This->TypeAttr.cFuncs)
7298 return TYPE_E_ELEMENTNOTFOUND;
7300 if(indexParam >= pFDesc->funcdesc.cParams)
7301 return TYPE_E_ELEMENTNOTFOUND;
7303 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7304 pCData = pCData->next)
7305 if( IsEqualIID(guid, &pCData->guid)) break;
7307 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7311 VariantInit( pVarVal);
7312 VariantCopy( pVarVal, &pCData->data);
7315 return TYPE_E_ELEMENTNOTFOUND;
7318 /* ITypeInfo2::GetVarCustData
7320 * Gets the custom data
7322 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7328 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7329 TLBCustData *pCData=NULL;
7330 TLBVarDesc *pVDesc = &This->vardescs[index];
7332 TRACE("%p %s %p\n", This, debugstr_guid(guid), pVarVal);
7334 if(index >= This->TypeAttr.cVars)
7335 return TYPE_E_ELEMENTNOTFOUND;
7337 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7338 if(IsEqualIID(guid, &pCData->guid))
7341 return TYPE_E_ELEMENTNOTFOUND;
7343 VariantInit( pVarVal);
7344 VariantCopy( pVarVal, &pCData->data);
7348 /* ITypeInfo2::GetImplCustData
7350 * Gets the custom data
7352 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7358 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7359 TLBCustData *pCData=NULL;
7360 TLBImplType *pRDesc = &This->impltypes[index];
7362 if(index >= This->TypeAttr.cImplTypes)
7363 return TYPE_E_ELEMENTNOTFOUND;
7365 for(pCData = pRDesc->pCustData; pCData; pCData = pCData->next)
7367 if( IsEqualIID(guid, &pCData->guid)) break;
7370 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7374 VariantInit( pVarVal);
7375 VariantCopy( pVarVal, &pCData->data);
7379 return TYPE_E_ELEMENTNOTFOUND;
7382 /* ITypeInfo2::GetDocumentation2
7384 * Retrieves the documentation string, the complete Help file name and path,
7385 * the localization context to use, and the context ID for the library Help
7386 * topic in the Help file.
7389 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7393 BSTR *pbstrHelpString,
7394 DWORD *pdwHelpStringContext,
7395 BSTR *pbstrHelpStringDll)
7397 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7398 const TLBFuncDesc *pFDesc;
7399 const TLBVarDesc *pVDesc;
7400 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7401 "HelpStringContext(%p) HelpStringDll(%p)\n",
7402 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7403 pbstrHelpStringDll );
7404 /* the help string should be obtained from the helpstringdll,
7405 * using the _DLLGetDocumentation function, based on the supplied
7406 * lcid. Nice to do sometime...
7408 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7410 *pbstrHelpString=SysAllocString(This->Name);
7411 if(pdwHelpStringContext)
7412 *pdwHelpStringContext=This->dwHelpStringContext;
7413 if(pbstrHelpStringDll)
7414 *pbstrHelpStringDll=
7415 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7417 }else {/* for a member */
7418 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7421 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7422 if(pdwHelpStringContext)
7423 *pdwHelpStringContext=pFDesc->HelpStringContext;
7424 if(pbstrHelpStringDll)
7425 *pbstrHelpStringDll=
7426 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7429 pVDesc = TLB_get_vardesc_by_memberid(This->vardescs, This->TypeAttr.cVars, memid);
7432 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7433 if(pdwHelpStringContext)
7434 *pdwHelpStringContext=pVDesc->HelpStringContext;
7435 if(pbstrHelpStringDll)
7436 *pbstrHelpStringDll=
7437 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7441 return TYPE_E_ELEMENTNOTFOUND;
7444 /* ITypeInfo2::GetAllCustData
7446 * Gets all custom data items for the Type info.
7449 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7451 CUSTDATA *pCustData)
7453 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7454 TLBCustData *pCData;
7457 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7459 pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
7460 if(pCustData->prgCustData ){
7461 pCustData->cCustData=This->ctCustData;
7462 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7463 pCustData->prgCustData[i].guid=pCData->guid;
7464 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7467 ERR(" OUT OF MEMORY!\n");
7468 return E_OUTOFMEMORY;
7473 /* ITypeInfo2::GetAllFuncCustData
7475 * Gets all custom data items for the specified Function
7478 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7481 CUSTDATA *pCustData)
7483 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7484 TLBCustData *pCData;
7485 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7487 TRACE("(%p) index %d\n", This, index);
7489 if(index >= This->TypeAttr.cFuncs)
7490 return TYPE_E_ELEMENTNOTFOUND;
7492 pCustData->prgCustData =
7493 heap_alloc_zero(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7494 if(pCustData->prgCustData ){
7495 pCustData->cCustData=pFDesc->ctCustData;
7496 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7497 pCData = pCData->next){
7498 pCustData->prgCustData[i].guid=pCData->guid;
7499 VariantCopy(& pCustData->prgCustData[i].varValue,
7503 ERR(" OUT OF MEMORY!\n");
7504 return E_OUTOFMEMORY;
7509 /* ITypeInfo2::GetAllParamCustData
7511 * Gets all custom data items for the Functions
7514 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7515 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7517 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7518 TLBCustData *pCData=NULL;
7519 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7521 TRACE("(%p) index %d\n", This, indexFunc);
7523 if(indexFunc >= This->TypeAttr.cFuncs)
7524 return TYPE_E_ELEMENTNOTFOUND;
7526 if(indexParam >= pFDesc->funcdesc.cParams)
7527 return TYPE_E_ELEMENTNOTFOUND;
7529 pCustData->prgCustData =
7530 heap_alloc_zero(pFDesc->pParamDesc[indexParam].ctCustData *
7531 sizeof(CUSTDATAITEM));
7532 if(pCustData->prgCustData ){
7533 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7534 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7535 pCData; i++, pCData = pCData->next){
7536 pCustData->prgCustData[i].guid=pCData->guid;
7537 VariantCopy(& pCustData->prgCustData[i].varValue,
7541 ERR(" OUT OF MEMORY!\n");
7542 return E_OUTOFMEMORY;
7547 /* ITypeInfo2::GetAllVarCustData
7549 * Gets all custom data items for the specified Variable
7552 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7553 UINT index, CUSTDATA *pCustData)
7555 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7556 TLBCustData *pCData;
7557 TLBVarDesc * pVDesc = &This->vardescs[index];
7559 TRACE("(%p) index %d\n", This, index);
7561 if(index >= This->TypeAttr.cVars)
7562 return TYPE_E_ELEMENTNOTFOUND;
7564 pCustData->prgCustData =
7565 heap_alloc_zero(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7566 if(pCustData->prgCustData ){
7567 pCustData->cCustData=pVDesc->ctCustData;
7568 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7569 pCData = pCData->next){
7570 pCustData->prgCustData[i].guid=pCData->guid;
7571 VariantCopy(& pCustData->prgCustData[i].varValue,
7575 ERR(" OUT OF MEMORY!\n");
7576 return E_OUTOFMEMORY;
7581 /* ITypeInfo2::GetAllImplCustData
7583 * Gets all custom data items for the specified implementation type
7586 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7589 CUSTDATA *pCustData)
7591 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7592 TLBCustData *pCData;
7593 TLBImplType *pRDesc = &This->impltypes[index];
7596 TRACE("(%p) index %d\n", This, index);
7598 if(index >= This->TypeAttr.cImplTypes)
7599 return TYPE_E_ELEMENTNOTFOUND;
7601 pCustData->prgCustData = heap_alloc_zero(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7602 if(!pCustData->prgCustData)
7603 return E_OUTOFMEMORY;
7605 pCustData->cCustData=pRDesc->ctCustData;
7606 for(i = 0, pCData = pRDesc->pCustData; pCData; i++, pCData = pCData->next){
7607 pCustData->prgCustData[i].guid = pCData->guid;
7608 VariantCopy(&pCustData->prgCustData[i].varValue, &pCData->data);
7614 static const ITypeInfo2Vtbl tinfvt =
7617 ITypeInfo_fnQueryInterface,
7619 ITypeInfo_fnRelease,
7621 ITypeInfo_fnGetTypeAttr,
7622 ITypeInfo_fnGetTypeComp,
7623 ITypeInfo_fnGetFuncDesc,
7624 ITypeInfo_fnGetVarDesc,
7625 ITypeInfo_fnGetNames,
7626 ITypeInfo_fnGetRefTypeOfImplType,
7627 ITypeInfo_fnGetImplTypeFlags,
7628 ITypeInfo_fnGetIDsOfNames,
7630 ITypeInfo_fnGetDocumentation,
7631 ITypeInfo_fnGetDllEntry,
7632 ITypeInfo_fnGetRefTypeInfo,
7633 ITypeInfo_fnAddressOfMember,
7634 ITypeInfo_fnCreateInstance,
7635 ITypeInfo_fnGetMops,
7636 ITypeInfo_fnGetContainingTypeLib,
7637 ITypeInfo_fnReleaseTypeAttr,
7638 ITypeInfo_fnReleaseFuncDesc,
7639 ITypeInfo_fnReleaseVarDesc,
7641 ITypeInfo2_fnGetTypeKind,
7642 ITypeInfo2_fnGetTypeFlags,
7643 ITypeInfo2_fnGetFuncIndexOfMemId,
7644 ITypeInfo2_fnGetVarIndexOfMemId,
7645 ITypeInfo2_fnGetCustData,
7646 ITypeInfo2_fnGetFuncCustData,
7647 ITypeInfo2_fnGetParamCustData,
7648 ITypeInfo2_fnGetVarCustData,
7649 ITypeInfo2_fnGetImplTypeCustData,
7650 ITypeInfo2_fnGetDocumentation2,
7651 ITypeInfo2_fnGetAllCustData,
7652 ITypeInfo2_fnGetAllFuncCustData,
7653 ITypeInfo2_fnGetAllParamCustData,
7654 ITypeInfo2_fnGetAllVarCustData,
7655 ITypeInfo2_fnGetAllImplTypeCustData,
7658 /******************************************************************************
7659 * CreateDispTypeInfo [OLEAUT32.31]
7661 * Build type information for an object so it can be called through an
7662 * IDispatch interface.
7665 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7666 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7669 * This call allows an objects methods to be accessed through IDispatch, by
7670 * building an ITypeInfo object that IDispatch can use to call through.
7672 HRESULT WINAPI CreateDispTypeInfo(
7673 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7674 LCID lcid, /* [I] Locale Id */
7675 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7677 ITypeInfoImpl *pTIClass, *pTIIface;
7678 ITypeLibImpl *pTypeLibImpl;
7679 unsigned int param, func;
7680 TLBFuncDesc *pFuncDesc;
7684 pTypeLibImpl = TypeLibImpl_Constructor();
7685 if (!pTypeLibImpl) return E_FAIL;
7687 pTypeLibImpl->TypeInfoCount = 2;
7688 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
7690 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
7691 pTIIface->pTypeLib = pTypeLibImpl;
7692 pTIIface->index = 0;
7693 pTIIface->Name = NULL;
7694 pTIIface->dwHelpContext = -1;
7695 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7696 pTIIface->TypeAttr.lcid = lcid;
7697 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7698 pTIIface->TypeAttr.wMajorVerNum = 0;
7699 pTIIface->TypeAttr.wMinorVerNum = 0;
7700 pTIIface->TypeAttr.cbAlignment = 2;
7701 pTIIface->TypeAttr.cbSizeInstance = -1;
7702 pTIIface->TypeAttr.cbSizeVft = -1;
7703 pTIIface->TypeAttr.cFuncs = 0;
7704 pTIIface->TypeAttr.cImplTypes = 0;
7705 pTIIface->TypeAttr.cVars = 0;
7706 pTIIface->TypeAttr.wTypeFlags = 0;
7708 pTIIface->funcdescs = heap_alloc_zero(pidata->cMembers * sizeof(TLBFuncDesc));
7709 pFuncDesc = pTIIface->funcdescs;
7710 for(func = 0; func < pidata->cMembers; func++) {
7711 METHODDATA *md = pidata->pmethdata + func;
7712 pFuncDesc->Name = SysAllocString(md->szName);
7713 pFuncDesc->funcdesc.memid = md->dispid;
7714 pFuncDesc->funcdesc.lprgscode = NULL;
7715 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
7716 pFuncDesc->funcdesc.invkind = md->wFlags;
7717 pFuncDesc->funcdesc.callconv = md->cc;
7718 pFuncDesc->funcdesc.cParams = md->cArgs;
7719 pFuncDesc->funcdesc.cParamsOpt = 0;
7720 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
7721 pFuncDesc->funcdesc.cScodes = 0;
7722 pFuncDesc->funcdesc.wFuncFlags = 0;
7723 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7724 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7725 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7726 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7727 md->cArgs * sizeof(ELEMDESC));
7728 pFuncDesc->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7729 md->cArgs * sizeof(TLBParDesc));
7730 for(param = 0; param < md->cArgs; param++) {
7731 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7732 pFuncDesc->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7734 pFuncDesc->helpcontext = 0;
7735 pFuncDesc->HelpStringContext = 0;
7736 pFuncDesc->HelpString = NULL;
7737 pFuncDesc->Entry = NULL;
7738 pFuncDesc->ctCustData = 0;
7739 pFuncDesc->pCustData = NULL;
7740 pTIIface->TypeAttr.cFuncs++;
7744 dump_TypeInfo(pTIIface);
7746 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
7747 pTIClass->pTypeLib = pTypeLibImpl;
7748 pTIClass->index = 1;
7749 pTIClass->Name = NULL;
7750 pTIClass->dwHelpContext = -1;
7751 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7752 pTIClass->TypeAttr.lcid = lcid;
7753 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7754 pTIClass->TypeAttr.wMajorVerNum = 0;
7755 pTIClass->TypeAttr.wMinorVerNum = 0;
7756 pTIClass->TypeAttr.cbAlignment = 2;
7757 pTIClass->TypeAttr.cbSizeInstance = -1;
7758 pTIClass->TypeAttr.cbSizeVft = -1;
7759 pTIClass->TypeAttr.cFuncs = 0;
7760 pTIClass->TypeAttr.cImplTypes = 1;
7761 pTIClass->TypeAttr.cVars = 0;
7762 pTIClass->TypeAttr.wTypeFlags = 0;
7764 pTIClass->impltypes = heap_alloc_zero(sizeof(*pTIClass->impltypes));
7765 pTIClass->impltypes[0].hRef = 0;
7767 ref = heap_alloc_zero(sizeof(*ref));
7770 ref->pImpTLInfo = TLB_REF_INTERNAL;
7771 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7773 dump_TypeInfo(pTIClass);
7775 *pptinfo = (ITypeInfo*)pTIClass;
7777 ITypeInfo_AddRef(*pptinfo);
7778 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7784 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7786 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7788 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7791 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7793 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7795 return ITypeInfo_AddRef((ITypeInfo *)This);
7798 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7800 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7802 return ITypeInfo_Release((ITypeInfo *)This);
7805 static HRESULT WINAPI ITypeComp_fnBind(
7810 ITypeInfo ** ppTInfo,
7811 DESCKIND * pDescKind,
7814 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7815 const TLBFuncDesc *pFDesc;
7816 const TLBVarDesc *pVDesc;
7817 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7820 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7822 *pDescKind = DESCKIND_NONE;
7823 pBindPtr->lpfuncdesc = NULL;
7826 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7827 pFDesc = &This->funcdescs[fdc];
7828 if (!strcmpiW(pFDesc->Name, szName)) {
7829 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7832 /* name found, but wrong flags */
7833 hr = TYPE_E_TYPEMISMATCH;
7837 if (fdc < This->TypeAttr.cFuncs)
7839 HRESULT hr = TLB_AllocAndInitFuncDesc(
7841 &pBindPtr->lpfuncdesc,
7842 This->TypeAttr.typekind == TKIND_DISPATCH);
7845 *pDescKind = DESCKIND_FUNCDESC;
7846 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7847 ITypeInfo_AddRef(*ppTInfo);
7850 pVDesc = TLB_get_vardesc_by_name(This->vardescs, This->TypeAttr.cVars, szName);
7852 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7855 *pDescKind = DESCKIND_VARDESC;
7856 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7857 ITypeInfo_AddRef(*ppTInfo);
7861 /* FIXME: search each inherited interface, not just the first */
7862 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypes) {
7863 /* recursive search */
7867 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypes[0].hRef, &pTInfo);
7870 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7871 ITypeInfo_Release(pTInfo);
7875 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7876 ITypeComp_Release(pTComp);
7879 WARN("Could not search inherited interface!\n");
7881 if (hr == DISP_E_MEMBERNOTFOUND)
7883 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7887 static HRESULT WINAPI ITypeComp_fnBindType(
7891 ITypeInfo ** ppTInfo,
7892 ITypeComp ** ppTComp)
7894 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7896 /* strange behaviour (does nothing) but like the
7899 if (!ppTInfo || !ppTComp)
7908 static const ITypeCompVtbl tcompvt =
7911 ITypeComp_fnQueryInterface,
7913 ITypeComp_fnRelease,
7916 ITypeComp_fnBindType