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; */
1088 struct tagTLBVarDesc * next;
1091 /* internal implemented interface data */
1092 typedef struct tagTLBImplType
1094 HREFTYPE hRef; /* hRef of interface */
1095 int implflags; /* IMPLFLAG_*s */
1097 TLBCustData * pCustData;/* linked list to custom data; */
1098 struct tagTLBImplType *next;
1101 /* internal TypeInfo data */
1102 typedef struct tagITypeInfoImpl
1104 const ITypeInfo2Vtbl *lpVtbl;
1105 const ITypeCompVtbl *lpVtblTypeComp;
1107 BOOL not_attached_to_typelib;
1108 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1109 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1110 int index; /* index in this typelib; */
1111 HREFTYPE hreftype; /* hreftype for app object binding */
1112 /* type libs seem to store the doc strings in ascii
1113 * so why should we do it in unicode?
1118 DWORD dwHelpContext;
1119 DWORD dwHelpStringContext;
1122 TLBFuncDesc *funcdescs;
1125 TLBVarDesc * varlist; /* linked list with variable descriptions */
1127 /* Implemented Interfaces */
1128 TLBImplType * impltypelist;
1131 TLBCustData * pCustData; /* linked list to cust data; */
1134 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1136 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1139 static const ITypeInfo2Vtbl tinfvt;
1140 static const ITypeCompVtbl tcompvt;
1142 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1143 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This);
1145 typedef struct tagTLBContext
1147 unsigned int oStart; /* start of TLB in file */
1148 unsigned int pos; /* current pos */
1149 unsigned int length; /* total length */
1150 void *mapping; /* memory mapping */
1151 MSFT_SegDir * pTblDir;
1152 ITypeLibImpl* pLibInfo;
1156 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1161 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1162 if (pTD->vt & VT_RESERVED)
1163 szVarType += strlen(strcpy(szVarType, "reserved | "));
1164 if (pTD->vt & VT_BYREF)
1165 szVarType += strlen(strcpy(szVarType, "ref to "));
1166 if (pTD->vt & VT_ARRAY)
1167 szVarType += strlen(strcpy(szVarType, "array of "));
1168 if (pTD->vt & VT_VECTOR)
1169 szVarType += strlen(strcpy(szVarType, "vector of "));
1170 switch(pTD->vt & VT_TYPEMASK) {
1171 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1172 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1173 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1174 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1175 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1176 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1177 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1178 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1179 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1180 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1181 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1182 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1183 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1184 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1185 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1186 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1187 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1188 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1189 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1190 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1191 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1192 pTD->u.hreftype); break;
1193 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1194 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1195 case VT_PTR: sprintf(szVarType, "ptr to ");
1196 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1198 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1199 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1201 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1202 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1203 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1206 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1210 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1212 USHORT flags = edesc->u.paramdesc.wParamFlags;
1213 dump_TypeDesc(&edesc->tdesc,buf);
1214 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1215 MESSAGE("\t\tu.paramdesc.wParamFlags");
1216 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1217 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1218 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1219 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1220 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1221 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1222 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1223 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1224 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1226 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1228 MESSAGE("memid is %08x\n",funcdesc->memid);
1229 for (i=0;i<funcdesc->cParams;i++) {
1230 MESSAGE("Param %d:\n",i);
1231 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1233 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1234 switch (funcdesc->funckind) {
1235 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1236 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1237 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1238 case FUNC_STATIC: MESSAGE("static");break;
1239 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1240 default: MESSAGE("unknown");break;
1242 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1243 switch (funcdesc->invkind) {
1244 case INVOKE_FUNC: MESSAGE("func");break;
1245 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1246 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1247 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1249 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1250 switch (funcdesc->callconv) {
1251 case CC_CDECL: MESSAGE("cdecl");break;
1252 case CC_PASCAL: MESSAGE("pascal");break;
1253 case CC_STDCALL: MESSAGE("stdcall");break;
1254 case CC_SYSCALL: MESSAGE("syscall");break;
1257 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1258 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1259 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1261 MESSAGE("\telemdescFunc (return value type):\n");
1262 dump_ELEMDESC(&funcdesc->elemdescFunc);
1265 static const char * const typekind_desc[] =
1278 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1281 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1282 for (i=0;i<pfd->funcdesc.cParams;i++)
1283 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1286 dump_FUNCDESC(&(pfd->funcdesc));
1288 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1289 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1291 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd, UINT n)
1295 dump_TLBFuncDescOne(pfd);
1300 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1304 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1309 static void dump_TLBImpLib(const TLBImpLib *import)
1311 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1312 debugstr_w(import->name));
1313 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1314 import->wVersionMinor, import->lcid, import->offset);
1317 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1321 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1323 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1324 if(ref->index == -1)
1325 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1327 TRACE_(typelib)("type no: %d\n", ref->index);
1329 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1331 TRACE_(typelib)("in lib\n");
1332 dump_TLBImpLib(ref->pImpTLInfo);
1337 static void dump_TLBImplType(const TLBImplType * impl)
1341 "implementing/inheriting interface hRef = %x implflags %x\n",
1342 impl->hRef, impl->implflags);
1347 static void dump_Variant(const VARIANT * pvar)
1351 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1355 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1356 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1358 TRACE(",%p", V_BYREF(pvar));
1360 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1362 TRACE(",%p", V_ARRAY(pvar));
1364 else switch (V_TYPE(pvar))
1366 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1367 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1368 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1369 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1371 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1373 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1374 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1375 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1376 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1377 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1378 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1379 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1380 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1381 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1382 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1383 V_CY(pvar).s.Lo); break;
1385 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1386 TRACE(",<invalid>");
1388 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1389 st.wHour, st.wMinute, st.wSecond);
1393 case VT_USERDEFINED:
1395 case VT_NULL: break;
1396 default: TRACE(",?"); break;
1402 static void dump_DispParms(const DISPPARAMS * pdp)
1406 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1408 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1410 TRACE("named args:\n");
1411 for (index = 0; index < pdp->cNamedArgs; index++)
1412 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1415 if (pdp->cArgs && pdp->rgvarg)
1418 for (index = 0; index < pdp->cArgs; index++)
1419 dump_Variant( &pdp->rgvarg[index] );
1423 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1425 TRACE("%p ref=%u\n", pty, pty->ref);
1426 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1427 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1428 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1429 TRACE("fct:%u var:%u impl:%u\n",
1430 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1431 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1432 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1433 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1435 dump_TLBFuncDesc(pty->funcdescs, pty->TypeAttr.cFuncs);
1436 dump_TLBVarDesc(pty->varlist);
1437 dump_TLBImplType(pty->impltypelist);
1440 static void dump_VARDESC(const VARDESC *v)
1442 MESSAGE("memid %d\n",v->memid);
1443 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1444 MESSAGE("oInst %d\n",v->u.oInst);
1445 dump_ELEMDESC(&(v->elemdescVar));
1446 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1447 MESSAGE("varkind %d\n",v->varkind);
1450 static TYPEDESC std_typedesc[VT_LPWSTR+1] =
1452 /* VT_LPWSTR is largest type that, may appear in type description */
1453 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1454 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1455 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1456 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1457 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1458 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1459 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1460 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1463 static void TLB_abort(void)
1468 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1470 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1471 if (!ret) ERR("cannot allocate memory\n");
1475 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1477 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1478 if (!ret) ERR("cannot allocate memory\n");
1482 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1484 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1487 void heap_free(void *ptr)
1489 HeapFree(GetProcessHeap(), 0, ptr);
1492 /* returns the size required for a deep copy of a typedesc into a
1494 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1498 if (alloc_initial_space)
1499 size += sizeof(TYPEDESC);
1505 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1508 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1509 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1515 /* deep copy a typedesc into a flat buffer */
1516 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1521 buffer = (char *)buffer + sizeof(TYPEDESC);
1530 dest->u.lptdesc = buffer;
1531 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1534 dest->u.lpadesc = buffer;
1535 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1536 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1537 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1543 /* free custom data allocated by MSFT_CustData */
1544 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1546 TLBCustData *pCustDataNext;
1547 for (; pCustData; pCustData = pCustDataNext)
1549 VariantClear(&pCustData->data);
1551 pCustDataNext = pCustData->next;
1552 heap_free(pCustData);
1556 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1561 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1562 ret = SysAllocStringLen(NULL, len - 1);
1563 if (!ret) return ret;
1564 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1568 static inline TLBFuncDesc *TLB_get_funcdesc_by_memberid(TLBFuncDesc *funcdescs,
1569 UINT n, MEMBERID memid)
1572 if(funcdescs->funcdesc.memid == memid)
1580 static inline TLBFuncDesc *TLB_get_funcdesc_by_name(TLBFuncDesc *funcdescs,
1581 UINT n, const OLECHAR *name)
1584 if(!lstrcmpiW(funcdescs->Name, name))
1592 /**********************************************************************
1594 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1596 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1601 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1603 if (where != DO_NOT_SEEK)
1605 where += pcx->oStart;
1606 if (where > pcx->length)
1609 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1617 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1619 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1620 pcx->pos, count, pcx->oStart, pcx->length, where);
1622 MSFT_Seek(pcx, where);
1623 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1624 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1629 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1634 ret = MSFT_Read(buffer, count, pcx, where);
1635 FromLEDWords(buffer, ret);
1640 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1645 ret = MSFT_Read(buffer, count, pcx, where);
1646 FromLEWords(buffer, ret);
1651 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1653 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1654 memset(pGuid,0, sizeof(GUID));
1657 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1658 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1659 pGuid->Data2 = FromLEWord(pGuid->Data2);
1660 pGuid->Data3 = FromLEWord(pGuid->Data3);
1661 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1664 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1666 MSFT_NameIntro niName;
1670 ERR_(typelib)("bad offset %d\n", offset);
1674 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1675 pcx->pTblDir->pNametab.offset+offset);
1677 return niName.hreftype;
1680 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1683 MSFT_NameIntro niName;
1685 BSTR bstrName = NULL;
1689 ERR_(typelib)("bad offset %d\n", offset);
1692 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1693 pcx->pTblDir->pNametab.offset+offset);
1694 niName.namelen &= 0xFF; /* FIXME: correct ? */
1695 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1696 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1697 name[niName.namelen & 0xff]='\0';
1699 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1702 /* no invalid characters in string */
1705 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1707 /* don't check for invalid character since this has been done previously */
1708 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1712 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1716 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1723 if(offset<0) return NULL;
1724 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1725 if(length <= 0) return 0;
1726 string = heap_alloc_zero(length +1);
1727 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1728 string[length]='\0';
1730 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1731 string, -1, NULL, 0);
1733 /* no invalid characters in string */
1736 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1738 /* don't check for invalid character since this has been done previously */
1739 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1743 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1747 * read a value and fill a VARIANT structure
1749 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1753 TRACE_(typelib)("\n");
1755 if(offset <0) { /* data are packed in here */
1756 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1757 V_I4(pVar) = offset & 0x3ffffff;
1760 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1761 pcx->pTblDir->pCustData.offset + offset );
1762 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1763 switch (V_VT(pVar)){
1764 case VT_EMPTY: /* FIXME: is this right? */
1765 case VT_NULL: /* FIXME: is this right? */
1766 case VT_I2 : /* this should not happen */
1777 case VT_VOID : /* FIXME: is this right? */
1785 case VT_DECIMAL : /* FIXME: is this right? */
1788 /* pointer types with known behaviour */
1791 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1794 DWORD origPos = MSFT_Tell(pcx), nullPos;
1797 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1799 nullPos = MSFT_Tell(pcx);
1800 size = nullPos - origPos;
1801 MSFT_Seek(pcx, origPos);
1803 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1804 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1805 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1806 /* FIXME: do we need a AtoW conversion here? */
1807 V_UNION(pVar, bstrVal[size])='\0';
1808 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1812 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1819 case VT_USERDEFINED :
1825 case VT_STREAMED_OBJECT :
1826 case VT_STORED_OBJECT :
1827 case VT_BLOB_OBJECT :
1832 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1836 if(size>0) /* (big|small) endian correct? */
1837 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1841 * create a linked list with custom data
1843 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1849 TRACE_(typelib)("\n");
1853 pNew=heap_alloc_zero(sizeof(TLBCustData));
1854 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1855 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1856 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1857 /* add new custom data at head of the list */
1858 pNew->next=*ppCustData;
1860 offset = entry.next;
1865 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1869 pTd->vt=type & VT_TYPEMASK;
1871 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1873 if(pTd->vt == VT_USERDEFINED)
1874 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1876 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1879 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1881 /* resolve referenced type if any */
1884 switch (lpTypeDesc->vt)
1887 lpTypeDesc = lpTypeDesc->u.lptdesc;
1891 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1894 case VT_USERDEFINED:
1895 MSFT_DoRefType(pcx, pTI->pTypeLib,
1896 lpTypeDesc->u.hreftype);
1908 MSFT_DoFuncs(TLBContext* pcx,
1913 TLBFuncDesc** pptfd)
1916 * member information is stored in a data structure at offset
1917 * indicated by the memoffset field of the typeinfo structure
1918 * There are several distinctive parts.
1919 * The first part starts with a field that holds the total length
1920 * of this (first) part excluding this field. Then follow the records,
1921 * for each member there is one record.
1923 * The first entry is always the length of the record (including this
1925 * The rest of the record depends on the type of the member. If there is
1926 * a field indicating the member type (function, variable, interface, etc)
1927 * I have not found it yet. At this time we depend on the information
1928 * in the type info and the usual order how things are stored.
1930 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1933 * Third is an equal sized array with file offsets to the name entry
1936 * The fourth and last (?) part is an array with offsets to the records
1937 * in the first part of this file segment.
1940 int infolen, nameoffset, reclength, i;
1941 int recoffset = offset + sizeof(INT);
1943 char *recbuf = heap_alloc(0xffff);
1944 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
1945 TLBFuncDesc *ptfd_prev = NULL, *ptfd;
1947 TRACE_(typelib)("\n");
1949 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1951 *pptfd = heap_alloc_zero(sizeof(TLBFuncDesc) * cFuncs);
1953 for ( i = 0; i < cFuncs ; i++ )
1957 /* name, eventually add to a hash table */
1958 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1959 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1961 /* nameoffset is sometimes -1 on the second half of a propget/propput
1962 * pair of functions */
1963 if ((nameoffset == -1) && (i > 0))
1964 ptfd->Name = SysAllocString(ptfd_prev->Name);
1966 ptfd->Name = MSFT_ReadName(pcx, nameoffset);
1968 /* read the function information record */
1969 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
1971 reclength &= 0xffff;
1973 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
1975 /* size without argument data */
1976 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
1978 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
1979 ptfd->helpcontext = pFuncRec->HelpContext;
1981 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
1982 ptfd->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
1984 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
1986 if (pFuncRec->FKCCIC & 0x2000 )
1988 if (!IS_INTRESOURCE(pFuncRec->oEntry))
1989 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
1990 ptfd->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
1993 ptfd->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
1996 ptfd->Entry = (BSTR)-1;
1998 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
1999 ptfd->HelpStringContext = pFuncRec->HelpStringContext;
2001 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
2002 MSFT_CustData(pcx, pFuncRec->oCustData, &ptfd->pCustData);
2004 /* fill the FuncDesc Structure */
2005 MSFT_ReadLEDWords( & ptfd->funcdesc.memid, sizeof(INT), pcx,
2006 offset + infolen + ( i + 1) * sizeof(INT));
2008 ptfd->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
2009 ptfd->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
2010 ptfd->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
2011 ptfd->funcdesc.cParams = pFuncRec->nrargs ;
2012 ptfd->funcdesc.cParamsOpt = pFuncRec->nroargs ;
2013 ptfd->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
2014 ptfd->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
2018 &ptfd->funcdesc.elemdescFunc.tdesc,
2020 MSFT_ResolveReferencedTypes(pcx, pTI, &ptfd->funcdesc.elemdescFunc.tdesc);
2022 /* do the parameters/arguments */
2023 if(pFuncRec->nrargs)
2026 MSFT_ParameterInfo paraminfo;
2028 ptfd->funcdesc.lprgelemdescParam =
2029 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2032 heap_alloc_zero(pFuncRec->nrargs * sizeof(TLBParDesc));
2034 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
2035 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2037 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2039 ELEMDESC *elemdesc = &ptfd->funcdesc.lprgelemdescParam[j];
2046 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2049 if (paraminfo.oName == -1)
2050 /* this occurs for [propput] or [propget] methods, so
2051 * we should just set the name of the parameter to the
2052 * name of the method. */
2053 ptfd->pParamDesc[j].Name = SysAllocString(ptfd->Name);
2055 ptfd->pParamDesc[j].Name =
2056 MSFT_ReadName( pcx, paraminfo.oName );
2057 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w(ptfd->pParamDesc[j].Name));
2059 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2062 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2063 (pFuncRec->FKCCIC & 0x1000) )
2065 INT* pInt = (INT *)((char *)pFuncRec +
2067 (pFuncRec->nrargs * 4) * sizeof(INT) );
2069 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2071 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2072 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2074 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2078 elemdesc->u.paramdesc.pparamdescex = NULL;
2081 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2082 j*sizeof(pFuncRec->oArgCustData[0])) &&
2083 pFuncRec->FKCCIC & 0x80 )
2086 pFuncRec->oArgCustData[j],
2087 &ptfd->pParamDesc[j].pCustData);
2090 /* SEEK value = jump to offset,
2091 * from there jump to the end of record,
2092 * go back by (j-1) arguments
2094 MSFT_ReadLEDWords( ¶minfo ,
2095 sizeof(MSFT_ParameterInfo), pcx,
2096 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2097 * sizeof(MSFT_ParameterInfo)));
2101 /* scode is not used: archaic win16 stuff FIXME: right? */
2102 ptfd->funcdesc.cScodes = 0 ;
2103 ptfd->funcdesc.lprgscode = NULL ;
2107 recoffset += reclength;
2112 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2113 int cVars, int offset, TLBVarDesc ** pptvd)
2115 int infolen, nameoffset, reclength;
2117 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2121 TRACE_(typelib)("\n");
2123 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2124 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2125 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2126 recoffset += offset+sizeof(INT);
2127 for(i=0;i<cVars;i++){
2128 *pptvd = heap_alloc_zero(sizeof(TLBVarDesc));
2129 /* name, eventually add to a hash table */
2130 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2131 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2132 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2133 /* read the variable information record */
2134 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2136 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2139 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2140 (*pptvd)->HelpContext = pVarRec->HelpContext;
2142 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2143 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2145 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2146 (*pptvd)->HelpStringContext = pVarRec->HelpStringContext;
2148 /* fill the VarDesc Structure */
2149 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2150 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2151 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2152 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2153 MSFT_GetTdesc(pcx, pVarRec->DataType,
2154 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2155 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2156 if(pVarRec->VarKind == VAR_CONST ){
2157 (*pptvd)->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2158 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2159 pVarRec->OffsValue, pcx);
2161 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2162 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2163 pptvd=&((*pptvd)->next);
2164 recoffset += reclength;
2167 /* fill in data for a hreftype (offset). When the referenced type is contained
2168 * in the typelib, it's just an (file) offset in the type info base dir.
2169 * If comes from import, it's an offset+1 in the ImpInfo table
2171 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2176 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2178 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2180 if(ref->reference == offset) return;
2183 ref = heap_alloc_zero(sizeof(TLBRefType));
2184 list_add_tail(&pTL->ref_list, &ref->entry);
2186 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2187 /* external typelib */
2188 MSFT_ImpInfo impinfo;
2189 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2191 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2193 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2194 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2195 while (pImpLib){ /* search the known offsets of all import libraries */
2196 if(pImpLib->offset==impinfo.oImpFile) break;
2197 pImpLib=pImpLib->next;
2200 ref->reference = offset;
2201 ref->pImpTLInfo = pImpLib;
2202 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2203 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2204 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2205 ref->index = TLB_REF_USE_GUID;
2207 ref->index = impinfo.oGuid;
2209 ERR("Cannot find a reference\n");
2210 ref->reference = -1;
2211 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2214 /* in this typelib */
2215 ref->index = MSFT_HREFTYPE_INDEX(offset);
2216 ref->reference = offset;
2217 ref->pImpTLInfo = TLB_REF_INTERNAL;
2221 /* process Implemented Interfaces of a com class */
2222 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2226 MSFT_RefRecord refrec;
2227 TLBImplType **ppImpl = &pTI->impltypelist;
2229 TRACE_(typelib)("\n");
2231 for(i=0;i<count;i++){
2232 if(offset<0) break; /* paranoia */
2233 *ppImpl = heap_alloc_zero(sizeof(**ppImpl));
2234 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2235 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2236 (*ppImpl)->hRef = refrec.reftype;
2237 (*ppImpl)->implflags=refrec.flags;
2238 (*ppImpl)->ctCustData=
2239 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2240 offset=refrec.onext;
2241 ppImpl=&((*ppImpl)->next);
2245 * process a typeinfo record
2247 static ITypeInfoImpl * MSFT_DoTypeInfo(
2250 ITypeLibImpl * pLibInfo)
2252 MSFT_TypeInfoBase tiBase;
2253 ITypeInfoImpl *ptiRet;
2255 TRACE_(typelib)("count=%u\n", count);
2257 ptiRet = ITypeInfoImpl_Constructor();
2258 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2259 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2261 /* this is where we are coming from */
2262 ptiRet->pTypeLib = pLibInfo;
2263 ptiRet->index=count;
2264 /* fill in the typeattr fields */
2266 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2267 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2268 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2269 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2270 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2271 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2272 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2273 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2274 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2275 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2276 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2277 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2278 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2279 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2280 MSFT_GetTdesc(pcx, tiBase.datatype1,
2281 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2284 /* IDLDESC idldescType; *//* never saw this one != zero */
2286 /* name, eventually add to a hash table */
2287 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2288 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2289 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2291 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2292 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2293 ptiRet->dwHelpContext=tiBase.helpcontext;
2295 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2296 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2298 /* note: InfoType's Help file and HelpStringDll come from the containing
2299 * library. Further HelpString and Docstring appear to be the same thing :(
2302 if(ptiRet->TypeAttr.cFuncs >0 )
2303 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2304 ptiRet->TypeAttr.cVars,
2305 tiBase.memoffset, &ptiRet->funcdescs);
2307 if(ptiRet->TypeAttr.cVars >0 )
2308 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2309 ptiRet->TypeAttr.cVars,
2310 tiBase.memoffset, & ptiRet->varlist);
2311 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2312 switch(ptiRet->TypeAttr.typekind)
2315 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2318 case TKIND_DISPATCH:
2319 /* This is not -1 when the interface is a non-base dual interface or
2320 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2321 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2325 if (tiBase.datatype1 != -1)
2327 ptiRet->impltypelist = heap_alloc_zero(sizeof(TLBImplType));
2328 ptiRet->impltypelist->hRef = tiBase.datatype1;
2329 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2333 ptiRet->impltypelist = heap_alloc_zero(sizeof(TLBImplType));
2334 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2335 ptiRet->impltypelist->hRef = tiBase.datatype1;
2340 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2342 TRACE_(typelib)("%s guid: %s kind:%s\n",
2343 debugstr_w(ptiRet->Name),
2344 debugstr_guid(&ptiRet->TypeAttr.guid),
2345 typekind_desc[ptiRet->TypeAttr.typekind]);
2346 if (TRACE_ON(typelib))
2347 dump_TypeInfo(ptiRet);
2352 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2353 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2354 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2357 static ITypeLibImpl *tlb_cache_first;
2358 static CRITICAL_SECTION cache_section;
2359 static CRITICAL_SECTION_DEBUG cache_section_debug =
2361 0, 0, &cache_section,
2362 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2363 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2365 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2368 typedef struct TLB_PEFile
2370 const IUnknownVtbl *lpvtbl;
2373 HRSRC typelib_resource;
2374 HGLOBAL typelib_global;
2375 LPVOID typelib_base;
2378 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2380 if (IsEqualIID(riid, &IID_IUnknown))
2383 IUnknown_AddRef(iface);
2387 return E_NOINTERFACE;
2390 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2392 TLB_PEFile *This = (TLB_PEFile *)iface;
2393 return InterlockedIncrement(&This->refs);
2396 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2398 TLB_PEFile *This = (TLB_PEFile *)iface;
2399 ULONG refs = InterlockedDecrement(&This->refs);
2402 if (This->typelib_global)
2403 FreeResource(This->typelib_global);
2405 FreeLibrary(This->dll);
2411 static const IUnknownVtbl TLB_PEFile_Vtable =
2413 TLB_PEFile_QueryInterface,
2418 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2422 This = heap_alloc(sizeof(TLB_PEFile));
2424 return E_OUTOFMEMORY;
2426 This->lpvtbl = &TLB_PEFile_Vtable;
2429 This->typelib_resource = NULL;
2430 This->typelib_global = NULL;
2431 This->typelib_base = NULL;
2433 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2434 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2438 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2439 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2440 if (This->typelib_resource)
2442 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2443 if (This->typelib_global)
2445 This->typelib_base = LockResource(This->typelib_global);
2447 if (This->typelib_base)
2449 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2450 *ppBase = This->typelib_base;
2451 *ppFile = (IUnknown *)&This->lpvtbl;
2458 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2459 return TYPE_E_CANTLOADLIBRARY;
2462 typedef struct TLB_NEFile
2464 const IUnknownVtbl *lpvtbl;
2466 LPVOID typelib_base;
2469 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2471 if (IsEqualIID(riid, &IID_IUnknown))
2474 IUnknown_AddRef(iface);
2478 return E_NOINTERFACE;
2481 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2483 TLB_NEFile *This = (TLB_NEFile *)iface;
2484 return InterlockedIncrement(&This->refs);
2487 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2489 TLB_NEFile *This = (TLB_NEFile *)iface;
2490 ULONG refs = InterlockedDecrement(&This->refs);
2493 heap_free(This->typelib_base);
2499 static const IUnknownVtbl TLB_NEFile_Vtable =
2501 TLB_NEFile_QueryInterface,
2506 /***********************************************************************
2507 * read_xx_header [internal]
2509 static int read_xx_header( HFILE lzfd )
2511 IMAGE_DOS_HEADER mzh;
2514 LZSeek( lzfd, 0, SEEK_SET );
2515 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2517 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2520 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2521 if ( 2 != LZRead( lzfd, magic, 2 ) )
2524 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2526 if ( magic[0] == 'N' && magic[1] == 'E' )
2527 return IMAGE_OS2_SIGNATURE;
2528 if ( magic[0] == 'P' && magic[1] == 'E' )
2529 return IMAGE_NT_SIGNATURE;
2532 WARN("Can't handle %s files.\n", magic );
2537 /***********************************************************************
2538 * find_ne_resource [internal]
2540 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2541 DWORD *resLen, DWORD *resOff )
2543 IMAGE_OS2_HEADER nehd;
2544 NE_TYPEINFO *typeInfo;
2545 NE_NAMEINFO *nameInfo;
2551 /* Read in NE header */
2552 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2553 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2555 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2558 TRACE("No resources in NE dll\n" );
2562 /* Read in resource table */
2563 resTab = heap_alloc( resTabSize );
2564 if ( !resTab ) return FALSE;
2566 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2567 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2569 heap_free( resTab );
2574 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2576 if (!IS_INTRESOURCE(typeid)) /* named type */
2578 BYTE len = strlen( typeid );
2579 while (typeInfo->type_id)
2581 if (!(typeInfo->type_id & 0x8000))
2583 BYTE *p = resTab + typeInfo->type_id;
2584 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2586 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2587 typeInfo->count * sizeof(NE_NAMEINFO));
2590 else /* numeric type id */
2592 WORD id = LOWORD(typeid) | 0x8000;
2593 while (typeInfo->type_id)
2595 if (typeInfo->type_id == id) goto found_type;
2596 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2597 typeInfo->count * sizeof(NE_NAMEINFO));
2600 TRACE("No typeid entry found for %p\n", typeid );
2601 heap_free( resTab );
2605 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2607 if (!IS_INTRESOURCE(resid)) /* named resource */
2609 BYTE len = strlen( resid );
2610 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2612 BYTE *p = resTab + nameInfo->id;
2613 if (nameInfo->id & 0x8000) continue;
2614 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2617 else /* numeric resource id */
2619 WORD id = LOWORD(resid) | 0x8000;
2620 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2621 if (nameInfo->id == id) goto found_name;
2623 TRACE("No resid entry found for %p\n", typeid );
2624 heap_free( resTab );
2628 /* Return resource data */
2629 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2630 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2632 heap_free( resTab );
2636 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2640 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2643 This = heap_alloc(sizeof(TLB_NEFile));
2644 if (!This) return E_OUTOFMEMORY;
2646 This->lpvtbl = &TLB_NEFile_Vtable;
2648 This->typelib_base = NULL;
2650 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2651 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2653 DWORD reslen, offset;
2654 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2656 This->typelib_base = heap_alloc(reslen);
2657 if( !This->typelib_base )
2661 LZSeek( lzfd, offset, SEEK_SET );
2662 reslen = LZRead( lzfd, This->typelib_base, reslen );
2664 *ppBase = This->typelib_base;
2665 *pdwTLBLength = reslen;
2666 *ppFile = (IUnknown *)&This->lpvtbl;
2672 if( lzfd >= 0) LZClose( lzfd );
2673 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2677 typedef struct TLB_Mapping
2679 const IUnknownVtbl *lpvtbl;
2683 LPVOID typelib_base;
2686 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2688 if (IsEqualIID(riid, &IID_IUnknown))
2691 IUnknown_AddRef(iface);
2695 return E_NOINTERFACE;
2698 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2700 TLB_Mapping *This = (TLB_Mapping *)iface;
2701 return InterlockedIncrement(&This->refs);
2704 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2706 TLB_Mapping *This = (TLB_Mapping *)iface;
2707 ULONG refs = InterlockedDecrement(&This->refs);
2710 if (This->typelib_base)
2711 UnmapViewOfFile(This->typelib_base);
2713 CloseHandle(This->mapping);
2714 if (This->file != INVALID_HANDLE_VALUE)
2715 CloseHandle(This->file);
2721 static const IUnknownVtbl TLB_Mapping_Vtable =
2723 TLB_Mapping_QueryInterface,
2728 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2732 This = heap_alloc(sizeof(TLB_Mapping));
2734 return E_OUTOFMEMORY;
2736 This->lpvtbl = &TLB_Mapping_Vtable;
2738 This->file = INVALID_HANDLE_VALUE;
2739 This->mapping = NULL;
2740 This->typelib_base = NULL;
2742 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2743 if (INVALID_HANDLE_VALUE != This->file)
2745 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2748 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2749 if(This->typelib_base)
2751 /* retrieve file size */
2752 *pdwTLBLength = GetFileSize(This->file, NULL);
2753 *ppBase = This->typelib_base;
2754 *ppFile = (IUnknown *)&This->lpvtbl;
2760 IUnknown_Release((IUnknown *)&This->lpvtbl);
2761 return TYPE_E_CANTLOADLIBRARY;
2764 /****************************************************************************
2767 * find the type of the typelib file and map the typelib resource into
2771 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2772 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2774 ITypeLibImpl *entry;
2777 LPWSTR index_str, file = (LPWSTR)pszFileName;
2778 LPVOID pBase = NULL;
2779 DWORD dwTLBLength = 0;
2780 IUnknown *pFile = NULL;
2784 index_str = strrchrW(pszFileName, '\\');
2785 if(index_str && *++index_str != '\0')
2788 LONG idx = strtolW(index_str, &end_ptr, 10);
2789 if(*end_ptr == '\0')
2791 int str_len = index_str - pszFileName - 1;
2793 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2794 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2799 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2801 if(strchrW(file, '\\'))
2803 lstrcpyW(pszPath, file);
2807 int len = GetSystemDirectoryW(pszPath, cchPath);
2808 pszPath[len] = '\\';
2809 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2813 if(file != pszFileName) heap_free(file);
2815 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2817 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2818 EnterCriticalSection(&cache_section);
2819 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2821 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2823 TRACE("cache hit\n");
2824 *ppTypeLib = (ITypeLib2*)entry;
2825 ITypeLib_AddRef(*ppTypeLib);
2826 LeaveCriticalSection(&cache_section);
2830 LeaveCriticalSection(&cache_section);
2832 /* now actually load and parse the typelib */
2834 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2835 if (ret == TYPE_E_CANTLOADLIBRARY)
2836 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2837 if (ret == TYPE_E_CANTLOADLIBRARY)
2838 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2841 if (dwTLBLength >= 4)
2843 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2844 if (dwSignature == MSFT_SIGNATURE)
2845 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2846 else if (dwSignature == SLTG_SIGNATURE)
2847 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2850 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2851 ret = TYPE_E_CANTLOADLIBRARY;
2855 ret = TYPE_E_CANTLOADLIBRARY;
2856 IUnknown_Release(pFile);
2860 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2862 TRACE("adding to cache\n");
2863 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2864 lstrcpyW(impl->path, pszPath);
2865 /* We should really canonicalise the path here. */
2866 impl->index = index;
2868 /* FIXME: check if it has added already in the meantime */
2869 EnterCriticalSection(&cache_section);
2870 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2872 tlb_cache_first = impl;
2873 LeaveCriticalSection(&cache_section);
2876 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2881 /*================== ITypeLib(2) Methods ===================================*/
2883 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2885 ITypeLibImpl* pTypeLibImpl;
2887 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2888 if (!pTypeLibImpl) return NULL;
2890 pTypeLibImpl->lpVtbl = &tlbvt;
2891 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2892 pTypeLibImpl->ref = 1;
2894 list_init(&pTypeLibImpl->ref_list);
2895 pTypeLibImpl->dispatch_href = -1;
2897 return pTypeLibImpl;
2900 /****************************************************************************
2901 * ITypeLib2_Constructor_MSFT
2903 * loading an MSFT typelib from an in-memory image
2905 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2909 MSFT_Header tlbHeader;
2910 MSFT_SegDir tlbSegDir;
2911 ITypeLibImpl * pTypeLibImpl;
2913 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2915 pTypeLibImpl = TypeLibImpl_Constructor();
2916 if (!pTypeLibImpl) return NULL;
2918 /* get pointer to beginning of typelib data */
2922 cx.pLibInfo = pTypeLibImpl;
2923 cx.length = dwTLBLength;
2926 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2927 TRACE_(typelib)("header:\n");
2928 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2929 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2930 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2933 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2935 /* there is a small amount of information here until the next important
2937 * the segment directory . Try to calculate the amount of data */
2938 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2940 /* now read the segment directory */
2941 TRACE("read segment directory (at %d)\n",lPSegDir);
2942 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2943 cx.pTblDir = &tlbSegDir;
2945 /* just check two entries */
2946 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2948 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
2949 heap_free(pTypeLibImpl);
2953 /* now fill our internal data */
2954 /* TLIBATTR fields */
2955 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2957 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2958 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2959 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2960 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2961 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2963 pTypeLibImpl->lcid = tlbHeader.lcid;
2965 /* name, eventually add to a hash table */
2966 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2969 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2970 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2972 if( tlbHeader.varflags & HELPDLLFLAG)
2975 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2976 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2979 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2982 if(tlbHeader.CustomDataOffset >= 0)
2984 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2987 /* fill in type descriptions */
2988 if(tlbSegDir.pTypdescTab.length > 0)
2990 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2992 pTypeLibImpl->ctTypeDesc = cTD;
2993 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
2994 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2997 /* FIXME: add several sanity checks here */
2998 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2999 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
3001 /* FIXME: check safearray */
3003 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
3005 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
3007 else if(td[0] == VT_CARRAY)
3009 /* array descr table here */
3010 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
3012 else if(td[0] == VT_USERDEFINED)
3014 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
3016 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
3019 /* second time around to fill the array subscript info */
3022 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3023 if(tlbSegDir.pArrayDescriptions.offset>0)
3025 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3026 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3029 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3031 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3033 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3035 for(j = 0; j<td[2]; j++)
3037 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3038 sizeof(INT), &cx, DO_NOT_SEEK);
3039 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3040 sizeof(INT), &cx, DO_NOT_SEEK);
3045 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3046 ERR("didn't find array description data\n");
3051 /* imported type libs */
3052 if(tlbSegDir.pImpFiles.offset>0)
3054 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
3055 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3058 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3062 *ppImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3063 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
3064 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3066 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3067 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3068 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3069 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3072 name = heap_alloc_zero(size+1);
3073 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3074 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3077 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3078 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3080 ppImpLib = &(*ppImpLib)->next;
3084 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3085 if(pTypeLibImpl->dispatch_href != -1)
3086 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3089 if(tlbHeader.nrtypeinfos >= 0 )
3091 ITypeInfoImpl **ppTI;
3094 ppTI = pTypeLibImpl->typeinfos = heap_alloc_zero(sizeof(ITypeInfoImpl*) * tlbHeader.nrtypeinfos);
3096 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3098 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3101 (pTypeLibImpl->TypeInfoCount)++;
3105 TRACE("(%p)\n", pTypeLibImpl);
3106 return (ITypeLib2*) pTypeLibImpl;
3110 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3116 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3117 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3121 guid->Data4[0] = s >> 8;
3122 guid->Data4[1] = s & 0xff;
3125 for(i = 0; i < 6; i++) {
3126 memcpy(b, str + 24 + 2 * i, 2);
3127 guid->Data4[i + 2] = strtol(b, NULL, 16);
3132 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3138 bytelen = *(const WORD*)ptr;
3139 if(bytelen == 0xffff) return 2;
3140 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3141 *pBstr = SysAllocStringLen(NULL, len);
3143 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3147 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3152 bytelen = *(const WORD*)ptr;
3153 if(bytelen == 0xffff) return 2;
3154 *str = heap_alloc(bytelen + 1);
3155 memcpy(*str, ptr + 2, bytelen);
3156 (*str)[bytelen] = '\0';
3160 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3162 char *ptr = pLibBlk;
3165 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3166 FIXME("libblk magic = %04x\n", w);
3171 if((w = *(WORD*)ptr) != 0xffff) {
3172 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3177 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3179 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3181 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3184 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3187 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3188 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3190 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3193 ptr += 4; /* skip res12 */
3195 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3198 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3201 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3204 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3205 ptr += sizeof(GUID);
3207 return ptr - (char*)pLibBlk;
3210 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3215 } sltg_ref_lookup_t;
3217 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3218 HREFTYPE *typelib_ref)
3220 if(table && typeinfo_ref < table->num)
3222 *typelib_ref = table->refs[typeinfo_ref];
3226 ERR_(typelib)("Unable to find reference\n");
3231 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3236 if((*pType & 0xe00) == 0xe00) {
3238 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3239 pTD = pTD->u.lptdesc;
3241 switch(*pType & 0x3f) {
3244 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3245 pTD = pTD->u.lptdesc;
3248 case VT_USERDEFINED:
3249 pTD->vt = VT_USERDEFINED;
3250 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3256 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3259 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3261 pTD->vt = VT_CARRAY;
3262 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3263 pTD->u.lpadesc->cDims = pSA->cDims;
3264 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3265 pSA->cDims * sizeof(SAFEARRAYBOUND));
3267 pTD = &pTD->u.lpadesc->tdescElem;
3273 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3277 pTD->vt = VT_SAFEARRAY;
3278 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3279 pTD = pTD->u.lptdesc;
3283 pTD->vt = *pType & 0x3f;
3292 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3293 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3295 /* Handle [in/out] first */
3296 if((*pType & 0xc000) == 0xc000)
3297 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3298 else if(*pType & 0x8000)
3299 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3300 else if(*pType & 0x4000)
3301 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3303 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3306 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3309 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3311 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3315 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3320 TLBRefType *ref_type;
3321 sltg_ref_lookup_t *table;
3322 HREFTYPE typelib_ref;
3324 if(pRef->magic != SLTG_REF_MAGIC) {
3325 FIXME("Ref magic = %x\n", pRef->magic);
3328 name = ( (char*)pRef->names + pRef->number);
3330 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3331 table->num = pRef->number >> 3;
3333 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3335 /* We don't want the first href to be 0 */
3336 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3338 for(ref = 0; ref < pRef->number >> 3; ref++) {
3340 unsigned int lib_offs, type_num;
3342 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3344 name += SLTG_ReadStringA(name, &refname);
3345 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3346 FIXME_(typelib)("Can't sscanf ref\n");
3347 if(lib_offs != 0xffff) {
3348 TLBImpLib **import = &pTL->pImpLibs;
3351 if((*import)->offset == lib_offs)
3353 import = &(*import)->next;
3356 char fname[MAX_PATH+1];
3359 *import = heap_alloc_zero(sizeof(**import));
3360 (*import)->offset = lib_offs;
3361 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3363 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3364 &(*import)->wVersionMajor,
3365 &(*import)->wVersionMinor,
3366 &(*import)->lcid, fname) != 4) {
3367 FIXME_(typelib)("can't sscanf ref %s\n",
3368 pNameTable + lib_offs + 40);
3370 len = strlen(fname);
3371 if(fname[len-1] != '#')
3372 FIXME("fname = %s\n", fname);
3373 fname[len-1] = '\0';
3374 (*import)->name = TLB_MultiByteToBSTR(fname);
3376 ref_type->pImpTLInfo = *import;
3378 /* Store a reference to IDispatch */
3379 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3380 pTL->dispatch_href = typelib_ref;
3382 } else { /* internal ref */
3383 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3385 ref_type->reference = typelib_ref;
3386 ref_type->index = type_num;
3389 list_add_tail(&pTL->ref_list, &ref_type->entry);
3391 table->refs[ref] = typelib_ref;
3394 if((BYTE)*name != SLTG_REF_MAGIC)
3395 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3396 dump_TLBRefType(pTL);
3400 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3401 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3403 SLTG_ImplInfo *info;
3404 TLBImplType **ppImplType = &pTI->impltypelist;
3405 /* I don't really get this structure, usually it's 0x16 bytes
3406 long, but iuser.tlb contains some that are 0x18 bytes long.
3407 That's ok because we can use the next ptr to jump to the next
3408 one. But how do we know the length of the last one? The WORD
3409 at offs 0x8 might be the clue. For now I'm just assuming that
3410 the last one is the regular 0x16 bytes. */
3412 info = (SLTG_ImplInfo*)pBlk;
3414 *ppImplType = heap_alloc_zero(sizeof(**ppImplType));
3415 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3416 (*ppImplType)->implflags = info->impltypeflags;
3417 pTI->TypeAttr.cImplTypes++;
3418 ppImplType = &(*ppImplType)->next;
3420 if(info->next == 0xffff)
3423 FIXME_(typelib)("Interface inheriting more than one interface\n");
3424 info = (SLTG_ImplInfo*)(pBlk + info->next);
3426 info++; /* see comment at top of function */
3430 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3431 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3433 TLBVarDesc **ppVarDesc = &pTI->varlist;
3434 BSTR bstrPrevName = NULL;
3435 SLTG_Variable *pItem;
3439 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3440 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3442 *ppVarDesc = heap_alloc_zero(sizeof(**ppVarDesc));
3443 (*ppVarDesc)->vardesc.memid = pItem->memid;
3445 if (pItem->magic != SLTG_VAR_MAGIC &&
3446 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3447 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3451 if (pItem->name == 0xfffe)
3452 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3454 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3456 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3457 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3458 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3460 if(pItem->flags & 0x02)
3461 pType = &pItem->type;
3463 pType = (WORD*)(pBlk + pItem->type);
3465 if (pItem->flags & ~0xda)
3466 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3468 SLTG_DoElem(pType, pBlk,
3469 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3471 if (TRACE_ON(typelib)) {
3473 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3474 TRACE_(typelib)("elemdescVar: %s\n", buf);
3477 if (pItem->flags & 0x40) {
3478 TRACE_(typelib)("VAR_DISPATCH\n");
3479 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3481 else if (pItem->flags & 0x10) {
3482 TRACE_(typelib)("VAR_CONST\n");
3483 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3484 (*ppVarDesc)->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3485 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3486 if (pItem->flags & 0x08)
3487 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3489 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3495 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3497 TRACE_(typelib)("len = %u\n", len);
3498 if (len == 0xffff) {
3501 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3502 str = SysAllocStringLen(NULL, alloc_len);
3503 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3505 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3506 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3515 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3516 *(INT*)(pBlk + pItem->byte_offs);
3519 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3524 TRACE_(typelib)("VAR_PERINSTANCE\n");
3525 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3526 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3529 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3530 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3532 if (pItem->flags & 0x80)
3533 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3535 bstrPrevName = (*ppVarDesc)->Name;
3536 ppVarDesc = &((*ppVarDesc)->next);
3538 pTI->TypeAttr.cVars = cVars;
3541 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3542 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3544 SLTG_Function *pFunc;
3546 TLBFuncDesc *pFuncDesc;
3548 pTI->funcdescs = heap_alloc_zero(cFuncs * sizeof(TLBFuncDesc));
3550 pFuncDesc = pTI->funcdescs;
3551 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs && pFunc != (SLTG_Function*)0xFFFF;
3552 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++, ++pFuncDesc) {
3557 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3558 case SLTG_FUNCTION_MAGIC:
3559 pFuncDesc->funcdesc.funckind = FUNC_PUREVIRTUAL;
3561 case SLTG_DISPATCH_FUNCTION_MAGIC:
3562 pFuncDesc->funcdesc.funckind = FUNC_DISPATCH;
3564 case SLTG_STATIC_FUNCTION_MAGIC:
3565 pFuncDesc->funcdesc.funckind = FUNC_STATIC;
3568 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3571 pFuncDesc->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3573 pFuncDesc->funcdesc.memid = pFunc->dispid;
3574 pFuncDesc->funcdesc.invkind = pFunc->inv >> 4;
3575 pFuncDesc->funcdesc.callconv = pFunc->nacc & 0x7;
3576 pFuncDesc->funcdesc.cParams = pFunc->nacc >> 3;
3577 pFuncDesc->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3578 pFuncDesc->funcdesc.oVft = pFunc->vtblpos & ~1;
3580 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3581 pFuncDesc->funcdesc.wFuncFlags = pFunc->funcflags;
3583 if(pFunc->retnextopt & 0x80)
3584 pType = &pFunc->rettype;
3586 pType = (WORD*)(pBlk + pFunc->rettype);
3588 SLTG_DoElem(pType, pBlk, &pFuncDesc->funcdesc.elemdescFunc, ref_lookup);
3590 pFuncDesc->funcdesc.lprgelemdescParam =
3591 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(ELEMDESC));
3592 pFuncDesc->pParamDesc =
3593 heap_alloc_zero(pFuncDesc->funcdesc.cParams * sizeof(TLBParDesc));
3595 pArg = (WORD*)(pBlk + pFunc->arg_off);
3597 for(param = 0; param < pFuncDesc->funcdesc.cParams; param++) {
3598 char *paramName = pNameTable + *pArg;
3600 /* If arg type follows then paramName points to the 2nd
3601 letter of the name, else the next WORD is an offset to
3602 the arg type and paramName points to the first letter.
3603 So let's take one char off paramName and see if we're
3604 pointing at an alpha-numeric char. However if *pArg is
3605 0xffff or 0xfffe then the param has no name, the former
3606 meaning that the next WORD is the type, the latter
3607 meaning that the next WORD is an offset to the type. */
3612 else if(*pArg == 0xfffe) {
3616 else if(paramName[-1] && !isalnum(paramName[-1]))
3621 if(HaveOffs) { /* the next word is an offset to type */
3622 pType = (WORD*)(pBlk + *pArg);
3623 SLTG_DoElem(pType, pBlk,
3624 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3629 pArg = SLTG_DoElem(pArg, pBlk,
3630 &pFuncDesc->funcdesc.lprgelemdescParam[param], ref_lookup);
3633 /* Are we an optional param ? */
3634 if(pFuncDesc->funcdesc.cParams - param <=
3635 pFuncDesc->funcdesc.cParamsOpt)
3636 pFuncDesc->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3639 pFuncDesc->pParamDesc[param].Name =
3640 TLB_MultiByteToBSTR(paramName);
3642 pFuncDesc->pParamDesc[param].Name =
3643 SysAllocString(pFuncDesc->Name);
3647 pTI->TypeAttr.cFuncs = cFuncs;
3650 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3651 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3652 SLTG_TypeInfoTail *pTITail)
3655 sltg_ref_lookup_t *ref_lookup = NULL;
3657 if(pTIHeader->href_table != 0xffffffff) {
3658 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3664 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3665 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3667 heap_free(ref_lookup);
3671 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3672 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3673 const SLTG_TypeInfoTail *pTITail)
3676 sltg_ref_lookup_t *ref_lookup = NULL;
3678 if(pTIHeader->href_table != 0xffffffff) {
3679 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3685 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3686 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3689 if (pTITail->funcs_off != 0xffff)
3690 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3692 heap_free(ref_lookup);
3694 if (TRACE_ON(typelib))
3695 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3698 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3699 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3700 const SLTG_TypeInfoTail *pTITail)
3702 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3705 static void SLTG_ProcessAlias(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 (pTITail->simple_alias) {
3713 /* if simple alias, no more processing required */
3714 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3718 if(pTIHeader->href_table != 0xffffffff) {
3719 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3723 /* otherwise it is an offset to a type */
3724 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3726 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3728 heap_free(ref_lookup);
3731 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3732 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3733 const SLTG_TypeInfoTail *pTITail)
3735 sltg_ref_lookup_t *ref_lookup = NULL;
3736 if (pTIHeader->href_table != 0xffffffff)
3737 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3740 if (pTITail->vars_off != 0xffff)
3741 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3743 if (pTITail->funcs_off != 0xffff)
3744 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3746 if (pTITail->impls_off != 0xffff)
3747 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3749 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3750 * of dispinterface functions including the IDispatch ones, so
3751 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3752 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3754 heap_free(ref_lookup);
3755 if (TRACE_ON(typelib))
3756 dump_TLBFuncDesc(pTI->funcdescs, pTI->TypeAttr.cFuncs);
3759 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3760 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3761 const SLTG_TypeInfoTail *pTITail)
3763 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3766 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3767 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3768 const SLTG_TypeInfoTail *pTITail)
3770 sltg_ref_lookup_t *ref_lookup = NULL;
3771 if (pTIHeader->href_table != 0xffffffff)
3772 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3775 if (pTITail->vars_off != 0xffff)
3776 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3778 if (pTITail->funcs_off != 0xffff)
3779 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3780 heap_free(ref_lookup);
3781 if (TRACE_ON(typelib))
3785 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3786 managable copy of it into this */
3799 } SLTG_InternalOtherTypeInfo;
3801 /****************************************************************************
3802 * ITypeLib2_Constructor_SLTG
3804 * loading a SLTG typelib from an in-memory image
3806 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3808 ITypeLibImpl *pTypeLibImpl;
3809 SLTG_Header *pHeader;
3810 SLTG_BlkEntry *pBlkEntry;
3814 LPVOID pBlk, pFirstBlk;
3815 SLTG_LibBlk *pLibBlk;
3816 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3817 char *pAfterOTIBlks = NULL;
3818 char *pNameTable, *ptr;
3821 ITypeInfoImpl **ppTypeInfoImpl;
3823 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3826 pTypeLibImpl = TypeLibImpl_Constructor();
3827 if (!pTypeLibImpl) return NULL;
3831 TRACE_(typelib)("header:\n");
3832 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3833 pHeader->nrOfFileBlks );
3834 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3835 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3836 pHeader->SLTG_magic);
3840 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3841 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3843 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3844 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3846 /* Next we have a magic block */
3847 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3849 /* Let's see if we're still in sync */
3850 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3851 sizeof(SLTG_COMPOBJ_MAGIC))) {
3852 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3855 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3856 sizeof(SLTG_DIR_MAGIC))) {
3857 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3861 pIndex = (SLTG_Index*)(pMagic+1);
3863 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3865 pFirstBlk = pPad9 + 1;
3867 /* We'll set up a ptr to the main library block, which is the last one. */
3869 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3870 pBlkEntry[order].next != 0;
3871 order = pBlkEntry[order].next - 1, i++) {
3872 pBlk = (char*)pBlk + pBlkEntry[order].len;
3876 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3878 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3883 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3885 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3888 ptr = (char*)pLibBlk + len;
3890 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3894 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3896 w = *(WORD*)(ptr + 2);
3899 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
3900 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3901 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3903 w = *(WORD*)(ptr + 4 + len);
3905 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3907 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
3908 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3909 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3911 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3912 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3913 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3915 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
3916 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3919 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3920 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3921 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3922 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3923 len += sizeof(SLTG_OtherTypeInfo);
3927 pAfterOTIBlks = ptr;
3929 /* Skip this WORD and get the next DWORD */
3930 len = *(DWORD*)(pAfterOTIBlks + 2);
3932 /* Now add this to pLibBLk look at what we're pointing at and
3933 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3934 dust and we should be pointing at the beginning of the name
3937 pNameTable = (char*)pLibBlk + len;
3939 switch(*(WORD*)pNameTable) {
3946 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3950 pNameTable += 0x216;
3954 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3956 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3959 /* Hopefully we now have enough ptrs set up to actually read in
3960 some TypeInfos. It's not clear which order to do them in, so
3961 I'll just follow the links along the BlkEntry chain and read
3962 them in the order in which they are in the file */
3964 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
3965 ppTypeInfoImpl = pTypeLibImpl->typeinfos;
3967 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3968 pBlkEntry[order].next != 0;
3969 order = pBlkEntry[order].next - 1, i++) {
3971 SLTG_TypeInfoHeader *pTIHeader;
3972 SLTG_TypeInfoTail *pTITail;
3973 SLTG_MemberHeader *pMemHeader;
3975 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3976 pOtherTypeInfoBlks[i].index_name)) {
3977 FIXME_(typelib)("Index strings don't match\n");
3982 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3983 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3986 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3987 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3988 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3990 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
3991 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3992 (*ppTypeInfoImpl)->index = i;
3993 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3994 pOtherTypeInfoBlks[i].name_offs +
3996 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3997 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3998 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3999 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
4000 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
4001 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
4002 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
4004 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
4005 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
4007 if((pTIHeader->typeflags1 & 7) != 2)
4008 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4009 if(pTIHeader->typeflags3 != 2)
4010 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4012 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4013 debugstr_w((*ppTypeInfoImpl)->Name),
4014 typekind_desc[pTIHeader->typekind],
4015 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4016 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4018 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4020 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4022 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4023 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4024 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4026 switch(pTIHeader->typekind) {
4028 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4029 pTIHeader, pTITail);
4033 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4034 pTIHeader, pTITail);
4037 case TKIND_INTERFACE:
4038 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4039 pTIHeader, pTITail);
4043 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4044 pTIHeader, pTITail);
4048 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4049 pTIHeader, pTITail);
4052 case TKIND_DISPATCH:
4053 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4054 pTIHeader, pTITail);
4058 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4059 pTIHeader, pTITail);
4063 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4068 /* could get cFuncs, cVars and cImplTypes from here
4069 but we've already set those */
4070 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4086 pBlk = (char*)pBlk + pBlkEntry[order].len;
4089 if(i != pTypeLibImpl->TypeInfoCount) {
4090 FIXME("Somehow processed %d TypeInfos\n", i);
4094 heap_free(pOtherTypeInfoBlks);
4095 return (ITypeLib2*)pTypeLibImpl;
4098 /* ITypeLib::QueryInterface
4100 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4105 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4107 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4110 if(IsEqualIID(riid, &IID_IUnknown) ||
4111 IsEqualIID(riid,&IID_ITypeLib)||
4112 IsEqualIID(riid,&IID_ITypeLib2))
4119 ITypeLib2_AddRef(iface);
4120 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4123 TRACE("-- Interface: E_NOINTERFACE\n");
4124 return E_NOINTERFACE;
4129 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4131 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4132 ULONG ref = InterlockedIncrement(&This->ref);
4134 TRACE("(%p)->ref was %u\n",This, ref - 1);
4139 /* ITypeLib::Release
4141 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4143 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4144 ULONG ref = InterlockedDecrement(&This->ref);
4146 TRACE("(%p)->(%u)\n",This, ref);
4150 TLBImpLib *pImpLib, *pImpLibNext;
4151 TLBCustData *pCustData, *pCustDataNext;
4152 TLBRefType *ref_type;
4156 /* remove cache entry */
4159 TRACE("removing from cache list\n");
4160 EnterCriticalSection(&cache_section);
4161 if (This->next) This->next->prev = This->prev;
4162 if (This->prev) This->prev->next = This->next;
4163 else tlb_cache_first = This->next;
4164 LeaveCriticalSection(&cache_section);
4165 heap_free(This->path);
4167 TRACE(" destroying ITypeLib(%p)\n",This);
4169 SysFreeString(This->Name);
4172 SysFreeString(This->DocString);
4173 This->DocString = NULL;
4175 SysFreeString(This->HelpFile);
4176 This->HelpFile = NULL;
4178 SysFreeString(This->HelpStringDll);
4179 This->HelpStringDll = NULL;
4181 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4183 VariantClear(&pCustData->data);
4185 pCustDataNext = pCustData->next;
4186 heap_free(pCustData);
4189 for (i = 0; i < This->ctTypeDesc; i++)
4190 if (This->pTypeDesc[i].vt == VT_CARRAY)
4191 heap_free(This->pTypeDesc[i].u.lpadesc);
4193 heap_free(This->pTypeDesc);
4195 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4197 if (pImpLib->pImpTypeLib)
4198 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4199 SysFreeString(pImpLib->name);
4201 pImpLibNext = pImpLib->next;
4205 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4207 list_remove(&ref_type->entry);
4208 heap_free(ref_type);
4211 for (i = 0; i < This->TypeInfoCount; ++i)
4212 ITypeInfoImpl_Destroy(This->typeinfos[i]);
4213 heap_free(This->typeinfos);
4221 /* ITypeLib::GetTypeInfoCount
4223 * Returns the number of type descriptions in the type library
4225 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4227 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4228 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4229 return This->TypeInfoCount;
4232 /* ITypeLib::GetTypeInfo
4234 * retrieves the specified type description in the library.
4236 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4239 ITypeInfo **ppTInfo)
4241 ITypeLibImpl *This = (ITypeLibImpl*)iface;
4243 TRACE("%p %u %p\n", This, index, ppTInfo);
4246 return E_INVALIDARG;
4248 if(index >= This->TypeInfoCount)
4249 return TYPE_E_ELEMENTNOTFOUND;
4251 *ppTInfo = (ITypeInfo*)This->typeinfos[index];
4252 ITypeInfo_AddRef(*ppTInfo);
4258 /* ITypeLibs::GetTypeInfoType
4260 * Retrieves the type of a type description.
4262 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4267 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4269 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4272 return E_INVALIDARG;
4274 if(index >= This->TypeInfoCount)
4275 return TYPE_E_ELEMENTNOTFOUND;
4277 *pTKind = This->typeinfos[index]->TypeAttr.typekind;
4282 /* ITypeLib::GetTypeInfoOfGuid
4284 * Retrieves the type description that corresponds to the specified GUID.
4287 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4290 ITypeInfo **ppTInfo)
4292 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4295 TRACE("%p %s %p\n", This, debugstr_guid(guid), ppTInfo);
4297 for(i = 0; i < This->TypeInfoCount; ++i){
4298 if(IsEqualIID(&This->typeinfos[i]->TypeAttr.guid, guid)){
4299 *ppTInfo = (ITypeInfo*)This->typeinfos[i];
4300 ITypeInfo_AddRef(*ppTInfo);
4305 return TYPE_E_ELEMENTNOTFOUND;
4308 /* ITypeLib::GetLibAttr
4310 * Retrieves the structure that contains the library's attributes.
4313 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4317 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4319 TRACE("(%p, %p)\n", This, attr);
4321 if (!attr) return E_INVALIDARG;
4323 *attr = heap_alloc(sizeof(**attr));
4324 if (!*attr) return E_OUTOFMEMORY;
4326 **attr = This->LibAttr;
4330 /* ITypeLib::GetTypeComp
4332 * Enables a client compiler to bind to a library's types, variables,
4333 * constants, and global functions.
4336 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4338 ITypeComp **ppTComp)
4340 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4342 TRACE("(%p)->(%p)\n",This,ppTComp);
4343 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4344 ITypeComp_AddRef(*ppTComp);
4349 /* ITypeLib::GetDocumentation
4351 * Retrieves the library's documentation string, the complete Help file name
4352 * and path, and the context identifier for the library Help topic in the Help
4355 * On a successful return all non-null BSTR pointers will have been set,
4358 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4362 BSTR *pBstrDocString,
4363 DWORD *pdwHelpContext,
4364 BSTR *pBstrHelpFile)
4366 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4368 HRESULT result = E_INVALIDARG;
4373 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4375 pBstrName, pBstrDocString,
4376 pdwHelpContext, pBstrHelpFile);
4380 /* documentation for the typelib */
4385 if(!(*pBstrName = SysAllocString(This->Name)))
4393 if (This->DocString)
4395 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4398 else if (This->Name)
4400 if(!(*pBstrDocString = SysAllocString(This->Name)))
4404 *pBstrDocString = NULL;
4408 *pdwHelpContext = This->dwHelpContext;
4414 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4418 *pBstrHelpFile = NULL;
4425 /* for a typeinfo */
4426 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4428 if(SUCCEEDED(result))
4430 result = ITypeInfo_GetDocumentation(pTInfo,
4434 pdwHelpContext, pBstrHelpFile);
4436 ITypeInfo_Release(pTInfo);
4441 if (pBstrDocString) SysFreeString (*pBstrDocString);
4443 if (pBstrName) SysFreeString (*pBstrName);
4445 return STG_E_INSUFFICIENTMEMORY;
4450 * Indicates whether a passed-in string contains the name of a type or member
4451 * described in the library.
4454 static HRESULT WINAPI ITypeLib2_fnIsName(
4460 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4462 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR), tic, fdc, pc;
4464 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4468 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4469 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4470 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4471 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4472 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4473 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4474 for(pc=0; pc < pFInfo->funcdesc.cParams; pc++)
4475 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name, nNameBufLen))
4476 goto ITypeLib2_fnIsName_exit;
4478 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4479 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4484 ITypeLib2_fnIsName_exit:
4485 TRACE("(%p)slow! search for %s: %s found!\n", This,
4486 debugstr_w(szNameBuf), *pfName?"NOT":"");
4491 /* ITypeLib::FindName
4493 * Finds occurrences of a type description in a type library. This may be used
4494 * to quickly verify that a name exists in a type library.
4497 static HRESULT WINAPI ITypeLib2_fnFindName(
4501 ITypeInfo **ppTInfo,
4505 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4507 UINT tic, fdc, pc, count = 0;
4508 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4510 for(tic = 0; tic < This->TypeInfoCount; ++tic){
4511 ITypeInfoImpl *pTInfo = This->typeinfos[tic];
4512 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4513 for(fdc = 0; fdc < pTInfo->TypeAttr.cFuncs; ++fdc) {
4514 TLBFuncDesc *pFInfo = &pTInfo->funcdescs[fdc];
4515 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4516 for(pc = 0;pc < pFInfo->funcdesc.cParams; pc++) {
4517 if(!memcmp(szNameBuf,pFInfo->pParamDesc[pc].Name,nNameBufLen))
4518 goto ITypeLib2_fnFindName_exit;
4521 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4522 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4524 ITypeLib2_fnFindName_exit:
4525 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4526 ppTInfo[count]=(LPTYPEINFO)pTInfo;
4529 TRACE("(%p)slow! search for %d with %s: found %d TypeInfos!\n",
4530 This, *pcFound, debugstr_w(szNameBuf), count);
4537 /* ITypeLib::ReleaseTLibAttr
4539 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4542 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4544 TLIBATTR *pTLibAttr)
4546 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4547 TRACE("freeing (%p)\n",This);
4548 heap_free(pTLibAttr);
4552 /* ITypeLib2::GetCustData
4554 * gets the custom data
4556 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4561 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4562 TLBCustData *pCData;
4564 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4566 if( IsEqualIID(guid, &pCData->guid)) break;
4569 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4573 VariantInit( pVarVal);
4574 VariantCopy( pVarVal, &pCData->data);
4577 return E_INVALIDARG; /* FIXME: correct? */
4580 /* ITypeLib2::GetLibStatistics
4582 * Returns statistics about a type library that are required for efficient
4583 * sizing of hash tables.
4586 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4588 ULONG *pcUniqueNames,
4589 ULONG *pcchUniqueNames)
4591 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4593 FIXME("(%p): stub!\n", This);
4595 if(pcUniqueNames) *pcUniqueNames=1;
4596 if(pcchUniqueNames) *pcchUniqueNames=1;
4600 /* ITypeLib2::GetDocumentation2
4602 * Retrieves the library's documentation string, the complete Help file name
4603 * and path, the localization context to use, and the context ID for the
4604 * library Help topic in the Help file.
4607 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4611 BSTR *pbstrHelpString,
4612 DWORD *pdwHelpStringContext,
4613 BSTR *pbstrHelpStringDll)
4615 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4619 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4621 /* the help string should be obtained from the helpstringdll,
4622 * using the _DLLGetDocumentation function, based on the supplied
4623 * lcid. Nice to do sometime...
4627 /* documentation for the typelib */
4629 *pbstrHelpString=SysAllocString(This->DocString);
4630 if(pdwHelpStringContext)
4631 *pdwHelpStringContext=This->dwHelpContext;
4632 if(pbstrHelpStringDll)
4633 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4639 /* for a typeinfo */
4640 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4642 if(SUCCEEDED(result))
4644 ITypeInfo2 * pTInfo2;
4645 result = ITypeInfo_QueryInterface(pTInfo,
4647 (LPVOID*) &pTInfo2);
4649 if(SUCCEEDED(result))
4651 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4655 pdwHelpStringContext,
4656 pbstrHelpStringDll);
4658 ITypeInfo2_Release(pTInfo2);
4661 ITypeInfo_Release(pTInfo);
4667 /* ITypeLib2::GetAllCustData
4669 * Gets all custom data items for the library.
4672 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4674 CUSTDATA *pCustData)
4676 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4677 TLBCustData *pCData;
4679 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4680 pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
4681 if(pCustData->prgCustData ){
4682 pCustData->cCustData=This->ctCustData;
4683 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4684 pCustData->prgCustData[i].guid=pCData->guid;
4685 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4688 ERR(" OUT OF MEMORY!\n");
4689 return E_OUTOFMEMORY;
4694 static const ITypeLib2Vtbl tlbvt = {
4695 ITypeLib2_fnQueryInterface,
4697 ITypeLib2_fnRelease,
4698 ITypeLib2_fnGetTypeInfoCount,
4699 ITypeLib2_fnGetTypeInfo,
4700 ITypeLib2_fnGetTypeInfoType,
4701 ITypeLib2_fnGetTypeInfoOfGuid,
4702 ITypeLib2_fnGetLibAttr,
4703 ITypeLib2_fnGetTypeComp,
4704 ITypeLib2_fnGetDocumentation,
4706 ITypeLib2_fnFindName,
4707 ITypeLib2_fnReleaseTLibAttr,
4709 ITypeLib2_fnGetCustData,
4710 ITypeLib2_fnGetLibStatistics,
4711 ITypeLib2_fnGetDocumentation2,
4712 ITypeLib2_fnGetAllCustData
4716 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4718 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4720 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4723 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4725 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4727 return ITypeLib2_AddRef((ITypeLib2 *)This);
4730 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4732 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4734 return ITypeLib2_Release((ITypeLib2 *)This);
4737 static HRESULT WINAPI ITypeLibComp_fnBind(
4742 ITypeInfo ** ppTInfo,
4743 DESCKIND * pDescKind,
4746 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4747 int typemismatch=0, i;
4749 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4751 *pDescKind = DESCKIND_NONE;
4752 pBindPtr->lptcomp = NULL;
4755 for(i = 0; i < This->TypeInfoCount; ++i){
4756 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4757 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4759 /* FIXME: check wFlags here? */
4760 /* FIXME: we should use a hash table to look this info up using lHash
4761 * instead of an O(n) search */
4762 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4763 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4765 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4767 *pDescKind = DESCKIND_TYPECOMP;
4768 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4769 ITypeComp_AddRef(pBindPtr->lptcomp);
4770 TRACE("module or enum: %s\n", debugstr_w(szName));
4775 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4776 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4778 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4781 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4782 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4784 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4787 else if (hr == TYPE_E_TYPEMISMATCH)
4791 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4792 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4794 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4796 ITypeInfo *subtypeinfo;
4798 DESCKIND subdesckind;
4800 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4801 &subtypeinfo, &subdesckind, &subbindptr);
4802 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4804 TYPEDESC tdesc_appobject;
4805 const VARDESC vardesc_appobject =
4808 NULL, /* lpstrSchema */
4823 VAR_STATIC /* varkind */
4826 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4827 tdesc_appobject.vt = VT_USERDEFINED;
4829 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4831 /* cleanup things filled in by Bind call so we can put our
4832 * application object data in there instead */
4833 switch (subdesckind)
4835 case DESCKIND_FUNCDESC:
4836 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4838 case DESCKIND_VARDESC:
4839 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4844 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4846 if (pTypeInfo->hreftype == -1)
4847 FIXME("no hreftype for interface %p\n", pTypeInfo);
4849 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4853 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4854 *ppTInfo = (ITypeInfo *)pTypeInfo;
4855 ITypeInfo_AddRef(*ppTInfo);
4858 else if (hr == TYPE_E_TYPEMISMATCH)
4865 TRACE("type mismatch %s\n", debugstr_w(szName));
4866 return TYPE_E_TYPEMISMATCH;
4870 TRACE("name not found %s\n", debugstr_w(szName));
4875 static HRESULT WINAPI ITypeLibComp_fnBindType(
4879 ITypeInfo ** ppTInfo,
4880 ITypeComp ** ppTComp)
4882 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4885 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4887 if(!szName || !ppTInfo || !ppTComp)
4888 return E_INVALIDARG;
4890 for(i = 0; i < This->TypeInfoCount; ++i)
4892 ITypeInfoImpl *pTypeInfo = This->typeinfos[i];
4893 /* FIXME: should use lHash to do the search */
4894 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
4896 TRACE("returning %p\n", pTypeInfo);
4897 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4898 ITypeInfo_AddRef(*ppTInfo);
4899 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4900 ITypeComp_AddRef(*ppTComp);
4905 TRACE("not found\n");
4911 static const ITypeCompVtbl tlbtcvt =
4914 ITypeLibComp_fnQueryInterface,
4915 ITypeLibComp_fnAddRef,
4916 ITypeLibComp_fnRelease,
4918 ITypeLibComp_fnBind,
4919 ITypeLibComp_fnBindType
4922 /*================== ITypeInfo(2) Methods ===================================*/
4923 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
4925 ITypeInfoImpl *pTypeInfoImpl;
4927 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
4930 pTypeInfoImpl->lpVtbl = &tinfvt;
4931 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4932 pTypeInfoImpl->ref = 0;
4933 pTypeInfoImpl->hreftype = -1;
4934 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4935 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4937 TRACE("(%p)\n", pTypeInfoImpl);
4938 return pTypeInfoImpl;
4941 /* ITypeInfo::QueryInterface
4943 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4948 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4950 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4953 if(IsEqualIID(riid, &IID_IUnknown) ||
4954 IsEqualIID(riid,&IID_ITypeInfo)||
4955 IsEqualIID(riid,&IID_ITypeInfo2))
4959 ITypeInfo_AddRef(iface);
4960 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4963 TRACE("-- Interface: E_NOINTERFACE\n");
4964 return E_NOINTERFACE;
4967 /* ITypeInfo::AddRef
4969 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4971 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4972 ULONG ref = InterlockedIncrement(&This->ref);
4974 TRACE("(%p)->ref is %u\n",This, ref);
4976 if (ref == 1 /* incremented from 0 */)
4977 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4982 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
4984 TLBVarDesc *pVInfo, *pVInfoNext;
4985 TLBImplType *pImpl, *pImplNext;
4988 TRACE("destroying ITypeInfo(%p)\n",This);
4990 SysFreeString(This->Name);
4993 SysFreeString(This->DocString);
4994 This->DocString = NULL;
4996 SysFreeString(This->DllName);
4997 This->DllName = NULL;
4999 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc)
5002 TLBFuncDesc *pFInfo = &This->funcdescs[fdc];
5003 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
5005 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
5006 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5008 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5009 heap_free(elemdesc->u.paramdesc.pparamdescex);
5011 TLB_FreeCustData(pFInfo->pParamDesc[i].pCustData);
5012 SysFreeString(pFInfo->pParamDesc[i].Name);
5014 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5015 heap_free(pFInfo->pParamDesc);
5016 TLB_FreeCustData(pFInfo->pCustData);
5017 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5018 SysFreeString(pFInfo->Entry);
5019 SysFreeString(pFInfo->HelpString);
5020 SysFreeString(pFInfo->Name);
5022 heap_free(This->funcdescs);
5024 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5026 if (pVInfo->vardesc.varkind == VAR_CONST)
5028 VariantClear(pVInfo->vardesc.u.lpvarValue);
5029 heap_free(pVInfo->vardesc.u.lpvarValue);
5031 TLB_FreeCustData(pVInfo->pCustData);
5032 SysFreeString(pVInfo->Name);
5033 SysFreeString(pVInfo->HelpString);
5034 pVInfoNext = pVInfo->next;
5037 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5039 TLB_FreeCustData(pImpl->pCustData);
5040 pImplNext = pImpl->next;
5043 TLB_FreeCustData(This->pCustData);
5048 /* ITypeInfo::Release
5050 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5052 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5053 ULONG ref = InterlockedDecrement(&This->ref);
5055 TRACE("(%p)->(%u)\n",This, ref);
5059 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5060 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5061 if (not_attached_to_typelib)
5063 /* otherwise This will be freed when typelib is freed */
5069 /* ITypeInfo::GetTypeAttr
5071 * Retrieves a TYPEATTR structure that contains the attributes of the type
5075 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5076 LPTYPEATTR *ppTypeAttr)
5078 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5081 TRACE("(%p)\n",This);
5083 size = sizeof(**ppTypeAttr);
5084 if (This->TypeAttr.typekind == TKIND_ALIAS)
5085 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5087 *ppTypeAttr = heap_alloc(size);
5089 return E_OUTOFMEMORY;
5091 **ppTypeAttr = This->TypeAttr;
5093 if (This->TypeAttr.typekind == TKIND_ALIAS)
5094 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5095 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5097 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5098 /* This should include all the inherited funcs */
5099 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5100 /* This is always the size of IDispatch's vtbl */
5101 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5102 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5107 /* ITypeInfo::GetTypeComp
5109 * Retrieves the ITypeComp interface for the type description, which enables a
5110 * client compiler to bind to the type description's members.
5113 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5114 ITypeComp * *ppTComp)
5116 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5118 TRACE("(%p)->(%p)\n", This, ppTComp);
5120 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5121 ITypeComp_AddRef(*ppTComp);
5125 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5127 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5128 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5129 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5133 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5136 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5137 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5139 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5140 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5141 *buffer += sizeof(PARAMDESCEX);
5142 *pparamdescex_dest = *pparamdescex_src;
5143 VariantInit(&pparamdescex_dest->varDefaultValue);
5144 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5145 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5148 dest->u.paramdesc.pparamdescex = NULL;
5152 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5154 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5155 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5158 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5162 SIZE_T size = sizeof(*src);
5166 size += sizeof(*src->lprgscode) * src->cScodes;
5167 size += TLB_SizeElemDesc(&src->elemdescFunc);
5168 for (i = 0; i < src->cParams; i++)
5170 size += sizeof(ELEMDESC);
5171 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5174 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5175 if (!dest) return E_OUTOFMEMORY;
5178 if (dispinterface) /* overwrite funckind */
5179 dest->funckind = FUNC_DISPATCH;
5180 buffer = (char *)(dest + 1);
5182 dest->lprgscode = (SCODE *)buffer;
5183 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5184 buffer += sizeof(*src->lprgscode) * src->cScodes;
5186 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5189 SysFreeString((BSTR)dest);
5193 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5194 buffer += sizeof(ELEMDESC) * src->cParams;
5195 for (i = 0; i < src->cParams; i++)
5197 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5203 /* undo the above actions */
5204 for (i = i - 1; i >= 0; i--)
5205 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5206 TLB_FreeElemDesc(&dest->elemdescFunc);
5207 SysFreeString((BSTR)dest);
5211 /* special treatment for dispinterfaces: this makes functions appear
5212 * to return their [retval] value when it is really returning an
5214 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5216 if (dest->cParams &&
5217 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5219 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5220 if (elemdesc->tdesc.vt != VT_PTR)
5222 ERR("elemdesc should have started with VT_PTR instead of:\n");
5224 dump_ELEMDESC(elemdesc);
5225 return E_UNEXPECTED;
5228 /* copy last parameter to the return value. we are using a flat
5229 * buffer so there is no danger of leaking memory in
5231 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5233 /* remove the last parameter */
5237 /* otherwise this function is made to appear to have no return
5239 dest->elemdescFunc.tdesc.vt = VT_VOID;
5247 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5249 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5251 if (index >= This->TypeAttr.cFuncs)
5252 return TYPE_E_ELEMENTNOTFOUND;
5254 *ppFuncDesc = &This->funcdescs[index].funcdesc;
5258 /* internal function to make the inherited interfaces' methods appear
5259 * part of the interface */
5260 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5261 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5263 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5265 UINT implemented_funcs = 0;
5270 *hrefoffset = DISPATCH_HREF_OFFSET;
5272 if(This->impltypelist)
5274 ITypeInfo *pSubTypeInfo;
5277 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5281 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5284 &sub_funcs, hrefoffset);
5285 implemented_funcs += sub_funcs;
5286 ITypeInfo_Release(pSubTypeInfo);
5289 *hrefoffset += DISPATCH_HREF_OFFSET;
5293 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5297 if (index < implemented_funcs)
5298 return E_INVALIDARG;
5299 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5303 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5305 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5308 switch (pTypeDesc->vt)
5310 case VT_USERDEFINED:
5311 pTypeDesc->u.hreftype += hrefoffset;
5315 pTypeDesc = pTypeDesc->u.lptdesc;
5318 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5326 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5329 for (i = 0; i < pFuncDesc->cParams; i++)
5330 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5331 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5334 /* ITypeInfo::GetFuncDesc
5336 * Retrieves the FUNCDESC structure that contains information about a
5337 * specified function.
5340 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5341 LPFUNCDESC *ppFuncDesc)
5343 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5344 const FUNCDESC *internal_funcdesc;
5346 UINT hrefoffset = 0;
5348 TRACE("(%p) index %d\n", This, index);
5350 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5351 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5352 &internal_funcdesc, NULL,
5355 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5356 &internal_funcdesc);
5359 WARN("description for function %d not found\n", index);
5363 hr = TLB_AllocAndInitFuncDesc(
5366 This->TypeAttr.typekind == TKIND_DISPATCH);
5368 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5369 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5371 TRACE("-- 0x%08x\n", hr);
5375 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5379 SIZE_T size = sizeof(*src);
5382 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5383 if (src->varkind == VAR_CONST)
5384 size += sizeof(VARIANT);
5385 size += TLB_SizeElemDesc(&src->elemdescVar);
5387 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5388 if (!dest) return E_OUTOFMEMORY;
5391 buffer = (char *)(dest + 1);
5392 if (src->lpstrSchema)
5395 dest->lpstrSchema = (LPOLESTR)buffer;
5396 len = strlenW(src->lpstrSchema);
5397 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5398 buffer += (len + 1) * sizeof(WCHAR);
5401 if (src->varkind == VAR_CONST)
5405 dest->u.lpvarValue = (VARIANT *)buffer;
5406 *dest->u.lpvarValue = *src->u.lpvarValue;
5407 buffer += sizeof(VARIANT);
5408 VariantInit(dest->u.lpvarValue);
5409 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5412 SysFreeString((BSTR)dest);
5416 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5419 if (src->varkind == VAR_CONST)
5420 VariantClear(dest->u.lpvarValue);
5421 SysFreeString((BSTR)dest);
5428 /* ITypeInfo::GetVarDesc
5430 * Retrieves a VARDESC structure that describes the specified variable.
5433 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5434 LPVARDESC *ppVarDesc)
5436 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5438 const TLBVarDesc *pVDesc;
5440 TRACE("(%p) index %d\n", This, index);
5442 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5446 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5448 return E_INVALIDARG;
5451 /* ITypeInfo_GetNames
5453 * Retrieves the variable with the specified member ID (or the name of the
5454 * property or method and its parameters) that correspond to the specified
5457 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5458 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5460 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5461 const TLBFuncDesc *pFDesc;
5462 const TLBVarDesc *pVDesc;
5464 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5465 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
5468 /* function found, now return function and parameter names */
5469 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5472 *rgBstrNames=SysAllocString(pFDesc->Name);
5474 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5480 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5483 *rgBstrNames=SysAllocString(pVDesc->Name);
5488 if(This->impltypelist &&
5489 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5490 /* recursive search */
5493 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5495 if(SUCCEEDED(result))
5497 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5498 ITypeInfo_Release(pTInfo);
5501 WARN("Could not search inherited interface!\n");
5505 WARN("no names found\n");
5508 return TYPE_E_ELEMENTNOTFOUND;
5515 /* ITypeInfo::GetRefTypeOfImplType
5517 * If a type description describes a COM class, it retrieves the type
5518 * description of the implemented interface types. For an interface,
5519 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5523 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5528 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5531 const TLBImplType *pImpl = This->impltypelist;
5533 TRACE("(%p) index %d\n", This, index);
5534 if (TRACE_ON(ole)) dump_TypeInfo(This);
5538 /* only valid on dual interfaces;
5539 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5541 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5543 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5549 hr = TYPE_E_ELEMENTNOTFOUND;
5552 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5554 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5555 *pRefType = This->pTypeLib->dispatch_href;
5559 /* get element n from linked list */
5560 for(i=0; pImpl && i<index; i++)
5562 pImpl = pImpl->next;
5566 *pRefType = pImpl->hRef;
5568 hr = TYPE_E_ELEMENTNOTFOUND;
5574 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5576 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5582 /* ITypeInfo::GetImplTypeFlags
5584 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5585 * or base interface in a type description.
5587 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5588 UINT index, INT *pImplTypeFlags)
5590 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5594 TRACE("(%p) index %d\n", This, index);
5595 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5596 i++, pImpl=pImpl->next)
5598 if(i==index && pImpl){
5599 *pImplTypeFlags=pImpl->implflags;
5604 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5607 WARN("ImplType %d not found\n", index);
5608 return TYPE_E_ELEMENTNOTFOUND;
5612 * Maps between member names and member IDs, and parameter names and
5615 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5616 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5618 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5619 const TLBVarDesc *pVDesc;
5623 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5626 /* init out parameters in case of failure */
5627 for (i = 0; i < cNames; i++)
5628 pMemId[i] = MEMBERID_NIL;
5630 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc) {
5632 const TLBFuncDesc *pFDesc = &This->funcdescs[fdc];
5633 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5634 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5635 for(i=1; i < cNames; i++){
5636 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5637 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5639 if( j<pFDesc->funcdesc.cParams)
5642 ret=DISP_E_UNKNOWNNAME;
5644 TRACE("-- 0x%08x\n", ret);
5648 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5649 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5650 if(cNames) *pMemId=pVDesc->vardesc.memid;
5654 /* not found, see if it can be found in an inherited interface */
5655 if(This->impltypelist) {
5656 /* recursive search */
5658 ret=ITypeInfo_GetRefTypeInfo(iface,
5659 This->impltypelist->hRef, &pTInfo);
5661 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5662 ITypeInfo_Release(pTInfo);
5665 WARN("Could not search inherited interface!\n");
5667 WARN("no names found\n");
5668 return DISP_E_UNKNOWNNAME;
5674 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5675 __ASM_GLOBAL_FUNC( call_method,
5677 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5678 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5679 "movl %esp,%ebp\n\t"
5680 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5682 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5684 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5685 "movl 12(%ebp),%edx\n\t"
5686 "movl %esp,%edi\n\t"
5689 "subl %edx,%edi\n\t"
5690 "andl $~15,%edi\n\t"
5691 "movl %edi,%esp\n\t"
5692 "movl 12(%ebp),%ecx\n\t"
5693 "movl 16(%ebp),%esi\n\t"
5696 "1:\tcall *8(%ebp)\n\t"
5697 "subl %esp,%edi\n\t"
5698 "movl 20(%ebp),%ecx\n\t"
5699 "movl %edi,(%ecx)\n\t"
5700 "leal -8(%ebp),%esp\n\t"
5702 __ASM_CFI(".cfi_same_value %edi\n\t")
5704 __ASM_CFI(".cfi_same_value %esi\n\t")
5706 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5707 __ASM_CFI(".cfi_same_value %ebp\n\t")
5710 /* same function but returning floating point */
5711 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5713 /* ITypeInfo::Invoke
5715 * Invokes a method, or accesses a property of an object, that implements the
5716 * interface described by the type description.
5719 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5723 if (TRACE_ON(ole)) {
5725 TRACE("Calling %p(",func);
5726 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5727 if (nrargs > 30) TRACE("...");
5734 res = call_method( func, nrargs, args, &stack_offset );
5737 FIXME("unsupported calling convention %d\n",callconv);
5741 TRACE("returns %08x\n",res);
5745 #elif defined(__x86_64__)
5747 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5748 __ASM_GLOBAL_FUNC( call_method,
5750 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5751 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5752 "movq %rsp,%rbp\n\t"
5753 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5755 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5757 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5758 "movq %rcx,%rax\n\t"
5761 "cmovgq %rdx,%rcx\n\t"
5762 "leaq 0(,%rcx,8),%rdx\n\t"
5763 "subq %rdx,%rsp\n\t"
5764 "andq $~15,%rsp\n\t"
5765 "movq %rsp,%rdi\n\t"
5768 "movq 0(%rsp),%rcx\n\t"
5769 "movq 8(%rsp),%rdx\n\t"
5770 "movq 16(%rsp),%r8\n\t"
5771 "movq 24(%rsp),%r9\n\t"
5772 "movq %rcx,%xmm0\n\t"
5773 "movq %rdx,%xmm1\n\t"
5774 "movq %r8,%xmm2\n\t"
5775 "movq %r9,%xmm3\n\t"
5777 "leaq -16(%rbp),%rsp\n\t"
5779 __ASM_CFI(".cfi_same_value %rdi\n\t")
5781 __ASM_CFI(".cfi_same_value %rsi\n\t")
5782 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5784 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5785 __ASM_CFI(".cfi_same_value %rbp\n\t")
5788 /* same function but returning floating point */
5789 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5791 #endif /* __x86_64__ */
5793 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5796 ITypeInfo *tinfo2 = NULL;
5797 TYPEATTR *tattr = NULL;
5799 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5802 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5804 tdesc->u.hreftype, hr);
5807 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5810 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5811 ITypeInfo_Release(tinfo2);
5815 switch (tattr->typekind)
5822 tdesc = &tattr->tdescAlias;
5823 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5826 case TKIND_INTERFACE:
5827 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5833 case TKIND_DISPATCH:
5842 FIXME("TKIND_RECORD unhandled.\n");
5847 FIXME("TKIND_UNION unhandled.\n");
5852 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5856 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5857 ITypeInfo_Release(tinfo2);
5861 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5865 /* enforce only one level of pointer indirection */
5866 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5868 tdesc = tdesc->u.lptdesc;
5870 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5871 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5872 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5873 if ((tdesc->vt == VT_USERDEFINED) ||
5874 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5876 VARTYPE vt_userdefined = 0;
5877 const TYPEDESC *tdesc_userdefined = tdesc;
5878 if (tdesc->vt == VT_PTR)
5880 vt_userdefined = VT_BYREF;
5881 tdesc_userdefined = tdesc->u.lptdesc;
5883 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5885 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5886 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5888 *vt |= vt_userdefined;
5900 case VT_USERDEFINED:
5901 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5908 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5909 hr = DISP_E_BADVARTYPE;
5913 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5928 /***********************************************************************
5929 * DispCallFunc (OLEAUT32.@)
5931 * Invokes a function of the specified calling convention, passing the
5932 * specified arguments and returns the result.
5935 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5936 * oVft [I] The offset in the vtable. See notes.
5937 * cc [I] Calling convention of the function to call.
5938 * vtReturn [I] The return type of the function.
5939 * cActuals [I] Number of parameters.
5940 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5941 * prgpvarg [I] The arguments to pass.
5942 * pvargResult [O] The return value of the function. Can be NULL.
5946 * Failure: HRESULT code.
5949 * The HRESULT return value of this function is not affected by the return
5950 * value of the user supplied function, which is returned in pvargResult.
5952 * If pvInstance is NULL then a non-object function is to be called and oVft
5953 * is the address of the function to call.
5955 * The cc parameter can be one of the following values:
5968 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5969 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5972 int argspos, stack_offset;
5977 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5978 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5979 pvargResult, V_VT(pvargResult));
5981 if (cc != CC_STDCALL && cc != CC_CDECL)
5983 FIXME("unsupported calling convention %d\n",cc);
5984 return E_INVALIDARG;
5987 /* maximum size for an argument is sizeof(VARIANT) */
5988 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
5990 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
5994 const FARPROC *vtable = *(FARPROC **)pvInstance;
5995 func = vtable[oVft/sizeof(void *)];
5996 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5998 else func = (void *)oVft;
6000 for (i = 0; i < cActuals; i++)
6002 VARIANT *arg = prgpvarg[i];
6013 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6014 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6018 memcpy( &args[argspos], arg, sizeof(*arg) );
6019 argspos += sizeof(*arg) / sizeof(DWORD);
6021 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6022 args[argspos++] = V_BOOL(arg);
6025 args[argspos++] = V_UI4(arg);
6028 TRACE("arg %u: type %d\n",i,prgvt[i]);
6035 call_method( func, argspos - 1, args + 1, &stack_offset );
6038 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6042 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6046 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6047 call_method( func, argspos, args, &stack_offset );
6052 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6055 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6059 if (stack_offset && cc == CC_STDCALL)
6061 WARN( "stack pointer off by %d\n", stack_offset );
6062 return DISP_E_BADCALLEE;
6064 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6065 TRACE("retval: "); dump_Variant(pvargResult);
6068 #elif defined(__x86_64__)
6074 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6075 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6076 pvargResult, V_VT(pvargResult));
6078 if (cc != CC_STDCALL && cc != CC_CDECL)
6080 FIXME("unsupported calling convention %d\n",cc);
6081 return E_INVALIDARG;
6084 /* maximum size for an argument is sizeof(DWORD_PTR) */
6085 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6087 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6091 const FARPROC *vtable = *(FARPROC **)pvInstance;
6092 func = vtable[oVft/sizeof(void *)];
6093 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6095 else func = (void *)oVft;
6097 for (i = 0; i < cActuals; i++)
6099 VARIANT *arg = prgpvarg[i];
6105 args[argspos++] = (ULONG_PTR)arg;
6107 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6108 args[argspos++] = V_BOOL(arg);
6111 args[argspos++] = V_UI8(arg);
6114 TRACE("arg %u: type %d\n",i,prgvt[i]);
6121 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6125 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6129 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6130 call_method( func, argspos, args );
6133 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6137 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6138 TRACE("retval: "); dump_Variant(pvargResult);
6142 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6143 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6148 #define INVBUF_ELEMENT_SIZE \
6149 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6150 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6151 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6152 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6153 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6154 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6155 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6156 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6158 static HRESULT WINAPI ITypeInfo_fnInvoke(
6163 DISPPARAMS *pDispParams,
6164 VARIANT *pVarResult,
6165 EXCEPINFO *pExcepInfo,
6168 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6170 unsigned int var_index;
6173 const TLBFuncDesc *pFuncInfo;
6176 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6177 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6180 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6181 return DISP_E_MEMBERNOTFOUND;
6185 ERR("NULL pDispParams not allowed\n");
6186 return E_INVALIDARG;
6189 dump_DispParms(pDispParams);
6191 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6193 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6194 pDispParams->cNamedArgs, pDispParams->cArgs);
6195 return E_INVALIDARG;
6198 /* we do this instead of using GetFuncDesc since it will return a fake
6199 * FUNCDESC for dispinterfaces and we want the real function description */
6200 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
6201 pFuncInfo = &This->funcdescs[fdc];
6202 if ((memid == pFuncInfo->funcdesc.memid) &&
6203 (wFlags & pFuncInfo->funcdesc.invkind) &&
6204 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6208 if (fdc < This->TypeAttr.cFuncs) {
6209 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6213 TRACE("invoking:\n");
6214 dump_TLBFuncDescOne(pFuncInfo);
6217 switch (func_desc->funckind) {
6218 case FUNC_PUREVIRTUAL:
6219 case FUNC_VIRTUAL: {
6220 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6222 VARIANT retval; /* pointer for storing byref retvals in */
6223 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6224 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6225 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6226 UINT cNamedArgs = pDispParams->cNamedArgs;
6227 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6228 UINT vargs_converted=0;
6232 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6234 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6236 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6237 hres = DISP_E_PARAMNOTFOUND;
6242 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6244 ERR("functions with the vararg attribute do not support named arguments\n");
6245 hres = DISP_E_NONAMEDARGS;
6249 for (i = 0; i < func_desc->cParams; i++)
6251 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6252 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6257 TRACE("changing args\n");
6258 for (i = 0; i < func_desc->cParams; i++)
6260 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6261 VARIANTARG *src_arg;
6263 if (wParamFlags & PARAMFLAG_FLCID)
6266 arg = prgpvarg[i] = &rgvarg[i];
6268 V_I4(arg) = This->pTypeLib->lcid;
6277 for (j = 0; j < cNamedArgs; j++)
6278 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6280 src_arg = &pDispParams->rgvarg[j];
6285 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6287 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6291 if (wParamFlags & PARAMFLAG_FRETVAL)
6293 /* under most conditions the caller is not allowed to
6294 * pass in a dispparam arg in the index of what would be
6295 * the retval parameter. however, there is an exception
6296 * where the extra parameter is used in an extra
6297 * IDispatch::Invoke below */
6298 if ((i < pDispParams->cArgs) &&
6299 ((func_desc->cParams != 1) || !pVarResult ||
6300 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6302 hres = DISP_E_BADPARAMCOUNT;
6306 /* note: this check is placed so that if the caller passes
6307 * in a VARIANTARG for the retval we just ignore it, like
6309 if (i == func_desc->cParams - 1)
6312 arg = prgpvarg[i] = &rgvarg[i];
6313 memset(arg, 0, sizeof(*arg));
6314 V_VT(arg) = rgvt[i];
6315 memset(&retval, 0, sizeof(retval));
6316 V_BYREF(arg) = &retval;
6320 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6321 hres = E_UNEXPECTED;
6327 dump_Variant(src_arg);
6329 if (rgvt[i] == VT_VARIANT)
6330 hres = VariantCopy(&rgvarg[i], src_arg);
6331 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6333 if (rgvt[i] == V_VT(src_arg))
6334 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6337 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6338 if (wParamFlags & PARAMFLAG_FIN)
6339 hres = VariantCopy(&missing_arg[i], src_arg);
6340 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6342 V_VT(&rgvarg[i]) = rgvt[i];
6344 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6347 SAFEARRAYBOUND bound;
6351 bound.cElements = pDispParams->cArgs-i;
6352 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6354 ERR("SafeArrayCreate failed\n");
6357 hres = SafeArrayAccessData(a, (LPVOID)&v);
6360 ERR("SafeArrayAccessData failed with %x\n", hres);
6363 for (j = 0; j < bound.cElements; j++)
6364 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6365 hres = SafeArrayUnaccessData(a);
6368 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6371 V_ARRAY(&rgvarg[i]) = a;
6372 V_VT(&rgvarg[i]) = rgvt[i];
6374 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6376 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6377 if (wParamFlags & PARAMFLAG_FIN)
6378 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6380 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6381 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6382 V_VT(&rgvarg[i]) = rgvt[i];
6384 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6386 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6387 V_VT(&rgvarg[i]) = rgvt[i];
6391 /* FIXME: this doesn't work for VT_BYREF arguments if
6392 * they are not the same type as in the paramdesc */
6393 V_VT(&rgvarg[i]) = V_VT(src_arg);
6394 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6395 V_VT(&rgvarg[i]) = rgvt[i];
6400 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6401 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6402 debugstr_VT(src_arg), debugstr_VF(src_arg));
6405 prgpvarg[i] = &rgvarg[i];
6407 else if (wParamFlags & PARAMFLAG_FOPT)
6410 arg = prgpvarg[i] = &rgvarg[i];
6411 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6413 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6419 VARIANTARG *missing_arg;
6420 /* if the function wants a pointer to a variant then
6421 * set that up, otherwise just pass the VT_ERROR in
6422 * the argument by value */
6423 if (rgvt[i] & VT_BYREF)
6425 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6426 V_VT(arg) = VT_VARIANT | VT_BYREF;
6427 V_VARIANTREF(arg) = missing_arg;
6431 V_VT(missing_arg) = VT_ERROR;
6432 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6437 hres = DISP_E_BADPARAMCOUNT;
6441 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6443 /* VT_VOID is a special case for return types, so it is not
6444 * handled in the general function */
6445 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6446 V_VT(&varresult) = VT_EMPTY;
6449 V_VT(&varresult) = 0;
6450 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6451 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6454 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6455 V_VT(&varresult), func_desc->cParams, rgvt,
6456 prgpvarg, &varresult);
6458 vargs_converted = 0;
6460 for (i = 0; i < func_desc->cParams; i++)
6462 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6463 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6465 if (wParamFlags & PARAMFLAG_FLCID)
6467 else if (wParamFlags & PARAMFLAG_FRETVAL)
6471 TRACE("[retval] value: ");
6472 dump_Variant(prgpvarg[i]);
6477 VariantInit(pVarResult);
6478 /* deref return value */
6479 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6482 VARIANT_ClearInd(prgpvarg[i]);
6484 else if (vargs_converted < pDispParams->cArgs)
6486 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6487 if (wParamFlags & PARAMFLAG_FOUT)
6489 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6491 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6495 ERR("failed to convert param %d to vt %d\n", i,
6496 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6501 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6502 func_desc->cParamsOpt < 0 &&
6503 i == func_desc->cParams-1)
6505 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6508 hres = SafeArrayGetUBound(a, 1, &ubound);
6511 ERR("SafeArrayGetUBound failed with %x\n", hres);
6514 hres = SafeArrayAccessData(a, (LPVOID)&v);
6517 ERR("SafeArrayAccessData failed with %x\n", hres);
6520 for (j = 0; j <= ubound; j++)
6521 VariantClear(&v[j]);
6522 hres = SafeArrayUnaccessData(a);
6525 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6529 VariantClear(&rgvarg[i]);
6532 else if (wParamFlags & PARAMFLAG_FOPT)
6534 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6535 VariantClear(&rgvarg[i]);
6538 VariantClear(&missing_arg[i]);
6541 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6543 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6544 hres = DISP_E_EXCEPTION;
6547 IErrorInfo *pErrorInfo;
6548 pExcepInfo->scode = V_ERROR(&varresult);
6549 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6551 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6552 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6553 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6554 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6556 IErrorInfo_Release(pErrorInfo);
6560 if (V_VT(&varresult) != VT_ERROR)
6562 TRACE("varresult value: ");
6563 dump_Variant(&varresult);
6567 VariantClear(pVarResult);
6568 *pVarResult = varresult;
6571 VariantClear(&varresult);
6574 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6575 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6576 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6577 (pDispParams->cArgs != 0))
6579 if (V_VT(pVarResult) == VT_DISPATCH)
6581 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6582 /* Note: not VariantClear; we still need the dispatch
6583 * pointer to be valid */
6584 VariantInit(pVarResult);
6585 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6586 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6587 pDispParams, pVarResult, pExcepInfo, pArgErr);
6588 IDispatch_Release(pDispatch);
6592 VariantClear(pVarResult);
6593 hres = DISP_E_NOTACOLLECTION;
6601 case FUNC_DISPATCH: {
6604 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6605 if (SUCCEEDED(hres)) {
6606 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6607 hres = IDispatch_Invoke(
6608 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6609 pVarResult,pExcepInfo,pArgErr
6612 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6613 IDispatch_Release(disp);
6615 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6619 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6624 TRACE("-- 0x%08x\n", hres);
6627 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6630 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6631 if(FAILED(hres)) return hres;
6633 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6634 dump_VARDESC(var_desc);
6635 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6639 /* not found, look for it in inherited interfaces */
6640 ITypeInfo2_GetTypeKind(iface, &type_kind);
6641 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6642 if(This->impltypelist) {
6643 /* recursive search */
6645 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6646 if(SUCCEEDED(hres)){
6647 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6648 ITypeInfo_Release(pTInfo);
6651 WARN("Could not search inherited interface!\n");
6654 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6655 return DISP_E_MEMBERNOTFOUND;
6658 /* ITypeInfo::GetDocumentation
6660 * Retrieves the documentation string, the complete Help file name and path,
6661 * and the context ID for the Help topic for a specified type description.
6663 * (Can be tested by the Visual Basic Editor in Word for instance.)
6665 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6666 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6667 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6669 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6670 const TLBFuncDesc *pFDesc;
6671 const TLBVarDesc *pVDesc;
6672 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6673 " HelpContext(%p) HelpFile(%p)\n",
6674 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6675 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6677 *pBstrName=SysAllocString(This->Name);
6679 *pBstrDocString=SysAllocString(This->DocString);
6681 *pdwHelpContext=This->dwHelpContext;
6683 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6685 }else {/* for a member */
6686 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6689 *pBstrName = SysAllocString(pFDesc->Name);
6691 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6693 *pdwHelpContext=pFDesc->helpcontext;
6696 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6697 if(pVDesc->vardesc.memid==memid){
6699 *pBstrName = SysAllocString(pVDesc->Name);
6701 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6703 *pdwHelpContext=pVDesc->HelpContext;
6708 if(This->impltypelist &&
6709 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6710 /* recursive search */
6713 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6715 if(SUCCEEDED(result)) {
6716 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6717 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6718 ITypeInfo_Release(pTInfo);
6721 WARN("Could not search inherited interface!\n");
6724 WARN("member %d not found\n", memid);
6725 return TYPE_E_ELEMENTNOTFOUND;
6728 /* ITypeInfo::GetDllEntry
6730 * Retrieves a description or specification of an entry point for a function
6733 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6734 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6737 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6738 const TLBFuncDesc *pFDesc;
6740 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6742 if (pBstrDllName) *pBstrDllName = NULL;
6743 if (pBstrName) *pBstrName = NULL;
6744 if (pwOrdinal) *pwOrdinal = 0;
6746 if (This->TypeAttr.typekind != TKIND_MODULE)
6747 return TYPE_E_BADMODULEKIND;
6749 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
6751 dump_TypeInfo(This);
6753 dump_TLBFuncDescOne(pFDesc);
6756 *pBstrDllName = SysAllocString(This->DllName);
6758 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6760 *pBstrName = SysAllocString(pFDesc->Entry);
6768 *pwOrdinal = LOWORD(pFDesc->Entry);
6771 return TYPE_E_ELEMENTNOTFOUND;
6774 /* internal function to make the inherited interfaces' methods appear
6775 * part of the interface */
6776 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6777 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6779 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6782 TRACE("%p, 0x%x\n", iface, *hRefType);
6784 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6786 ITypeInfo *pSubTypeInfo;
6788 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6792 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6794 ITypeInfo_Release(pSubTypeInfo);
6798 *hRefType -= DISPATCH_HREF_OFFSET;
6800 if (!(*hRefType & DISPATCH_HREF_MASK))
6801 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6806 /* ITypeInfo::GetRefTypeInfo
6808 * If a type description references other type descriptions, it retrieves
6809 * the referenced type descriptions.
6811 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6814 ITypeInfo **ppTInfo)
6816 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6817 HRESULT result = E_FAIL;
6819 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6821 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6822 ITypeInfo_AddRef(*ppTInfo);
6825 else if (hRefType == -1 &&
6826 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6827 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6829 /* when we meet a DUAL dispinterface, we must create the interface
6832 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
6835 /* the interface version contains the same information as the dispinterface
6836 * copy the contents of the structs.
6838 *pTypeInfoImpl = *This;
6839 pTypeInfoImpl->ref = 0;
6841 /* change the type to interface */
6842 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6844 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6846 /* the AddRef implicitly adds a reference to the parent typelib, which
6847 * stops the copied data from being destroyed until the new typeinfo's
6848 * refcount goes to zero, but we need to signal to the new instance to
6849 * not free its data structures when it is destroyed */
6850 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6852 ITypeInfo_AddRef(*ppTInfo);
6856 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6857 (This->TypeAttr.typekind == TKIND_DISPATCH))
6859 HREFTYPE href_dispatch = hRefType;
6860 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6862 TLBRefType *ref_type;
6863 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6865 if(ref_type->reference == hRefType)
6868 if(&ref_type->entry == &This->pTypeLib->ref_list)
6870 FIXME("Can't find pRefType for ref %x\n", hRefType);
6873 if(hRefType != -1) {
6874 ITypeLib *pTLib = NULL;
6876 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6878 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6880 if(ref_type->pImpTLInfo->pImpTypeLib) {
6881 TRACE("typeinfo in imported typelib that is already loaded\n");
6882 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6883 ITypeLib2_AddRef(pTLib);
6886 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6887 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6888 ref_type->pImpTLInfo->wVersionMajor,
6889 ref_type->pImpTLInfo->wVersionMinor,
6890 ref_type->pImpTLInfo->lcid,
6893 if(FAILED(result)) {
6894 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6895 result=LoadTypeLib(libnam, &pTLib);
6896 SysFreeString(libnam);
6898 if(SUCCEEDED(result)) {
6899 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6900 ITypeLib2_AddRef(pTLib);
6904 if(SUCCEEDED(result)) {
6905 if(ref_type->index == TLB_REF_USE_GUID)
6906 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6910 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6914 ITypeLib2_Release(pTLib);
6919 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6920 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6924 /* ITypeInfo::AddressOfMember
6926 * Retrieves the addresses of static functions or variables, such as those
6929 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6930 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6932 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6938 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6940 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6944 module = LoadLibraryW(dll);
6947 ERR("couldn't load %s\n", debugstr_w(dll));
6949 SysFreeString(entry);
6950 return STG_E_FILENOTFOUND;
6952 /* FIXME: store library somewhere where we can free it */
6957 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6958 entryA = heap_alloc(len);
6959 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6961 *ppv = GetProcAddress(module, entryA);
6963 ERR("function not found %s\n", debugstr_a(entryA));
6969 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6971 ERR("function not found %d\n", ordinal);
6975 SysFreeString(entry);
6978 return TYPE_E_DLLFUNCTIONNOTFOUND;
6983 /* ITypeInfo::CreateInstance
6985 * Creates a new instance of a type that describes a component object class
6988 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6989 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6991 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6995 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7001 WARN("Not able to aggregate\n");
7002 return CLASS_E_NOAGGREGATION;
7005 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
7006 if(FAILED(hr)) return hr;
7008 if(pTA->typekind != TKIND_COCLASS)
7010 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7016 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7019 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7020 TRACE("GetActiveObject rets %08x\n", hr);
7023 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7024 IUnknown_Release(pUnk);
7029 hr = CoCreateInstance(&pTA->guid, NULL,
7030 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7034 ITypeInfo_ReleaseTypeAttr(iface, pTA);
7038 /* ITypeInfo::GetMops
7040 * Retrieves marshalling information.
7042 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7045 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7046 FIXME("(%p %d) stub!\n", This, memid);
7051 /* ITypeInfo::GetContainingTypeLib
7053 * Retrieves the containing type library and the index of the type description
7054 * within that type library.
7056 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7057 ITypeLib * *ppTLib, UINT *pIndex)
7059 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7061 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7063 *pIndex=This->index;
7064 TRACE("returning pIndex=%d\n", *pIndex);
7068 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7069 ITypeLib2_AddRef(*ppTLib);
7070 TRACE("returning ppTLib=%p\n", *ppTLib);
7076 /* ITypeInfo::ReleaseTypeAttr
7078 * Releases a TYPEATTR previously returned by GetTypeAttr.
7081 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7082 TYPEATTR* pTypeAttr)
7084 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7085 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7086 heap_free(pTypeAttr);
7089 /* ITypeInfo::ReleaseFuncDesc
7091 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7093 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7095 FUNCDESC *pFuncDesc)
7097 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7100 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7102 for (i = 0; i < pFuncDesc->cParams; i++)
7103 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7104 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7106 SysFreeString((BSTR)pFuncDesc);
7109 /* ITypeInfo::ReleaseVarDesc
7111 * Releases a VARDESC previously returned by GetVarDesc.
7113 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7116 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7117 TRACE("(%p)->(%p)\n", This, pVarDesc);
7119 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7120 if (pVarDesc->varkind == VAR_CONST)
7121 VariantClear(pVarDesc->u.lpvarValue);
7122 SysFreeString((BSTR)pVarDesc);
7125 /* ITypeInfo2::GetTypeKind
7127 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7130 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7131 TYPEKIND *pTypeKind)
7133 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7134 *pTypeKind=This->TypeAttr.typekind;
7135 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7139 /* ITypeInfo2::GetTypeFlags
7141 * Returns the type flags without any allocations. This returns a DWORD type
7142 * flag, which expands the type flags without growing the TYPEATTR (type
7146 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7148 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7149 *pTypeFlags=This->TypeAttr.wTypeFlags;
7150 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7154 /* ITypeInfo2::GetFuncIndexOfMemId
7155 * Binds to a specific member based on a known DISPID, where the member name
7156 * is not known (for example, when binding to a default member).
7159 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7160 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7162 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7166 for (fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7167 const TLBFuncDesc *pFuncInfo = &This->funcdescs[fdc];
7168 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7171 if(fdc < This->TypeAttr.cFuncs) {
7175 result = TYPE_E_ELEMENTNOTFOUND;
7177 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7178 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7182 /* TypeInfo2::GetVarIndexOfMemId
7184 * Binds to a specific member based on a known DISPID, where the member name
7185 * is not known (for example, when binding to a default member).
7188 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7189 MEMBERID memid, UINT *pVarIndex)
7191 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7192 TLBVarDesc *pVarInfo;
7195 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7196 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7202 result = TYPE_E_ELEMENTNOTFOUND;
7204 TRACE("(%p) memid 0x%08x -> %s\n", This,
7205 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7209 /* ITypeInfo2::GetCustData
7211 * Gets the custom data
7213 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7218 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7219 TLBCustData *pCData;
7221 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7222 if( IsEqualIID(guid, &pCData->guid)) break;
7224 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7226 VariantInit( pVarVal);
7228 VariantCopy( pVarVal, &pCData->data);
7230 VariantClear( pVarVal );
7234 /* ITypeInfo2::GetFuncCustData
7236 * Gets the custom data
7238 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7244 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7245 TLBCustData *pCData=NULL;
7246 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7248 if(index >= This->TypeAttr.cFuncs)
7249 return TYPE_E_ELEMENTNOTFOUND;
7251 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7252 if( IsEqualIID(guid, &pCData->guid)) break;
7254 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7257 VariantInit( pVarVal);
7258 VariantCopy( pVarVal, &pCData->data);
7261 return TYPE_E_ELEMENTNOTFOUND;
7264 /* ITypeInfo2::GetParamCustData
7266 * Gets the custom data
7268 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7275 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7276 TLBCustData *pCData;
7277 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7279 if(indexFunc >= This->TypeAttr.cFuncs)
7280 return TYPE_E_ELEMENTNOTFOUND;
7282 if(indexParam >= pFDesc->funcdesc.cParams)
7283 return TYPE_E_ELEMENTNOTFOUND;
7285 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7286 pCData = pCData->next)
7287 if( IsEqualIID(guid, &pCData->guid)) break;
7289 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7293 VariantInit( pVarVal);
7294 VariantCopy( pVarVal, &pCData->data);
7297 return TYPE_E_ELEMENTNOTFOUND;
7300 /* ITypeInfo2::GetVarCustData
7302 * Gets the custom data
7304 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7310 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7311 TLBCustData *pCData=NULL;
7312 TLBVarDesc * pVDesc;
7315 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7319 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7321 if( IsEqualIID(guid, &pCData->guid)) break;
7325 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7329 VariantInit( pVarVal);
7330 VariantCopy( pVarVal, &pCData->data);
7333 return E_INVALIDARG; /* FIXME: correct? */
7336 /* ITypeInfo2::GetImplCustData
7338 * Gets the custom data
7340 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7346 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7347 TLBCustData *pCData=NULL;
7348 TLBImplType * pRDesc;
7351 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7355 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7357 if( IsEqualIID(guid, &pCData->guid)) break;
7361 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7365 VariantInit( pVarVal);
7366 VariantCopy( pVarVal, &pCData->data);
7369 return E_INVALIDARG; /* FIXME: correct? */
7372 /* ITypeInfo2::GetDocumentation2
7374 * Retrieves the documentation string, the complete Help file name and path,
7375 * the localization context to use, and the context ID for the library Help
7376 * topic in the Help file.
7379 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7383 BSTR *pbstrHelpString,
7384 DWORD *pdwHelpStringContext,
7385 BSTR *pbstrHelpStringDll)
7387 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7388 const TLBFuncDesc *pFDesc;
7389 const TLBVarDesc *pVDesc;
7390 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7391 "HelpStringContext(%p) HelpStringDll(%p)\n",
7392 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7393 pbstrHelpStringDll );
7394 /* the help string should be obtained from the helpstringdll,
7395 * using the _DLLGetDocumentation function, based on the supplied
7396 * lcid. Nice to do sometime...
7398 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7400 *pbstrHelpString=SysAllocString(This->Name);
7401 if(pdwHelpStringContext)
7402 *pdwHelpStringContext=This->dwHelpStringContext;
7403 if(pbstrHelpStringDll)
7404 *pbstrHelpStringDll=
7405 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7407 }else {/* for a member */
7408 pFDesc = TLB_get_funcdesc_by_memberid(This->funcdescs, This->TypeAttr.cFuncs, memid);
7411 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7412 if(pdwHelpStringContext)
7413 *pdwHelpStringContext=pFDesc->HelpStringContext;
7414 if(pbstrHelpStringDll)
7415 *pbstrHelpStringDll=
7416 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7419 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7420 if(pVDesc->vardesc.memid==memid){
7422 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7423 if(pdwHelpStringContext)
7424 *pdwHelpStringContext=pVDesc->HelpStringContext;
7425 if(pbstrHelpStringDll)
7426 *pbstrHelpStringDll=
7427 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7431 return TYPE_E_ELEMENTNOTFOUND;
7434 /* ITypeInfo2::GetAllCustData
7436 * Gets all custom data items for the Type info.
7439 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7441 CUSTDATA *pCustData)
7443 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7444 TLBCustData *pCData;
7447 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7449 pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
7450 if(pCustData->prgCustData ){
7451 pCustData->cCustData=This->ctCustData;
7452 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7453 pCustData->prgCustData[i].guid=pCData->guid;
7454 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7457 ERR(" OUT OF MEMORY!\n");
7458 return E_OUTOFMEMORY;
7463 /* ITypeInfo2::GetAllFuncCustData
7465 * Gets all custom data items for the specified Function
7468 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7471 CUSTDATA *pCustData)
7473 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7474 TLBCustData *pCData;
7475 TLBFuncDesc *pFDesc = &This->funcdescs[index];
7477 TRACE("(%p) index %d\n", This, index);
7479 if(index >= This->TypeAttr.cFuncs)
7480 return TYPE_E_ELEMENTNOTFOUND;
7482 pCustData->prgCustData =
7483 heap_alloc_zero(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7484 if(pCustData->prgCustData ){
7485 pCustData->cCustData=pFDesc->ctCustData;
7486 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7487 pCData = pCData->next){
7488 pCustData->prgCustData[i].guid=pCData->guid;
7489 VariantCopy(& pCustData->prgCustData[i].varValue,
7493 ERR(" OUT OF MEMORY!\n");
7494 return E_OUTOFMEMORY;
7499 /* ITypeInfo2::GetAllParamCustData
7501 * Gets all custom data items for the Functions
7504 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7505 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7507 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7508 TLBCustData *pCData=NULL;
7509 TLBFuncDesc *pFDesc = &This->funcdescs[indexFunc];
7511 TRACE("(%p) index %d\n", This, indexFunc);
7513 if(indexFunc >= This->TypeAttr.cFuncs)
7514 return TYPE_E_ELEMENTNOTFOUND;
7516 if(indexParam >= pFDesc->funcdesc.cParams)
7517 return TYPE_E_ELEMENTNOTFOUND;
7519 pCustData->prgCustData =
7520 heap_alloc_zero(pFDesc->pParamDesc[indexParam].ctCustData *
7521 sizeof(CUSTDATAITEM));
7522 if(pCustData->prgCustData ){
7523 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7524 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7525 pCData; i++, pCData = pCData->next){
7526 pCustData->prgCustData[i].guid=pCData->guid;
7527 VariantCopy(& pCustData->prgCustData[i].varValue,
7531 ERR(" OUT OF MEMORY!\n");
7532 return E_OUTOFMEMORY;
7537 /* ITypeInfo2::GetAllVarCustData
7539 * Gets all custom data items for the specified Variable
7542 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7543 UINT index, CUSTDATA *pCustData)
7545 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7546 TLBCustData *pCData;
7547 TLBVarDesc * pVDesc;
7549 TRACE("(%p) index %d\n", This, index);
7550 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7551 pVDesc=pVDesc->next)
7554 pCustData->prgCustData =
7555 heap_alloc_zero(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7556 if(pCustData->prgCustData ){
7557 pCustData->cCustData=pVDesc->ctCustData;
7558 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7559 pCData = pCData->next){
7560 pCustData->prgCustData[i].guid=pCData->guid;
7561 VariantCopy(& pCustData->prgCustData[i].varValue,
7565 ERR(" OUT OF MEMORY!\n");
7566 return E_OUTOFMEMORY;
7570 return TYPE_E_ELEMENTNOTFOUND;
7573 /* ITypeInfo2::GetAllImplCustData
7575 * Gets all custom data items for the specified implementation type
7578 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7581 CUSTDATA *pCustData)
7583 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7584 TLBCustData *pCData;
7585 TLBImplType * pRDesc;
7587 TRACE("(%p) index %d\n", This, index);
7588 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7589 pRDesc=pRDesc->next)
7592 pCustData->prgCustData =
7593 heap_alloc_zero(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7594 if(pCustData->prgCustData ){
7595 pCustData->cCustData=pRDesc->ctCustData;
7596 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7597 pCData = pCData->next){
7598 pCustData->prgCustData[i].guid=pCData->guid;
7599 VariantCopy(& pCustData->prgCustData[i].varValue,
7603 ERR(" OUT OF MEMORY!\n");
7604 return E_OUTOFMEMORY;
7608 return TYPE_E_ELEMENTNOTFOUND;
7611 static const ITypeInfo2Vtbl tinfvt =
7614 ITypeInfo_fnQueryInterface,
7616 ITypeInfo_fnRelease,
7618 ITypeInfo_fnGetTypeAttr,
7619 ITypeInfo_fnGetTypeComp,
7620 ITypeInfo_fnGetFuncDesc,
7621 ITypeInfo_fnGetVarDesc,
7622 ITypeInfo_fnGetNames,
7623 ITypeInfo_fnGetRefTypeOfImplType,
7624 ITypeInfo_fnGetImplTypeFlags,
7625 ITypeInfo_fnGetIDsOfNames,
7627 ITypeInfo_fnGetDocumentation,
7628 ITypeInfo_fnGetDllEntry,
7629 ITypeInfo_fnGetRefTypeInfo,
7630 ITypeInfo_fnAddressOfMember,
7631 ITypeInfo_fnCreateInstance,
7632 ITypeInfo_fnGetMops,
7633 ITypeInfo_fnGetContainingTypeLib,
7634 ITypeInfo_fnReleaseTypeAttr,
7635 ITypeInfo_fnReleaseFuncDesc,
7636 ITypeInfo_fnReleaseVarDesc,
7638 ITypeInfo2_fnGetTypeKind,
7639 ITypeInfo2_fnGetTypeFlags,
7640 ITypeInfo2_fnGetFuncIndexOfMemId,
7641 ITypeInfo2_fnGetVarIndexOfMemId,
7642 ITypeInfo2_fnGetCustData,
7643 ITypeInfo2_fnGetFuncCustData,
7644 ITypeInfo2_fnGetParamCustData,
7645 ITypeInfo2_fnGetVarCustData,
7646 ITypeInfo2_fnGetImplTypeCustData,
7647 ITypeInfo2_fnGetDocumentation2,
7648 ITypeInfo2_fnGetAllCustData,
7649 ITypeInfo2_fnGetAllFuncCustData,
7650 ITypeInfo2_fnGetAllParamCustData,
7651 ITypeInfo2_fnGetAllVarCustData,
7652 ITypeInfo2_fnGetAllImplTypeCustData,
7655 /******************************************************************************
7656 * CreateDispTypeInfo [OLEAUT32.31]
7658 * Build type information for an object so it can be called through an
7659 * IDispatch interface.
7662 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7663 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7666 * This call allows an objects methods to be accessed through IDispatch, by
7667 * building an ITypeInfo object that IDispatch can use to call through.
7669 HRESULT WINAPI CreateDispTypeInfo(
7670 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7671 LCID lcid, /* [I] Locale Id */
7672 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7674 ITypeInfoImpl *pTIClass, *pTIIface;
7675 ITypeLibImpl *pTypeLibImpl;
7676 unsigned int param, func;
7677 TLBFuncDesc *pFuncDesc;
7681 pTypeLibImpl = TypeLibImpl_Constructor();
7682 if (!pTypeLibImpl) return E_FAIL;
7684 pTypeLibImpl->TypeInfoCount = 2;
7685 pTypeLibImpl->typeinfos = heap_alloc_zero(pTypeLibImpl->TypeInfoCount * sizeof(ITypeInfoImpl*));
7687 pTIIface = pTypeLibImpl->typeinfos[0] = ITypeInfoImpl_Constructor();
7688 pTIIface->pTypeLib = pTypeLibImpl;
7689 pTIIface->index = 0;
7690 pTIIface->Name = NULL;
7691 pTIIface->dwHelpContext = -1;
7692 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7693 pTIIface->TypeAttr.lcid = lcid;
7694 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7695 pTIIface->TypeAttr.wMajorVerNum = 0;
7696 pTIIface->TypeAttr.wMinorVerNum = 0;
7697 pTIIface->TypeAttr.cbAlignment = 2;
7698 pTIIface->TypeAttr.cbSizeInstance = -1;
7699 pTIIface->TypeAttr.cbSizeVft = -1;
7700 pTIIface->TypeAttr.cFuncs = 0;
7701 pTIIface->TypeAttr.cImplTypes = 0;
7702 pTIIface->TypeAttr.cVars = 0;
7703 pTIIface->TypeAttr.wTypeFlags = 0;
7705 pTIIface->funcdescs = heap_alloc_zero(pidata->cMembers * sizeof(TLBFuncDesc));
7706 pFuncDesc = pTIIface->funcdescs;
7707 for(func = 0; func < pidata->cMembers; func++) {
7708 METHODDATA *md = pidata->pmethdata + func;
7709 pFuncDesc->Name = SysAllocString(md->szName);
7710 pFuncDesc->funcdesc.memid = md->dispid;
7711 pFuncDesc->funcdesc.lprgscode = NULL;
7712 pFuncDesc->funcdesc.funckind = FUNC_VIRTUAL;
7713 pFuncDesc->funcdesc.invkind = md->wFlags;
7714 pFuncDesc->funcdesc.callconv = md->cc;
7715 pFuncDesc->funcdesc.cParams = md->cArgs;
7716 pFuncDesc->funcdesc.cParamsOpt = 0;
7717 pFuncDesc->funcdesc.oVft = md->iMeth * sizeof(void *);
7718 pFuncDesc->funcdesc.cScodes = 0;
7719 pFuncDesc->funcdesc.wFuncFlags = 0;
7720 pFuncDesc->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7721 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7722 pFuncDesc->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7723 pFuncDesc->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7724 md->cArgs * sizeof(ELEMDESC));
7725 pFuncDesc->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7726 md->cArgs * sizeof(TLBParDesc));
7727 for(param = 0; param < md->cArgs; param++) {
7728 pFuncDesc->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7729 pFuncDesc->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7731 pFuncDesc->helpcontext = 0;
7732 pFuncDesc->HelpStringContext = 0;
7733 pFuncDesc->HelpString = NULL;
7734 pFuncDesc->Entry = NULL;
7735 pFuncDesc->ctCustData = 0;
7736 pFuncDesc->pCustData = NULL;
7737 pTIIface->TypeAttr.cFuncs++;
7741 dump_TypeInfo(pTIIface);
7743 pTIClass = pTypeLibImpl->typeinfos[1] = ITypeInfoImpl_Constructor();
7744 pTIClass->pTypeLib = pTypeLibImpl;
7745 pTIClass->index = 1;
7746 pTIClass->Name = NULL;
7747 pTIClass->dwHelpContext = -1;
7748 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7749 pTIClass->TypeAttr.lcid = lcid;
7750 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7751 pTIClass->TypeAttr.wMajorVerNum = 0;
7752 pTIClass->TypeAttr.wMinorVerNum = 0;
7753 pTIClass->TypeAttr.cbAlignment = 2;
7754 pTIClass->TypeAttr.cbSizeInstance = -1;
7755 pTIClass->TypeAttr.cbSizeVft = -1;
7756 pTIClass->TypeAttr.cFuncs = 0;
7757 pTIClass->TypeAttr.cImplTypes = 1;
7758 pTIClass->TypeAttr.cVars = 0;
7759 pTIClass->TypeAttr.wTypeFlags = 0;
7761 pTIClass->impltypelist = heap_alloc_zero(sizeof(*pTIClass->impltypelist));
7762 pTIClass->impltypelist->hRef = 0;
7764 ref = heap_alloc_zero(sizeof(*ref));
7767 ref->pImpTLInfo = TLB_REF_INTERNAL;
7768 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7770 dump_TypeInfo(pTIClass);
7772 *pptinfo = (ITypeInfo*)pTIClass;
7774 ITypeInfo_AddRef(*pptinfo);
7775 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7781 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7783 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7785 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7788 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7790 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7792 return ITypeInfo_AddRef((ITypeInfo *)This);
7795 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7797 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7799 return ITypeInfo_Release((ITypeInfo *)This);
7802 static HRESULT WINAPI ITypeComp_fnBind(
7807 ITypeInfo ** ppTInfo,
7808 DESCKIND * pDescKind,
7811 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7812 const TLBFuncDesc *pFDesc;
7813 const TLBVarDesc *pVDesc;
7814 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7817 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7819 *pDescKind = DESCKIND_NONE;
7820 pBindPtr->lpfuncdesc = NULL;
7823 for(fdc = 0; fdc < This->TypeAttr.cFuncs; ++fdc){
7824 pFDesc = &This->funcdescs[fdc];
7825 if (!strcmpiW(pFDesc->Name, szName)) {
7826 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7829 /* name found, but wrong flags */
7830 hr = TYPE_E_TYPEMISMATCH;
7834 if (fdc < This->TypeAttr.cFuncs)
7836 HRESULT hr = TLB_AllocAndInitFuncDesc(
7838 &pBindPtr->lpfuncdesc,
7839 This->TypeAttr.typekind == TKIND_DISPATCH);
7842 *pDescKind = DESCKIND_FUNCDESC;
7843 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7844 ITypeInfo_AddRef(*ppTInfo);
7847 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7848 if (!strcmpiW(pVDesc->Name, szName)) {
7849 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7852 *pDescKind = DESCKIND_VARDESC;
7853 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7854 ITypeInfo_AddRef(*ppTInfo);
7859 /* FIXME: search each inherited interface, not just the first */
7860 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7861 /* recursive search */
7865 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7868 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7869 ITypeInfo_Release(pTInfo);
7873 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7874 ITypeComp_Release(pTComp);
7877 WARN("Could not search inherited interface!\n");
7879 if (hr == DISP_E_MEMBERNOTFOUND)
7881 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7885 static HRESULT WINAPI ITypeComp_fnBindType(
7889 ITypeInfo ** ppTInfo,
7890 ITypeComp ** ppTComp)
7892 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7894 /* strange behaviour (does nothing) but like the
7897 if (!ppTInfo || !ppTComp)
7906 static const ITypeCompVtbl tcompvt =
7909 ITypeComp_fnQueryInterface,
7911 ITypeComp_fnRelease,
7914 ITypeComp_fnBindType