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 *pTypeInfo; /* linked list of type info data */
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; */
1076 struct tagTLBFuncDesc * next;
1079 /* internal Variable data */
1080 typedef struct tagTLBVarDesc
1082 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1083 BSTR Name; /* the name of this variable */
1085 int HelpStringContext; /* FIXME: where? */
1088 TLBCustData * pCustData;/* linked list to cust data; */
1089 struct tagTLBVarDesc * next;
1092 /* internal implemented interface data */
1093 typedef struct tagTLBImplType
1095 HREFTYPE hRef; /* hRef of interface */
1096 int implflags; /* IMPLFLAG_*s */
1098 TLBCustData * pCustData;/* linked list to custom data; */
1099 struct tagTLBImplType *next;
1102 /* internal TypeInfo data */
1103 typedef struct tagITypeInfoImpl
1105 const ITypeInfo2Vtbl *lpVtbl;
1106 const ITypeCompVtbl *lpVtblTypeComp;
1108 BOOL not_attached_to_typelib;
1109 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1110 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1111 int index; /* index in this typelib; */
1112 HREFTYPE hreftype; /* hreftype for app object binding */
1113 /* type libs seem to store the doc strings in ascii
1114 * so why should we do it in unicode?
1119 DWORD dwHelpContext;
1120 DWORD dwHelpStringContext;
1123 TLBFuncDesc * funclist; /* linked list with function descriptions */
1126 TLBVarDesc * varlist; /* linked list with variable descriptions */
1128 /* Implemented Interfaces */
1129 TLBImplType * impltypelist;
1132 TLBCustData * pCustData; /* linked list to cust data; */
1133 struct tagITypeInfoImpl * next;
1136 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1138 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1141 static const ITypeInfo2Vtbl tinfvt;
1142 static const ITypeCompVtbl tcompvt;
1144 static ITypeInfo2 * ITypeInfo_Constructor(void);
1145 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This);
1147 typedef struct tagTLBContext
1149 unsigned int oStart; /* start of TLB in file */
1150 unsigned int pos; /* current pos */
1151 unsigned int length; /* total length */
1152 void *mapping; /* memory mapping */
1153 MSFT_SegDir * pTblDir;
1154 ITypeLibImpl* pLibInfo;
1158 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1163 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1164 if (pTD->vt & VT_RESERVED)
1165 szVarType += strlen(strcpy(szVarType, "reserved | "));
1166 if (pTD->vt & VT_BYREF)
1167 szVarType += strlen(strcpy(szVarType, "ref to "));
1168 if (pTD->vt & VT_ARRAY)
1169 szVarType += strlen(strcpy(szVarType, "array of "));
1170 if (pTD->vt & VT_VECTOR)
1171 szVarType += strlen(strcpy(szVarType, "vector of "));
1172 switch(pTD->vt & VT_TYPEMASK) {
1173 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1174 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1175 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1176 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1177 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1178 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1179 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1180 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1181 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1182 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1183 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1184 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1185 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1186 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1187 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1188 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1189 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1190 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1191 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1192 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1193 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1194 pTD->u.hreftype); break;
1195 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1196 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1197 case VT_PTR: sprintf(szVarType, "ptr to ");
1198 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1200 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1201 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1203 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1204 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1205 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1208 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1212 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1214 USHORT flags = edesc->u.paramdesc.wParamFlags;
1215 dump_TypeDesc(&edesc->tdesc,buf);
1216 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1217 MESSAGE("\t\tu.paramdesc.wParamFlags");
1218 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1219 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1220 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1221 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1222 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1223 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1224 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1225 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1226 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1228 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1230 MESSAGE("memid is %08x\n",funcdesc->memid);
1231 for (i=0;i<funcdesc->cParams;i++) {
1232 MESSAGE("Param %d:\n",i);
1233 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1235 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1236 switch (funcdesc->funckind) {
1237 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1238 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1239 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1240 case FUNC_STATIC: MESSAGE("static");break;
1241 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1242 default: MESSAGE("unknown");break;
1244 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1245 switch (funcdesc->invkind) {
1246 case INVOKE_FUNC: MESSAGE("func");break;
1247 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1248 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1249 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1251 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1252 switch (funcdesc->callconv) {
1253 case CC_CDECL: MESSAGE("cdecl");break;
1254 case CC_PASCAL: MESSAGE("pascal");break;
1255 case CC_STDCALL: MESSAGE("stdcall");break;
1256 case CC_SYSCALL: MESSAGE("syscall");break;
1259 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1260 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1261 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1263 MESSAGE("\telemdescFunc (return value type):\n");
1264 dump_ELEMDESC(&funcdesc->elemdescFunc);
1267 static const char * const typekind_desc[] =
1280 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1283 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1284 for (i=0;i<pfd->funcdesc.cParams;i++)
1285 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1288 dump_FUNCDESC(&(pfd->funcdesc));
1290 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1291 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1293 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1297 dump_TLBFuncDescOne(pfd);
1301 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1305 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1310 static void dump_TLBImpLib(const TLBImpLib *import)
1312 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1313 debugstr_w(import->name));
1314 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1315 import->wVersionMinor, import->lcid, import->offset);
1318 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1322 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1324 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1325 if(ref->index == -1)
1326 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1328 TRACE_(typelib)("type no: %d\n", ref->index);
1330 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1332 TRACE_(typelib)("in lib\n");
1333 dump_TLBImpLib(ref->pImpTLInfo);
1338 static void dump_TLBImplType(const TLBImplType * impl)
1342 "implementing/inheriting interface hRef = %x implflags %x\n",
1343 impl->hRef, impl->implflags);
1348 static void dump_Variant(const VARIANT * pvar)
1352 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1356 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1357 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1359 TRACE(",%p", V_BYREF(pvar));
1361 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1363 TRACE(",%p", V_ARRAY(pvar));
1365 else switch (V_TYPE(pvar))
1367 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1368 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1369 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1370 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1372 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1374 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1375 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1376 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1377 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1378 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1379 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1380 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1381 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1382 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1383 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1384 V_CY(pvar).s.Lo); break;
1386 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1387 TRACE(",<invalid>");
1389 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1390 st.wHour, st.wMinute, st.wSecond);
1394 case VT_USERDEFINED:
1396 case VT_NULL: break;
1397 default: TRACE(",?"); break;
1403 static void dump_DispParms(const DISPPARAMS * pdp)
1407 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1409 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1411 TRACE("named args:\n");
1412 for (index = 0; index < pdp->cNamedArgs; index++)
1413 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1416 if (pdp->cArgs && pdp->rgvarg)
1419 for (index = 0; index < pdp->cArgs; index++)
1420 dump_Variant( &pdp->rgvarg[index] );
1424 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1426 TRACE("%p ref=%u\n", pty, pty->ref);
1427 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1428 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1429 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1430 TRACE("fct:%u var:%u impl:%u\n",
1431 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1432 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1433 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1434 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1436 dump_TLBFuncDesc(pty->funclist);
1437 dump_TLBVarDesc(pty->varlist);
1438 dump_TLBImplType(pty->impltypelist);
1441 static void dump_VARDESC(const VARDESC *v)
1443 MESSAGE("memid %d\n",v->memid);
1444 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1445 MESSAGE("oInst %d\n",v->u.oInst);
1446 dump_ELEMDESC(&(v->elemdescVar));
1447 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1448 MESSAGE("varkind %d\n",v->varkind);
1451 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1453 /* VT_LPWSTR is largest type that */
1454 /* may appear in type description*/
1455 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1456 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1457 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1458 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1459 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1460 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1464 static void TLB_abort(void)
1469 static inline void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1471 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1472 if (!ret) ERR("cannot allocate memory\n");
1476 static inline void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1478 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1479 if (!ret) ERR("cannot allocate memory\n");
1483 static inline void heap_free(void *ptr)
1485 HeapFree(GetProcessHeap(), 0, ptr);
1488 /* returns the size required for a deep copy of a typedesc into a
1490 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1494 if (alloc_initial_space)
1495 size += sizeof(TYPEDESC);
1501 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1504 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1505 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1511 /* deep copy a typedesc into a flat buffer */
1512 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1517 buffer = (char *)buffer + sizeof(TYPEDESC);
1526 dest->u.lptdesc = buffer;
1527 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1530 dest->u.lpadesc = buffer;
1531 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1532 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1533 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1539 /* free custom data allocated by MSFT_CustData */
1540 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1542 TLBCustData *pCustDataNext;
1543 for (; pCustData; pCustData = pCustDataNext)
1545 VariantClear(&pCustData->data);
1547 pCustDataNext = pCustData->next;
1548 heap_free(pCustData);
1552 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1557 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1558 ret = SysAllocStringLen(NULL, len - 1);
1559 if (!ret) return ret;
1560 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1564 /**********************************************************************
1566 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1568 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1573 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1575 if (where != DO_NOT_SEEK)
1577 where += pcx->oStart;
1578 if (where > pcx->length)
1581 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1589 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1591 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1592 pcx->pos, count, pcx->oStart, pcx->length, where);
1594 MSFT_Seek(pcx, where);
1595 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1596 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1601 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1606 ret = MSFT_Read(buffer, count, pcx, where);
1607 FromLEDWords(buffer, ret);
1612 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1617 ret = MSFT_Read(buffer, count, pcx, where);
1618 FromLEWords(buffer, ret);
1623 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1625 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1626 memset(pGuid,0, sizeof(GUID));
1629 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1630 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1631 pGuid->Data2 = FromLEWord(pGuid->Data2);
1632 pGuid->Data3 = FromLEWord(pGuid->Data3);
1633 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1636 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1638 MSFT_NameIntro niName;
1642 ERR_(typelib)("bad offset %d\n", offset);
1646 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1647 pcx->pTblDir->pNametab.offset+offset);
1649 return niName.hreftype;
1652 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1655 MSFT_NameIntro niName;
1657 BSTR bstrName = NULL;
1661 ERR_(typelib)("bad offset %d\n", offset);
1664 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1665 pcx->pTblDir->pNametab.offset+offset);
1666 niName.namelen &= 0xFF; /* FIXME: correct ? */
1667 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1668 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1669 name[niName.namelen & 0xff]='\0';
1671 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1674 /* no invalid characters in string */
1677 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1679 /* don't check for invalid character since this has been done previously */
1680 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1684 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1688 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1695 if(offset<0) return NULL;
1696 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1697 if(length <= 0) return 0;
1698 string = heap_alloc_zero(length +1);
1699 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1700 string[length]='\0';
1702 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1703 string, -1, NULL, 0);
1705 /* no invalid characters in string */
1708 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1710 /* don't check for invalid character since this has been done previously */
1711 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1715 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1719 * read a value and fill a VARIANT structure
1721 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1725 TRACE_(typelib)("\n");
1727 if(offset <0) { /* data are packed in here */
1728 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1729 V_I4(pVar) = offset & 0x3ffffff;
1732 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1733 pcx->pTblDir->pCustData.offset + offset );
1734 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1735 switch (V_VT(pVar)){
1736 case VT_EMPTY: /* FIXME: is this right? */
1737 case VT_NULL: /* FIXME: is this right? */
1738 case VT_I2 : /* this should not happen */
1749 case VT_VOID : /* FIXME: is this right? */
1757 case VT_DECIMAL : /* FIXME: is this right? */
1760 /* pointer types with known behaviour */
1763 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1766 DWORD origPos = MSFT_Tell(pcx), nullPos;
1769 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1771 nullPos = MSFT_Tell(pcx);
1772 size = nullPos - origPos;
1773 MSFT_Seek(pcx, origPos);
1775 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1776 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1777 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1778 /* FIXME: do we need a AtoW conversion here? */
1779 V_UNION(pVar, bstrVal[size])='\0';
1780 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1784 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1791 case VT_USERDEFINED :
1797 case VT_STREAMED_OBJECT :
1798 case VT_STORED_OBJECT :
1799 case VT_BLOB_OBJECT :
1804 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1808 if(size>0) /* (big|small) endian correct? */
1809 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1813 * create a linked list with custom data
1815 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1821 TRACE_(typelib)("\n");
1825 pNew=heap_alloc_zero(sizeof(TLBCustData));
1826 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1827 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1828 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1829 /* add new custom data at head of the list */
1830 pNew->next=*ppCustData;
1832 offset = entry.next;
1837 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1841 pTd->vt=type & VT_TYPEMASK;
1843 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1845 if(pTd->vt == VT_USERDEFINED)
1846 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1848 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1851 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1853 /* resolve referenced type if any */
1856 switch (lpTypeDesc->vt)
1859 lpTypeDesc = lpTypeDesc->u.lptdesc;
1863 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1866 case VT_USERDEFINED:
1867 MSFT_DoRefType(pcx, pTI->pTypeLib,
1868 lpTypeDesc->u.hreftype);
1880 MSFT_DoFuncs(TLBContext* pcx,
1885 TLBFuncDesc** pptfd)
1888 * member information is stored in a data structure at offset
1889 * indicated by the memoffset field of the typeinfo structure
1890 * There are several distinctive parts.
1891 * The first part starts with a field that holds the total length
1892 * of this (first) part excluding this field. Then follow the records,
1893 * for each member there is one record.
1895 * The first entry is always the length of the record (including this
1897 * The rest of the record depends on the type of the member. If there is
1898 * a field indicating the member type (function, variable, interface, etc)
1899 * I have not found it yet. At this time we depend on the information
1900 * in the type info and the usual order how things are stored.
1902 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1905 * Third is an equal sized array with file offsets to the name entry
1908 * The fourth and last (?) part is an array with offsets to the records
1909 * in the first part of this file segment.
1912 int infolen, nameoffset, reclength, i;
1913 int recoffset = offset + sizeof(INT);
1915 char *recbuf = heap_alloc(0xffff);
1916 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
1917 TLBFuncDesc *ptfd_prev = NULL;
1919 TRACE_(typelib)("\n");
1921 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1923 for ( i = 0; i < cFuncs ; i++ )
1927 *pptfd = heap_alloc_zero(sizeof(TLBFuncDesc));
1929 /* name, eventually add to a hash table */
1930 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1931 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1933 /* nameoffset is sometimes -1 on the second half of a propget/propput
1934 * pair of functions */
1935 if ((nameoffset == -1) && (i > 0))
1936 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1938 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1940 /* read the function information record */
1941 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
1943 reclength &= 0xffff;
1945 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
1947 /* size without argument data */
1948 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
1950 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
1951 (*pptfd)->helpcontext = pFuncRec->HelpContext;
1953 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
1954 (*pptfd)->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
1956 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
1958 if (pFuncRec->FKCCIC & 0x2000 )
1960 if (!IS_INTRESOURCE(pFuncRec->oEntry))
1961 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
1962 (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
1965 (*pptfd)->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
1968 (*pptfd)->Entry = (BSTR)-1;
1970 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
1971 (*pptfd)->HelpStringContext = pFuncRec->HelpStringContext;
1973 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
1974 MSFT_CustData(pcx, pFuncRec->oCustData, &(*pptfd)->pCustData);
1976 /* fill the FuncDesc Structure */
1977 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1978 offset + infolen + ( i + 1) * sizeof(INT));
1980 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1981 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1982 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1983 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1984 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1985 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1986 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1990 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1992 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1994 /* do the parameters/arguments */
1995 if(pFuncRec->nrargs)
1998 MSFT_ParameterInfo paraminfo;
2000 (*pptfd)->funcdesc.lprgelemdescParam =
2001 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2003 (*pptfd)->pParamDesc =
2004 heap_alloc_zero(pFuncRec->nrargs * sizeof(TLBParDesc));
2006 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
2007 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2009 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2011 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
2018 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2021 if (paraminfo.oName == -1)
2022 /* this occurs for [propput] or [propget] methods, so
2023 * we should just set the name of the parameter to the
2024 * name of the method. */
2025 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
2027 (*pptfd)->pParamDesc[j].Name =
2028 MSFT_ReadName( pcx, paraminfo.oName );
2029 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
2031 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2034 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2035 (pFuncRec->FKCCIC & 0x1000) )
2037 INT* pInt = (INT *)((char *)pFuncRec +
2039 (pFuncRec->nrargs * 4) * sizeof(INT) );
2041 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2043 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2044 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2046 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2050 elemdesc->u.paramdesc.pparamdescex = NULL;
2053 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2054 j*sizeof(pFuncRec->oArgCustData[0])) &&
2055 pFuncRec->FKCCIC & 0x80 )
2058 pFuncRec->oArgCustData[j],
2059 &(*pptfd)->pParamDesc[j].pCustData);
2062 /* SEEK value = jump to offset,
2063 * from there jump to the end of record,
2064 * go back by (j-1) arguments
2066 MSFT_ReadLEDWords( ¶minfo ,
2067 sizeof(MSFT_ParameterInfo), pcx,
2068 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2069 * sizeof(MSFT_ParameterInfo)));
2073 /* scode is not used: archaic win16 stuff FIXME: right? */
2074 (*pptfd)->funcdesc.cScodes = 0 ;
2075 (*pptfd)->funcdesc.lprgscode = NULL ;
2078 pptfd = & ((*pptfd)->next);
2079 recoffset += reclength;
2084 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2085 int cVars, int offset, TLBVarDesc ** pptvd)
2087 int infolen, nameoffset, reclength;
2089 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2093 TRACE_(typelib)("\n");
2095 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2096 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2097 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2098 recoffset += offset+sizeof(INT);
2099 for(i=0;i<cVars;i++){
2100 *pptvd = heap_alloc_zero(sizeof(TLBVarDesc));
2101 /* name, eventually add to a hash table */
2102 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2103 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2104 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2105 /* read the variable information record */
2106 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2108 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2111 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2112 (*pptvd)->HelpContext = pVarRec->HelpContext;
2114 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2115 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2117 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2118 (*pptvd)->HelpStringContext = pVarRec->HelpStringContext;
2120 /* fill the VarDesc Structure */
2121 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2122 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2123 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2124 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2125 MSFT_GetTdesc(pcx, pVarRec->DataType,
2126 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2127 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2128 if(pVarRec->VarKind == VAR_CONST ){
2129 (*pptvd)->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2130 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2131 pVarRec->OffsValue, pcx);
2133 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2134 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2135 pptvd=&((*pptvd)->next);
2136 recoffset += reclength;
2139 /* fill in data for a hreftype (offset). When the referenced type is contained
2140 * in the typelib, it's just an (file) offset in the type info base dir.
2141 * If comes from import, it's an offset+1 in the ImpInfo table
2143 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2148 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2150 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2152 if(ref->reference == offset) return;
2155 ref = heap_alloc_zero(sizeof(TLBRefType));
2156 list_add_tail(&pTL->ref_list, &ref->entry);
2158 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2159 /* external typelib */
2160 MSFT_ImpInfo impinfo;
2161 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2163 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2165 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2166 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2167 while (pImpLib){ /* search the known offsets of all import libraries */
2168 if(pImpLib->offset==impinfo.oImpFile) break;
2169 pImpLib=pImpLib->next;
2172 ref->reference = offset;
2173 ref->pImpTLInfo = pImpLib;
2174 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2175 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2176 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2177 ref->index = TLB_REF_USE_GUID;
2179 ref->index = impinfo.oGuid;
2181 ERR("Cannot find a reference\n");
2182 ref->reference = -1;
2183 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2186 /* in this typelib */
2187 ref->index = MSFT_HREFTYPE_INDEX(offset);
2188 ref->reference = offset;
2189 ref->pImpTLInfo = TLB_REF_INTERNAL;
2193 /* process Implemented Interfaces of a com class */
2194 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2198 MSFT_RefRecord refrec;
2199 TLBImplType **ppImpl = &pTI->impltypelist;
2201 TRACE_(typelib)("\n");
2203 for(i=0;i<count;i++){
2204 if(offset<0) break; /* paranoia */
2205 *ppImpl = heap_alloc_zero(sizeof(**ppImpl));
2206 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2207 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2208 (*ppImpl)->hRef = refrec.reftype;
2209 (*ppImpl)->implflags=refrec.flags;
2210 (*ppImpl)->ctCustData=
2211 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2212 offset=refrec.onext;
2213 ppImpl=&((*ppImpl)->next);
2217 * process a typeinfo record
2219 static ITypeInfoImpl * MSFT_DoTypeInfo(
2222 ITypeLibImpl * pLibInfo)
2224 MSFT_TypeInfoBase tiBase;
2225 ITypeInfoImpl *ptiRet;
2227 TRACE_(typelib)("count=%u\n", count);
2229 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2230 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2231 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2233 /* this is where we are coming from */
2234 ptiRet->pTypeLib = pLibInfo;
2235 ptiRet->index=count;
2236 /* fill in the typeattr fields */
2238 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2239 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2240 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2241 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2242 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2243 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2244 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2245 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2246 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2247 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2248 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2249 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2250 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2251 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2252 MSFT_GetTdesc(pcx, tiBase.datatype1,
2253 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2256 /* IDLDESC idldescType; *//* never saw this one != zero */
2258 /* name, eventually add to a hash table */
2259 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2260 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2261 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2263 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2264 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2265 ptiRet->dwHelpContext=tiBase.helpcontext;
2267 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2268 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2270 /* note: InfoType's Help file and HelpStringDll come from the containing
2271 * library. Further HelpString and Docstring appear to be the same thing :(
2274 if(ptiRet->TypeAttr.cFuncs >0 )
2275 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2276 ptiRet->TypeAttr.cVars,
2277 tiBase.memoffset, & ptiRet->funclist);
2279 if(ptiRet->TypeAttr.cVars >0 )
2280 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2281 ptiRet->TypeAttr.cVars,
2282 tiBase.memoffset, & ptiRet->varlist);
2283 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2284 switch(ptiRet->TypeAttr.typekind)
2287 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2290 case TKIND_DISPATCH:
2291 /* This is not -1 when the interface is a non-base dual interface or
2292 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2293 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2297 if (tiBase.datatype1 != -1)
2299 ptiRet->impltypelist = heap_alloc_zero(sizeof(TLBImplType));
2300 ptiRet->impltypelist->hRef = tiBase.datatype1;
2301 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2305 ptiRet->impltypelist = heap_alloc_zero(sizeof(TLBImplType));
2306 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2307 ptiRet->impltypelist->hRef = tiBase.datatype1;
2312 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2314 TRACE_(typelib)("%s guid: %s kind:%s\n",
2315 debugstr_w(ptiRet->Name),
2316 debugstr_guid(&ptiRet->TypeAttr.guid),
2317 typekind_desc[ptiRet->TypeAttr.typekind]);
2318 if (TRACE_ON(typelib))
2319 dump_TypeInfo(ptiRet);
2324 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2325 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2326 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2329 static ITypeLibImpl *tlb_cache_first;
2330 static CRITICAL_SECTION cache_section;
2331 static CRITICAL_SECTION_DEBUG cache_section_debug =
2333 0, 0, &cache_section,
2334 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2335 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2337 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2340 typedef struct TLB_PEFile
2342 const IUnknownVtbl *lpvtbl;
2345 HRSRC typelib_resource;
2346 HGLOBAL typelib_global;
2347 LPVOID typelib_base;
2350 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2352 if (IsEqualIID(riid, &IID_IUnknown))
2355 IUnknown_AddRef(iface);
2359 return E_NOINTERFACE;
2362 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2364 TLB_PEFile *This = (TLB_PEFile *)iface;
2365 return InterlockedIncrement(&This->refs);
2368 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2370 TLB_PEFile *This = (TLB_PEFile *)iface;
2371 ULONG refs = InterlockedDecrement(&This->refs);
2374 if (This->typelib_global)
2375 FreeResource(This->typelib_global);
2377 FreeLibrary(This->dll);
2383 static const IUnknownVtbl TLB_PEFile_Vtable =
2385 TLB_PEFile_QueryInterface,
2390 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2394 This = heap_alloc(sizeof(TLB_PEFile));
2396 return E_OUTOFMEMORY;
2398 This->lpvtbl = &TLB_PEFile_Vtable;
2401 This->typelib_resource = NULL;
2402 This->typelib_global = NULL;
2403 This->typelib_base = NULL;
2405 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2406 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2410 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2411 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2412 if (This->typelib_resource)
2414 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2415 if (This->typelib_global)
2417 This->typelib_base = LockResource(This->typelib_global);
2419 if (This->typelib_base)
2421 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2422 *ppBase = This->typelib_base;
2423 *ppFile = (IUnknown *)&This->lpvtbl;
2430 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2431 return TYPE_E_CANTLOADLIBRARY;
2434 typedef struct TLB_NEFile
2436 const IUnknownVtbl *lpvtbl;
2438 LPVOID typelib_base;
2441 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2443 if (IsEqualIID(riid, &IID_IUnknown))
2446 IUnknown_AddRef(iface);
2450 return E_NOINTERFACE;
2453 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2455 TLB_NEFile *This = (TLB_NEFile *)iface;
2456 return InterlockedIncrement(&This->refs);
2459 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2461 TLB_NEFile *This = (TLB_NEFile *)iface;
2462 ULONG refs = InterlockedDecrement(&This->refs);
2465 heap_free(This->typelib_base);
2471 static const IUnknownVtbl TLB_NEFile_Vtable =
2473 TLB_NEFile_QueryInterface,
2478 /***********************************************************************
2479 * read_xx_header [internal]
2481 static int read_xx_header( HFILE lzfd )
2483 IMAGE_DOS_HEADER mzh;
2486 LZSeek( lzfd, 0, SEEK_SET );
2487 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2489 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2492 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2493 if ( 2 != LZRead( lzfd, magic, 2 ) )
2496 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2498 if ( magic[0] == 'N' && magic[1] == 'E' )
2499 return IMAGE_OS2_SIGNATURE;
2500 if ( magic[0] == 'P' && magic[1] == 'E' )
2501 return IMAGE_NT_SIGNATURE;
2504 WARN("Can't handle %s files.\n", magic );
2509 /***********************************************************************
2510 * find_ne_resource [internal]
2512 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2513 DWORD *resLen, DWORD *resOff )
2515 IMAGE_OS2_HEADER nehd;
2516 NE_TYPEINFO *typeInfo;
2517 NE_NAMEINFO *nameInfo;
2523 /* Read in NE header */
2524 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2525 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2527 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2530 TRACE("No resources in NE dll\n" );
2534 /* Read in resource table */
2535 resTab = heap_alloc( resTabSize );
2536 if ( !resTab ) return FALSE;
2538 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2539 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2541 heap_free( resTab );
2546 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2548 if (!IS_INTRESOURCE(typeid)) /* named type */
2550 BYTE len = strlen( typeid );
2551 while (typeInfo->type_id)
2553 if (!(typeInfo->type_id & 0x8000))
2555 BYTE *p = resTab + typeInfo->type_id;
2556 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2558 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2559 typeInfo->count * sizeof(NE_NAMEINFO));
2562 else /* numeric type id */
2564 WORD id = LOWORD(typeid) | 0x8000;
2565 while (typeInfo->type_id)
2567 if (typeInfo->type_id == id) goto found_type;
2568 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2569 typeInfo->count * sizeof(NE_NAMEINFO));
2572 TRACE("No typeid entry found for %p\n", typeid );
2573 heap_free( resTab );
2577 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2579 if (!IS_INTRESOURCE(resid)) /* named resource */
2581 BYTE len = strlen( resid );
2582 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2584 BYTE *p = resTab + nameInfo->id;
2585 if (nameInfo->id & 0x8000) continue;
2586 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2589 else /* numeric resource id */
2591 WORD id = LOWORD(resid) | 0x8000;
2592 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2593 if (nameInfo->id == id) goto found_name;
2595 TRACE("No resid entry found for %p\n", typeid );
2596 heap_free( resTab );
2600 /* Return resource data */
2601 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2602 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2604 heap_free( resTab );
2608 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2612 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2615 This = heap_alloc(sizeof(TLB_NEFile));
2616 if (!This) return E_OUTOFMEMORY;
2618 This->lpvtbl = &TLB_NEFile_Vtable;
2620 This->typelib_base = NULL;
2622 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2623 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2625 DWORD reslen, offset;
2626 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2628 This->typelib_base = heap_alloc(reslen);
2629 if( !This->typelib_base )
2633 LZSeek( lzfd, offset, SEEK_SET );
2634 reslen = LZRead( lzfd, This->typelib_base, reslen );
2636 *ppBase = This->typelib_base;
2637 *pdwTLBLength = reslen;
2638 *ppFile = (IUnknown *)&This->lpvtbl;
2644 if( lzfd >= 0) LZClose( lzfd );
2645 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2649 typedef struct TLB_Mapping
2651 const IUnknownVtbl *lpvtbl;
2655 LPVOID typelib_base;
2658 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2660 if (IsEqualIID(riid, &IID_IUnknown))
2663 IUnknown_AddRef(iface);
2667 return E_NOINTERFACE;
2670 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2672 TLB_Mapping *This = (TLB_Mapping *)iface;
2673 return InterlockedIncrement(&This->refs);
2676 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2678 TLB_Mapping *This = (TLB_Mapping *)iface;
2679 ULONG refs = InterlockedDecrement(&This->refs);
2682 if (This->typelib_base)
2683 UnmapViewOfFile(This->typelib_base);
2685 CloseHandle(This->mapping);
2686 if (This->file != INVALID_HANDLE_VALUE)
2687 CloseHandle(This->file);
2693 static const IUnknownVtbl TLB_Mapping_Vtable =
2695 TLB_Mapping_QueryInterface,
2700 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2704 This = heap_alloc(sizeof(TLB_Mapping));
2706 return E_OUTOFMEMORY;
2708 This->lpvtbl = &TLB_Mapping_Vtable;
2710 This->file = INVALID_HANDLE_VALUE;
2711 This->mapping = NULL;
2712 This->typelib_base = NULL;
2714 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2715 if (INVALID_HANDLE_VALUE != This->file)
2717 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2720 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2721 if(This->typelib_base)
2723 /* retrieve file size */
2724 *pdwTLBLength = GetFileSize(This->file, NULL);
2725 *ppBase = This->typelib_base;
2726 *ppFile = (IUnknown *)&This->lpvtbl;
2732 IUnknown_Release((IUnknown *)&This->lpvtbl);
2733 return TYPE_E_CANTLOADLIBRARY;
2736 /****************************************************************************
2739 * find the type of the typelib file and map the typelib resource into
2743 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2744 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2746 ITypeLibImpl *entry;
2749 LPWSTR index_str, file = (LPWSTR)pszFileName;
2750 LPVOID pBase = NULL;
2751 DWORD dwTLBLength = 0;
2752 IUnknown *pFile = NULL;
2756 index_str = strrchrW(pszFileName, '\\');
2757 if(index_str && *++index_str != '\0')
2760 LONG idx = strtolW(index_str, &end_ptr, 10);
2761 if(*end_ptr == '\0')
2763 int str_len = index_str - pszFileName - 1;
2765 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2766 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2771 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2773 if(strchrW(file, '\\'))
2775 lstrcpyW(pszPath, file);
2779 int len = GetSystemDirectoryW(pszPath, cchPath);
2780 pszPath[len] = '\\';
2781 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2785 if(file != pszFileName) heap_free(file);
2787 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2789 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2790 EnterCriticalSection(&cache_section);
2791 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2793 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2795 TRACE("cache hit\n");
2796 *ppTypeLib = (ITypeLib2*)entry;
2797 ITypeLib_AddRef(*ppTypeLib);
2798 LeaveCriticalSection(&cache_section);
2802 LeaveCriticalSection(&cache_section);
2804 /* now actually load and parse the typelib */
2806 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2807 if (ret == TYPE_E_CANTLOADLIBRARY)
2808 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2809 if (ret == TYPE_E_CANTLOADLIBRARY)
2810 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2813 if (dwTLBLength >= 4)
2815 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2816 if (dwSignature == MSFT_SIGNATURE)
2817 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2818 else if (dwSignature == SLTG_SIGNATURE)
2819 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2822 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2823 ret = TYPE_E_CANTLOADLIBRARY;
2827 ret = TYPE_E_CANTLOADLIBRARY;
2828 IUnknown_Release(pFile);
2832 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2834 TRACE("adding to cache\n");
2835 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2836 lstrcpyW(impl->path, pszPath);
2837 /* We should really canonicalise the path here. */
2838 impl->index = index;
2840 /* FIXME: check if it has added already in the meantime */
2841 EnterCriticalSection(&cache_section);
2842 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2844 tlb_cache_first = impl;
2845 LeaveCriticalSection(&cache_section);
2848 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2853 /*================== ITypeLib(2) Methods ===================================*/
2855 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2857 ITypeLibImpl* pTypeLibImpl;
2859 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2860 if (!pTypeLibImpl) return NULL;
2862 pTypeLibImpl->lpVtbl = &tlbvt;
2863 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2864 pTypeLibImpl->ref = 1;
2866 list_init(&pTypeLibImpl->ref_list);
2867 pTypeLibImpl->dispatch_href = -1;
2869 return pTypeLibImpl;
2872 /****************************************************************************
2873 * ITypeLib2_Constructor_MSFT
2875 * loading an MSFT typelib from an in-memory image
2877 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2881 MSFT_Header tlbHeader;
2882 MSFT_SegDir tlbSegDir;
2883 ITypeLibImpl * pTypeLibImpl;
2885 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2887 pTypeLibImpl = TypeLibImpl_Constructor();
2888 if (!pTypeLibImpl) return NULL;
2890 /* get pointer to beginning of typelib data */
2894 cx.pLibInfo = pTypeLibImpl;
2895 cx.length = dwTLBLength;
2898 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2899 TRACE_(typelib)("header:\n");
2900 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2901 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2902 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2905 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2907 /* there is a small amount of information here until the next important
2909 * the segment directory . Try to calculate the amount of data */
2910 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2912 /* now read the segment directory */
2913 TRACE("read segment directory (at %d)\n",lPSegDir);
2914 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2915 cx.pTblDir = &tlbSegDir;
2917 /* just check two entries */
2918 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2920 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
2921 heap_free(pTypeLibImpl);
2925 /* now fill our internal data */
2926 /* TLIBATTR fields */
2927 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2929 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2930 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2931 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2932 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2933 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2935 pTypeLibImpl->lcid = tlbHeader.lcid;
2937 /* name, eventually add to a hash table */
2938 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2941 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2942 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2944 if( tlbHeader.varflags & HELPDLLFLAG)
2947 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2948 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2951 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2954 if(tlbHeader.CustomDataOffset >= 0)
2956 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2959 /* fill in type descriptions */
2960 if(tlbSegDir.pTypdescTab.length > 0)
2962 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2964 pTypeLibImpl->ctTypeDesc = cTD;
2965 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
2966 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2969 /* FIXME: add several sanity checks here */
2970 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2971 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2973 /* FIXME: check safearray */
2975 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2977 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2979 else if(td[0] == VT_CARRAY)
2981 /* array descr table here */
2982 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
2984 else if(td[0] == VT_USERDEFINED)
2986 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2988 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2991 /* second time around to fill the array subscript info */
2994 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2995 if(tlbSegDir.pArrayDescriptions.offset>0)
2997 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2998 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3001 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3003 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3005 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3007 for(j = 0; j<td[2]; j++)
3009 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3010 sizeof(INT), &cx, DO_NOT_SEEK);
3011 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3012 sizeof(INT), &cx, DO_NOT_SEEK);
3017 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3018 ERR("didn't find array description data\n");
3023 /* imported type libs */
3024 if(tlbSegDir.pImpFiles.offset>0)
3026 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
3027 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3030 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3034 *ppImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3035 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
3036 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3038 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3039 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3040 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3041 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3044 name = heap_alloc_zero(size+1);
3045 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3046 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3049 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3050 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3052 ppImpLib = &(*ppImpLib)->next;
3056 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3057 if(pTypeLibImpl->dispatch_href != -1)
3058 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3061 if(tlbHeader.nrtypeinfos >= 0 )
3063 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3064 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3067 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3069 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3071 ppTI = &((*ppTI)->next);
3072 (pTypeLibImpl->TypeInfoCount)++;
3076 TRACE("(%p)\n", pTypeLibImpl);
3077 return (ITypeLib2*) pTypeLibImpl;
3081 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3087 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3088 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3092 guid->Data4[0] = s >> 8;
3093 guid->Data4[1] = s & 0xff;
3096 for(i = 0; i < 6; i++) {
3097 memcpy(b, str + 24 + 2 * i, 2);
3098 guid->Data4[i + 2] = strtol(b, NULL, 16);
3103 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3109 bytelen = *(const WORD*)ptr;
3110 if(bytelen == 0xffff) return 2;
3111 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3112 *pBstr = SysAllocStringLen(NULL, len);
3114 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3118 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3123 bytelen = *(const WORD*)ptr;
3124 if(bytelen == 0xffff) return 2;
3125 *str = heap_alloc(bytelen + 1);
3126 memcpy(*str, ptr + 2, bytelen);
3127 (*str)[bytelen] = '\0';
3131 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3133 char *ptr = pLibBlk;
3136 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3137 FIXME("libblk magic = %04x\n", w);
3142 if((w = *(WORD*)ptr) != 0xffff) {
3143 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3148 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3150 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3152 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3155 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3158 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3159 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3161 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3164 ptr += 4; /* skip res12 */
3166 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3169 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3172 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3175 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3176 ptr += sizeof(GUID);
3178 return ptr - (char*)pLibBlk;
3181 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3186 } sltg_ref_lookup_t;
3188 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3189 HREFTYPE *typelib_ref)
3191 if(table && typeinfo_ref < table->num)
3193 *typelib_ref = table->refs[typeinfo_ref];
3197 ERR_(typelib)("Unable to find reference\n");
3202 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3207 if((*pType & 0xe00) == 0xe00) {
3209 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3210 pTD = pTD->u.lptdesc;
3212 switch(*pType & 0x3f) {
3215 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3216 pTD = pTD->u.lptdesc;
3219 case VT_USERDEFINED:
3220 pTD->vt = VT_USERDEFINED;
3221 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3227 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3230 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3232 pTD->vt = VT_CARRAY;
3233 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3234 pTD->u.lpadesc->cDims = pSA->cDims;
3235 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3236 pSA->cDims * sizeof(SAFEARRAYBOUND));
3238 pTD = &pTD->u.lpadesc->tdescElem;
3244 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3248 pTD->vt = VT_SAFEARRAY;
3249 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3250 pTD = pTD->u.lptdesc;
3254 pTD->vt = *pType & 0x3f;
3263 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3264 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3266 /* Handle [in/out] first */
3267 if((*pType & 0xc000) == 0xc000)
3268 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3269 else if(*pType & 0x8000)
3270 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3271 else if(*pType & 0x4000)
3272 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3274 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3277 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3280 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3282 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3286 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3291 TLBRefType *ref_type;
3292 sltg_ref_lookup_t *table;
3293 HREFTYPE typelib_ref;
3295 if(pRef->magic != SLTG_REF_MAGIC) {
3296 FIXME("Ref magic = %x\n", pRef->magic);
3299 name = ( (char*)pRef->names + pRef->number);
3301 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3302 table->num = pRef->number >> 3;
3304 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3306 /* We don't want the first href to be 0 */
3307 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3309 for(ref = 0; ref < pRef->number >> 3; ref++) {
3311 unsigned int lib_offs, type_num;
3313 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3315 name += SLTG_ReadStringA(name, &refname);
3316 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3317 FIXME_(typelib)("Can't sscanf ref\n");
3318 if(lib_offs != 0xffff) {
3319 TLBImpLib **import = &pTL->pImpLibs;
3322 if((*import)->offset == lib_offs)
3324 import = &(*import)->next;
3327 char fname[MAX_PATH+1];
3330 *import = heap_alloc_zero(sizeof(**import));
3331 (*import)->offset = lib_offs;
3332 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3334 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3335 &(*import)->wVersionMajor,
3336 &(*import)->wVersionMinor,
3337 &(*import)->lcid, fname) != 4) {
3338 FIXME_(typelib)("can't sscanf ref %s\n",
3339 pNameTable + lib_offs + 40);
3341 len = strlen(fname);
3342 if(fname[len-1] != '#')
3343 FIXME("fname = %s\n", fname);
3344 fname[len-1] = '\0';
3345 (*import)->name = TLB_MultiByteToBSTR(fname);
3347 ref_type->pImpTLInfo = *import;
3349 /* Store a reference to IDispatch */
3350 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3351 pTL->dispatch_href = typelib_ref;
3353 } else { /* internal ref */
3354 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3356 ref_type->reference = typelib_ref;
3357 ref_type->index = type_num;
3360 list_add_tail(&pTL->ref_list, &ref_type->entry);
3362 table->refs[ref] = typelib_ref;
3365 if((BYTE)*name != SLTG_REF_MAGIC)
3366 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3367 dump_TLBRefType(pTL);
3371 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3372 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3374 SLTG_ImplInfo *info;
3375 TLBImplType **ppImplType = &pTI->impltypelist;
3376 /* I don't really get this structure, usually it's 0x16 bytes
3377 long, but iuser.tlb contains some that are 0x18 bytes long.
3378 That's ok because we can use the next ptr to jump to the next
3379 one. But how do we know the length of the last one? The WORD
3380 at offs 0x8 might be the clue. For now I'm just assuming that
3381 the last one is the regular 0x16 bytes. */
3383 info = (SLTG_ImplInfo*)pBlk;
3385 *ppImplType = heap_alloc_zero(sizeof(**ppImplType));
3386 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3387 (*ppImplType)->implflags = info->impltypeflags;
3388 pTI->TypeAttr.cImplTypes++;
3389 ppImplType = &(*ppImplType)->next;
3391 if(info->next == 0xffff)
3394 FIXME_(typelib)("Interface inheriting more than one interface\n");
3395 info = (SLTG_ImplInfo*)(pBlk + info->next);
3397 info++; /* see comment at top of function */
3401 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3402 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3404 TLBVarDesc **ppVarDesc = &pTI->varlist;
3405 BSTR bstrPrevName = NULL;
3406 SLTG_Variable *pItem;
3410 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3411 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3413 *ppVarDesc = heap_alloc_zero(sizeof(**ppVarDesc));
3414 (*ppVarDesc)->vardesc.memid = pItem->memid;
3416 if (pItem->magic != SLTG_VAR_MAGIC &&
3417 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3418 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3422 if (pItem->name == 0xfffe)
3423 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3425 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3427 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3428 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3429 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3431 if(pItem->flags & 0x02)
3432 pType = &pItem->type;
3434 pType = (WORD*)(pBlk + pItem->type);
3436 if (pItem->flags & ~0xda)
3437 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3439 SLTG_DoElem(pType, pBlk,
3440 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3442 if (TRACE_ON(typelib)) {
3444 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3445 TRACE_(typelib)("elemdescVar: %s\n", buf);
3448 if (pItem->flags & 0x40) {
3449 TRACE_(typelib)("VAR_DISPATCH\n");
3450 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3452 else if (pItem->flags & 0x10) {
3453 TRACE_(typelib)("VAR_CONST\n");
3454 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3455 (*ppVarDesc)->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3456 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3457 if (pItem->flags & 0x08)
3458 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3460 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3466 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3468 TRACE_(typelib)("len = %u\n", len);
3469 if (len == 0xffff) {
3472 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3473 str = SysAllocStringLen(NULL, alloc_len);
3474 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3476 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3477 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3486 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3487 *(INT*)(pBlk + pItem->byte_offs);
3490 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3495 TRACE_(typelib)("VAR_PERINSTANCE\n");
3496 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3497 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3500 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3501 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3503 if (pItem->flags & 0x80)
3504 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3506 bstrPrevName = (*ppVarDesc)->Name;
3507 ppVarDesc = &((*ppVarDesc)->next);
3509 pTI->TypeAttr.cVars = cVars;
3512 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3513 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3515 SLTG_Function *pFunc;
3517 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3519 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3520 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3525 *ppFuncDesc = heap_alloc_zero(sizeof(**ppFuncDesc));
3527 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3528 case SLTG_FUNCTION_MAGIC:
3529 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3531 case SLTG_DISPATCH_FUNCTION_MAGIC:
3532 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3534 case SLTG_STATIC_FUNCTION_MAGIC:
3535 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3538 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3539 heap_free(*ppFuncDesc);
3543 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3545 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3546 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3547 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3548 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3549 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3550 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3552 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3553 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3555 if(pFunc->retnextopt & 0x80)
3556 pType = &pFunc->rettype;
3558 pType = (WORD*)(pBlk + pFunc->rettype);
3560 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3562 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3563 heap_alloc_zero((*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3564 (*ppFuncDesc)->pParamDesc =
3565 heap_alloc_zero((*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3567 pArg = (WORD*)(pBlk + pFunc->arg_off);
3569 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3570 char *paramName = pNameTable + *pArg;
3572 /* If arg type follows then paramName points to the 2nd
3573 letter of the name, else the next WORD is an offset to
3574 the arg type and paramName points to the first letter.
3575 So let's take one char off paramName and see if we're
3576 pointing at an alpha-numeric char. However if *pArg is
3577 0xffff or 0xfffe then the param has no name, the former
3578 meaning that the next WORD is the type, the latter
3579 meaning that the next WORD is an offset to the type. */
3584 else if(*pArg == 0xfffe) {
3588 else if(paramName[-1] && !isalnum(paramName[-1]))
3593 if(HaveOffs) { /* the next word is an offset to type */
3594 pType = (WORD*)(pBlk + *pArg);
3595 SLTG_DoElem(pType, pBlk,
3596 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3601 pArg = SLTG_DoElem(pArg, pBlk,
3602 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3605 /* Are we an optional param ? */
3606 if((*ppFuncDesc)->funcdesc.cParams - param <=
3607 (*ppFuncDesc)->funcdesc.cParamsOpt)
3608 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3611 (*ppFuncDesc)->pParamDesc[param].Name =
3612 TLB_MultiByteToBSTR(paramName);
3614 (*ppFuncDesc)->pParamDesc[param].Name =
3615 SysAllocString((*ppFuncDesc)->Name);
3619 ppFuncDesc = &((*ppFuncDesc)->next);
3620 if(pFunc->next == 0xffff) break;
3622 pTI->TypeAttr.cFuncs = cFuncs;
3625 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3626 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3627 SLTG_TypeInfoTail *pTITail)
3630 sltg_ref_lookup_t *ref_lookup = NULL;
3632 if(pTIHeader->href_table != 0xffffffff) {
3633 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3639 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3640 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3642 heap_free(ref_lookup);
3646 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3647 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3648 const SLTG_TypeInfoTail *pTITail)
3651 sltg_ref_lookup_t *ref_lookup = NULL;
3653 if(pTIHeader->href_table != 0xffffffff) {
3654 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3660 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3661 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3664 if (pTITail->funcs_off != 0xffff)
3665 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3667 heap_free(ref_lookup);
3669 if (TRACE_ON(typelib))
3670 dump_TLBFuncDesc(pTI->funclist);
3673 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3674 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3675 const SLTG_TypeInfoTail *pTITail)
3677 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3680 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3681 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3682 const SLTG_TypeInfoTail *pTITail)
3685 sltg_ref_lookup_t *ref_lookup = NULL;
3687 if (pTITail->simple_alias) {
3688 /* if simple alias, no more processing required */
3689 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3693 if(pTIHeader->href_table != 0xffffffff) {
3694 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3698 /* otherwise it is an offset to a type */
3699 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3701 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3703 heap_free(ref_lookup);
3706 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3707 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3708 const SLTG_TypeInfoTail *pTITail)
3710 sltg_ref_lookup_t *ref_lookup = NULL;
3711 if (pTIHeader->href_table != 0xffffffff)
3712 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3715 if (pTITail->vars_off != 0xffff)
3716 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3718 if (pTITail->funcs_off != 0xffff)
3719 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3721 if (pTITail->impls_off != 0xffff)
3722 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3724 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3725 * of dispinterface functions including the IDispatch ones, so
3726 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3727 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3729 heap_free(ref_lookup);
3730 if (TRACE_ON(typelib))
3731 dump_TLBFuncDesc(pTI->funclist);
3734 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3735 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3736 const SLTG_TypeInfoTail *pTITail)
3738 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3741 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3742 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3743 const SLTG_TypeInfoTail *pTITail)
3745 sltg_ref_lookup_t *ref_lookup = NULL;
3746 if (pTIHeader->href_table != 0xffffffff)
3747 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3750 if (pTITail->vars_off != 0xffff)
3751 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3753 if (pTITail->funcs_off != 0xffff)
3754 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3755 heap_free(ref_lookup);
3756 if (TRACE_ON(typelib))
3760 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3761 managable copy of it into this */
3774 } SLTG_InternalOtherTypeInfo;
3776 /****************************************************************************
3777 * ITypeLib2_Constructor_SLTG
3779 * loading a SLTG typelib from an in-memory image
3781 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3783 ITypeLibImpl *pTypeLibImpl;
3784 SLTG_Header *pHeader;
3785 SLTG_BlkEntry *pBlkEntry;
3789 LPVOID pBlk, pFirstBlk;
3790 SLTG_LibBlk *pLibBlk;
3791 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3792 char *pAfterOTIBlks = NULL;
3793 char *pNameTable, *ptr;
3796 ITypeInfoImpl **ppTypeInfoImpl;
3798 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3801 pTypeLibImpl = TypeLibImpl_Constructor();
3802 if (!pTypeLibImpl) return NULL;
3806 TRACE_(typelib)("header:\n");
3807 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3808 pHeader->nrOfFileBlks );
3809 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3810 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3811 pHeader->SLTG_magic);
3815 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3816 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3818 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3819 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3821 /* Next we have a magic block */
3822 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3824 /* Let's see if we're still in sync */
3825 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3826 sizeof(SLTG_COMPOBJ_MAGIC))) {
3827 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3830 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3831 sizeof(SLTG_DIR_MAGIC))) {
3832 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3836 pIndex = (SLTG_Index*)(pMagic+1);
3838 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3840 pFirstBlk = pPad9 + 1;
3842 /* We'll set up a ptr to the main library block, which is the last one. */
3844 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3845 pBlkEntry[order].next != 0;
3846 order = pBlkEntry[order].next - 1, i++) {
3847 pBlk = (char*)pBlk + pBlkEntry[order].len;
3851 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3853 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3858 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3860 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3863 ptr = (char*)pLibBlk + len;
3865 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3869 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3871 w = *(WORD*)(ptr + 2);
3874 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
3875 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3876 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3878 w = *(WORD*)(ptr + 4 + len);
3880 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3882 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
3883 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3884 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3886 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3887 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3888 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3890 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
3891 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3894 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3895 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3896 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3897 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3898 len += sizeof(SLTG_OtherTypeInfo);
3902 pAfterOTIBlks = ptr;
3904 /* Skip this WORD and get the next DWORD */
3905 len = *(DWORD*)(pAfterOTIBlks + 2);
3907 /* Now add this to pLibBLk look at what we're pointing at and
3908 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3909 dust and we should be pointing at the beginning of the name
3912 pNameTable = (char*)pLibBlk + len;
3914 switch(*(WORD*)pNameTable) {
3921 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3925 pNameTable += 0x216;
3929 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3931 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3934 /* Hopefully we now have enough ptrs set up to actually read in
3935 some TypeInfos. It's not clear which order to do them in, so
3936 I'll just follow the links along the BlkEntry chain and read
3937 them in the order in which they are in the file */
3939 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3941 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3942 pBlkEntry[order].next != 0;
3943 order = pBlkEntry[order].next - 1, i++) {
3945 SLTG_TypeInfoHeader *pTIHeader;
3946 SLTG_TypeInfoTail *pTITail;
3947 SLTG_MemberHeader *pMemHeader;
3949 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3950 pOtherTypeInfoBlks[i].index_name)) {
3951 FIXME_(typelib)("Index strings don't match\n");
3956 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3957 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3960 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3961 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3962 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3964 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3965 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3966 (*ppTypeInfoImpl)->index = i;
3967 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3968 pOtherTypeInfoBlks[i].name_offs +
3970 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3971 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3972 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3973 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3974 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3975 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3976 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3978 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3979 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3981 if((pTIHeader->typeflags1 & 7) != 2)
3982 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3983 if(pTIHeader->typeflags3 != 2)
3984 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3986 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3987 debugstr_w((*ppTypeInfoImpl)->Name),
3988 typekind_desc[pTIHeader->typekind],
3989 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3990 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3992 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3994 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3996 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3997 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3998 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4000 switch(pTIHeader->typekind) {
4002 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4003 pTIHeader, pTITail);
4007 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4008 pTIHeader, pTITail);
4011 case TKIND_INTERFACE:
4012 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4013 pTIHeader, pTITail);
4017 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4018 pTIHeader, pTITail);
4022 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4023 pTIHeader, pTITail);
4026 case TKIND_DISPATCH:
4027 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4028 pTIHeader, pTITail);
4032 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4033 pTIHeader, pTITail);
4037 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4042 /* could get cFuncs, cVars and cImplTypes from here
4043 but we've already set those */
4044 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4059 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4060 pBlk = (char*)pBlk + pBlkEntry[order].len;
4063 if(i != pTypeLibImpl->TypeInfoCount) {
4064 FIXME("Somehow processed %d TypeInfos\n", i);
4068 heap_free(pOtherTypeInfoBlks);
4069 return (ITypeLib2*)pTypeLibImpl;
4072 /* ITypeLib::QueryInterface
4074 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4079 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4081 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4084 if(IsEqualIID(riid, &IID_IUnknown) ||
4085 IsEqualIID(riid,&IID_ITypeLib)||
4086 IsEqualIID(riid,&IID_ITypeLib2))
4093 ITypeLib2_AddRef(iface);
4094 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4097 TRACE("-- Interface: E_NOINTERFACE\n");
4098 return E_NOINTERFACE;
4103 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4105 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4106 ULONG ref = InterlockedIncrement(&This->ref);
4108 TRACE("(%p)->ref was %u\n",This, ref - 1);
4113 /* ITypeLib::Release
4115 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4117 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4118 ULONG ref = InterlockedDecrement(&This->ref);
4120 TRACE("(%p)->(%u)\n",This, ref);
4124 TLBImpLib *pImpLib, *pImpLibNext;
4125 TLBCustData *pCustData, *pCustDataNext;
4126 TLBRefType *ref_type;
4129 ITypeInfoImpl *pTI, *pTINext;
4131 /* remove cache entry */
4134 TRACE("removing from cache list\n");
4135 EnterCriticalSection(&cache_section);
4136 if (This->next) This->next->prev = This->prev;
4137 if (This->prev) This->prev->next = This->next;
4138 else tlb_cache_first = This->next;
4139 LeaveCriticalSection(&cache_section);
4140 heap_free(This->path);
4142 TRACE(" destroying ITypeLib(%p)\n",This);
4144 SysFreeString(This->Name);
4147 SysFreeString(This->DocString);
4148 This->DocString = NULL;
4150 SysFreeString(This->HelpFile);
4151 This->HelpFile = NULL;
4153 SysFreeString(This->HelpStringDll);
4154 This->HelpStringDll = NULL;
4156 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4158 VariantClear(&pCustData->data);
4160 pCustDataNext = pCustData->next;
4161 heap_free(pCustData);
4164 for (i = 0; i < This->ctTypeDesc; i++)
4165 if (This->pTypeDesc[i].vt == VT_CARRAY)
4166 heap_free(This->pTypeDesc[i].u.lpadesc);
4168 heap_free(This->pTypeDesc);
4170 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4172 if (pImpLib->pImpTypeLib)
4173 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4174 SysFreeString(pImpLib->name);
4176 pImpLibNext = pImpLib->next;
4180 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4182 list_remove(&ref_type->entry);
4183 heap_free(ref_type);
4186 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4188 pTINext = pTI->next;
4189 ITypeInfo_fnDestroy(pTI);
4198 /* ITypeLib::GetTypeInfoCount
4200 * Returns the number of type descriptions in the type library
4202 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4204 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4205 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4206 return This->TypeInfoCount;
4209 /* ITypeLib::GetTypeInfo
4211 * retrieves the specified type description in the library.
4213 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4216 ITypeInfo **ppTInfo)
4220 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4221 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4223 TRACE("(%p)->(index=%d)\n", This, index);
4225 if (!ppTInfo) return E_INVALIDARG;
4227 /* search element n in list */
4228 for(i=0; i < index; i++)
4230 pTypeInfo = pTypeInfo->next;
4233 TRACE("-- element not found\n");
4234 return TYPE_E_ELEMENTNOTFOUND;
4238 *ppTInfo = (ITypeInfo *) pTypeInfo;
4240 ITypeInfo_AddRef(*ppTInfo);
4241 TRACE("-- found (%p)\n",*ppTInfo);
4246 /* ITypeLibs::GetTypeInfoType
4248 * Retrieves the type of a type description.
4250 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4255 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4257 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4259 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4261 if(!pTKind) return E_INVALIDARG;
4263 if(ITypeLib2_GetTypeInfoCount(iface) <= index)
4264 return TYPE_E_ELEMENTNOTFOUND;
4266 /* search element n in list */
4267 for(i=0; i < index; i++)
4271 TRACE("-- element not found\n");
4272 return TYPE_E_ELEMENTNOTFOUND;
4274 pTInfo = pTInfo->next;
4277 *pTKind = pTInfo->TypeAttr.typekind;
4278 TRACE("-- found Type (%d)\n", *pTKind);
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;
4293 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4295 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4299 WARN("-- element not found\n");
4300 return TYPE_E_ELEMENTNOTFOUND;
4303 /* search linked list for guid */
4304 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4306 pTypeInfo = pTypeInfo->next;
4310 /* end of list reached */
4311 WARN("-- element not found\n");
4312 return TYPE_E_ELEMENTNOTFOUND;
4316 TRACE("-- found (%p, %s)\n",
4318 debugstr_w(pTypeInfo->Name));
4320 *ppTInfo = (ITypeInfo*)pTypeInfo;
4321 ITypeInfo_AddRef(*ppTInfo);
4325 /* ITypeLib::GetLibAttr
4327 * Retrieves the structure that contains the library's attributes.
4330 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4334 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4336 TRACE("(%p, %p)\n", This, attr);
4338 if (!attr) return E_INVALIDARG;
4340 *attr = heap_alloc(sizeof(**attr));
4341 if (!*attr) return E_OUTOFMEMORY;
4343 **attr = This->LibAttr;
4347 /* ITypeLib::GetTypeComp
4349 * Enables a client compiler to bind to a library's types, variables,
4350 * constants, and global functions.
4353 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4355 ITypeComp **ppTComp)
4357 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4359 TRACE("(%p)->(%p)\n",This,ppTComp);
4360 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4361 ITypeComp_AddRef(*ppTComp);
4366 /* ITypeLib::GetDocumentation
4368 * Retrieves the library's documentation string, the complete Help file name
4369 * and path, and the context identifier for the library Help topic in the Help
4372 * On a successful return all non-null BSTR pointers will have been set,
4375 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4379 BSTR *pBstrDocString,
4380 DWORD *pdwHelpContext,
4381 BSTR *pBstrHelpFile)
4383 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4385 HRESULT result = E_INVALIDARG;
4390 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4392 pBstrName, pBstrDocString,
4393 pdwHelpContext, pBstrHelpFile);
4397 /* documentation for the typelib */
4402 if(!(*pBstrName = SysAllocString(This->Name)))
4410 if (This->DocString)
4412 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4415 else if (This->Name)
4417 if(!(*pBstrDocString = SysAllocString(This->Name)))
4421 *pBstrDocString = NULL;
4425 *pdwHelpContext = This->dwHelpContext;
4431 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4435 *pBstrHelpFile = NULL;
4442 /* for a typeinfo */
4443 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4445 if(SUCCEEDED(result))
4447 result = ITypeInfo_GetDocumentation(pTInfo,
4451 pdwHelpContext, pBstrHelpFile);
4453 ITypeInfo_Release(pTInfo);
4458 if (pBstrDocString) SysFreeString (*pBstrDocString);
4460 if (pBstrName) SysFreeString (*pBstrName);
4462 return STG_E_INSUFFICIENTMEMORY;
4467 * Indicates whether a passed-in string contains the name of a type or member
4468 * described in the library.
4471 static HRESULT WINAPI ITypeLib2_fnIsName(
4477 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4478 ITypeInfoImpl *pTInfo;
4479 TLBFuncDesc *pFInfo;
4482 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4484 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4488 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4489 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4490 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4491 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4492 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4493 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4494 goto ITypeLib2_fnIsName_exit;
4496 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4497 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4502 ITypeLib2_fnIsName_exit:
4503 TRACE("(%p)slow! search for %s: %s found!\n", This,
4504 debugstr_w(szNameBuf), *pfName?"NOT":"");
4509 /* ITypeLib::FindName
4511 * Finds occurrences of a type description in a type library. This may be used
4512 * to quickly verify that a name exists in a type library.
4515 static HRESULT WINAPI ITypeLib2_fnFindName(
4519 ITypeInfo **ppTInfo,
4523 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4524 ITypeInfoImpl *pTInfo;
4525 TLBFuncDesc *pFInfo;
4528 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4530 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4531 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4532 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4533 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4534 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4535 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4536 goto ITypeLib2_fnFindName_exit;
4539 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4540 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4542 ITypeLib2_fnFindName_exit:
4543 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4544 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4547 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4548 This, *pcFound, debugstr_w(szNameBuf), j);
4555 /* ITypeLib::ReleaseTLibAttr
4557 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4560 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4562 TLIBATTR *pTLibAttr)
4564 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4565 TRACE("freeing (%p)\n",This);
4566 heap_free(pTLibAttr);
4570 /* ITypeLib2::GetCustData
4572 * gets the custom data
4574 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4579 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4580 TLBCustData *pCData;
4582 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4584 if( IsEqualIID(guid, &pCData->guid)) break;
4587 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4591 VariantInit( pVarVal);
4592 VariantCopy( pVarVal, &pCData->data);
4595 return E_INVALIDARG; /* FIXME: correct? */
4598 /* ITypeLib2::GetLibStatistics
4600 * Returns statistics about a type library that are required for efficient
4601 * sizing of hash tables.
4604 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4606 ULONG *pcUniqueNames,
4607 ULONG *pcchUniqueNames)
4609 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4611 FIXME("(%p): stub!\n", This);
4613 if(pcUniqueNames) *pcUniqueNames=1;
4614 if(pcchUniqueNames) *pcchUniqueNames=1;
4618 /* ITypeLib2::GetDocumentation2
4620 * Retrieves the library's documentation string, the complete Help file name
4621 * and path, the localization context to use, and the context ID for the
4622 * library Help topic in the Help file.
4625 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4629 BSTR *pbstrHelpString,
4630 DWORD *pdwHelpStringContext,
4631 BSTR *pbstrHelpStringDll)
4633 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4637 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4639 /* the help string should be obtained from the helpstringdll,
4640 * using the _DLLGetDocumentation function, based on the supplied
4641 * lcid. Nice to do sometime...
4645 /* documentation for the typelib */
4647 *pbstrHelpString=SysAllocString(This->DocString);
4648 if(pdwHelpStringContext)
4649 *pdwHelpStringContext=This->dwHelpContext;
4650 if(pbstrHelpStringDll)
4651 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4657 /* for a typeinfo */
4658 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4660 if(SUCCEEDED(result))
4662 ITypeInfo2 * pTInfo2;
4663 result = ITypeInfo_QueryInterface(pTInfo,
4665 (LPVOID*) &pTInfo2);
4667 if(SUCCEEDED(result))
4669 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4673 pdwHelpStringContext,
4674 pbstrHelpStringDll);
4676 ITypeInfo2_Release(pTInfo2);
4679 ITypeInfo_Release(pTInfo);
4685 /* ITypeLib2::GetAllCustData
4687 * Gets all custom data items for the library.
4690 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4692 CUSTDATA *pCustData)
4694 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4695 TLBCustData *pCData;
4697 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4698 pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
4699 if(pCustData->prgCustData ){
4700 pCustData->cCustData=This->ctCustData;
4701 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4702 pCustData->prgCustData[i].guid=pCData->guid;
4703 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4706 ERR(" OUT OF MEMORY!\n");
4707 return E_OUTOFMEMORY;
4712 static const ITypeLib2Vtbl tlbvt = {
4713 ITypeLib2_fnQueryInterface,
4715 ITypeLib2_fnRelease,
4716 ITypeLib2_fnGetTypeInfoCount,
4717 ITypeLib2_fnGetTypeInfo,
4718 ITypeLib2_fnGetTypeInfoType,
4719 ITypeLib2_fnGetTypeInfoOfGuid,
4720 ITypeLib2_fnGetLibAttr,
4721 ITypeLib2_fnGetTypeComp,
4722 ITypeLib2_fnGetDocumentation,
4724 ITypeLib2_fnFindName,
4725 ITypeLib2_fnReleaseTLibAttr,
4727 ITypeLib2_fnGetCustData,
4728 ITypeLib2_fnGetLibStatistics,
4729 ITypeLib2_fnGetDocumentation2,
4730 ITypeLib2_fnGetAllCustData
4734 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4736 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4738 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4741 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4743 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4745 return ITypeLib2_AddRef((ITypeLib2 *)This);
4748 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4750 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4752 return ITypeLib2_Release((ITypeLib2 *)This);
4755 static HRESULT WINAPI ITypeLibComp_fnBind(
4760 ITypeInfo ** ppTInfo,
4761 DESCKIND * pDescKind,
4764 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4765 ITypeInfoImpl *pTypeInfo;
4768 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4770 *pDescKind = DESCKIND_NONE;
4771 pBindPtr->lptcomp = NULL;
4774 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4776 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4778 /* FIXME: check wFlags here? */
4779 /* FIXME: we should use a hash table to look this info up using lHash
4780 * instead of an O(n) search */
4781 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4782 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4784 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4786 *pDescKind = DESCKIND_TYPECOMP;
4787 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4788 ITypeComp_AddRef(pBindPtr->lptcomp);
4789 TRACE("module or enum: %s\n", debugstr_w(szName));
4794 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4795 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4797 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4800 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4801 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4803 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4806 else if (hr == TYPE_E_TYPEMISMATCH)
4810 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4811 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4813 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4815 ITypeInfo *subtypeinfo;
4817 DESCKIND subdesckind;
4819 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4820 &subtypeinfo, &subdesckind, &subbindptr);
4821 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4823 TYPEDESC tdesc_appobject;
4824 const VARDESC vardesc_appobject =
4827 NULL, /* lpstrSchema */
4842 VAR_STATIC /* varkind */
4845 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4846 tdesc_appobject.vt = VT_USERDEFINED;
4848 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4850 /* cleanup things filled in by Bind call so we can put our
4851 * application object data in there instead */
4852 switch (subdesckind)
4854 case DESCKIND_FUNCDESC:
4855 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4857 case DESCKIND_VARDESC:
4858 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4863 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4865 if (pTypeInfo->hreftype == -1)
4866 FIXME("no hreftype for interface %p\n", pTypeInfo);
4868 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4872 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4873 *ppTInfo = (ITypeInfo *)pTypeInfo;
4874 ITypeInfo_AddRef(*ppTInfo);
4877 else if (hr == TYPE_E_TYPEMISMATCH)
4884 TRACE("type mismatch %s\n", debugstr_w(szName));
4885 return TYPE_E_TYPEMISMATCH;
4889 TRACE("name not found %s\n", debugstr_w(szName));
4894 static HRESULT WINAPI ITypeLibComp_fnBindType(
4898 ITypeInfo ** ppTInfo,
4899 ITypeComp ** ppTComp)
4901 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4902 ITypeInfoImpl *pTypeInfo;
4904 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4906 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4908 /* FIXME: should use lHash to do the search */
4909 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4911 TRACE("returning %p\n", pTypeInfo);
4912 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4913 ITypeInfo_AddRef(*ppTInfo);
4914 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4915 ITypeComp_AddRef(*ppTComp);
4920 TRACE("not found\n");
4926 static const ITypeCompVtbl tlbtcvt =
4929 ITypeLibComp_fnQueryInterface,
4930 ITypeLibComp_fnAddRef,
4931 ITypeLibComp_fnRelease,
4933 ITypeLibComp_fnBind,
4934 ITypeLibComp_fnBindType
4937 /*================== ITypeInfo(2) Methods ===================================*/
4938 static ITypeInfo2 * ITypeInfo_Constructor(void)
4940 ITypeInfoImpl * pTypeInfoImpl;
4942 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
4945 pTypeInfoImpl->lpVtbl = &tinfvt;
4946 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4947 pTypeInfoImpl->ref = 0;
4948 pTypeInfoImpl->hreftype = -1;
4949 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4950 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4952 TRACE("(%p)\n", pTypeInfoImpl);
4953 return (ITypeInfo2*) pTypeInfoImpl;
4956 /* ITypeInfo::QueryInterface
4958 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4963 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4965 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4968 if(IsEqualIID(riid, &IID_IUnknown) ||
4969 IsEqualIID(riid,&IID_ITypeInfo)||
4970 IsEqualIID(riid,&IID_ITypeInfo2))
4974 ITypeInfo_AddRef(iface);
4975 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4978 TRACE("-- Interface: E_NOINTERFACE\n");
4979 return E_NOINTERFACE;
4982 /* ITypeInfo::AddRef
4984 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4986 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4987 ULONG ref = InterlockedIncrement(&This->ref);
4989 TRACE("(%p)->ref is %u\n",This, ref);
4991 if (ref == 1 /* incremented from 0 */)
4992 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4997 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This)
4999 TLBFuncDesc *pFInfo, *pFInfoNext;
5000 TLBVarDesc *pVInfo, *pVInfoNext;
5001 TLBImplType *pImpl, *pImplNext;
5003 TRACE("destroying ITypeInfo(%p)\n",This);
5005 SysFreeString(This->Name);
5008 SysFreeString(This->DocString);
5009 This->DocString = NULL;
5011 SysFreeString(This->DllName);
5012 This->DllName = NULL;
5014 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
5017 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
5019 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
5020 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5022 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5023 heap_free(elemdesc->u.paramdesc.pparamdescex);
5025 SysFreeString(pFInfo->pParamDesc[i].Name);
5027 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5028 heap_free(pFInfo->pParamDesc);
5029 TLB_FreeCustData(pFInfo->pCustData);
5030 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5031 SysFreeString(pFInfo->Entry);
5032 SysFreeString(pFInfo->HelpString);
5033 SysFreeString(pFInfo->Name);
5035 pFInfoNext = pFInfo->next;
5038 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5040 if (pVInfo->vardesc.varkind == VAR_CONST)
5042 VariantClear(pVInfo->vardesc.u.lpvarValue);
5043 heap_free(pVInfo->vardesc.u.lpvarValue);
5045 TLB_FreeCustData(pVInfo->pCustData);
5046 SysFreeString(pVInfo->Name);
5047 pVInfoNext = pVInfo->next;
5050 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5052 TLB_FreeCustData(pImpl->pCustData);
5053 pImplNext = pImpl->next;
5056 TLB_FreeCustData(This->pCustData);
5061 /* ITypeInfo::Release
5063 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5065 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5066 ULONG ref = InterlockedDecrement(&This->ref);
5068 TRACE("(%p)->(%u)\n",This, ref);
5072 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5073 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5074 if (not_attached_to_typelib)
5076 /* otherwise This will be freed when typelib is freed */
5082 /* ITypeInfo::GetTypeAttr
5084 * Retrieves a TYPEATTR structure that contains the attributes of the type
5088 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5089 LPTYPEATTR *ppTypeAttr)
5091 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5094 TRACE("(%p)\n",This);
5096 size = sizeof(**ppTypeAttr);
5097 if (This->TypeAttr.typekind == TKIND_ALIAS)
5098 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5100 *ppTypeAttr = heap_alloc(size);
5102 return E_OUTOFMEMORY;
5104 **ppTypeAttr = This->TypeAttr;
5106 if (This->TypeAttr.typekind == TKIND_ALIAS)
5107 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5108 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5110 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5111 /* This should include all the inherited funcs */
5112 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5113 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5114 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5119 /* ITypeInfo::GetTypeComp
5121 * Retrieves the ITypeComp interface for the type description, which enables a
5122 * client compiler to bind to the type description's members.
5125 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5126 ITypeComp * *ppTComp)
5128 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5130 TRACE("(%p)->(%p)\n", This, ppTComp);
5132 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5133 ITypeComp_AddRef(*ppTComp);
5137 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5139 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5140 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5141 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5145 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5148 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5149 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5151 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5152 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5153 *buffer += sizeof(PARAMDESCEX);
5154 *pparamdescex_dest = *pparamdescex_src;
5155 VariantInit(&pparamdescex_dest->varDefaultValue);
5156 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5157 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5160 dest->u.paramdesc.pparamdescex = NULL;
5164 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5166 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5167 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5170 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5174 SIZE_T size = sizeof(*src);
5178 size += sizeof(*src->lprgscode) * src->cScodes;
5179 size += TLB_SizeElemDesc(&src->elemdescFunc);
5180 for (i = 0; i < src->cParams; i++)
5182 size += sizeof(ELEMDESC);
5183 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5186 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5187 if (!dest) return E_OUTOFMEMORY;
5190 if (dispinterface) /* overwrite funckind */
5191 dest->funckind = FUNC_DISPATCH;
5192 buffer = (char *)(dest + 1);
5194 dest->lprgscode = (SCODE *)buffer;
5195 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5196 buffer += sizeof(*src->lprgscode) * src->cScodes;
5198 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5201 SysFreeString((BSTR)dest);
5205 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5206 buffer += sizeof(ELEMDESC) * src->cParams;
5207 for (i = 0; i < src->cParams; i++)
5209 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5215 /* undo the above actions */
5216 for (i = i - 1; i >= 0; i--)
5217 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5218 TLB_FreeElemDesc(&dest->elemdescFunc);
5219 SysFreeString((BSTR)dest);
5223 /* special treatment for dispinterfaces: this makes functions appear
5224 * to return their [retval] value when it is really returning an
5226 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5228 if (dest->cParams &&
5229 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5231 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5232 if (elemdesc->tdesc.vt != VT_PTR)
5234 ERR("elemdesc should have started with VT_PTR instead of:\n");
5236 dump_ELEMDESC(elemdesc);
5237 return E_UNEXPECTED;
5240 /* copy last parameter to the return value. we are using a flat
5241 * buffer so there is no danger of leaking memory in
5243 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5245 /* remove the last parameter */
5249 /* otherwise this function is made to appear to have no return
5251 dest->elemdescFunc.tdesc.vt = VT_VOID;
5259 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5261 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5262 const TLBFuncDesc *pFDesc;
5265 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5270 *ppFuncDesc = &pFDesc->funcdesc;
5274 return TYPE_E_ELEMENTNOTFOUND;
5277 /* internal function to make the inherited interfaces' methods appear
5278 * part of the interface */
5279 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5280 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5282 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5284 UINT implemented_funcs = 0;
5289 *hrefoffset = DISPATCH_HREF_OFFSET;
5291 if(This->impltypelist)
5293 ITypeInfo *pSubTypeInfo;
5296 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5300 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5303 &sub_funcs, hrefoffset);
5304 implemented_funcs += sub_funcs;
5305 ITypeInfo_Release(pSubTypeInfo);
5308 *hrefoffset += DISPATCH_HREF_OFFSET;
5312 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5316 if (index < implemented_funcs)
5317 return E_INVALIDARG;
5318 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5322 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5324 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5327 switch (pTypeDesc->vt)
5329 case VT_USERDEFINED:
5330 pTypeDesc->u.hreftype += hrefoffset;
5334 pTypeDesc = pTypeDesc->u.lptdesc;
5337 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5345 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5348 for (i = 0; i < pFuncDesc->cParams; i++)
5349 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5350 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5353 /* ITypeInfo::GetFuncDesc
5355 * Retrieves the FUNCDESC structure that contains information about a
5356 * specified function.
5359 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5360 LPFUNCDESC *ppFuncDesc)
5362 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5363 const FUNCDESC *internal_funcdesc;
5365 UINT hrefoffset = 0;
5367 TRACE("(%p) index %d\n", This, index);
5369 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5370 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5371 &internal_funcdesc, NULL,
5374 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5375 &internal_funcdesc);
5378 WARN("description for function %d not found\n", index);
5382 hr = TLB_AllocAndInitFuncDesc(
5385 This->TypeAttr.typekind == TKIND_DISPATCH);
5387 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5388 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5390 TRACE("-- 0x%08x\n", hr);
5394 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5398 SIZE_T size = sizeof(*src);
5401 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5402 if (src->varkind == VAR_CONST)
5403 size += sizeof(VARIANT);
5404 size += TLB_SizeElemDesc(&src->elemdescVar);
5406 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5407 if (!dest) return E_OUTOFMEMORY;
5410 buffer = (char *)(dest + 1);
5411 if (src->lpstrSchema)
5414 dest->lpstrSchema = (LPOLESTR)buffer;
5415 len = strlenW(src->lpstrSchema);
5416 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5417 buffer += (len + 1) * sizeof(WCHAR);
5420 if (src->varkind == VAR_CONST)
5424 dest->u.lpvarValue = (VARIANT *)buffer;
5425 *dest->u.lpvarValue = *src->u.lpvarValue;
5426 buffer += sizeof(VARIANT);
5427 VariantInit(dest->u.lpvarValue);
5428 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5431 SysFreeString((BSTR)dest);
5435 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5438 if (src->varkind == VAR_CONST)
5439 VariantClear(dest->u.lpvarValue);
5440 SysFreeString((BSTR)dest);
5447 /* ITypeInfo::GetVarDesc
5449 * Retrieves a VARDESC structure that describes the specified variable.
5452 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5453 LPVARDESC *ppVarDesc)
5455 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5457 const TLBVarDesc *pVDesc;
5459 TRACE("(%p) index %d\n", This, index);
5461 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5465 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5467 return E_INVALIDARG;
5470 /* ITypeInfo_GetNames
5472 * Retrieves the variable with the specified member ID (or the name of the
5473 * property or method and its parameters) that correspond to the specified
5476 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5477 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5479 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5480 const TLBFuncDesc *pFDesc;
5481 const TLBVarDesc *pVDesc;
5483 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5484 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5487 /* function found, now return function and parameter names */
5488 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5491 *rgBstrNames=SysAllocString(pFDesc->Name);
5493 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5499 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5502 *rgBstrNames=SysAllocString(pVDesc->Name);
5507 if(This->impltypelist &&
5508 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5509 /* recursive search */
5512 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5514 if(SUCCEEDED(result))
5516 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5517 ITypeInfo_Release(pTInfo);
5520 WARN("Could not search inherited interface!\n");
5524 WARN("no names found\n");
5527 return TYPE_E_ELEMENTNOTFOUND;
5534 /* ITypeInfo::GetRefTypeOfImplType
5536 * If a type description describes a COM class, it retrieves the type
5537 * description of the implemented interface types. For an interface,
5538 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5542 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5547 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5550 const TLBImplType *pImpl = This->impltypelist;
5552 TRACE("(%p) index %d\n", This, index);
5553 if (TRACE_ON(ole)) dump_TypeInfo(This);
5557 /* only valid on dual interfaces;
5558 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5560 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5562 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5568 hr = TYPE_E_ELEMENTNOTFOUND;
5571 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5573 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5574 *pRefType = This->pTypeLib->dispatch_href;
5578 /* get element n from linked list */
5579 for(i=0; pImpl && i<index; i++)
5581 pImpl = pImpl->next;
5585 *pRefType = pImpl->hRef;
5587 hr = TYPE_E_ELEMENTNOTFOUND;
5593 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5595 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5601 /* ITypeInfo::GetImplTypeFlags
5603 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5604 * or base interface in a type description.
5606 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5607 UINT index, INT *pImplTypeFlags)
5609 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5613 TRACE("(%p) index %d\n", This, index);
5614 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5615 i++, pImpl=pImpl->next)
5617 if(i==index && pImpl){
5618 *pImplTypeFlags=pImpl->implflags;
5623 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5626 WARN("ImplType %d not found\n", index);
5627 return TYPE_E_ELEMENTNOTFOUND;
5631 * Maps between member names and member IDs, and parameter names and
5634 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5635 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5637 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5638 const TLBFuncDesc *pFDesc;
5639 const TLBVarDesc *pVDesc;
5643 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5646 /* init out parameters in case of failure */
5647 for (i = 0; i < cNames; i++)
5648 pMemId[i] = MEMBERID_NIL;
5650 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5652 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5653 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5654 for(i=1; i < cNames; i++){
5655 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5656 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5658 if( j<pFDesc->funcdesc.cParams)
5661 ret=DISP_E_UNKNOWNNAME;
5663 TRACE("-- 0x%08x\n", ret);
5667 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5668 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5669 if(cNames) *pMemId=pVDesc->vardesc.memid;
5673 /* not found, see if it can be found in an inherited interface */
5674 if(This->impltypelist) {
5675 /* recursive search */
5677 ret=ITypeInfo_GetRefTypeInfo(iface,
5678 This->impltypelist->hRef, &pTInfo);
5680 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5681 ITypeInfo_Release(pTInfo);
5684 WARN("Could not search inherited interface!\n");
5686 WARN("no names found\n");
5687 return DISP_E_UNKNOWNNAME;
5693 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5694 __ASM_GLOBAL_FUNC( call_method,
5696 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5697 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5698 "movl %esp,%ebp\n\t"
5699 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5701 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5703 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5704 "movl 12(%ebp),%edx\n\t"
5705 "movl %esp,%edi\n\t"
5708 "subl %edx,%edi\n\t"
5709 "andl $~15,%edi\n\t"
5710 "movl %edi,%esp\n\t"
5711 "movl 12(%ebp),%ecx\n\t"
5712 "movl 16(%ebp),%esi\n\t"
5715 "1:\tcall *8(%ebp)\n\t"
5716 "subl %esp,%edi\n\t"
5717 "movl 20(%ebp),%ecx\n\t"
5718 "movl %edi,(%ecx)\n\t"
5719 "leal -8(%ebp),%esp\n\t"
5721 __ASM_CFI(".cfi_same_value %edi\n\t")
5723 __ASM_CFI(".cfi_same_value %esi\n\t")
5725 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5726 __ASM_CFI(".cfi_same_value %ebp\n\t")
5729 /* same function but returning floating point */
5730 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5732 /* ITypeInfo::Invoke
5734 * Invokes a method, or accesses a property of an object, that implements the
5735 * interface described by the type description.
5738 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5742 if (TRACE_ON(ole)) {
5744 TRACE("Calling %p(",func);
5745 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5746 if (nrargs > 30) TRACE("...");
5753 res = call_method( func, nrargs, args, &stack_offset );
5756 FIXME("unsupported calling convention %d\n",callconv);
5760 TRACE("returns %08x\n",res);
5764 #elif defined(__x86_64__)
5766 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5767 __ASM_GLOBAL_FUNC( call_method,
5769 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5770 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5771 "movq %rsp,%rbp\n\t"
5772 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5774 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5776 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5777 "movq %rcx,%rax\n\t"
5780 "cmovgq %rdx,%rcx\n\t"
5781 "leaq 0(,%rcx,8),%rdx\n\t"
5782 "subq %rdx,%rsp\n\t"
5783 "andq $~15,%rsp\n\t"
5784 "movq %rsp,%rdi\n\t"
5787 "movq 0(%rsp),%rcx\n\t"
5788 "movq 8(%rsp),%rdx\n\t"
5789 "movq 16(%rsp),%r8\n\t"
5790 "movq 24(%rsp),%r9\n\t"
5791 "movq %rcx,%xmm0\n\t"
5792 "movq %rdx,%xmm1\n\t"
5793 "movq %r8,%xmm2\n\t"
5794 "movq %r9,%xmm3\n\t"
5796 "leaq -16(%rbp),%rsp\n\t"
5798 __ASM_CFI(".cfi_same_value %rdi\n\t")
5800 __ASM_CFI(".cfi_same_value %rsi\n\t")
5801 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5803 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5804 __ASM_CFI(".cfi_same_value %rbp\n\t")
5807 /* same function but returning floating point */
5808 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5810 #endif /* __x86_64__ */
5812 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5815 ITypeInfo *tinfo2 = NULL;
5816 TYPEATTR *tattr = NULL;
5818 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5821 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5823 tdesc->u.hreftype, hr);
5826 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5829 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5830 ITypeInfo_Release(tinfo2);
5834 switch (tattr->typekind)
5841 tdesc = &tattr->tdescAlias;
5842 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5845 case TKIND_INTERFACE:
5846 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5852 case TKIND_DISPATCH:
5861 FIXME("TKIND_RECORD unhandled.\n");
5866 FIXME("TKIND_UNION unhandled.\n");
5871 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5875 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5876 ITypeInfo_Release(tinfo2);
5880 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5884 /* enforce only one level of pointer indirection */
5885 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5887 tdesc = tdesc->u.lptdesc;
5889 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5890 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5891 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5892 if ((tdesc->vt == VT_USERDEFINED) ||
5893 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5895 VARTYPE vt_userdefined = 0;
5896 const TYPEDESC *tdesc_userdefined = tdesc;
5897 if (tdesc->vt == VT_PTR)
5899 vt_userdefined = VT_BYREF;
5900 tdesc_userdefined = tdesc->u.lptdesc;
5902 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5904 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5905 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5907 *vt |= vt_userdefined;
5919 case VT_USERDEFINED:
5920 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5927 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5928 hr = DISP_E_BADVARTYPE;
5932 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5947 /***********************************************************************
5948 * DispCallFunc (OLEAUT32.@)
5950 * Invokes a function of the specified calling convention, passing the
5951 * specified arguments and returns the result.
5954 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5955 * oVft [I] The offset in the vtable. See notes.
5956 * cc [I] Calling convention of the function to call.
5957 * vtReturn [I] The return type of the function.
5958 * cActuals [I] Number of parameters.
5959 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5960 * prgpvarg [I] The arguments to pass.
5961 * pvargResult [O] The return value of the function. Can be NULL.
5965 * Failure: HRESULT code.
5968 * The HRESULT return value of this function is not affected by the return
5969 * value of the user supplied function, which is returned in pvargResult.
5971 * If pvInstance is NULL then a non-object function is to be called and oVft
5972 * is the address of the function to call.
5974 * The cc parameter can be one of the following values:
5987 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5988 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5991 int argspos, stack_offset;
5996 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5997 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5998 pvargResult, V_VT(pvargResult));
6000 if (cc != CC_STDCALL && cc != CC_CDECL)
6002 FIXME("unsupported calling convention %d\n",cc);
6003 return E_INVALIDARG;
6006 /* maximum size for an argument is sizeof(VARIANT) */
6007 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6009 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6013 const FARPROC *vtable = *(FARPROC **)pvInstance;
6014 func = vtable[oVft/sizeof(void *)];
6015 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6017 else func = (void *)oVft;
6019 for (i = 0; i < cActuals; i++)
6021 VARIANT *arg = prgpvarg[i];
6032 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6033 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6037 memcpy( &args[argspos], arg, sizeof(*arg) );
6038 argspos += sizeof(*arg) / sizeof(DWORD);
6040 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6041 args[argspos++] = V_BOOL(arg);
6044 args[argspos++] = V_UI4(arg);
6047 TRACE("arg %u: type %d\n",i,prgvt[i]);
6054 call_method( func, argspos - 1, args + 1, &stack_offset );
6057 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6061 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6065 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6066 call_method( func, argspos, args, &stack_offset );
6071 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6074 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6078 if (stack_offset && cc == CC_STDCALL)
6080 WARN( "stack pointer off by %d\n", stack_offset );
6081 return DISP_E_BADCALLEE;
6083 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6084 TRACE("retval: "); dump_Variant(pvargResult);
6087 #elif defined(__x86_64__)
6093 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6094 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6095 pvargResult, V_VT(pvargResult));
6097 if (cc != CC_STDCALL && cc != CC_CDECL)
6099 FIXME("unsupported calling convention %d\n",cc);
6100 return E_INVALIDARG;
6103 /* maximum size for an argument is sizeof(DWORD_PTR) */
6104 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6106 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6110 const FARPROC *vtable = *(FARPROC **)pvInstance;
6111 func = vtable[oVft/sizeof(void *)];
6112 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6114 else func = (void *)oVft;
6116 for (i = 0; i < cActuals; i++)
6118 VARIANT *arg = prgpvarg[i];
6124 args[argspos++] = (ULONG_PTR)arg;
6126 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6127 args[argspos++] = V_BOOL(arg);
6130 args[argspos++] = V_UI8(arg);
6133 TRACE("arg %u: type %d\n",i,prgvt[i]);
6140 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6144 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6148 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6149 call_method( func, argspos, args );
6152 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6156 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6157 TRACE("retval: "); dump_Variant(pvargResult);
6161 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6162 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6167 #define INVBUF_ELEMENT_SIZE \
6168 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6169 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6170 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6171 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6172 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6173 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6174 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6175 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6177 static HRESULT WINAPI ITypeInfo_fnInvoke(
6182 DISPPARAMS *pDispParams,
6183 VARIANT *pVarResult,
6184 EXCEPINFO *pExcepInfo,
6187 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6189 unsigned int var_index;
6192 const TLBFuncDesc *pFuncInfo;
6194 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6195 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6198 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6199 return DISP_E_MEMBERNOTFOUND;
6203 ERR("NULL pDispParams not allowed\n");
6204 return E_INVALIDARG;
6207 dump_DispParms(pDispParams);
6209 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6211 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6212 pDispParams->cNamedArgs, pDispParams->cArgs);
6213 return E_INVALIDARG;
6216 /* we do this instead of using GetFuncDesc since it will return a fake
6217 * FUNCDESC for dispinterfaces and we want the real function description */
6218 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6219 if ((memid == pFuncInfo->funcdesc.memid) &&
6220 (wFlags & pFuncInfo->funcdesc.invkind) &&
6221 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6225 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6229 TRACE("invoking:\n");
6230 dump_TLBFuncDescOne(pFuncInfo);
6233 switch (func_desc->funckind) {
6234 case FUNC_PUREVIRTUAL:
6235 case FUNC_VIRTUAL: {
6236 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6238 VARIANT retval; /* pointer for storing byref retvals in */
6239 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6240 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6241 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6242 UINT cNamedArgs = pDispParams->cNamedArgs;
6243 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6244 UINT vargs_converted=0;
6248 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6250 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6252 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6253 hres = DISP_E_PARAMNOTFOUND;
6258 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6260 ERR("functions with the vararg attribute do not support named arguments\n");
6261 hres = DISP_E_NONAMEDARGS;
6265 for (i = 0; i < func_desc->cParams; i++)
6267 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6268 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6273 TRACE("changing args\n");
6274 for (i = 0; i < func_desc->cParams; i++)
6276 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6277 VARIANTARG *src_arg;
6279 if (wParamFlags & PARAMFLAG_FLCID)
6282 arg = prgpvarg[i] = &rgvarg[i];
6284 V_I4(arg) = This->pTypeLib->lcid;
6293 for (j = 0; j < cNamedArgs; j++)
6294 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6296 src_arg = &pDispParams->rgvarg[j];
6301 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6303 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6307 if (wParamFlags & PARAMFLAG_FRETVAL)
6309 /* under most conditions the caller is not allowed to
6310 * pass in a dispparam arg in the index of what would be
6311 * the retval parameter. however, there is an exception
6312 * where the extra parameter is used in an extra
6313 * IDispatch::Invoke below */
6314 if ((i < pDispParams->cArgs) &&
6315 ((func_desc->cParams != 1) || !pVarResult ||
6316 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6318 hres = DISP_E_BADPARAMCOUNT;
6322 /* note: this check is placed so that if the caller passes
6323 * in a VARIANTARG for the retval we just ignore it, like
6325 if (i == func_desc->cParams - 1)
6328 arg = prgpvarg[i] = &rgvarg[i];
6329 memset(arg, 0, sizeof(*arg));
6330 V_VT(arg) = rgvt[i];
6331 memset(&retval, 0, sizeof(retval));
6332 V_BYREF(arg) = &retval;
6336 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6337 hres = E_UNEXPECTED;
6343 dump_Variant(src_arg);
6345 if (rgvt[i] == VT_VARIANT)
6346 hres = VariantCopy(&rgvarg[i], src_arg);
6347 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6349 if (rgvt[i] == V_VT(src_arg))
6350 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6353 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6354 if (wParamFlags & PARAMFLAG_FIN)
6355 hres = VariantCopy(&missing_arg[i], src_arg);
6356 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6358 V_VT(&rgvarg[i]) = rgvt[i];
6360 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6363 SAFEARRAYBOUND bound;
6367 bound.cElements = pDispParams->cArgs-i;
6368 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6370 ERR("SafeArrayCreate failed\n");
6373 hres = SafeArrayAccessData(a, (LPVOID)&v);
6376 ERR("SafeArrayAccessData failed with %x\n", hres);
6379 for (j = 0; j < bound.cElements; j++)
6380 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6381 hres = SafeArrayUnaccessData(a);
6384 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6387 V_ARRAY(&rgvarg[i]) = a;
6388 V_VT(&rgvarg[i]) = rgvt[i];
6390 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6392 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6393 if (wParamFlags & PARAMFLAG_FIN)
6394 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6396 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6397 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6398 V_VT(&rgvarg[i]) = rgvt[i];
6400 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6402 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6403 V_VT(&rgvarg[i]) = rgvt[i];
6407 /* FIXME: this doesn't work for VT_BYREF arguments if
6408 * they are not the same type as in the paramdesc */
6409 V_VT(&rgvarg[i]) = V_VT(src_arg);
6410 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6411 V_VT(&rgvarg[i]) = rgvt[i];
6416 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6417 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6418 debugstr_VT(src_arg), debugstr_VF(src_arg));
6421 prgpvarg[i] = &rgvarg[i];
6423 else if (wParamFlags & PARAMFLAG_FOPT)
6426 arg = prgpvarg[i] = &rgvarg[i];
6427 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6429 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6435 VARIANTARG *missing_arg;
6436 /* if the function wants a pointer to a variant then
6437 * set that up, otherwise just pass the VT_ERROR in
6438 * the argument by value */
6439 if (rgvt[i] & VT_BYREF)
6441 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6442 V_VT(arg) = VT_VARIANT | VT_BYREF;
6443 V_VARIANTREF(arg) = missing_arg;
6447 V_VT(missing_arg) = VT_ERROR;
6448 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6453 hres = DISP_E_BADPARAMCOUNT;
6457 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6459 /* VT_VOID is a special case for return types, so it is not
6460 * handled in the general function */
6461 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6462 V_VT(&varresult) = VT_EMPTY;
6465 V_VT(&varresult) = 0;
6466 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6467 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6470 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6471 V_VT(&varresult), func_desc->cParams, rgvt,
6472 prgpvarg, &varresult);
6474 vargs_converted = 0;
6476 for (i = 0; i < func_desc->cParams; i++)
6478 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6479 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6481 if (wParamFlags & PARAMFLAG_FLCID)
6483 else if (wParamFlags & PARAMFLAG_FRETVAL)
6487 TRACE("[retval] value: ");
6488 dump_Variant(prgpvarg[i]);
6493 VariantInit(pVarResult);
6494 /* deref return value */
6495 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6498 VARIANT_ClearInd(prgpvarg[i]);
6500 else if (vargs_converted < pDispParams->cArgs)
6502 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6503 if (wParamFlags & PARAMFLAG_FOUT)
6505 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6507 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6511 ERR("failed to convert param %d to vt %d\n", i,
6512 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6517 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6518 func_desc->cParamsOpt < 0 &&
6519 i == func_desc->cParams-1)
6521 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6524 hres = SafeArrayGetUBound(a, 1, &ubound);
6527 ERR("SafeArrayGetUBound failed with %x\n", hres);
6530 hres = SafeArrayAccessData(a, (LPVOID)&v);
6533 ERR("SafeArrayAccessData failed with %x\n", hres);
6536 for (j = 0; j <= ubound; j++)
6537 VariantClear(&v[j]);
6538 hres = SafeArrayUnaccessData(a);
6541 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6545 VariantClear(&rgvarg[i]);
6548 else if (wParamFlags & PARAMFLAG_FOPT)
6550 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6551 VariantClear(&rgvarg[i]);
6554 VariantClear(&missing_arg[i]);
6557 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6559 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6560 hres = DISP_E_EXCEPTION;
6563 IErrorInfo *pErrorInfo;
6564 pExcepInfo->scode = V_ERROR(&varresult);
6565 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6567 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6568 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6569 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6570 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6572 IErrorInfo_Release(pErrorInfo);
6576 if (V_VT(&varresult) != VT_ERROR)
6578 TRACE("varresult value: ");
6579 dump_Variant(&varresult);
6583 VariantClear(pVarResult);
6584 *pVarResult = varresult;
6587 VariantClear(&varresult);
6590 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6591 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6592 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6593 (pDispParams->cArgs != 0))
6595 if (V_VT(pVarResult) == VT_DISPATCH)
6597 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6598 /* Note: not VariantClear; we still need the dispatch
6599 * pointer to be valid */
6600 VariantInit(pVarResult);
6601 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6602 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6603 pDispParams, pVarResult, pExcepInfo, pArgErr);
6604 IDispatch_Release(pDispatch);
6608 VariantClear(pVarResult);
6609 hres = DISP_E_NOTACOLLECTION;
6617 case FUNC_DISPATCH: {
6620 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6621 if (SUCCEEDED(hres)) {
6622 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6623 hres = IDispatch_Invoke(
6624 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6625 pVarResult,pExcepInfo,pArgErr
6628 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6629 IDispatch_Release(disp);
6631 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6635 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6640 TRACE("-- 0x%08x\n", hres);
6643 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6646 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6647 if(FAILED(hres)) return hres;
6649 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6650 dump_VARDESC(var_desc);
6651 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6655 /* not found, look for it in inherited interfaces */
6656 ITypeInfo2_GetTypeKind(iface, &type_kind);
6657 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6658 if(This->impltypelist) {
6659 /* recursive search */
6661 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6662 if(SUCCEEDED(hres)){
6663 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6664 ITypeInfo_Release(pTInfo);
6667 WARN("Could not search inherited interface!\n");
6670 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6671 return DISP_E_MEMBERNOTFOUND;
6674 /* ITypeInfo::GetDocumentation
6676 * Retrieves the documentation string, the complete Help file name and path,
6677 * and the context ID for the Help topic for a specified type description.
6679 * (Can be tested by the Visual Basic Editor in Word for instance.)
6681 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6682 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6683 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6685 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6686 const TLBFuncDesc *pFDesc;
6687 const TLBVarDesc *pVDesc;
6688 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6689 " HelpContext(%p) HelpFile(%p)\n",
6690 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6691 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6693 *pBstrName=SysAllocString(This->Name);
6695 *pBstrDocString=SysAllocString(This->DocString);
6697 *pdwHelpContext=This->dwHelpContext;
6699 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6701 }else {/* for a member */
6702 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6703 if(pFDesc->funcdesc.memid==memid){
6705 *pBstrName = SysAllocString(pFDesc->Name);
6707 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6709 *pdwHelpContext=pFDesc->helpcontext;
6712 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6713 if(pVDesc->vardesc.memid==memid){
6715 *pBstrName = SysAllocString(pVDesc->Name);
6717 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6719 *pdwHelpContext=pVDesc->HelpContext;
6724 if(This->impltypelist &&
6725 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6726 /* recursive search */
6729 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6731 if(SUCCEEDED(result)) {
6732 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6733 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6734 ITypeInfo_Release(pTInfo);
6737 WARN("Could not search inherited interface!\n");
6740 WARN("member %d not found\n", memid);
6741 return TYPE_E_ELEMENTNOTFOUND;
6744 /* ITypeInfo::GetDllEntry
6746 * Retrieves a description or specification of an entry point for a function
6749 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6750 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6753 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6754 const TLBFuncDesc *pFDesc;
6756 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6758 if (pBstrDllName) *pBstrDllName = NULL;
6759 if (pBstrName) *pBstrName = NULL;
6760 if (pwOrdinal) *pwOrdinal = 0;
6762 if (This->TypeAttr.typekind != TKIND_MODULE)
6763 return TYPE_E_BADMODULEKIND;
6765 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6766 if(pFDesc->funcdesc.memid==memid){
6767 dump_TypeInfo(This);
6769 dump_TLBFuncDescOne(pFDesc);
6772 *pBstrDllName = SysAllocString(This->DllName);
6774 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6776 *pBstrName = SysAllocString(pFDesc->Entry);
6784 *pwOrdinal = LOWORD(pFDesc->Entry);
6787 return TYPE_E_ELEMENTNOTFOUND;
6790 /* internal function to make the inherited interfaces' methods appear
6791 * part of the interface */
6792 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6793 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6795 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6798 TRACE("%p, 0x%x\n", iface, *hRefType);
6800 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6802 ITypeInfo *pSubTypeInfo;
6804 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6808 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6810 ITypeInfo_Release(pSubTypeInfo);
6814 *hRefType -= DISPATCH_HREF_OFFSET;
6816 if (!(*hRefType & DISPATCH_HREF_MASK))
6817 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6822 /* ITypeInfo::GetRefTypeInfo
6824 * If a type description references other type descriptions, it retrieves
6825 * the referenced type descriptions.
6827 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6830 ITypeInfo **ppTInfo)
6832 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6833 HRESULT result = E_FAIL;
6835 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6837 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6838 ITypeInfo_AddRef(*ppTInfo);
6841 else if (hRefType == -1 &&
6842 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6843 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6845 /* when we meet a DUAL dispinterface, we must create the interface
6848 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6851 /* the interface version contains the same information as the dispinterface
6852 * copy the contents of the structs.
6854 *pTypeInfoImpl = *This;
6855 pTypeInfoImpl->ref = 0;
6857 /* change the type to interface */
6858 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6860 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6862 /* the AddRef implicitly adds a reference to the parent typelib, which
6863 * stops the copied data from being destroyed until the new typeinfo's
6864 * refcount goes to zero, but we need to signal to the new instance to
6865 * not free its data structures when it is destroyed */
6866 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6868 ITypeInfo_AddRef(*ppTInfo);
6872 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6873 (This->TypeAttr.typekind == TKIND_DISPATCH))
6875 HREFTYPE href_dispatch = hRefType;
6876 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6878 TLBRefType *ref_type;
6879 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6881 if(ref_type->reference == hRefType)
6884 if(&ref_type->entry == &This->pTypeLib->ref_list)
6886 FIXME("Can't find pRefType for ref %x\n", hRefType);
6889 if(hRefType != -1) {
6890 ITypeLib *pTLib = NULL;
6892 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6894 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6896 if(ref_type->pImpTLInfo->pImpTypeLib) {
6897 TRACE("typeinfo in imported typelib that is already loaded\n");
6898 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6899 ITypeLib2_AddRef(pTLib);
6902 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6903 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6904 ref_type->pImpTLInfo->wVersionMajor,
6905 ref_type->pImpTLInfo->wVersionMinor,
6906 ref_type->pImpTLInfo->lcid,
6909 if(FAILED(result)) {
6910 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6911 result=LoadTypeLib(libnam, &pTLib);
6912 SysFreeString(libnam);
6914 if(SUCCEEDED(result)) {
6915 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6916 ITypeLib2_AddRef(pTLib);
6920 if(SUCCEEDED(result)) {
6921 if(ref_type->index == TLB_REF_USE_GUID)
6922 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6926 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6930 ITypeLib2_Release(pTLib);
6935 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6936 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6940 /* ITypeInfo::AddressOfMember
6942 * Retrieves the addresses of static functions or variables, such as those
6945 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6946 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6948 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6954 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6956 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6960 module = LoadLibraryW(dll);
6963 ERR("couldn't load %s\n", debugstr_w(dll));
6965 SysFreeString(entry);
6966 return STG_E_FILENOTFOUND;
6968 /* FIXME: store library somewhere where we can free it */
6973 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6974 entryA = heap_alloc(len);
6975 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6977 *ppv = GetProcAddress(module, entryA);
6979 ERR("function not found %s\n", debugstr_a(entryA));
6985 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6987 ERR("function not found %d\n", ordinal);
6991 SysFreeString(entry);
6994 return TYPE_E_DLLFUNCTIONNOTFOUND;
6999 /* ITypeInfo::CreateInstance
7001 * Creates a new instance of a type that describes a component object class
7004 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7005 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7007 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7011 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7017 WARN("Not able to aggregate\n");
7018 return CLASS_E_NOAGGREGATION;
7021 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
7022 if(FAILED(hr)) return hr;
7024 if(pTA->typekind != TKIND_COCLASS)
7026 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7032 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7035 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7036 TRACE("GetActiveObject rets %08x\n", hr);
7039 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7040 IUnknown_Release(pUnk);
7045 hr = CoCreateInstance(&pTA->guid, NULL,
7046 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7050 ITypeInfo_ReleaseTypeAttr(iface, pTA);
7054 /* ITypeInfo::GetMops
7056 * Retrieves marshalling information.
7058 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7061 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7062 FIXME("(%p %d) stub!\n", This, memid);
7067 /* ITypeInfo::GetContainingTypeLib
7069 * Retrieves the containing type library and the index of the type description
7070 * within that type library.
7072 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7073 ITypeLib * *ppTLib, UINT *pIndex)
7075 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7077 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7079 *pIndex=This->index;
7080 TRACE("returning pIndex=%d\n", *pIndex);
7084 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7085 ITypeLib2_AddRef(*ppTLib);
7086 TRACE("returning ppTLib=%p\n", *ppTLib);
7092 /* ITypeInfo::ReleaseTypeAttr
7094 * Releases a TYPEATTR previously returned by GetTypeAttr.
7097 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7098 TYPEATTR* pTypeAttr)
7100 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7101 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7102 heap_free(pTypeAttr);
7105 /* ITypeInfo::ReleaseFuncDesc
7107 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7109 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7111 FUNCDESC *pFuncDesc)
7113 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7116 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7118 for (i = 0; i < pFuncDesc->cParams; i++)
7119 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7120 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7122 SysFreeString((BSTR)pFuncDesc);
7125 /* ITypeInfo::ReleaseVarDesc
7127 * Releases a VARDESC previously returned by GetVarDesc.
7129 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7132 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7133 TRACE("(%p)->(%p)\n", This, pVarDesc);
7135 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7136 if (pVarDesc->varkind == VAR_CONST)
7137 VariantClear(pVarDesc->u.lpvarValue);
7138 SysFreeString((BSTR)pVarDesc);
7141 /* ITypeInfo2::GetTypeKind
7143 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7146 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7147 TYPEKIND *pTypeKind)
7149 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7150 *pTypeKind=This->TypeAttr.typekind;
7151 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7155 /* ITypeInfo2::GetTypeFlags
7157 * Returns the type flags without any allocations. This returns a DWORD type
7158 * flag, which expands the type flags without growing the TYPEATTR (type
7162 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7164 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7165 *pTypeFlags=This->TypeAttr.wTypeFlags;
7166 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7170 /* ITypeInfo2::GetFuncIndexOfMemId
7171 * Binds to a specific member based on a known DISPID, where the member name
7172 * is not known (for example, when binding to a default member).
7175 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7176 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7178 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7179 const TLBFuncDesc *pFuncInfo;
7183 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7184 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7190 result = TYPE_E_ELEMENTNOTFOUND;
7192 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7193 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7197 /* TypeInfo2::GetVarIndexOfMemId
7199 * Binds to a specific member based on a known DISPID, where the member name
7200 * is not known (for example, when binding to a default member).
7203 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7204 MEMBERID memid, UINT *pVarIndex)
7206 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7207 TLBVarDesc *pVarInfo;
7210 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7211 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7217 result = TYPE_E_ELEMENTNOTFOUND;
7219 TRACE("(%p) memid 0x%08x -> %s\n", This,
7220 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7224 /* ITypeInfo2::GetCustData
7226 * Gets the custom data
7228 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7233 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7234 TLBCustData *pCData;
7236 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7237 if( IsEqualIID(guid, &pCData->guid)) break;
7239 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7241 VariantInit( pVarVal);
7243 VariantCopy( pVarVal, &pCData->data);
7245 VariantClear( pVarVal );
7249 /* ITypeInfo2::GetFuncCustData
7251 * Gets the custom data
7253 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7259 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7260 TLBCustData *pCData=NULL;
7261 TLBFuncDesc * pFDesc;
7263 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7264 pFDesc=pFDesc->next);
7267 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7268 if( IsEqualIID(guid, &pCData->guid)) break;
7270 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7273 VariantInit( pVarVal);
7274 VariantCopy( pVarVal, &pCData->data);
7277 return E_INVALIDARG; /* FIXME: correct? */
7280 /* ITypeInfo2::GetParamCustData
7282 * Gets the custom data
7284 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7291 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7292 TLBCustData *pCData=NULL;
7293 TLBFuncDesc * pFDesc;
7296 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7298 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7299 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7300 pCData = pCData->next)
7301 if( IsEqualIID(guid, &pCData->guid)) break;
7303 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7307 VariantInit( pVarVal);
7308 VariantCopy( pVarVal, &pCData->data);
7311 return E_INVALIDARG; /* FIXME: correct? */
7314 /* ITypeInfo2::GetVarCustData
7316 * Gets the custom data
7318 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7324 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7325 TLBCustData *pCData=NULL;
7326 TLBVarDesc * pVDesc;
7329 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7333 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7335 if( IsEqualIID(guid, &pCData->guid)) break;
7339 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7343 VariantInit( pVarVal);
7344 VariantCopy( pVarVal, &pCData->data);
7347 return E_INVALIDARG; /* FIXME: correct? */
7350 /* ITypeInfo2::GetImplCustData
7352 * Gets the custom data
7354 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7360 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7361 TLBCustData *pCData=NULL;
7362 TLBImplType * pRDesc;
7365 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7369 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7371 if( IsEqualIID(guid, &pCData->guid)) break;
7375 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7379 VariantInit( pVarVal);
7380 VariantCopy( pVarVal, &pCData->data);
7383 return E_INVALIDARG; /* FIXME: correct? */
7386 /* ITypeInfo2::GetDocumentation2
7388 * Retrieves the documentation string, the complete Help file name and path,
7389 * the localization context to use, and the context ID for the library Help
7390 * topic in the Help file.
7393 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7397 BSTR *pbstrHelpString,
7398 DWORD *pdwHelpStringContext,
7399 BSTR *pbstrHelpStringDll)
7401 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7402 const TLBFuncDesc *pFDesc;
7403 const TLBVarDesc *pVDesc;
7404 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7405 "HelpStringContext(%p) HelpStringDll(%p)\n",
7406 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7407 pbstrHelpStringDll );
7408 /* the help string should be obtained from the helpstringdll,
7409 * using the _DLLGetDocumentation function, based on the supplied
7410 * lcid. Nice to do sometime...
7412 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7414 *pbstrHelpString=SysAllocString(This->Name);
7415 if(pdwHelpStringContext)
7416 *pdwHelpStringContext=This->dwHelpStringContext;
7417 if(pbstrHelpStringDll)
7418 *pbstrHelpStringDll=
7419 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7421 }else {/* for a member */
7422 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7423 if(pFDesc->funcdesc.memid==memid){
7425 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7426 if(pdwHelpStringContext)
7427 *pdwHelpStringContext=pFDesc->HelpStringContext;
7428 if(pbstrHelpStringDll)
7429 *pbstrHelpStringDll=
7430 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7433 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7434 if(pVDesc->vardesc.memid==memid){
7436 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7437 if(pdwHelpStringContext)
7438 *pdwHelpStringContext=pVDesc->HelpStringContext;
7439 if(pbstrHelpStringDll)
7440 *pbstrHelpStringDll=
7441 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7445 return TYPE_E_ELEMENTNOTFOUND;
7448 /* ITypeInfo2::GetAllCustData
7450 * Gets all custom data items for the Type info.
7453 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7455 CUSTDATA *pCustData)
7457 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7458 TLBCustData *pCData;
7461 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7463 pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
7464 if(pCustData->prgCustData ){
7465 pCustData->cCustData=This->ctCustData;
7466 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7467 pCustData->prgCustData[i].guid=pCData->guid;
7468 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7471 ERR(" OUT OF MEMORY!\n");
7472 return E_OUTOFMEMORY;
7477 /* ITypeInfo2::GetAllFuncCustData
7479 * Gets all custom data items for the specified Function
7482 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7485 CUSTDATA *pCustData)
7487 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7488 TLBCustData *pCData;
7489 TLBFuncDesc * pFDesc;
7491 TRACE("(%p) index %d\n", This, index);
7492 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7493 pFDesc=pFDesc->next)
7496 pCustData->prgCustData =
7497 heap_alloc_zero(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7498 if(pCustData->prgCustData ){
7499 pCustData->cCustData=pFDesc->ctCustData;
7500 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7501 pCData = pCData->next){
7502 pCustData->prgCustData[i].guid=pCData->guid;
7503 VariantCopy(& pCustData->prgCustData[i].varValue,
7507 ERR(" OUT OF MEMORY!\n");
7508 return E_OUTOFMEMORY;
7512 return TYPE_E_ELEMENTNOTFOUND;
7515 /* ITypeInfo2::GetAllParamCustData
7517 * Gets all custom data items for the Functions
7520 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7521 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7523 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7524 TLBCustData *pCData=NULL;
7525 TLBFuncDesc * pFDesc;
7527 TRACE("(%p) index %d\n", This, indexFunc);
7528 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7529 pFDesc=pFDesc->next)
7531 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7532 pCustData->prgCustData =
7533 heap_alloc_zero(pFDesc->pParamDesc[indexParam].ctCustData *
7534 sizeof(CUSTDATAITEM));
7535 if(pCustData->prgCustData ){
7536 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7537 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7538 pCData; i++, pCData = pCData->next){
7539 pCustData->prgCustData[i].guid=pCData->guid;
7540 VariantCopy(& pCustData->prgCustData[i].varValue,
7544 ERR(" OUT OF MEMORY!\n");
7545 return E_OUTOFMEMORY;
7549 return TYPE_E_ELEMENTNOTFOUND;
7552 /* ITypeInfo2::GetAllVarCustData
7554 * Gets all custom data items for the specified Variable
7557 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7558 UINT index, CUSTDATA *pCustData)
7560 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7561 TLBCustData *pCData;
7562 TLBVarDesc * pVDesc;
7564 TRACE("(%p) index %d\n", This, index);
7565 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7566 pVDesc=pVDesc->next)
7569 pCustData->prgCustData =
7570 heap_alloc_zero(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7571 if(pCustData->prgCustData ){
7572 pCustData->cCustData=pVDesc->ctCustData;
7573 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7574 pCData = pCData->next){
7575 pCustData->prgCustData[i].guid=pCData->guid;
7576 VariantCopy(& pCustData->prgCustData[i].varValue,
7580 ERR(" OUT OF MEMORY!\n");
7581 return E_OUTOFMEMORY;
7585 return TYPE_E_ELEMENTNOTFOUND;
7588 /* ITypeInfo2::GetAllImplCustData
7590 * Gets all custom data items for the specified implementation type
7593 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7596 CUSTDATA *pCustData)
7598 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7599 TLBCustData *pCData;
7600 TLBImplType * pRDesc;
7602 TRACE("(%p) index %d\n", This, index);
7603 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7604 pRDesc=pRDesc->next)
7607 pCustData->prgCustData =
7608 heap_alloc_zero(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7609 if(pCustData->prgCustData ){
7610 pCustData->cCustData=pRDesc->ctCustData;
7611 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7612 pCData = pCData->next){
7613 pCustData->prgCustData[i].guid=pCData->guid;
7614 VariantCopy(& pCustData->prgCustData[i].varValue,
7618 ERR(" OUT OF MEMORY!\n");
7619 return E_OUTOFMEMORY;
7623 return TYPE_E_ELEMENTNOTFOUND;
7626 static const ITypeInfo2Vtbl tinfvt =
7629 ITypeInfo_fnQueryInterface,
7631 ITypeInfo_fnRelease,
7633 ITypeInfo_fnGetTypeAttr,
7634 ITypeInfo_fnGetTypeComp,
7635 ITypeInfo_fnGetFuncDesc,
7636 ITypeInfo_fnGetVarDesc,
7637 ITypeInfo_fnGetNames,
7638 ITypeInfo_fnGetRefTypeOfImplType,
7639 ITypeInfo_fnGetImplTypeFlags,
7640 ITypeInfo_fnGetIDsOfNames,
7642 ITypeInfo_fnGetDocumentation,
7643 ITypeInfo_fnGetDllEntry,
7644 ITypeInfo_fnGetRefTypeInfo,
7645 ITypeInfo_fnAddressOfMember,
7646 ITypeInfo_fnCreateInstance,
7647 ITypeInfo_fnGetMops,
7648 ITypeInfo_fnGetContainingTypeLib,
7649 ITypeInfo_fnReleaseTypeAttr,
7650 ITypeInfo_fnReleaseFuncDesc,
7651 ITypeInfo_fnReleaseVarDesc,
7653 ITypeInfo2_fnGetTypeKind,
7654 ITypeInfo2_fnGetTypeFlags,
7655 ITypeInfo2_fnGetFuncIndexOfMemId,
7656 ITypeInfo2_fnGetVarIndexOfMemId,
7657 ITypeInfo2_fnGetCustData,
7658 ITypeInfo2_fnGetFuncCustData,
7659 ITypeInfo2_fnGetParamCustData,
7660 ITypeInfo2_fnGetVarCustData,
7661 ITypeInfo2_fnGetImplTypeCustData,
7662 ITypeInfo2_fnGetDocumentation2,
7663 ITypeInfo2_fnGetAllCustData,
7664 ITypeInfo2_fnGetAllFuncCustData,
7665 ITypeInfo2_fnGetAllParamCustData,
7666 ITypeInfo2_fnGetAllVarCustData,
7667 ITypeInfo2_fnGetAllImplTypeCustData,
7670 /******************************************************************************
7671 * CreateDispTypeInfo [OLEAUT32.31]
7673 * Build type information for an object so it can be called through an
7674 * IDispatch interface.
7677 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7678 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7681 * This call allows an objects methods to be accessed through IDispatch, by
7682 * building an ITypeInfo object that IDispatch can use to call through.
7684 HRESULT WINAPI CreateDispTypeInfo(
7685 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7686 LCID lcid, /* [I] Locale Id */
7687 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7689 ITypeInfoImpl *pTIClass, *pTIIface;
7690 ITypeLibImpl *pTypeLibImpl;
7691 unsigned int param, func;
7692 TLBFuncDesc **ppFuncDesc;
7696 pTypeLibImpl = TypeLibImpl_Constructor();
7697 if (!pTypeLibImpl) return E_FAIL;
7699 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7700 pTIIface->pTypeLib = pTypeLibImpl;
7701 pTIIface->index = 0;
7702 pTIIface->Name = NULL;
7703 pTIIface->dwHelpContext = -1;
7704 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7705 pTIIface->TypeAttr.lcid = lcid;
7706 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7707 pTIIface->TypeAttr.wMajorVerNum = 0;
7708 pTIIface->TypeAttr.wMinorVerNum = 0;
7709 pTIIface->TypeAttr.cbAlignment = 2;
7710 pTIIface->TypeAttr.cbSizeInstance = -1;
7711 pTIIface->TypeAttr.cbSizeVft = -1;
7712 pTIIface->TypeAttr.cFuncs = 0;
7713 pTIIface->TypeAttr.cImplTypes = 0;
7714 pTIIface->TypeAttr.cVars = 0;
7715 pTIIface->TypeAttr.wTypeFlags = 0;
7717 ppFuncDesc = &pTIIface->funclist;
7718 for(func = 0; func < pidata->cMembers; func++) {
7719 METHODDATA *md = pidata->pmethdata + func;
7720 *ppFuncDesc = heap_alloc(sizeof(**ppFuncDesc));
7721 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7722 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7723 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7724 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7725 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7726 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7727 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7728 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7729 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7730 (*ppFuncDesc)->funcdesc.cScodes = 0;
7731 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7732 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7733 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7734 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7735 (*ppFuncDesc)->funcdesc.lprgelemdescParam = heap_alloc_zero(md->cArgs * sizeof(ELEMDESC));
7736 (*ppFuncDesc)->pParamDesc = heap_alloc_zero(md->cArgs * sizeof(TLBParDesc));
7737 for(param = 0; param < md->cArgs; param++) {
7738 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7739 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7741 (*ppFuncDesc)->helpcontext = 0;
7742 (*ppFuncDesc)->HelpStringContext = 0;
7743 (*ppFuncDesc)->HelpString = NULL;
7744 (*ppFuncDesc)->Entry = NULL;
7745 (*ppFuncDesc)->ctCustData = 0;
7746 (*ppFuncDesc)->pCustData = NULL;
7747 (*ppFuncDesc)->next = NULL;
7748 pTIIface->TypeAttr.cFuncs++;
7749 ppFuncDesc = &(*ppFuncDesc)->next;
7752 dump_TypeInfo(pTIIface);
7754 pTypeLibImpl->pTypeInfo = pTIIface;
7755 pTypeLibImpl->TypeInfoCount++;
7757 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7758 pTIClass->pTypeLib = pTypeLibImpl;
7759 pTIClass->index = 1;
7760 pTIClass->Name = NULL;
7761 pTIClass->dwHelpContext = -1;
7762 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7763 pTIClass->TypeAttr.lcid = lcid;
7764 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7765 pTIClass->TypeAttr.wMajorVerNum = 0;
7766 pTIClass->TypeAttr.wMinorVerNum = 0;
7767 pTIClass->TypeAttr.cbAlignment = 2;
7768 pTIClass->TypeAttr.cbSizeInstance = -1;
7769 pTIClass->TypeAttr.cbSizeVft = -1;
7770 pTIClass->TypeAttr.cFuncs = 0;
7771 pTIClass->TypeAttr.cImplTypes = 1;
7772 pTIClass->TypeAttr.cVars = 0;
7773 pTIClass->TypeAttr.wTypeFlags = 0;
7775 pTIClass->impltypelist = heap_alloc_zero(sizeof(*pTIClass->impltypelist));
7776 pTIClass->impltypelist->hRef = 0;
7778 ref = heap_alloc_zero(sizeof(*ref));
7781 ref->pImpTLInfo = TLB_REF_INTERNAL;
7782 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7784 dump_TypeInfo(pTIClass);
7786 pTIIface->next = pTIClass;
7787 pTypeLibImpl->TypeInfoCount++;
7789 *pptinfo = (ITypeInfo*)pTIClass;
7791 ITypeInfo_AddRef(*pptinfo);
7792 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7798 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7800 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7802 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7805 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7807 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7809 return ITypeInfo_AddRef((ITypeInfo *)This);
7812 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7814 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7816 return ITypeInfo_Release((ITypeInfo *)This);
7819 static HRESULT WINAPI ITypeComp_fnBind(
7824 ITypeInfo ** ppTInfo,
7825 DESCKIND * pDescKind,
7828 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7829 const TLBFuncDesc *pFDesc;
7830 const TLBVarDesc *pVDesc;
7831 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7833 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7835 *pDescKind = DESCKIND_NONE;
7836 pBindPtr->lpfuncdesc = NULL;
7839 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7840 if (!strcmpiW(pFDesc->Name, szName)) {
7841 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7844 /* name found, but wrong flags */
7845 hr = TYPE_E_TYPEMISMATCH;
7850 HRESULT hr = TLB_AllocAndInitFuncDesc(
7852 &pBindPtr->lpfuncdesc,
7853 This->TypeAttr.typekind == TKIND_DISPATCH);
7856 *pDescKind = DESCKIND_FUNCDESC;
7857 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7858 ITypeInfo_AddRef(*ppTInfo);
7861 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7862 if (!strcmpiW(pVDesc->Name, szName)) {
7863 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7866 *pDescKind = DESCKIND_VARDESC;
7867 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7868 ITypeInfo_AddRef(*ppTInfo);
7873 /* FIXME: search each inherited interface, not just the first */
7874 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7875 /* recursive search */
7879 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7882 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7883 ITypeInfo_Release(pTInfo);
7887 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7888 ITypeComp_Release(pTComp);
7891 WARN("Could not search inherited interface!\n");
7893 if (hr == DISP_E_MEMBERNOTFOUND)
7895 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7899 static HRESULT WINAPI ITypeComp_fnBindType(
7903 ITypeInfo ** ppTInfo,
7904 ITypeComp ** ppTComp)
7906 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7908 /* strange behaviour (does nothing) but like the
7911 if (!ppTInfo || !ppTComp)
7920 static const ITypeCompVtbl tcompvt =
7923 ITypeComp_fnQueryInterface,
7925 ITypeComp_fnRelease,
7928 ITypeComp_fnBindType