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;
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 ITypeInfoImpl* ITypeInfoImpl_Constructor(void);
1145 static void ITypeInfoImpl_Destroy(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 std_typedesc[VT_LPWSTR+1] =
1453 /* VT_LPWSTR is largest type that, may appear in type description */
1454 {{0}, VT_EMPTY}, {{0}, VT_NULL}, {{0}, VT_I2}, {{0}, VT_I4},
1455 {{0}, VT_R4}, {{0}, VT_R8}, {{0}, VT_CY}, {{0}, VT_DATE},
1456 {{0}, VT_BSTR}, {{0}, VT_DISPATCH}, {{0}, VT_ERROR}, {{0}, VT_BOOL},
1457 {{0}, VT_VARIANT},{{0}, VT_UNKNOWN}, {{0}, VT_DECIMAL}, {{0}, 15}, /* unused in VARENUM */
1458 {{0}, VT_I1}, {{0}, VT_UI1}, {{0}, VT_UI2}, {{0}, VT_UI4},
1459 {{0}, VT_I8}, {{0}, VT_UI8}, {{0}, VT_INT}, {{0}, VT_UINT},
1460 {{0}, VT_VOID}, {{0}, VT_HRESULT}, {{0}, VT_PTR}, {{0}, VT_SAFEARRAY},
1461 {{0}, VT_CARRAY}, {{0}, VT_USERDEFINED}, {{0}, VT_LPSTR}, {{0}, VT_LPWSTR}
1464 static void TLB_abort(void)
1469 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size)
1471 void *ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
1472 if (!ret) ERR("cannot allocate memory\n");
1476 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size)
1478 void *ret = HeapAlloc(GetProcessHeap(), 0, size);
1479 if (!ret) ERR("cannot allocate memory\n");
1483 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr, unsigned size)
1485 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
1488 void heap_free(void *ptr)
1490 HeapFree(GetProcessHeap(), 0, ptr);
1493 /* returns the size required for a deep copy of a typedesc into a
1495 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1499 if (alloc_initial_space)
1500 size += sizeof(TYPEDESC);
1506 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1509 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1510 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1516 /* deep copy a typedesc into a flat buffer */
1517 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1522 buffer = (char *)buffer + sizeof(TYPEDESC);
1531 dest->u.lptdesc = buffer;
1532 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1535 dest->u.lpadesc = buffer;
1536 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1537 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1538 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1544 /* free custom data allocated by MSFT_CustData */
1545 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1547 TLBCustData *pCustDataNext;
1548 for (; pCustData; pCustData = pCustDataNext)
1550 VariantClear(&pCustData->data);
1552 pCustDataNext = pCustData->next;
1553 heap_free(pCustData);
1557 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1562 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1563 ret = SysAllocStringLen(NULL, len - 1);
1564 if (!ret) return ret;
1565 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1569 /**********************************************************************
1571 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1573 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1578 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1580 if (where != DO_NOT_SEEK)
1582 where += pcx->oStart;
1583 if (where > pcx->length)
1586 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1594 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1596 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1597 pcx->pos, count, pcx->oStart, pcx->length, where);
1599 MSFT_Seek(pcx, where);
1600 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1601 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1606 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1611 ret = MSFT_Read(buffer, count, pcx, where);
1612 FromLEDWords(buffer, ret);
1617 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1622 ret = MSFT_Read(buffer, count, pcx, where);
1623 FromLEWords(buffer, ret);
1628 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1630 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1631 memset(pGuid,0, sizeof(GUID));
1634 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1635 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1636 pGuid->Data2 = FromLEWord(pGuid->Data2);
1637 pGuid->Data3 = FromLEWord(pGuid->Data3);
1638 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1641 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1643 MSFT_NameIntro niName;
1647 ERR_(typelib)("bad offset %d\n", offset);
1651 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1652 pcx->pTblDir->pNametab.offset+offset);
1654 return niName.hreftype;
1657 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1660 MSFT_NameIntro niName;
1662 BSTR bstrName = NULL;
1666 ERR_(typelib)("bad offset %d\n", offset);
1669 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1670 pcx->pTblDir->pNametab.offset+offset);
1671 niName.namelen &= 0xFF; /* FIXME: correct ? */
1672 name = heap_alloc_zero((niName.namelen & 0xff) +1);
1673 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1674 name[niName.namelen & 0xff]='\0';
1676 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1679 /* no invalid characters in string */
1682 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1684 /* don't check for invalid character since this has been done previously */
1685 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1689 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1693 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1700 if(offset<0) return NULL;
1701 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1702 if(length <= 0) return 0;
1703 string = heap_alloc_zero(length +1);
1704 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1705 string[length]='\0';
1707 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1708 string, -1, NULL, 0);
1710 /* no invalid characters in string */
1713 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1715 /* don't check for invalid character since this has been done previously */
1716 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1720 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1724 * read a value and fill a VARIANT structure
1726 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1730 TRACE_(typelib)("\n");
1732 if(offset <0) { /* data are packed in here */
1733 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1734 V_I4(pVar) = offset & 0x3ffffff;
1737 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1738 pcx->pTblDir->pCustData.offset + offset );
1739 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1740 switch (V_VT(pVar)){
1741 case VT_EMPTY: /* FIXME: is this right? */
1742 case VT_NULL: /* FIXME: is this right? */
1743 case VT_I2 : /* this should not happen */
1754 case VT_VOID : /* FIXME: is this right? */
1762 case VT_DECIMAL : /* FIXME: is this right? */
1765 /* pointer types with known behaviour */
1768 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1771 DWORD origPos = MSFT_Tell(pcx), nullPos;
1774 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1776 nullPos = MSFT_Tell(pcx);
1777 size = nullPos - origPos;
1778 MSFT_Seek(pcx, origPos);
1780 ptr = heap_alloc_zero(size);/* allocate temp buffer */
1781 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1782 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1783 /* FIXME: do we need a AtoW conversion here? */
1784 V_UNION(pVar, bstrVal[size])='\0';
1785 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1789 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1796 case VT_USERDEFINED :
1802 case VT_STREAMED_OBJECT :
1803 case VT_STORED_OBJECT :
1804 case VT_BLOB_OBJECT :
1809 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1813 if(size>0) /* (big|small) endian correct? */
1814 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1818 * create a linked list with custom data
1820 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1826 TRACE_(typelib)("\n");
1830 pNew=heap_alloc_zero(sizeof(TLBCustData));
1831 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1832 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1833 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1834 /* add new custom data at head of the list */
1835 pNew->next=*ppCustData;
1837 offset = entry.next;
1842 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1846 pTd->vt=type & VT_TYPEMASK;
1848 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1850 if(pTd->vt == VT_USERDEFINED)
1851 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1853 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1856 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1858 /* resolve referenced type if any */
1861 switch (lpTypeDesc->vt)
1864 lpTypeDesc = lpTypeDesc->u.lptdesc;
1868 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1871 case VT_USERDEFINED:
1872 MSFT_DoRefType(pcx, pTI->pTypeLib,
1873 lpTypeDesc->u.hreftype);
1885 MSFT_DoFuncs(TLBContext* pcx,
1890 TLBFuncDesc** pptfd)
1893 * member information is stored in a data structure at offset
1894 * indicated by the memoffset field of the typeinfo structure
1895 * There are several distinctive parts.
1896 * The first part starts with a field that holds the total length
1897 * of this (first) part excluding this field. Then follow the records,
1898 * for each member there is one record.
1900 * The first entry is always the length of the record (including this
1902 * The rest of the record depends on the type of the member. If there is
1903 * a field indicating the member type (function, variable, interface, etc)
1904 * I have not found it yet. At this time we depend on the information
1905 * in the type info and the usual order how things are stored.
1907 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1910 * Third is an equal sized array with file offsets to the name entry
1913 * The fourth and last (?) part is an array with offsets to the records
1914 * in the first part of this file segment.
1917 int infolen, nameoffset, reclength, i;
1918 int recoffset = offset + sizeof(INT);
1920 char *recbuf = heap_alloc(0xffff);
1921 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
1922 TLBFuncDesc *ptfd_prev = NULL;
1924 TRACE_(typelib)("\n");
1926 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1928 for ( i = 0; i < cFuncs ; i++ )
1932 *pptfd = heap_alloc_zero(sizeof(TLBFuncDesc));
1934 /* name, eventually add to a hash table */
1935 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1936 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1938 /* nameoffset is sometimes -1 on the second half of a propget/propput
1939 * pair of functions */
1940 if ((nameoffset == -1) && (i > 0))
1941 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1943 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1945 /* read the function information record */
1946 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
1948 reclength &= 0xffff;
1950 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
1952 /* size without argument data */
1953 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
1955 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
1956 (*pptfd)->helpcontext = pFuncRec->HelpContext;
1958 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
1959 (*pptfd)->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
1961 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
1963 if (pFuncRec->FKCCIC & 0x2000 )
1965 if (!IS_INTRESOURCE(pFuncRec->oEntry))
1966 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
1967 (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
1970 (*pptfd)->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
1973 (*pptfd)->Entry = (BSTR)-1;
1975 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
1976 (*pptfd)->HelpStringContext = pFuncRec->HelpStringContext;
1978 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
1979 MSFT_CustData(pcx, pFuncRec->oCustData, &(*pptfd)->pCustData);
1981 /* fill the FuncDesc Structure */
1982 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1983 offset + infolen + ( i + 1) * sizeof(INT));
1985 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1986 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1987 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1988 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1989 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1990 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset & ~1;
1991 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1995 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1997 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1999 /* do the parameters/arguments */
2000 if(pFuncRec->nrargs)
2003 MSFT_ParameterInfo paraminfo;
2005 (*pptfd)->funcdesc.lprgelemdescParam =
2006 heap_alloc_zero(pFuncRec->nrargs * sizeof(ELEMDESC));
2008 (*pptfd)->pParamDesc =
2009 heap_alloc_zero(pFuncRec->nrargs * sizeof(TLBParDesc));
2011 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
2012 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2014 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2016 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
2023 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2026 if (paraminfo.oName == -1)
2027 /* this occurs for [propput] or [propget] methods, so
2028 * we should just set the name of the parameter to the
2029 * name of the method. */
2030 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
2032 (*pptfd)->pParamDesc[j].Name =
2033 MSFT_ReadName( pcx, paraminfo.oName );
2034 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
2036 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2039 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2040 (pFuncRec->FKCCIC & 0x1000) )
2042 INT* pInt = (INT *)((char *)pFuncRec +
2044 (pFuncRec->nrargs * 4) * sizeof(INT) );
2046 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2048 pParamDesc->pparamdescex = heap_alloc_zero(sizeof(PARAMDESCEX));
2049 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2051 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2055 elemdesc->u.paramdesc.pparamdescex = NULL;
2058 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2059 j*sizeof(pFuncRec->oArgCustData[0])) &&
2060 pFuncRec->FKCCIC & 0x80 )
2063 pFuncRec->oArgCustData[j],
2064 &(*pptfd)->pParamDesc[j].pCustData);
2067 /* SEEK value = jump to offset,
2068 * from there jump to the end of record,
2069 * go back by (j-1) arguments
2071 MSFT_ReadLEDWords( ¶minfo ,
2072 sizeof(MSFT_ParameterInfo), pcx,
2073 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2074 * sizeof(MSFT_ParameterInfo)));
2078 /* scode is not used: archaic win16 stuff FIXME: right? */
2079 (*pptfd)->funcdesc.cScodes = 0 ;
2080 (*pptfd)->funcdesc.lprgscode = NULL ;
2083 pptfd = & ((*pptfd)->next);
2084 recoffset += reclength;
2089 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2090 int cVars, int offset, TLBVarDesc ** pptvd)
2092 int infolen, nameoffset, reclength;
2094 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2098 TRACE_(typelib)("\n");
2100 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2101 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2102 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2103 recoffset += offset+sizeof(INT);
2104 for(i=0;i<cVars;i++){
2105 *pptvd = heap_alloc_zero(sizeof(TLBVarDesc));
2106 /* name, eventually add to a hash table */
2107 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2108 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2109 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2110 /* read the variable information record */
2111 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2113 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2116 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2117 (*pptvd)->HelpContext = pVarRec->HelpContext;
2119 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2120 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2122 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2123 (*pptvd)->HelpStringContext = pVarRec->HelpStringContext;
2125 /* fill the VarDesc Structure */
2126 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2127 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2128 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2129 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2130 MSFT_GetTdesc(pcx, pVarRec->DataType,
2131 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2132 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2133 if(pVarRec->VarKind == VAR_CONST ){
2134 (*pptvd)->vardesc.u.lpvarValue = heap_alloc_zero(sizeof(VARIANT));
2135 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2136 pVarRec->OffsValue, pcx);
2138 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2139 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2140 pptvd=&((*pptvd)->next);
2141 recoffset += reclength;
2144 /* fill in data for a hreftype (offset). When the referenced type is contained
2145 * in the typelib, it's just an (file) offset in the type info base dir.
2146 * If comes from import, it's an offset+1 in the ImpInfo table
2148 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2153 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2155 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2157 if(ref->reference == offset) return;
2160 ref = heap_alloc_zero(sizeof(TLBRefType));
2161 list_add_tail(&pTL->ref_list, &ref->entry);
2163 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2164 /* external typelib */
2165 MSFT_ImpInfo impinfo;
2166 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2168 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2170 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2171 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2172 while (pImpLib){ /* search the known offsets of all import libraries */
2173 if(pImpLib->offset==impinfo.oImpFile) break;
2174 pImpLib=pImpLib->next;
2177 ref->reference = offset;
2178 ref->pImpTLInfo = pImpLib;
2179 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2180 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2181 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2182 ref->index = TLB_REF_USE_GUID;
2184 ref->index = impinfo.oGuid;
2186 ERR("Cannot find a reference\n");
2187 ref->reference = -1;
2188 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2191 /* in this typelib */
2192 ref->index = MSFT_HREFTYPE_INDEX(offset);
2193 ref->reference = offset;
2194 ref->pImpTLInfo = TLB_REF_INTERNAL;
2198 /* process Implemented Interfaces of a com class */
2199 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2203 MSFT_RefRecord refrec;
2204 TLBImplType **ppImpl = &pTI->impltypelist;
2206 TRACE_(typelib)("\n");
2208 for(i=0;i<count;i++){
2209 if(offset<0) break; /* paranoia */
2210 *ppImpl = heap_alloc_zero(sizeof(**ppImpl));
2211 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2212 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2213 (*ppImpl)->hRef = refrec.reftype;
2214 (*ppImpl)->implflags=refrec.flags;
2215 (*ppImpl)->ctCustData=
2216 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2217 offset=refrec.onext;
2218 ppImpl=&((*ppImpl)->next);
2222 * process a typeinfo record
2224 static ITypeInfoImpl * MSFT_DoTypeInfo(
2227 ITypeLibImpl * pLibInfo)
2229 MSFT_TypeInfoBase tiBase;
2230 ITypeInfoImpl *ptiRet;
2232 TRACE_(typelib)("count=%u\n", count);
2234 ptiRet = ITypeInfoImpl_Constructor();
2235 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2236 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2238 /* this is where we are coming from */
2239 ptiRet->pTypeLib = pLibInfo;
2240 ptiRet->index=count;
2241 /* fill in the typeattr fields */
2243 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2244 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2245 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2246 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2247 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2248 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2249 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2250 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2251 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2252 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2253 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2254 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2255 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2256 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2257 MSFT_GetTdesc(pcx, tiBase.datatype1,
2258 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2261 /* IDLDESC idldescType; *//* never saw this one != zero */
2263 /* name, eventually add to a hash table */
2264 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2265 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2266 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2268 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2269 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2270 ptiRet->dwHelpContext=tiBase.helpcontext;
2272 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2273 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2275 /* note: InfoType's Help file and HelpStringDll come from the containing
2276 * library. Further HelpString and Docstring appear to be the same thing :(
2279 if(ptiRet->TypeAttr.cFuncs >0 )
2280 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2281 ptiRet->TypeAttr.cVars,
2282 tiBase.memoffset, & ptiRet->funclist);
2284 if(ptiRet->TypeAttr.cVars >0 )
2285 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2286 ptiRet->TypeAttr.cVars,
2287 tiBase.memoffset, & ptiRet->varlist);
2288 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2289 switch(ptiRet->TypeAttr.typekind)
2292 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2295 case TKIND_DISPATCH:
2296 /* This is not -1 when the interface is a non-base dual interface or
2297 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2298 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2302 if (tiBase.datatype1 != -1)
2304 ptiRet->impltypelist = heap_alloc_zero(sizeof(TLBImplType));
2305 ptiRet->impltypelist->hRef = tiBase.datatype1;
2306 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2310 ptiRet->impltypelist = heap_alloc_zero(sizeof(TLBImplType));
2311 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2312 ptiRet->impltypelist->hRef = tiBase.datatype1;
2317 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2319 TRACE_(typelib)("%s guid: %s kind:%s\n",
2320 debugstr_w(ptiRet->Name),
2321 debugstr_guid(&ptiRet->TypeAttr.guid),
2322 typekind_desc[ptiRet->TypeAttr.typekind]);
2323 if (TRACE_ON(typelib))
2324 dump_TypeInfo(ptiRet);
2329 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2330 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2331 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2334 static ITypeLibImpl *tlb_cache_first;
2335 static CRITICAL_SECTION cache_section;
2336 static CRITICAL_SECTION_DEBUG cache_section_debug =
2338 0, 0, &cache_section,
2339 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2340 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2342 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2345 typedef struct TLB_PEFile
2347 const IUnknownVtbl *lpvtbl;
2350 HRSRC typelib_resource;
2351 HGLOBAL typelib_global;
2352 LPVOID typelib_base;
2355 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2357 if (IsEqualIID(riid, &IID_IUnknown))
2360 IUnknown_AddRef(iface);
2364 return E_NOINTERFACE;
2367 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2369 TLB_PEFile *This = (TLB_PEFile *)iface;
2370 return InterlockedIncrement(&This->refs);
2373 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2375 TLB_PEFile *This = (TLB_PEFile *)iface;
2376 ULONG refs = InterlockedDecrement(&This->refs);
2379 if (This->typelib_global)
2380 FreeResource(This->typelib_global);
2382 FreeLibrary(This->dll);
2388 static const IUnknownVtbl TLB_PEFile_Vtable =
2390 TLB_PEFile_QueryInterface,
2395 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2399 This = heap_alloc(sizeof(TLB_PEFile));
2401 return E_OUTOFMEMORY;
2403 This->lpvtbl = &TLB_PEFile_Vtable;
2406 This->typelib_resource = NULL;
2407 This->typelib_global = NULL;
2408 This->typelib_base = NULL;
2410 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2411 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2415 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2416 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2417 if (This->typelib_resource)
2419 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2420 if (This->typelib_global)
2422 This->typelib_base = LockResource(This->typelib_global);
2424 if (This->typelib_base)
2426 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2427 *ppBase = This->typelib_base;
2428 *ppFile = (IUnknown *)&This->lpvtbl;
2435 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2436 return TYPE_E_CANTLOADLIBRARY;
2439 typedef struct TLB_NEFile
2441 const IUnknownVtbl *lpvtbl;
2443 LPVOID typelib_base;
2446 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2448 if (IsEqualIID(riid, &IID_IUnknown))
2451 IUnknown_AddRef(iface);
2455 return E_NOINTERFACE;
2458 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2460 TLB_NEFile *This = (TLB_NEFile *)iface;
2461 return InterlockedIncrement(&This->refs);
2464 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2466 TLB_NEFile *This = (TLB_NEFile *)iface;
2467 ULONG refs = InterlockedDecrement(&This->refs);
2470 heap_free(This->typelib_base);
2476 static const IUnknownVtbl TLB_NEFile_Vtable =
2478 TLB_NEFile_QueryInterface,
2483 /***********************************************************************
2484 * read_xx_header [internal]
2486 static int read_xx_header( HFILE lzfd )
2488 IMAGE_DOS_HEADER mzh;
2491 LZSeek( lzfd, 0, SEEK_SET );
2492 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2494 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2497 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2498 if ( 2 != LZRead( lzfd, magic, 2 ) )
2501 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2503 if ( magic[0] == 'N' && magic[1] == 'E' )
2504 return IMAGE_OS2_SIGNATURE;
2505 if ( magic[0] == 'P' && magic[1] == 'E' )
2506 return IMAGE_NT_SIGNATURE;
2509 WARN("Can't handle %s files.\n", magic );
2514 /***********************************************************************
2515 * find_ne_resource [internal]
2517 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2518 DWORD *resLen, DWORD *resOff )
2520 IMAGE_OS2_HEADER nehd;
2521 NE_TYPEINFO *typeInfo;
2522 NE_NAMEINFO *nameInfo;
2528 /* Read in NE header */
2529 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2530 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2532 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2535 TRACE("No resources in NE dll\n" );
2539 /* Read in resource table */
2540 resTab = heap_alloc( resTabSize );
2541 if ( !resTab ) return FALSE;
2543 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2544 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2546 heap_free( resTab );
2551 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2553 if (!IS_INTRESOURCE(typeid)) /* named type */
2555 BYTE len = strlen( typeid );
2556 while (typeInfo->type_id)
2558 if (!(typeInfo->type_id & 0x8000))
2560 BYTE *p = resTab + typeInfo->type_id;
2561 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2563 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2564 typeInfo->count * sizeof(NE_NAMEINFO));
2567 else /* numeric type id */
2569 WORD id = LOWORD(typeid) | 0x8000;
2570 while (typeInfo->type_id)
2572 if (typeInfo->type_id == id) goto found_type;
2573 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2574 typeInfo->count * sizeof(NE_NAMEINFO));
2577 TRACE("No typeid entry found for %p\n", typeid );
2578 heap_free( resTab );
2582 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2584 if (!IS_INTRESOURCE(resid)) /* named resource */
2586 BYTE len = strlen( resid );
2587 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2589 BYTE *p = resTab + nameInfo->id;
2590 if (nameInfo->id & 0x8000) continue;
2591 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2594 else /* numeric resource id */
2596 WORD id = LOWORD(resid) | 0x8000;
2597 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2598 if (nameInfo->id == id) goto found_name;
2600 TRACE("No resid entry found for %p\n", typeid );
2601 heap_free( resTab );
2605 /* Return resource data */
2606 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2607 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2609 heap_free( resTab );
2613 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2617 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2620 This = heap_alloc(sizeof(TLB_NEFile));
2621 if (!This) return E_OUTOFMEMORY;
2623 This->lpvtbl = &TLB_NEFile_Vtable;
2625 This->typelib_base = NULL;
2627 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2628 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2630 DWORD reslen, offset;
2631 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2633 This->typelib_base = heap_alloc(reslen);
2634 if( !This->typelib_base )
2638 LZSeek( lzfd, offset, SEEK_SET );
2639 reslen = LZRead( lzfd, This->typelib_base, reslen );
2641 *ppBase = This->typelib_base;
2642 *pdwTLBLength = reslen;
2643 *ppFile = (IUnknown *)&This->lpvtbl;
2649 if( lzfd >= 0) LZClose( lzfd );
2650 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2654 typedef struct TLB_Mapping
2656 const IUnknownVtbl *lpvtbl;
2660 LPVOID typelib_base;
2663 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2665 if (IsEqualIID(riid, &IID_IUnknown))
2668 IUnknown_AddRef(iface);
2672 return E_NOINTERFACE;
2675 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2677 TLB_Mapping *This = (TLB_Mapping *)iface;
2678 return InterlockedIncrement(&This->refs);
2681 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2683 TLB_Mapping *This = (TLB_Mapping *)iface;
2684 ULONG refs = InterlockedDecrement(&This->refs);
2687 if (This->typelib_base)
2688 UnmapViewOfFile(This->typelib_base);
2690 CloseHandle(This->mapping);
2691 if (This->file != INVALID_HANDLE_VALUE)
2692 CloseHandle(This->file);
2698 static const IUnknownVtbl TLB_Mapping_Vtable =
2700 TLB_Mapping_QueryInterface,
2705 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2709 This = heap_alloc(sizeof(TLB_Mapping));
2711 return E_OUTOFMEMORY;
2713 This->lpvtbl = &TLB_Mapping_Vtable;
2715 This->file = INVALID_HANDLE_VALUE;
2716 This->mapping = NULL;
2717 This->typelib_base = NULL;
2719 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2720 if (INVALID_HANDLE_VALUE != This->file)
2722 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2725 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2726 if(This->typelib_base)
2728 /* retrieve file size */
2729 *pdwTLBLength = GetFileSize(This->file, NULL);
2730 *ppBase = This->typelib_base;
2731 *ppFile = (IUnknown *)&This->lpvtbl;
2737 IUnknown_Release((IUnknown *)&This->lpvtbl);
2738 return TYPE_E_CANTLOADLIBRARY;
2741 /****************************************************************************
2744 * find the type of the typelib file and map the typelib resource into
2748 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2749 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2751 ITypeLibImpl *entry;
2754 LPWSTR index_str, file = (LPWSTR)pszFileName;
2755 LPVOID pBase = NULL;
2756 DWORD dwTLBLength = 0;
2757 IUnknown *pFile = NULL;
2761 index_str = strrchrW(pszFileName, '\\');
2762 if(index_str && *++index_str != '\0')
2765 LONG idx = strtolW(index_str, &end_ptr, 10);
2766 if(*end_ptr == '\0')
2768 int str_len = index_str - pszFileName - 1;
2770 file = heap_alloc((str_len + 1) * sizeof(WCHAR));
2771 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2776 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2778 if(strchrW(file, '\\'))
2780 lstrcpyW(pszPath, file);
2784 int len = GetSystemDirectoryW(pszPath, cchPath);
2785 pszPath[len] = '\\';
2786 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2790 if(file != pszFileName) heap_free(file);
2792 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2794 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2795 EnterCriticalSection(&cache_section);
2796 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2798 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2800 TRACE("cache hit\n");
2801 *ppTypeLib = (ITypeLib2*)entry;
2802 ITypeLib_AddRef(*ppTypeLib);
2803 LeaveCriticalSection(&cache_section);
2807 LeaveCriticalSection(&cache_section);
2809 /* now actually load and parse the typelib */
2811 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2812 if (ret == TYPE_E_CANTLOADLIBRARY)
2813 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2814 if (ret == TYPE_E_CANTLOADLIBRARY)
2815 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2818 if (dwTLBLength >= 4)
2820 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2821 if (dwSignature == MSFT_SIGNATURE)
2822 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2823 else if (dwSignature == SLTG_SIGNATURE)
2824 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2827 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2828 ret = TYPE_E_CANTLOADLIBRARY;
2832 ret = TYPE_E_CANTLOADLIBRARY;
2833 IUnknown_Release(pFile);
2837 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2839 TRACE("adding to cache\n");
2840 impl->path = heap_alloc((strlenW(pszPath)+1) * sizeof(WCHAR));
2841 lstrcpyW(impl->path, pszPath);
2842 /* We should really canonicalise the path here. */
2843 impl->index = index;
2845 /* FIXME: check if it has added already in the meantime */
2846 EnterCriticalSection(&cache_section);
2847 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2849 tlb_cache_first = impl;
2850 LeaveCriticalSection(&cache_section);
2853 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2858 /*================== ITypeLib(2) Methods ===================================*/
2860 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2862 ITypeLibImpl* pTypeLibImpl;
2864 pTypeLibImpl = heap_alloc_zero(sizeof(ITypeLibImpl));
2865 if (!pTypeLibImpl) return NULL;
2867 pTypeLibImpl->lpVtbl = &tlbvt;
2868 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2869 pTypeLibImpl->ref = 1;
2871 list_init(&pTypeLibImpl->ref_list);
2872 pTypeLibImpl->dispatch_href = -1;
2874 return pTypeLibImpl;
2877 /****************************************************************************
2878 * ITypeLib2_Constructor_MSFT
2880 * loading an MSFT typelib from an in-memory image
2882 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2886 MSFT_Header tlbHeader;
2887 MSFT_SegDir tlbSegDir;
2888 ITypeLibImpl * pTypeLibImpl;
2890 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2892 pTypeLibImpl = TypeLibImpl_Constructor();
2893 if (!pTypeLibImpl) return NULL;
2895 /* get pointer to beginning of typelib data */
2899 cx.pLibInfo = pTypeLibImpl;
2900 cx.length = dwTLBLength;
2903 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2904 TRACE_(typelib)("header:\n");
2905 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2906 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2907 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2910 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2912 /* there is a small amount of information here until the next important
2914 * the segment directory . Try to calculate the amount of data */
2915 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2917 /* now read the segment directory */
2918 TRACE("read segment directory (at %d)\n",lPSegDir);
2919 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2920 cx.pTblDir = &tlbSegDir;
2922 /* just check two entries */
2923 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2925 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
2926 heap_free(pTypeLibImpl);
2930 /* now fill our internal data */
2931 /* TLIBATTR fields */
2932 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2934 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2935 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2936 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2937 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2938 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2940 pTypeLibImpl->lcid = tlbHeader.lcid;
2942 /* name, eventually add to a hash table */
2943 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2946 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2947 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2949 if( tlbHeader.varflags & HELPDLLFLAG)
2952 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2953 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2956 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2959 if(tlbHeader.CustomDataOffset >= 0)
2961 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2964 /* fill in type descriptions */
2965 if(tlbSegDir.pTypdescTab.length > 0)
2967 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2969 pTypeLibImpl->ctTypeDesc = cTD;
2970 pTypeLibImpl->pTypeDesc = heap_alloc_zero( cTD * sizeof(TYPEDESC));
2971 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2974 /* FIXME: add several sanity checks here */
2975 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2976 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2978 /* FIXME: check safearray */
2980 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &std_typedesc[td[2]];
2982 pTypeLibImpl->pTypeDesc[i].u.lptdesc = &pTypeLibImpl->pTypeDesc[td[2]/8];
2984 else if(td[0] == VT_CARRAY)
2986 /* array descr table here */
2987 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
2989 else if(td[0] == VT_USERDEFINED)
2991 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2993 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2996 /* second time around to fill the array subscript info */
2999 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
3000 if(tlbSegDir.pArrayDescriptions.offset>0)
3002 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
3003 pTypeLibImpl->pTypeDesc[i].u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3006 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3008 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3010 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3012 for(j = 0; j<td[2]; j++)
3014 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3015 sizeof(INT), &cx, DO_NOT_SEEK);
3016 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3017 sizeof(INT), &cx, DO_NOT_SEEK);
3022 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3023 ERR("didn't find array description data\n");
3028 /* imported type libs */
3029 if(tlbSegDir.pImpFiles.offset>0)
3031 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
3032 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3035 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3039 *ppImpLib = heap_alloc_zero(sizeof(TLBImpLib));
3040 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
3041 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3043 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3044 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3045 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3046 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3049 name = heap_alloc_zero(size+1);
3050 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3051 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3054 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3055 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3057 ppImpLib = &(*ppImpLib)->next;
3061 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3062 if(pTypeLibImpl->dispatch_href != -1)
3063 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3066 if(tlbHeader.nrtypeinfos >= 0 )
3068 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3069 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3072 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3074 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3076 ppTI = &((*ppTI)->next);
3077 (pTypeLibImpl->TypeInfoCount)++;
3081 TRACE("(%p)\n", pTypeLibImpl);
3082 return (ITypeLib2*) pTypeLibImpl;
3086 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3092 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3093 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3097 guid->Data4[0] = s >> 8;
3098 guid->Data4[1] = s & 0xff;
3101 for(i = 0; i < 6; i++) {
3102 memcpy(b, str + 24 + 2 * i, 2);
3103 guid->Data4[i + 2] = strtol(b, NULL, 16);
3108 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3114 bytelen = *(const WORD*)ptr;
3115 if(bytelen == 0xffff) return 2;
3116 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3117 *pBstr = SysAllocStringLen(NULL, len);
3119 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3123 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3128 bytelen = *(const WORD*)ptr;
3129 if(bytelen == 0xffff) return 2;
3130 *str = heap_alloc(bytelen + 1);
3131 memcpy(*str, ptr + 2, bytelen);
3132 (*str)[bytelen] = '\0';
3136 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3138 char *ptr = pLibBlk;
3141 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3142 FIXME("libblk magic = %04x\n", w);
3147 if((w = *(WORD*)ptr) != 0xffff) {
3148 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3153 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3155 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3157 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3160 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3163 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3164 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3166 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3169 ptr += 4; /* skip res12 */
3171 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3174 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3177 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3180 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3181 ptr += sizeof(GUID);
3183 return ptr - (char*)pLibBlk;
3186 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3191 } sltg_ref_lookup_t;
3193 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3194 HREFTYPE *typelib_ref)
3196 if(table && typeinfo_ref < table->num)
3198 *typelib_ref = table->refs[typeinfo_ref];
3202 ERR_(typelib)("Unable to find reference\n");
3207 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3212 if((*pType & 0xe00) == 0xe00) {
3214 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3215 pTD = pTD->u.lptdesc;
3217 switch(*pType & 0x3f) {
3220 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3221 pTD = pTD->u.lptdesc;
3224 case VT_USERDEFINED:
3225 pTD->vt = VT_USERDEFINED;
3226 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3232 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3235 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3237 pTD->vt = VT_CARRAY;
3238 pTD->u.lpadesc = heap_alloc_zero(sizeof(ARRAYDESC) + (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3239 pTD->u.lpadesc->cDims = pSA->cDims;
3240 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3241 pSA->cDims * sizeof(SAFEARRAYBOUND));
3243 pTD = &pTD->u.lpadesc->tdescElem;
3249 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3253 pTD->vt = VT_SAFEARRAY;
3254 pTD->u.lptdesc = heap_alloc_zero(sizeof(TYPEDESC));
3255 pTD = pTD->u.lptdesc;
3259 pTD->vt = *pType & 0x3f;
3268 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3269 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3271 /* Handle [in/out] first */
3272 if((*pType & 0xc000) == 0xc000)
3273 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3274 else if(*pType & 0x8000)
3275 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3276 else if(*pType & 0x4000)
3277 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3279 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3282 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3285 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3287 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3291 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3296 TLBRefType *ref_type;
3297 sltg_ref_lookup_t *table;
3298 HREFTYPE typelib_ref;
3300 if(pRef->magic != SLTG_REF_MAGIC) {
3301 FIXME("Ref magic = %x\n", pRef->magic);
3304 name = ( (char*)pRef->names + pRef->number);
3306 table = heap_alloc(sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3307 table->num = pRef->number >> 3;
3309 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3311 /* We don't want the first href to be 0 */
3312 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3314 for(ref = 0; ref < pRef->number >> 3; ref++) {
3316 unsigned int lib_offs, type_num;
3318 ref_type = heap_alloc_zero(sizeof(TLBRefType));
3320 name += SLTG_ReadStringA(name, &refname);
3321 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3322 FIXME_(typelib)("Can't sscanf ref\n");
3323 if(lib_offs != 0xffff) {
3324 TLBImpLib **import = &pTL->pImpLibs;
3327 if((*import)->offset == lib_offs)
3329 import = &(*import)->next;
3332 char fname[MAX_PATH+1];
3335 *import = heap_alloc_zero(sizeof(**import));
3336 (*import)->offset = lib_offs;
3337 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3339 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3340 &(*import)->wVersionMajor,
3341 &(*import)->wVersionMinor,
3342 &(*import)->lcid, fname) != 4) {
3343 FIXME_(typelib)("can't sscanf ref %s\n",
3344 pNameTable + lib_offs + 40);
3346 len = strlen(fname);
3347 if(fname[len-1] != '#')
3348 FIXME("fname = %s\n", fname);
3349 fname[len-1] = '\0';
3350 (*import)->name = TLB_MultiByteToBSTR(fname);
3352 ref_type->pImpTLInfo = *import;
3354 /* Store a reference to IDispatch */
3355 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3356 pTL->dispatch_href = typelib_ref;
3358 } else { /* internal ref */
3359 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3361 ref_type->reference = typelib_ref;
3362 ref_type->index = type_num;
3365 list_add_tail(&pTL->ref_list, &ref_type->entry);
3367 table->refs[ref] = typelib_ref;
3370 if((BYTE)*name != SLTG_REF_MAGIC)
3371 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3372 dump_TLBRefType(pTL);
3376 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3377 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3379 SLTG_ImplInfo *info;
3380 TLBImplType **ppImplType = &pTI->impltypelist;
3381 /* I don't really get this structure, usually it's 0x16 bytes
3382 long, but iuser.tlb contains some that are 0x18 bytes long.
3383 That's ok because we can use the next ptr to jump to the next
3384 one. But how do we know the length of the last one? The WORD
3385 at offs 0x8 might be the clue. For now I'm just assuming that
3386 the last one is the regular 0x16 bytes. */
3388 info = (SLTG_ImplInfo*)pBlk;
3390 *ppImplType = heap_alloc_zero(sizeof(**ppImplType));
3391 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3392 (*ppImplType)->implflags = info->impltypeflags;
3393 pTI->TypeAttr.cImplTypes++;
3394 ppImplType = &(*ppImplType)->next;
3396 if(info->next == 0xffff)
3399 FIXME_(typelib)("Interface inheriting more than one interface\n");
3400 info = (SLTG_ImplInfo*)(pBlk + info->next);
3402 info++; /* see comment at top of function */
3406 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3407 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3409 TLBVarDesc **ppVarDesc = &pTI->varlist;
3410 BSTR bstrPrevName = NULL;
3411 SLTG_Variable *pItem;
3415 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3416 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3418 *ppVarDesc = heap_alloc_zero(sizeof(**ppVarDesc));
3419 (*ppVarDesc)->vardesc.memid = pItem->memid;
3421 if (pItem->magic != SLTG_VAR_MAGIC &&
3422 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3423 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3427 if (pItem->name == 0xfffe)
3428 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3430 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3432 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3433 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3434 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3436 if(pItem->flags & 0x02)
3437 pType = &pItem->type;
3439 pType = (WORD*)(pBlk + pItem->type);
3441 if (pItem->flags & ~0xda)
3442 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3444 SLTG_DoElem(pType, pBlk,
3445 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3447 if (TRACE_ON(typelib)) {
3449 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3450 TRACE_(typelib)("elemdescVar: %s\n", buf);
3453 if (pItem->flags & 0x40) {
3454 TRACE_(typelib)("VAR_DISPATCH\n");
3455 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3457 else if (pItem->flags & 0x10) {
3458 TRACE_(typelib)("VAR_CONST\n");
3459 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3460 (*ppVarDesc)->vardesc.u.lpvarValue = heap_alloc(sizeof(VARIANT));
3461 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3462 if (pItem->flags & 0x08)
3463 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3465 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3471 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3473 TRACE_(typelib)("len = %u\n", len);
3474 if (len == 0xffff) {
3477 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3478 str = SysAllocStringLen(NULL, alloc_len);
3479 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3481 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3482 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3491 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3492 *(INT*)(pBlk + pItem->byte_offs);
3495 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3500 TRACE_(typelib)("VAR_PERINSTANCE\n");
3501 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3502 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3505 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3506 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3508 if (pItem->flags & 0x80)
3509 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3511 bstrPrevName = (*ppVarDesc)->Name;
3512 ppVarDesc = &((*ppVarDesc)->next);
3514 pTI->TypeAttr.cVars = cVars;
3517 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3518 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3520 SLTG_Function *pFunc;
3522 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3524 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3525 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3530 *ppFuncDesc = heap_alloc_zero(sizeof(**ppFuncDesc));
3532 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3533 case SLTG_FUNCTION_MAGIC:
3534 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3536 case SLTG_DISPATCH_FUNCTION_MAGIC:
3537 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3539 case SLTG_STATIC_FUNCTION_MAGIC:
3540 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3543 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3544 heap_free(*ppFuncDesc);
3548 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3550 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3551 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3552 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3553 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3554 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3555 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos & ~1;
3557 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3558 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3560 if(pFunc->retnextopt & 0x80)
3561 pType = &pFunc->rettype;
3563 pType = (WORD*)(pBlk + pFunc->rettype);
3565 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3567 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3568 heap_alloc_zero((*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3569 (*ppFuncDesc)->pParamDesc =
3570 heap_alloc_zero((*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3572 pArg = (WORD*)(pBlk + pFunc->arg_off);
3574 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3575 char *paramName = pNameTable + *pArg;
3577 /* If arg type follows then paramName points to the 2nd
3578 letter of the name, else the next WORD is an offset to
3579 the arg type and paramName points to the first letter.
3580 So let's take one char off paramName and see if we're
3581 pointing at an alpha-numeric char. However if *pArg is
3582 0xffff or 0xfffe then the param has no name, the former
3583 meaning that the next WORD is the type, the latter
3584 meaning that the next WORD is an offset to the type. */
3589 else if(*pArg == 0xfffe) {
3593 else if(paramName[-1] && !isalnum(paramName[-1]))
3598 if(HaveOffs) { /* the next word is an offset to type */
3599 pType = (WORD*)(pBlk + *pArg);
3600 SLTG_DoElem(pType, pBlk,
3601 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3606 pArg = SLTG_DoElem(pArg, pBlk,
3607 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3610 /* Are we an optional param ? */
3611 if((*ppFuncDesc)->funcdesc.cParams - param <=
3612 (*ppFuncDesc)->funcdesc.cParamsOpt)
3613 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3616 (*ppFuncDesc)->pParamDesc[param].Name =
3617 TLB_MultiByteToBSTR(paramName);
3619 (*ppFuncDesc)->pParamDesc[param].Name =
3620 SysAllocString((*ppFuncDesc)->Name);
3624 ppFuncDesc = &((*ppFuncDesc)->next);
3625 if(pFunc->next == 0xffff) break;
3627 pTI->TypeAttr.cFuncs = cFuncs;
3630 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3631 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3632 SLTG_TypeInfoTail *pTITail)
3635 sltg_ref_lookup_t *ref_lookup = NULL;
3637 if(pTIHeader->href_table != 0xffffffff) {
3638 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3644 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3645 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3647 heap_free(ref_lookup);
3651 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3652 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3653 const SLTG_TypeInfoTail *pTITail)
3656 sltg_ref_lookup_t *ref_lookup = NULL;
3658 if(pTIHeader->href_table != 0xffffffff) {
3659 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3665 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3666 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3669 if (pTITail->funcs_off != 0xffff)
3670 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3672 heap_free(ref_lookup);
3674 if (TRACE_ON(typelib))
3675 dump_TLBFuncDesc(pTI->funclist);
3678 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3679 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3680 const SLTG_TypeInfoTail *pTITail)
3682 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3685 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3686 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3687 const SLTG_TypeInfoTail *pTITail)
3690 sltg_ref_lookup_t *ref_lookup = NULL;
3692 if (pTITail->simple_alias) {
3693 /* if simple alias, no more processing required */
3694 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3698 if(pTIHeader->href_table != 0xffffffff) {
3699 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3703 /* otherwise it is an offset to a type */
3704 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3706 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3708 heap_free(ref_lookup);
3711 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3712 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3713 const SLTG_TypeInfoTail *pTITail)
3715 sltg_ref_lookup_t *ref_lookup = NULL;
3716 if (pTIHeader->href_table != 0xffffffff)
3717 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3720 if (pTITail->vars_off != 0xffff)
3721 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3723 if (pTITail->funcs_off != 0xffff)
3724 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3726 if (pTITail->impls_off != 0xffff)
3727 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3729 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3730 * of dispinterface functions including the IDispatch ones, so
3731 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3732 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3734 heap_free(ref_lookup);
3735 if (TRACE_ON(typelib))
3736 dump_TLBFuncDesc(pTI->funclist);
3739 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3740 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3741 const SLTG_TypeInfoTail *pTITail)
3743 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3746 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3747 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3748 const SLTG_TypeInfoTail *pTITail)
3750 sltg_ref_lookup_t *ref_lookup = NULL;
3751 if (pTIHeader->href_table != 0xffffffff)
3752 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3755 if (pTITail->vars_off != 0xffff)
3756 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3758 if (pTITail->funcs_off != 0xffff)
3759 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3760 heap_free(ref_lookup);
3761 if (TRACE_ON(typelib))
3765 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3766 managable copy of it into this */
3779 } SLTG_InternalOtherTypeInfo;
3781 /****************************************************************************
3782 * ITypeLib2_Constructor_SLTG
3784 * loading a SLTG typelib from an in-memory image
3786 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3788 ITypeLibImpl *pTypeLibImpl;
3789 SLTG_Header *pHeader;
3790 SLTG_BlkEntry *pBlkEntry;
3794 LPVOID pBlk, pFirstBlk;
3795 SLTG_LibBlk *pLibBlk;
3796 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3797 char *pAfterOTIBlks = NULL;
3798 char *pNameTable, *ptr;
3801 ITypeInfoImpl **ppTypeInfoImpl;
3803 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3806 pTypeLibImpl = TypeLibImpl_Constructor();
3807 if (!pTypeLibImpl) return NULL;
3811 TRACE_(typelib)("header:\n");
3812 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3813 pHeader->nrOfFileBlks );
3814 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3815 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3816 pHeader->SLTG_magic);
3820 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3821 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3823 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3824 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3826 /* Next we have a magic block */
3827 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3829 /* Let's see if we're still in sync */
3830 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3831 sizeof(SLTG_COMPOBJ_MAGIC))) {
3832 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3835 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3836 sizeof(SLTG_DIR_MAGIC))) {
3837 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3841 pIndex = (SLTG_Index*)(pMagic+1);
3843 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3845 pFirstBlk = pPad9 + 1;
3847 /* We'll set up a ptr to the main library block, which is the last one. */
3849 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3850 pBlkEntry[order].next != 0;
3851 order = pBlkEntry[order].next - 1, i++) {
3852 pBlk = (char*)pBlk + pBlkEntry[order].len;
3856 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3858 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3863 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3865 pOtherTypeInfoBlks = heap_alloc_zero(sizeof(*pOtherTypeInfoBlks) * pTypeLibImpl->TypeInfoCount);
3868 ptr = (char*)pLibBlk + len;
3870 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3874 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3876 w = *(WORD*)(ptr + 2);
3879 pOtherTypeInfoBlks[i].index_name = heap_alloc(w+1);
3880 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3881 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3883 w = *(WORD*)(ptr + 4 + len);
3885 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3887 pOtherTypeInfoBlks[i].other_name = heap_alloc(w+1);
3888 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3889 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3891 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3892 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3893 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3895 pOtherTypeInfoBlks[i].extra = heap_alloc(extra);
3896 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3899 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3900 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3901 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3902 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3903 len += sizeof(SLTG_OtherTypeInfo);
3907 pAfterOTIBlks = ptr;
3909 /* Skip this WORD and get the next DWORD */
3910 len = *(DWORD*)(pAfterOTIBlks + 2);
3912 /* Now add this to pLibBLk look at what we're pointing at and
3913 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3914 dust and we should be pointing at the beginning of the name
3917 pNameTable = (char*)pLibBlk + len;
3919 switch(*(WORD*)pNameTable) {
3926 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3930 pNameTable += 0x216;
3934 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3936 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3939 /* Hopefully we now have enough ptrs set up to actually read in
3940 some TypeInfos. It's not clear which order to do them in, so
3941 I'll just follow the links along the BlkEntry chain and read
3942 them in the order in which they are in the file */
3944 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3946 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3947 pBlkEntry[order].next != 0;
3948 order = pBlkEntry[order].next - 1, i++) {
3950 SLTG_TypeInfoHeader *pTIHeader;
3951 SLTG_TypeInfoTail *pTITail;
3952 SLTG_MemberHeader *pMemHeader;
3954 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3955 pOtherTypeInfoBlks[i].index_name)) {
3956 FIXME_(typelib)("Index strings don't match\n");
3961 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3962 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3965 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3966 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3967 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3969 *ppTypeInfoImpl = ITypeInfoImpl_Constructor();
3970 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3971 (*ppTypeInfoImpl)->index = i;
3972 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3973 pOtherTypeInfoBlks[i].name_offs +
3975 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3976 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3977 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3978 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3979 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3980 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3981 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3983 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3984 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3986 if((pTIHeader->typeflags1 & 7) != 2)
3987 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3988 if(pTIHeader->typeflags3 != 2)
3989 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3991 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3992 debugstr_w((*ppTypeInfoImpl)->Name),
3993 typekind_desc[pTIHeader->typekind],
3994 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3995 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3997 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3999 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4001 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4002 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4003 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4005 switch(pTIHeader->typekind) {
4007 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4008 pTIHeader, pTITail);
4012 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4013 pTIHeader, pTITail);
4016 case TKIND_INTERFACE:
4017 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4018 pTIHeader, pTITail);
4022 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4023 pTIHeader, pTITail);
4027 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4028 pTIHeader, pTITail);
4031 case TKIND_DISPATCH:
4032 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4033 pTIHeader, pTITail);
4037 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4038 pTIHeader, pTITail);
4042 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4047 /* could get cFuncs, cVars and cImplTypes from here
4048 but we've already set those */
4049 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4064 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4065 pBlk = (char*)pBlk + pBlkEntry[order].len;
4068 if(i != pTypeLibImpl->TypeInfoCount) {
4069 FIXME("Somehow processed %d TypeInfos\n", i);
4073 heap_free(pOtherTypeInfoBlks);
4074 return (ITypeLib2*)pTypeLibImpl;
4077 /* ITypeLib::QueryInterface
4079 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4084 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4086 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4089 if(IsEqualIID(riid, &IID_IUnknown) ||
4090 IsEqualIID(riid,&IID_ITypeLib)||
4091 IsEqualIID(riid,&IID_ITypeLib2))
4098 ITypeLib2_AddRef(iface);
4099 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4102 TRACE("-- Interface: E_NOINTERFACE\n");
4103 return E_NOINTERFACE;
4108 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4110 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4111 ULONG ref = InterlockedIncrement(&This->ref);
4113 TRACE("(%p)->ref was %u\n",This, ref - 1);
4118 /* ITypeLib::Release
4120 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4122 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4123 ULONG ref = InterlockedDecrement(&This->ref);
4125 TRACE("(%p)->(%u)\n",This, ref);
4129 TLBImpLib *pImpLib, *pImpLibNext;
4130 TLBCustData *pCustData, *pCustDataNext;
4131 TLBRefType *ref_type;
4134 ITypeInfoImpl *pTI, *pTINext;
4136 /* remove cache entry */
4139 TRACE("removing from cache list\n");
4140 EnterCriticalSection(&cache_section);
4141 if (This->next) This->next->prev = This->prev;
4142 if (This->prev) This->prev->next = This->next;
4143 else tlb_cache_first = This->next;
4144 LeaveCriticalSection(&cache_section);
4145 heap_free(This->path);
4147 TRACE(" destroying ITypeLib(%p)\n",This);
4149 SysFreeString(This->Name);
4152 SysFreeString(This->DocString);
4153 This->DocString = NULL;
4155 SysFreeString(This->HelpFile);
4156 This->HelpFile = NULL;
4158 SysFreeString(This->HelpStringDll);
4159 This->HelpStringDll = NULL;
4161 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4163 VariantClear(&pCustData->data);
4165 pCustDataNext = pCustData->next;
4166 heap_free(pCustData);
4169 for (i = 0; i < This->ctTypeDesc; i++)
4170 if (This->pTypeDesc[i].vt == VT_CARRAY)
4171 heap_free(This->pTypeDesc[i].u.lpadesc);
4173 heap_free(This->pTypeDesc);
4175 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4177 if (pImpLib->pImpTypeLib)
4178 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4179 SysFreeString(pImpLib->name);
4181 pImpLibNext = pImpLib->next;
4185 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4187 list_remove(&ref_type->entry);
4188 heap_free(ref_type);
4191 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4193 pTINext = pTI->next;
4194 ITypeInfoImpl_Destroy(pTI);
4203 /* ITypeLib::GetTypeInfoCount
4205 * Returns the number of type descriptions in the type library
4207 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4209 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4210 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4211 return This->TypeInfoCount;
4214 /* ITypeLib::GetTypeInfo
4216 * retrieves the specified type description in the library.
4218 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4221 ITypeInfo **ppTInfo)
4225 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4226 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4228 TRACE("(%p)->(index=%d)\n", This, index);
4230 if (!ppTInfo) return E_INVALIDARG;
4232 /* search element n in list */
4233 for(i=0; i < index; i++)
4235 pTypeInfo = pTypeInfo->next;
4238 TRACE("-- element not found\n");
4239 return TYPE_E_ELEMENTNOTFOUND;
4243 *ppTInfo = (ITypeInfo *) pTypeInfo;
4245 ITypeInfo_AddRef(*ppTInfo);
4246 TRACE("-- found (%p)\n",*ppTInfo);
4251 /* ITypeLibs::GetTypeInfoType
4253 * Retrieves the type of a type description.
4255 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4260 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4262 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4264 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4266 if(!pTKind) return E_INVALIDARG;
4268 if(ITypeLib2_GetTypeInfoCount(iface) <= index)
4269 return TYPE_E_ELEMENTNOTFOUND;
4271 /* search element n in list */
4272 for(i=0; i < index; i++)
4276 TRACE("-- element not found\n");
4277 return TYPE_E_ELEMENTNOTFOUND;
4279 pTInfo = pTInfo->next;
4282 *pTKind = pTInfo->TypeAttr.typekind;
4283 TRACE("-- found Type (%d)\n", *pTKind);
4287 /* ITypeLib::GetTypeInfoOfGuid
4289 * Retrieves the type description that corresponds to the specified GUID.
4292 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4295 ITypeInfo **ppTInfo)
4297 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4298 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4300 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4304 WARN("-- element not found\n");
4305 return TYPE_E_ELEMENTNOTFOUND;
4308 /* search linked list for guid */
4309 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4311 pTypeInfo = pTypeInfo->next;
4315 /* end of list reached */
4316 WARN("-- element not found\n");
4317 return TYPE_E_ELEMENTNOTFOUND;
4321 TRACE("-- found (%p, %s)\n",
4323 debugstr_w(pTypeInfo->Name));
4325 *ppTInfo = (ITypeInfo*)pTypeInfo;
4326 ITypeInfo_AddRef(*ppTInfo);
4330 /* ITypeLib::GetLibAttr
4332 * Retrieves the structure that contains the library's attributes.
4335 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4339 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4341 TRACE("(%p, %p)\n", This, attr);
4343 if (!attr) return E_INVALIDARG;
4345 *attr = heap_alloc(sizeof(**attr));
4346 if (!*attr) return E_OUTOFMEMORY;
4348 **attr = This->LibAttr;
4352 /* ITypeLib::GetTypeComp
4354 * Enables a client compiler to bind to a library's types, variables,
4355 * constants, and global functions.
4358 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4360 ITypeComp **ppTComp)
4362 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4364 TRACE("(%p)->(%p)\n",This,ppTComp);
4365 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4366 ITypeComp_AddRef(*ppTComp);
4371 /* ITypeLib::GetDocumentation
4373 * Retrieves the library's documentation string, the complete Help file name
4374 * and path, and the context identifier for the library Help topic in the Help
4377 * On a successful return all non-null BSTR pointers will have been set,
4380 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4384 BSTR *pBstrDocString,
4385 DWORD *pdwHelpContext,
4386 BSTR *pBstrHelpFile)
4388 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4390 HRESULT result = E_INVALIDARG;
4395 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4397 pBstrName, pBstrDocString,
4398 pdwHelpContext, pBstrHelpFile);
4402 /* documentation for the typelib */
4407 if(!(*pBstrName = SysAllocString(This->Name)))
4415 if (This->DocString)
4417 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4420 else if (This->Name)
4422 if(!(*pBstrDocString = SysAllocString(This->Name)))
4426 *pBstrDocString = NULL;
4430 *pdwHelpContext = This->dwHelpContext;
4436 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4440 *pBstrHelpFile = NULL;
4447 /* for a typeinfo */
4448 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4450 if(SUCCEEDED(result))
4452 result = ITypeInfo_GetDocumentation(pTInfo,
4456 pdwHelpContext, pBstrHelpFile);
4458 ITypeInfo_Release(pTInfo);
4463 if (pBstrDocString) SysFreeString (*pBstrDocString);
4465 if (pBstrName) SysFreeString (*pBstrName);
4467 return STG_E_INSUFFICIENTMEMORY;
4472 * Indicates whether a passed-in string contains the name of a type or member
4473 * described in the library.
4476 static HRESULT WINAPI ITypeLib2_fnIsName(
4482 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4483 ITypeInfoImpl *pTInfo;
4484 TLBFuncDesc *pFInfo;
4487 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4489 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4493 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4494 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4495 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4496 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4497 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4498 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4499 goto ITypeLib2_fnIsName_exit;
4501 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4502 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4507 ITypeLib2_fnIsName_exit:
4508 TRACE("(%p)slow! search for %s: %s found!\n", This,
4509 debugstr_w(szNameBuf), *pfName?"NOT":"");
4514 /* ITypeLib::FindName
4516 * Finds occurrences of a type description in a type library. This may be used
4517 * to quickly verify that a name exists in a type library.
4520 static HRESULT WINAPI ITypeLib2_fnFindName(
4524 ITypeInfo **ppTInfo,
4528 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4529 ITypeInfoImpl *pTInfo;
4530 TLBFuncDesc *pFInfo;
4533 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4535 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4536 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4537 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4538 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4539 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4540 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4541 goto ITypeLib2_fnFindName_exit;
4544 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4545 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4547 ITypeLib2_fnFindName_exit:
4548 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4549 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4552 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4553 This, *pcFound, debugstr_w(szNameBuf), j);
4560 /* ITypeLib::ReleaseTLibAttr
4562 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4565 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4567 TLIBATTR *pTLibAttr)
4569 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4570 TRACE("freeing (%p)\n",This);
4571 heap_free(pTLibAttr);
4575 /* ITypeLib2::GetCustData
4577 * gets the custom data
4579 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4584 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4585 TLBCustData *pCData;
4587 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4589 if( IsEqualIID(guid, &pCData->guid)) break;
4592 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4596 VariantInit( pVarVal);
4597 VariantCopy( pVarVal, &pCData->data);
4600 return E_INVALIDARG; /* FIXME: correct? */
4603 /* ITypeLib2::GetLibStatistics
4605 * Returns statistics about a type library that are required for efficient
4606 * sizing of hash tables.
4609 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4611 ULONG *pcUniqueNames,
4612 ULONG *pcchUniqueNames)
4614 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4616 FIXME("(%p): stub!\n", This);
4618 if(pcUniqueNames) *pcUniqueNames=1;
4619 if(pcchUniqueNames) *pcchUniqueNames=1;
4623 /* ITypeLib2::GetDocumentation2
4625 * Retrieves the library's documentation string, the complete Help file name
4626 * and path, the localization context to use, and the context ID for the
4627 * library Help topic in the Help file.
4630 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4634 BSTR *pbstrHelpString,
4635 DWORD *pdwHelpStringContext,
4636 BSTR *pbstrHelpStringDll)
4638 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4642 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4644 /* the help string should be obtained from the helpstringdll,
4645 * using the _DLLGetDocumentation function, based on the supplied
4646 * lcid. Nice to do sometime...
4650 /* documentation for the typelib */
4652 *pbstrHelpString=SysAllocString(This->DocString);
4653 if(pdwHelpStringContext)
4654 *pdwHelpStringContext=This->dwHelpContext;
4655 if(pbstrHelpStringDll)
4656 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4662 /* for a typeinfo */
4663 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4665 if(SUCCEEDED(result))
4667 ITypeInfo2 * pTInfo2;
4668 result = ITypeInfo_QueryInterface(pTInfo,
4670 (LPVOID*) &pTInfo2);
4672 if(SUCCEEDED(result))
4674 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4678 pdwHelpStringContext,
4679 pbstrHelpStringDll);
4681 ITypeInfo2_Release(pTInfo2);
4684 ITypeInfo_Release(pTInfo);
4690 /* ITypeLib2::GetAllCustData
4692 * Gets all custom data items for the library.
4695 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4697 CUSTDATA *pCustData)
4699 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4700 TLBCustData *pCData;
4702 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4703 pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
4704 if(pCustData->prgCustData ){
4705 pCustData->cCustData=This->ctCustData;
4706 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4707 pCustData->prgCustData[i].guid=pCData->guid;
4708 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4711 ERR(" OUT OF MEMORY!\n");
4712 return E_OUTOFMEMORY;
4717 static const ITypeLib2Vtbl tlbvt = {
4718 ITypeLib2_fnQueryInterface,
4720 ITypeLib2_fnRelease,
4721 ITypeLib2_fnGetTypeInfoCount,
4722 ITypeLib2_fnGetTypeInfo,
4723 ITypeLib2_fnGetTypeInfoType,
4724 ITypeLib2_fnGetTypeInfoOfGuid,
4725 ITypeLib2_fnGetLibAttr,
4726 ITypeLib2_fnGetTypeComp,
4727 ITypeLib2_fnGetDocumentation,
4729 ITypeLib2_fnFindName,
4730 ITypeLib2_fnReleaseTLibAttr,
4732 ITypeLib2_fnGetCustData,
4733 ITypeLib2_fnGetLibStatistics,
4734 ITypeLib2_fnGetDocumentation2,
4735 ITypeLib2_fnGetAllCustData
4739 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4741 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4743 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4746 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4748 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4750 return ITypeLib2_AddRef((ITypeLib2 *)This);
4753 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4755 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4757 return ITypeLib2_Release((ITypeLib2 *)This);
4760 static HRESULT WINAPI ITypeLibComp_fnBind(
4765 ITypeInfo ** ppTInfo,
4766 DESCKIND * pDescKind,
4769 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4770 ITypeInfoImpl *pTypeInfo;
4773 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4775 *pDescKind = DESCKIND_NONE;
4776 pBindPtr->lptcomp = NULL;
4779 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4781 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4783 /* FIXME: check wFlags here? */
4784 /* FIXME: we should use a hash table to look this info up using lHash
4785 * instead of an O(n) search */
4786 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4787 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4789 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4791 *pDescKind = DESCKIND_TYPECOMP;
4792 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4793 ITypeComp_AddRef(pBindPtr->lptcomp);
4794 TRACE("module or enum: %s\n", debugstr_w(szName));
4799 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4800 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4802 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4805 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4806 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4808 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4811 else if (hr == TYPE_E_TYPEMISMATCH)
4815 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4816 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4818 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4820 ITypeInfo *subtypeinfo;
4822 DESCKIND subdesckind;
4824 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4825 &subtypeinfo, &subdesckind, &subbindptr);
4826 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4828 TYPEDESC tdesc_appobject;
4829 const VARDESC vardesc_appobject =
4832 NULL, /* lpstrSchema */
4847 VAR_STATIC /* varkind */
4850 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4851 tdesc_appobject.vt = VT_USERDEFINED;
4853 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4855 /* cleanup things filled in by Bind call so we can put our
4856 * application object data in there instead */
4857 switch (subdesckind)
4859 case DESCKIND_FUNCDESC:
4860 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4862 case DESCKIND_VARDESC:
4863 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4868 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4870 if (pTypeInfo->hreftype == -1)
4871 FIXME("no hreftype for interface %p\n", pTypeInfo);
4873 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4877 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4878 *ppTInfo = (ITypeInfo *)pTypeInfo;
4879 ITypeInfo_AddRef(*ppTInfo);
4882 else if (hr == TYPE_E_TYPEMISMATCH)
4889 TRACE("type mismatch %s\n", debugstr_w(szName));
4890 return TYPE_E_TYPEMISMATCH;
4894 TRACE("name not found %s\n", debugstr_w(szName));
4899 static HRESULT WINAPI ITypeLibComp_fnBindType(
4903 ITypeInfo ** ppTInfo,
4904 ITypeComp ** ppTComp)
4906 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4907 ITypeInfoImpl *pTypeInfo;
4909 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4911 if(!szName || !ppTInfo || !ppTComp)
4912 return E_INVALIDARG;
4914 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4916 /* FIXME: should use lHash to do the search */
4917 if (pTypeInfo->Name && !strcmpiW(pTypeInfo->Name, szName))
4919 TRACE("returning %p\n", pTypeInfo);
4920 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4921 ITypeInfo_AddRef(*ppTInfo);
4922 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4923 ITypeComp_AddRef(*ppTComp);
4928 TRACE("not found\n");
4934 static const ITypeCompVtbl tlbtcvt =
4937 ITypeLibComp_fnQueryInterface,
4938 ITypeLibComp_fnAddRef,
4939 ITypeLibComp_fnRelease,
4941 ITypeLibComp_fnBind,
4942 ITypeLibComp_fnBindType
4945 /*================== ITypeInfo(2) Methods ===================================*/
4946 static ITypeInfoImpl* ITypeInfoImpl_Constructor(void)
4948 ITypeInfoImpl *pTypeInfoImpl;
4950 pTypeInfoImpl = heap_alloc_zero(sizeof(ITypeInfoImpl));
4953 pTypeInfoImpl->lpVtbl = &tinfvt;
4954 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4955 pTypeInfoImpl->ref = 0;
4956 pTypeInfoImpl->hreftype = -1;
4957 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4958 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4960 TRACE("(%p)\n", pTypeInfoImpl);
4961 return pTypeInfoImpl;
4964 /* ITypeInfo::QueryInterface
4966 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4971 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4973 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4976 if(IsEqualIID(riid, &IID_IUnknown) ||
4977 IsEqualIID(riid,&IID_ITypeInfo)||
4978 IsEqualIID(riid,&IID_ITypeInfo2))
4982 ITypeInfo_AddRef(iface);
4983 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4986 TRACE("-- Interface: E_NOINTERFACE\n");
4987 return E_NOINTERFACE;
4990 /* ITypeInfo::AddRef
4992 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4994 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4995 ULONG ref = InterlockedIncrement(&This->ref);
4997 TRACE("(%p)->ref is %u\n",This, ref);
4999 if (ref == 1 /* incremented from 0 */)
5000 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
5005 static void ITypeInfoImpl_Destroy(ITypeInfoImpl *This)
5007 TLBFuncDesc *pFInfo, *pFInfoNext;
5008 TLBVarDesc *pVInfo, *pVInfoNext;
5009 TLBImplType *pImpl, *pImplNext;
5011 TRACE("destroying ITypeInfo(%p)\n",This);
5013 SysFreeString(This->Name);
5016 SysFreeString(This->DocString);
5017 This->DocString = NULL;
5019 SysFreeString(This->DllName);
5020 This->DllName = NULL;
5022 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
5025 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
5027 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
5028 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5030 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5031 heap_free(elemdesc->u.paramdesc.pparamdescex);
5033 TLB_FreeCustData(pFInfo->pParamDesc[i].pCustData);
5034 SysFreeString(pFInfo->pParamDesc[i].Name);
5036 heap_free(pFInfo->funcdesc.lprgelemdescParam);
5037 heap_free(pFInfo->pParamDesc);
5038 TLB_FreeCustData(pFInfo->pCustData);
5039 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5040 SysFreeString(pFInfo->Entry);
5041 SysFreeString(pFInfo->HelpString);
5042 SysFreeString(pFInfo->Name);
5044 pFInfoNext = pFInfo->next;
5047 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5049 if (pVInfo->vardesc.varkind == VAR_CONST)
5051 VariantClear(pVInfo->vardesc.u.lpvarValue);
5052 heap_free(pVInfo->vardesc.u.lpvarValue);
5054 TLB_FreeCustData(pVInfo->pCustData);
5055 SysFreeString(pVInfo->Name);
5056 SysFreeString(pVInfo->HelpString);
5057 pVInfoNext = pVInfo->next;
5060 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5062 TLB_FreeCustData(pImpl->pCustData);
5063 pImplNext = pImpl->next;
5066 TLB_FreeCustData(This->pCustData);
5071 /* ITypeInfo::Release
5073 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5075 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5076 ULONG ref = InterlockedDecrement(&This->ref);
5078 TRACE("(%p)->(%u)\n",This, ref);
5082 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5083 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5084 if (not_attached_to_typelib)
5086 /* otherwise This will be freed when typelib is freed */
5092 /* ITypeInfo::GetTypeAttr
5094 * Retrieves a TYPEATTR structure that contains the attributes of the type
5098 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5099 LPTYPEATTR *ppTypeAttr)
5101 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5104 TRACE("(%p)\n",This);
5106 size = sizeof(**ppTypeAttr);
5107 if (This->TypeAttr.typekind == TKIND_ALIAS)
5108 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5110 *ppTypeAttr = heap_alloc(size);
5112 return E_OUTOFMEMORY;
5114 **ppTypeAttr = This->TypeAttr;
5116 if (This->TypeAttr.typekind == TKIND_ALIAS)
5117 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5118 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5120 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5121 /* This should include all the inherited funcs */
5122 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5123 /* This is always the size of IDispatch's vtbl */
5124 (*ppTypeAttr)->cbSizeVft = sizeof(IDispatchVtbl);
5125 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5130 /* ITypeInfo::GetTypeComp
5132 * Retrieves the ITypeComp interface for the type description, which enables a
5133 * client compiler to bind to the type description's members.
5136 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5137 ITypeComp * *ppTComp)
5139 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5141 TRACE("(%p)->(%p)\n", This, ppTComp);
5143 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5144 ITypeComp_AddRef(*ppTComp);
5148 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5150 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5151 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5152 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5156 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5159 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5160 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5162 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5163 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5164 *buffer += sizeof(PARAMDESCEX);
5165 *pparamdescex_dest = *pparamdescex_src;
5166 VariantInit(&pparamdescex_dest->varDefaultValue);
5167 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5168 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5171 dest->u.paramdesc.pparamdescex = NULL;
5175 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5177 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5178 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5181 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5185 SIZE_T size = sizeof(*src);
5189 size += sizeof(*src->lprgscode) * src->cScodes;
5190 size += TLB_SizeElemDesc(&src->elemdescFunc);
5191 for (i = 0; i < src->cParams; i++)
5193 size += sizeof(ELEMDESC);
5194 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5197 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5198 if (!dest) return E_OUTOFMEMORY;
5201 if (dispinterface) /* overwrite funckind */
5202 dest->funckind = FUNC_DISPATCH;
5203 buffer = (char *)(dest + 1);
5205 dest->lprgscode = (SCODE *)buffer;
5206 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5207 buffer += sizeof(*src->lprgscode) * src->cScodes;
5209 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5212 SysFreeString((BSTR)dest);
5216 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5217 buffer += sizeof(ELEMDESC) * src->cParams;
5218 for (i = 0; i < src->cParams; i++)
5220 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5226 /* undo the above actions */
5227 for (i = i - 1; i >= 0; i--)
5228 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5229 TLB_FreeElemDesc(&dest->elemdescFunc);
5230 SysFreeString((BSTR)dest);
5234 /* special treatment for dispinterfaces: this makes functions appear
5235 * to return their [retval] value when it is really returning an
5237 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5239 if (dest->cParams &&
5240 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5242 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5243 if (elemdesc->tdesc.vt != VT_PTR)
5245 ERR("elemdesc should have started with VT_PTR instead of:\n");
5247 dump_ELEMDESC(elemdesc);
5248 return E_UNEXPECTED;
5251 /* copy last parameter to the return value. we are using a flat
5252 * buffer so there is no danger of leaking memory in
5254 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5256 /* remove the last parameter */
5260 /* otherwise this function is made to appear to have no return
5262 dest->elemdescFunc.tdesc.vt = VT_VOID;
5270 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5272 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5273 const TLBFuncDesc *pFDesc;
5276 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5281 *ppFuncDesc = &pFDesc->funcdesc;
5285 return TYPE_E_ELEMENTNOTFOUND;
5288 /* internal function to make the inherited interfaces' methods appear
5289 * part of the interface */
5290 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5291 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5293 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5295 UINT implemented_funcs = 0;
5300 *hrefoffset = DISPATCH_HREF_OFFSET;
5302 if(This->impltypelist)
5304 ITypeInfo *pSubTypeInfo;
5307 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5311 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5314 &sub_funcs, hrefoffset);
5315 implemented_funcs += sub_funcs;
5316 ITypeInfo_Release(pSubTypeInfo);
5319 *hrefoffset += DISPATCH_HREF_OFFSET;
5323 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5327 if (index < implemented_funcs)
5328 return E_INVALIDARG;
5329 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5333 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5335 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5338 switch (pTypeDesc->vt)
5340 case VT_USERDEFINED:
5341 pTypeDesc->u.hreftype += hrefoffset;
5345 pTypeDesc = pTypeDesc->u.lptdesc;
5348 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5356 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5359 for (i = 0; i < pFuncDesc->cParams; i++)
5360 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5361 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5364 /* ITypeInfo::GetFuncDesc
5366 * Retrieves the FUNCDESC structure that contains information about a
5367 * specified function.
5370 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5371 LPFUNCDESC *ppFuncDesc)
5373 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5374 const FUNCDESC *internal_funcdesc;
5376 UINT hrefoffset = 0;
5378 TRACE("(%p) index %d\n", This, index);
5380 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5381 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5382 &internal_funcdesc, NULL,
5385 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5386 &internal_funcdesc);
5389 WARN("description for function %d not found\n", index);
5393 hr = TLB_AllocAndInitFuncDesc(
5396 This->TypeAttr.typekind == TKIND_DISPATCH);
5398 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5399 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5401 TRACE("-- 0x%08x\n", hr);
5405 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5409 SIZE_T size = sizeof(*src);
5412 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5413 if (src->varkind == VAR_CONST)
5414 size += sizeof(VARIANT);
5415 size += TLB_SizeElemDesc(&src->elemdescVar);
5417 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5418 if (!dest) return E_OUTOFMEMORY;
5421 buffer = (char *)(dest + 1);
5422 if (src->lpstrSchema)
5425 dest->lpstrSchema = (LPOLESTR)buffer;
5426 len = strlenW(src->lpstrSchema);
5427 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5428 buffer += (len + 1) * sizeof(WCHAR);
5431 if (src->varkind == VAR_CONST)
5435 dest->u.lpvarValue = (VARIANT *)buffer;
5436 *dest->u.lpvarValue = *src->u.lpvarValue;
5437 buffer += sizeof(VARIANT);
5438 VariantInit(dest->u.lpvarValue);
5439 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5442 SysFreeString((BSTR)dest);
5446 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5449 if (src->varkind == VAR_CONST)
5450 VariantClear(dest->u.lpvarValue);
5451 SysFreeString((BSTR)dest);
5458 /* ITypeInfo::GetVarDesc
5460 * Retrieves a VARDESC structure that describes the specified variable.
5463 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5464 LPVARDESC *ppVarDesc)
5466 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5468 const TLBVarDesc *pVDesc;
5470 TRACE("(%p) index %d\n", This, index);
5472 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5476 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5478 return E_INVALIDARG;
5481 /* ITypeInfo_GetNames
5483 * Retrieves the variable with the specified member ID (or the name of the
5484 * property or method and its parameters) that correspond to the specified
5487 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5488 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5490 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5491 const TLBFuncDesc *pFDesc;
5492 const TLBVarDesc *pVDesc;
5494 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5495 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5498 /* function found, now return function and parameter names */
5499 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5502 *rgBstrNames=SysAllocString(pFDesc->Name);
5504 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5510 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5513 *rgBstrNames=SysAllocString(pVDesc->Name);
5518 if(This->impltypelist &&
5519 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5520 /* recursive search */
5523 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5525 if(SUCCEEDED(result))
5527 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5528 ITypeInfo_Release(pTInfo);
5531 WARN("Could not search inherited interface!\n");
5535 WARN("no names found\n");
5538 return TYPE_E_ELEMENTNOTFOUND;
5545 /* ITypeInfo::GetRefTypeOfImplType
5547 * If a type description describes a COM class, it retrieves the type
5548 * description of the implemented interface types. For an interface,
5549 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5553 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5558 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5561 const TLBImplType *pImpl = This->impltypelist;
5563 TRACE("(%p) index %d\n", This, index);
5564 if (TRACE_ON(ole)) dump_TypeInfo(This);
5568 /* only valid on dual interfaces;
5569 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5571 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5573 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5579 hr = TYPE_E_ELEMENTNOTFOUND;
5582 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5584 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5585 *pRefType = This->pTypeLib->dispatch_href;
5589 /* get element n from linked list */
5590 for(i=0; pImpl && i<index; i++)
5592 pImpl = pImpl->next;
5596 *pRefType = pImpl->hRef;
5598 hr = TYPE_E_ELEMENTNOTFOUND;
5604 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5606 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5612 /* ITypeInfo::GetImplTypeFlags
5614 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5615 * or base interface in a type description.
5617 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5618 UINT index, INT *pImplTypeFlags)
5620 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5624 TRACE("(%p) index %d\n", This, index);
5625 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5626 i++, pImpl=pImpl->next)
5628 if(i==index && pImpl){
5629 *pImplTypeFlags=pImpl->implflags;
5634 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5637 WARN("ImplType %d not found\n", index);
5638 return TYPE_E_ELEMENTNOTFOUND;
5642 * Maps between member names and member IDs, and parameter names and
5645 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5646 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5648 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5649 const TLBFuncDesc *pFDesc;
5650 const TLBVarDesc *pVDesc;
5654 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5657 /* init out parameters in case of failure */
5658 for (i = 0; i < cNames; i++)
5659 pMemId[i] = MEMBERID_NIL;
5661 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5663 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5664 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5665 for(i=1; i < cNames; i++){
5666 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5667 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5669 if( j<pFDesc->funcdesc.cParams)
5672 ret=DISP_E_UNKNOWNNAME;
5674 TRACE("-- 0x%08x\n", ret);
5678 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5679 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5680 if(cNames) *pMemId=pVDesc->vardesc.memid;
5684 /* not found, see if it can be found in an inherited interface */
5685 if(This->impltypelist) {
5686 /* recursive search */
5688 ret=ITypeInfo_GetRefTypeInfo(iface,
5689 This->impltypelist->hRef, &pTInfo);
5691 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5692 ITypeInfo_Release(pTInfo);
5695 WARN("Could not search inherited interface!\n");
5697 WARN("no names found\n");
5698 return DISP_E_UNKNOWNNAME;
5704 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5705 __ASM_GLOBAL_FUNC( call_method,
5707 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5708 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5709 "movl %esp,%ebp\n\t"
5710 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5712 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5714 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5715 "movl 12(%ebp),%edx\n\t"
5716 "movl %esp,%edi\n\t"
5719 "subl %edx,%edi\n\t"
5720 "andl $~15,%edi\n\t"
5721 "movl %edi,%esp\n\t"
5722 "movl 12(%ebp),%ecx\n\t"
5723 "movl 16(%ebp),%esi\n\t"
5726 "1:\tcall *8(%ebp)\n\t"
5727 "subl %esp,%edi\n\t"
5728 "movl 20(%ebp),%ecx\n\t"
5729 "movl %edi,(%ecx)\n\t"
5730 "leal -8(%ebp),%esp\n\t"
5732 __ASM_CFI(".cfi_same_value %edi\n\t")
5734 __ASM_CFI(".cfi_same_value %esi\n\t")
5736 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5737 __ASM_CFI(".cfi_same_value %ebp\n\t")
5740 /* same function but returning floating point */
5741 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5743 /* ITypeInfo::Invoke
5745 * Invokes a method, or accesses a property of an object, that implements the
5746 * interface described by the type description.
5749 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5753 if (TRACE_ON(ole)) {
5755 TRACE("Calling %p(",func);
5756 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5757 if (nrargs > 30) TRACE("...");
5764 res = call_method( func, nrargs, args, &stack_offset );
5767 FIXME("unsupported calling convention %d\n",callconv);
5771 TRACE("returns %08x\n",res);
5775 #elif defined(__x86_64__)
5777 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5778 __ASM_GLOBAL_FUNC( call_method,
5780 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5781 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5782 "movq %rsp,%rbp\n\t"
5783 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5785 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5787 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5788 "movq %rcx,%rax\n\t"
5791 "cmovgq %rdx,%rcx\n\t"
5792 "leaq 0(,%rcx,8),%rdx\n\t"
5793 "subq %rdx,%rsp\n\t"
5794 "andq $~15,%rsp\n\t"
5795 "movq %rsp,%rdi\n\t"
5798 "movq 0(%rsp),%rcx\n\t"
5799 "movq 8(%rsp),%rdx\n\t"
5800 "movq 16(%rsp),%r8\n\t"
5801 "movq 24(%rsp),%r9\n\t"
5802 "movq %rcx,%xmm0\n\t"
5803 "movq %rdx,%xmm1\n\t"
5804 "movq %r8,%xmm2\n\t"
5805 "movq %r9,%xmm3\n\t"
5807 "leaq -16(%rbp),%rsp\n\t"
5809 __ASM_CFI(".cfi_same_value %rdi\n\t")
5811 __ASM_CFI(".cfi_same_value %rsi\n\t")
5812 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5814 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5815 __ASM_CFI(".cfi_same_value %rbp\n\t")
5818 /* same function but returning floating point */
5819 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5821 #endif /* __x86_64__ */
5823 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5826 ITypeInfo *tinfo2 = NULL;
5827 TYPEATTR *tattr = NULL;
5829 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5832 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5834 tdesc->u.hreftype, hr);
5837 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5840 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5841 ITypeInfo_Release(tinfo2);
5845 switch (tattr->typekind)
5852 tdesc = &tattr->tdescAlias;
5853 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5856 case TKIND_INTERFACE:
5857 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5863 case TKIND_DISPATCH:
5872 FIXME("TKIND_RECORD unhandled.\n");
5877 FIXME("TKIND_UNION unhandled.\n");
5882 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5886 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5887 ITypeInfo_Release(tinfo2);
5891 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5895 /* enforce only one level of pointer indirection */
5896 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5898 tdesc = tdesc->u.lptdesc;
5900 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5901 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5902 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5903 if ((tdesc->vt == VT_USERDEFINED) ||
5904 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5906 VARTYPE vt_userdefined = 0;
5907 const TYPEDESC *tdesc_userdefined = tdesc;
5908 if (tdesc->vt == VT_PTR)
5910 vt_userdefined = VT_BYREF;
5911 tdesc_userdefined = tdesc->u.lptdesc;
5913 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5915 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5916 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5918 *vt |= vt_userdefined;
5930 case VT_USERDEFINED:
5931 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5938 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5939 hr = DISP_E_BADVARTYPE;
5943 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5958 /***********************************************************************
5959 * DispCallFunc (OLEAUT32.@)
5961 * Invokes a function of the specified calling convention, passing the
5962 * specified arguments and returns the result.
5965 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5966 * oVft [I] The offset in the vtable. See notes.
5967 * cc [I] Calling convention of the function to call.
5968 * vtReturn [I] The return type of the function.
5969 * cActuals [I] Number of parameters.
5970 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5971 * prgpvarg [I] The arguments to pass.
5972 * pvargResult [O] The return value of the function. Can be NULL.
5976 * Failure: HRESULT code.
5979 * The HRESULT return value of this function is not affected by the return
5980 * value of the user supplied function, which is returned in pvargResult.
5982 * If pvInstance is NULL then a non-object function is to be called and oVft
5983 * is the address of the function to call.
5985 * The cc parameter can be one of the following values:
5998 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5999 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6002 int argspos, stack_offset;
6007 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6008 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6009 pvargResult, V_VT(pvargResult));
6011 if (cc != CC_STDCALL && cc != CC_CDECL)
6013 FIXME("unsupported calling convention %d\n",cc);
6014 return E_INVALIDARG;
6017 /* maximum size for an argument is sizeof(VARIANT) */
6018 args = heap_alloc(sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6020 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6024 const FARPROC *vtable = *(FARPROC **)pvInstance;
6025 func = vtable[oVft/sizeof(void *)];
6026 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6028 else func = (void *)oVft;
6030 for (i = 0; i < cActuals; i++)
6032 VARIANT *arg = prgpvarg[i];
6043 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6044 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6048 memcpy( &args[argspos], arg, sizeof(*arg) );
6049 argspos += sizeof(*arg) / sizeof(DWORD);
6051 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6052 args[argspos++] = V_BOOL(arg);
6055 args[argspos++] = V_UI4(arg);
6058 TRACE("arg %u: type %d\n",i,prgvt[i]);
6065 call_method( func, argspos - 1, args + 1, &stack_offset );
6068 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6072 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6076 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6077 call_method( func, argspos, args, &stack_offset );
6082 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6085 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6089 if (stack_offset && cc == CC_STDCALL)
6091 WARN( "stack pointer off by %d\n", stack_offset );
6092 return DISP_E_BADCALLEE;
6094 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6095 TRACE("retval: "); dump_Variant(pvargResult);
6098 #elif defined(__x86_64__)
6104 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6105 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6106 pvargResult, V_VT(pvargResult));
6108 if (cc != CC_STDCALL && cc != CC_CDECL)
6110 FIXME("unsupported calling convention %d\n",cc);
6111 return E_INVALIDARG;
6114 /* maximum size for an argument is sizeof(DWORD_PTR) */
6115 args = heap_alloc( sizeof(DWORD_PTR) * (cActuals + 2) );
6117 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6121 const FARPROC *vtable = *(FARPROC **)pvInstance;
6122 func = vtable[oVft/sizeof(void *)];
6123 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6125 else func = (void *)oVft;
6127 for (i = 0; i < cActuals; i++)
6129 VARIANT *arg = prgpvarg[i];
6135 args[argspos++] = (ULONG_PTR)arg;
6137 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6138 args[argspos++] = V_BOOL(arg);
6141 args[argspos++] = V_UI8(arg);
6144 TRACE("arg %u: type %d\n",i,prgvt[i]);
6151 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6155 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6159 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6160 call_method( func, argspos, args );
6163 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6167 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6168 TRACE("retval: "); dump_Variant(pvargResult);
6172 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6173 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6178 #define INVBUF_ELEMENT_SIZE \
6179 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6180 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6181 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6182 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6183 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6184 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6185 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6186 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6188 static HRESULT WINAPI ITypeInfo_fnInvoke(
6193 DISPPARAMS *pDispParams,
6194 VARIANT *pVarResult,
6195 EXCEPINFO *pExcepInfo,
6198 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6200 unsigned int var_index;
6203 const TLBFuncDesc *pFuncInfo;
6205 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6206 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6209 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6210 return DISP_E_MEMBERNOTFOUND;
6214 ERR("NULL pDispParams not allowed\n");
6215 return E_INVALIDARG;
6218 dump_DispParms(pDispParams);
6220 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6222 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6223 pDispParams->cNamedArgs, pDispParams->cArgs);
6224 return E_INVALIDARG;
6227 /* we do this instead of using GetFuncDesc since it will return a fake
6228 * FUNCDESC for dispinterfaces and we want the real function description */
6229 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6230 if ((memid == pFuncInfo->funcdesc.memid) &&
6231 (wFlags & pFuncInfo->funcdesc.invkind) &&
6232 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6236 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6240 TRACE("invoking:\n");
6241 dump_TLBFuncDescOne(pFuncInfo);
6244 switch (func_desc->funckind) {
6245 case FUNC_PUREVIRTUAL:
6246 case FUNC_VIRTUAL: {
6247 void *buffer = heap_alloc_zero(INVBUF_ELEMENT_SIZE * func_desc->cParams);
6249 VARIANT retval; /* pointer for storing byref retvals in */
6250 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6251 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6252 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6253 UINT cNamedArgs = pDispParams->cNamedArgs;
6254 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6255 UINT vargs_converted=0;
6259 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6261 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6263 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6264 hres = DISP_E_PARAMNOTFOUND;
6269 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6271 ERR("functions with the vararg attribute do not support named arguments\n");
6272 hres = DISP_E_NONAMEDARGS;
6276 for (i = 0; i < func_desc->cParams; i++)
6278 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6279 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6284 TRACE("changing args\n");
6285 for (i = 0; i < func_desc->cParams; i++)
6287 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6288 VARIANTARG *src_arg;
6290 if (wParamFlags & PARAMFLAG_FLCID)
6293 arg = prgpvarg[i] = &rgvarg[i];
6295 V_I4(arg) = This->pTypeLib->lcid;
6304 for (j = 0; j < cNamedArgs; j++)
6305 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6307 src_arg = &pDispParams->rgvarg[j];
6312 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6314 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6318 if (wParamFlags & PARAMFLAG_FRETVAL)
6320 /* under most conditions the caller is not allowed to
6321 * pass in a dispparam arg in the index of what would be
6322 * the retval parameter. however, there is an exception
6323 * where the extra parameter is used in an extra
6324 * IDispatch::Invoke below */
6325 if ((i < pDispParams->cArgs) &&
6326 ((func_desc->cParams != 1) || !pVarResult ||
6327 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6329 hres = DISP_E_BADPARAMCOUNT;
6333 /* note: this check is placed so that if the caller passes
6334 * in a VARIANTARG for the retval we just ignore it, like
6336 if (i == func_desc->cParams - 1)
6339 arg = prgpvarg[i] = &rgvarg[i];
6340 memset(arg, 0, sizeof(*arg));
6341 V_VT(arg) = rgvt[i];
6342 memset(&retval, 0, sizeof(retval));
6343 V_BYREF(arg) = &retval;
6347 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6348 hres = E_UNEXPECTED;
6354 dump_Variant(src_arg);
6356 if (rgvt[i] == VT_VARIANT)
6357 hres = VariantCopy(&rgvarg[i], src_arg);
6358 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6360 if (rgvt[i] == V_VT(src_arg))
6361 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6364 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6365 if (wParamFlags & PARAMFLAG_FIN)
6366 hres = VariantCopy(&missing_arg[i], src_arg);
6367 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6369 V_VT(&rgvarg[i]) = rgvt[i];
6371 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6374 SAFEARRAYBOUND bound;
6378 bound.cElements = pDispParams->cArgs-i;
6379 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6381 ERR("SafeArrayCreate failed\n");
6384 hres = SafeArrayAccessData(a, (LPVOID)&v);
6387 ERR("SafeArrayAccessData failed with %x\n", hres);
6390 for (j = 0; j < bound.cElements; j++)
6391 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6392 hres = SafeArrayUnaccessData(a);
6395 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6398 V_ARRAY(&rgvarg[i]) = a;
6399 V_VT(&rgvarg[i]) = rgvt[i];
6401 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6403 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6404 if (wParamFlags & PARAMFLAG_FIN)
6405 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6407 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6408 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6409 V_VT(&rgvarg[i]) = rgvt[i];
6411 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6413 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6414 V_VT(&rgvarg[i]) = rgvt[i];
6418 /* FIXME: this doesn't work for VT_BYREF arguments if
6419 * they are not the same type as in the paramdesc */
6420 V_VT(&rgvarg[i]) = V_VT(src_arg);
6421 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6422 V_VT(&rgvarg[i]) = rgvt[i];
6427 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6428 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6429 debugstr_VT(src_arg), debugstr_VF(src_arg));
6432 prgpvarg[i] = &rgvarg[i];
6434 else if (wParamFlags & PARAMFLAG_FOPT)
6437 arg = prgpvarg[i] = &rgvarg[i];
6438 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6440 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6446 VARIANTARG *missing_arg;
6447 /* if the function wants a pointer to a variant then
6448 * set that up, otherwise just pass the VT_ERROR in
6449 * the argument by value */
6450 if (rgvt[i] & VT_BYREF)
6452 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6453 V_VT(arg) = VT_VARIANT | VT_BYREF;
6454 V_VARIANTREF(arg) = missing_arg;
6458 V_VT(missing_arg) = VT_ERROR;
6459 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6464 hres = DISP_E_BADPARAMCOUNT;
6468 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6470 /* VT_VOID is a special case for return types, so it is not
6471 * handled in the general function */
6472 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6473 V_VT(&varresult) = VT_EMPTY;
6476 V_VT(&varresult) = 0;
6477 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6478 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6481 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6482 V_VT(&varresult), func_desc->cParams, rgvt,
6483 prgpvarg, &varresult);
6485 vargs_converted = 0;
6487 for (i = 0; i < func_desc->cParams; i++)
6489 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6490 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6492 if (wParamFlags & PARAMFLAG_FLCID)
6494 else if (wParamFlags & PARAMFLAG_FRETVAL)
6498 TRACE("[retval] value: ");
6499 dump_Variant(prgpvarg[i]);
6504 VariantInit(pVarResult);
6505 /* deref return value */
6506 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6509 VARIANT_ClearInd(prgpvarg[i]);
6511 else if (vargs_converted < pDispParams->cArgs)
6513 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6514 if (wParamFlags & PARAMFLAG_FOUT)
6516 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6518 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6522 ERR("failed to convert param %d to vt %d\n", i,
6523 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6528 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6529 func_desc->cParamsOpt < 0 &&
6530 i == func_desc->cParams-1)
6532 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6535 hres = SafeArrayGetUBound(a, 1, &ubound);
6538 ERR("SafeArrayGetUBound failed with %x\n", hres);
6541 hres = SafeArrayAccessData(a, (LPVOID)&v);
6544 ERR("SafeArrayAccessData failed with %x\n", hres);
6547 for (j = 0; j <= ubound; j++)
6548 VariantClear(&v[j]);
6549 hres = SafeArrayUnaccessData(a);
6552 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6556 VariantClear(&rgvarg[i]);
6559 else if (wParamFlags & PARAMFLAG_FOPT)
6561 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6562 VariantClear(&rgvarg[i]);
6565 VariantClear(&missing_arg[i]);
6568 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6570 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6571 hres = DISP_E_EXCEPTION;
6574 IErrorInfo *pErrorInfo;
6575 pExcepInfo->scode = V_ERROR(&varresult);
6576 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6578 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6579 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6580 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6581 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6583 IErrorInfo_Release(pErrorInfo);
6587 if (V_VT(&varresult) != VT_ERROR)
6589 TRACE("varresult value: ");
6590 dump_Variant(&varresult);
6594 VariantClear(pVarResult);
6595 *pVarResult = varresult;
6598 VariantClear(&varresult);
6601 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6602 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6603 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6604 (pDispParams->cArgs != 0))
6606 if (V_VT(pVarResult) == VT_DISPATCH)
6608 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6609 /* Note: not VariantClear; we still need the dispatch
6610 * pointer to be valid */
6611 VariantInit(pVarResult);
6612 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6613 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6614 pDispParams, pVarResult, pExcepInfo, pArgErr);
6615 IDispatch_Release(pDispatch);
6619 VariantClear(pVarResult);
6620 hres = DISP_E_NOTACOLLECTION;
6628 case FUNC_DISPATCH: {
6631 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6632 if (SUCCEEDED(hres)) {
6633 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6634 hres = IDispatch_Invoke(
6635 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6636 pVarResult,pExcepInfo,pArgErr
6639 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6640 IDispatch_Release(disp);
6642 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6646 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6651 TRACE("-- 0x%08x\n", hres);
6654 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6657 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6658 if(FAILED(hres)) return hres;
6660 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6661 dump_VARDESC(var_desc);
6662 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6666 /* not found, look for it in inherited interfaces */
6667 ITypeInfo2_GetTypeKind(iface, &type_kind);
6668 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6669 if(This->impltypelist) {
6670 /* recursive search */
6672 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6673 if(SUCCEEDED(hres)){
6674 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6675 ITypeInfo_Release(pTInfo);
6678 WARN("Could not search inherited interface!\n");
6681 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6682 return DISP_E_MEMBERNOTFOUND;
6685 /* ITypeInfo::GetDocumentation
6687 * Retrieves the documentation string, the complete Help file name and path,
6688 * and the context ID for the Help topic for a specified type description.
6690 * (Can be tested by the Visual Basic Editor in Word for instance.)
6692 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6693 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6694 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6696 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6697 const TLBFuncDesc *pFDesc;
6698 const TLBVarDesc *pVDesc;
6699 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6700 " HelpContext(%p) HelpFile(%p)\n",
6701 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6702 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6704 *pBstrName=SysAllocString(This->Name);
6706 *pBstrDocString=SysAllocString(This->DocString);
6708 *pdwHelpContext=This->dwHelpContext;
6710 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6712 }else {/* for a member */
6713 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6714 if(pFDesc->funcdesc.memid==memid){
6716 *pBstrName = SysAllocString(pFDesc->Name);
6718 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6720 *pdwHelpContext=pFDesc->helpcontext;
6723 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6724 if(pVDesc->vardesc.memid==memid){
6726 *pBstrName = SysAllocString(pVDesc->Name);
6728 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6730 *pdwHelpContext=pVDesc->HelpContext;
6735 if(This->impltypelist &&
6736 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6737 /* recursive search */
6740 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6742 if(SUCCEEDED(result)) {
6743 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6744 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6745 ITypeInfo_Release(pTInfo);
6748 WARN("Could not search inherited interface!\n");
6751 WARN("member %d not found\n", memid);
6752 return TYPE_E_ELEMENTNOTFOUND;
6755 /* ITypeInfo::GetDllEntry
6757 * Retrieves a description or specification of an entry point for a function
6760 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6761 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6764 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6765 const TLBFuncDesc *pFDesc;
6767 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6769 if (pBstrDllName) *pBstrDllName = NULL;
6770 if (pBstrName) *pBstrName = NULL;
6771 if (pwOrdinal) *pwOrdinal = 0;
6773 if (This->TypeAttr.typekind != TKIND_MODULE)
6774 return TYPE_E_BADMODULEKIND;
6776 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6777 if(pFDesc->funcdesc.memid==memid){
6778 dump_TypeInfo(This);
6780 dump_TLBFuncDescOne(pFDesc);
6783 *pBstrDllName = SysAllocString(This->DllName);
6785 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6787 *pBstrName = SysAllocString(pFDesc->Entry);
6795 *pwOrdinal = LOWORD(pFDesc->Entry);
6798 return TYPE_E_ELEMENTNOTFOUND;
6801 /* internal function to make the inherited interfaces' methods appear
6802 * part of the interface */
6803 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6804 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6806 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6809 TRACE("%p, 0x%x\n", iface, *hRefType);
6811 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6813 ITypeInfo *pSubTypeInfo;
6815 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6819 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6821 ITypeInfo_Release(pSubTypeInfo);
6825 *hRefType -= DISPATCH_HREF_OFFSET;
6827 if (!(*hRefType & DISPATCH_HREF_MASK))
6828 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6833 /* ITypeInfo::GetRefTypeInfo
6835 * If a type description references other type descriptions, it retrieves
6836 * the referenced type descriptions.
6838 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6841 ITypeInfo **ppTInfo)
6843 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6844 HRESULT result = E_FAIL;
6846 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6848 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6849 ITypeInfo_AddRef(*ppTInfo);
6852 else if (hRefType == -1 &&
6853 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6854 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6856 /* when we meet a DUAL dispinterface, we must create the interface
6859 ITypeInfoImpl *pTypeInfoImpl = ITypeInfoImpl_Constructor();
6862 /* the interface version contains the same information as the dispinterface
6863 * copy the contents of the structs.
6865 *pTypeInfoImpl = *This;
6866 pTypeInfoImpl->ref = 0;
6868 /* change the type to interface */
6869 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6871 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6873 /* the AddRef implicitly adds a reference to the parent typelib, which
6874 * stops the copied data from being destroyed until the new typeinfo's
6875 * refcount goes to zero, but we need to signal to the new instance to
6876 * not free its data structures when it is destroyed */
6877 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6879 ITypeInfo_AddRef(*ppTInfo);
6883 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6884 (This->TypeAttr.typekind == TKIND_DISPATCH))
6886 HREFTYPE href_dispatch = hRefType;
6887 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6889 TLBRefType *ref_type;
6890 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6892 if(ref_type->reference == hRefType)
6895 if(&ref_type->entry == &This->pTypeLib->ref_list)
6897 FIXME("Can't find pRefType for ref %x\n", hRefType);
6900 if(hRefType != -1) {
6901 ITypeLib *pTLib = NULL;
6903 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6905 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6907 if(ref_type->pImpTLInfo->pImpTypeLib) {
6908 TRACE("typeinfo in imported typelib that is already loaded\n");
6909 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6910 ITypeLib2_AddRef(pTLib);
6913 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6914 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6915 ref_type->pImpTLInfo->wVersionMajor,
6916 ref_type->pImpTLInfo->wVersionMinor,
6917 ref_type->pImpTLInfo->lcid,
6920 if(FAILED(result)) {
6921 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6922 result=LoadTypeLib(libnam, &pTLib);
6923 SysFreeString(libnam);
6925 if(SUCCEEDED(result)) {
6926 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6927 ITypeLib2_AddRef(pTLib);
6931 if(SUCCEEDED(result)) {
6932 if(ref_type->index == TLB_REF_USE_GUID)
6933 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6937 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6941 ITypeLib2_Release(pTLib);
6946 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6947 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6951 /* ITypeInfo::AddressOfMember
6953 * Retrieves the addresses of static functions or variables, such as those
6956 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6957 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6959 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6965 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6967 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6971 module = LoadLibraryW(dll);
6974 ERR("couldn't load %s\n", debugstr_w(dll));
6976 SysFreeString(entry);
6977 return STG_E_FILENOTFOUND;
6979 /* FIXME: store library somewhere where we can free it */
6984 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6985 entryA = heap_alloc(len);
6986 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6988 *ppv = GetProcAddress(module, entryA);
6990 ERR("function not found %s\n", debugstr_a(entryA));
6996 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6998 ERR("function not found %d\n", ordinal);
7002 SysFreeString(entry);
7005 return TYPE_E_DLLFUNCTIONNOTFOUND;
7010 /* ITypeInfo::CreateInstance
7012 * Creates a new instance of a type that describes a component object class
7015 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7016 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7018 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7022 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7028 WARN("Not able to aggregate\n");
7029 return CLASS_E_NOAGGREGATION;
7032 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
7033 if(FAILED(hr)) return hr;
7035 if(pTA->typekind != TKIND_COCLASS)
7037 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7043 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7046 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7047 TRACE("GetActiveObject rets %08x\n", hr);
7050 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7051 IUnknown_Release(pUnk);
7056 hr = CoCreateInstance(&pTA->guid, NULL,
7057 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7061 ITypeInfo_ReleaseTypeAttr(iface, pTA);
7065 /* ITypeInfo::GetMops
7067 * Retrieves marshalling information.
7069 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7072 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7073 FIXME("(%p %d) stub!\n", This, memid);
7078 /* ITypeInfo::GetContainingTypeLib
7080 * Retrieves the containing type library and the index of the type description
7081 * within that type library.
7083 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7084 ITypeLib * *ppTLib, UINT *pIndex)
7086 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7088 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7090 *pIndex=This->index;
7091 TRACE("returning pIndex=%d\n", *pIndex);
7095 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7096 ITypeLib2_AddRef(*ppTLib);
7097 TRACE("returning ppTLib=%p\n", *ppTLib);
7103 /* ITypeInfo::ReleaseTypeAttr
7105 * Releases a TYPEATTR previously returned by GetTypeAttr.
7108 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7109 TYPEATTR* pTypeAttr)
7111 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7112 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7113 heap_free(pTypeAttr);
7116 /* ITypeInfo::ReleaseFuncDesc
7118 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7120 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7122 FUNCDESC *pFuncDesc)
7124 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7127 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7129 for (i = 0; i < pFuncDesc->cParams; i++)
7130 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7131 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7133 SysFreeString((BSTR)pFuncDesc);
7136 /* ITypeInfo::ReleaseVarDesc
7138 * Releases a VARDESC previously returned by GetVarDesc.
7140 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7143 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7144 TRACE("(%p)->(%p)\n", This, pVarDesc);
7146 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7147 if (pVarDesc->varkind == VAR_CONST)
7148 VariantClear(pVarDesc->u.lpvarValue);
7149 SysFreeString((BSTR)pVarDesc);
7152 /* ITypeInfo2::GetTypeKind
7154 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7157 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7158 TYPEKIND *pTypeKind)
7160 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7161 *pTypeKind=This->TypeAttr.typekind;
7162 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7166 /* ITypeInfo2::GetTypeFlags
7168 * Returns the type flags without any allocations. This returns a DWORD type
7169 * flag, which expands the type flags without growing the TYPEATTR (type
7173 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7175 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7176 *pTypeFlags=This->TypeAttr.wTypeFlags;
7177 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7181 /* ITypeInfo2::GetFuncIndexOfMemId
7182 * Binds to a specific member based on a known DISPID, where the member name
7183 * is not known (for example, when binding to a default member).
7186 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7187 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7189 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7190 const TLBFuncDesc *pFuncInfo;
7194 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7195 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7201 result = TYPE_E_ELEMENTNOTFOUND;
7203 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7204 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7208 /* TypeInfo2::GetVarIndexOfMemId
7210 * Binds to a specific member based on a known DISPID, where the member name
7211 * is not known (for example, when binding to a default member).
7214 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7215 MEMBERID memid, UINT *pVarIndex)
7217 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7218 TLBVarDesc *pVarInfo;
7221 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7222 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7228 result = TYPE_E_ELEMENTNOTFOUND;
7230 TRACE("(%p) memid 0x%08x -> %s\n", This,
7231 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7235 /* ITypeInfo2::GetCustData
7237 * Gets the custom data
7239 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7244 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7245 TLBCustData *pCData;
7247 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7248 if( IsEqualIID(guid, &pCData->guid)) break;
7250 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7252 VariantInit( pVarVal);
7254 VariantCopy( pVarVal, &pCData->data);
7256 VariantClear( pVarVal );
7260 /* ITypeInfo2::GetFuncCustData
7262 * Gets the custom data
7264 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7270 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7271 TLBCustData *pCData=NULL;
7272 TLBFuncDesc * pFDesc;
7274 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7275 pFDesc=pFDesc->next);
7278 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7279 if( IsEqualIID(guid, &pCData->guid)) break;
7281 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7284 VariantInit( pVarVal);
7285 VariantCopy( pVarVal, &pCData->data);
7288 return E_INVALIDARG; /* FIXME: correct? */
7291 /* ITypeInfo2::GetParamCustData
7293 * Gets the custom data
7295 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7302 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7303 TLBCustData *pCData=NULL;
7304 TLBFuncDesc * pFDesc;
7307 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7309 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7310 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7311 pCData = pCData->next)
7312 if( IsEqualIID(guid, &pCData->guid)) break;
7314 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7318 VariantInit( pVarVal);
7319 VariantCopy( pVarVal, &pCData->data);
7322 return E_INVALIDARG; /* FIXME: correct? */
7325 /* ITypeInfo2::GetVarCustData
7327 * Gets the custom data
7329 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7335 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7336 TLBCustData *pCData=NULL;
7337 TLBVarDesc * pVDesc;
7340 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7344 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7346 if( IsEqualIID(guid, &pCData->guid)) break;
7350 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7354 VariantInit( pVarVal);
7355 VariantCopy( pVarVal, &pCData->data);
7358 return E_INVALIDARG; /* FIXME: correct? */
7361 /* ITypeInfo2::GetImplCustData
7363 * Gets the custom data
7365 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7371 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7372 TLBCustData *pCData=NULL;
7373 TLBImplType * pRDesc;
7376 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7380 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7382 if( IsEqualIID(guid, &pCData->guid)) break;
7386 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7390 VariantInit( pVarVal);
7391 VariantCopy( pVarVal, &pCData->data);
7394 return E_INVALIDARG; /* FIXME: correct? */
7397 /* ITypeInfo2::GetDocumentation2
7399 * Retrieves the documentation string, the complete Help file name and path,
7400 * the localization context to use, and the context ID for the library Help
7401 * topic in the Help file.
7404 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7408 BSTR *pbstrHelpString,
7409 DWORD *pdwHelpStringContext,
7410 BSTR *pbstrHelpStringDll)
7412 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7413 const TLBFuncDesc *pFDesc;
7414 const TLBVarDesc *pVDesc;
7415 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7416 "HelpStringContext(%p) HelpStringDll(%p)\n",
7417 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7418 pbstrHelpStringDll );
7419 /* the help string should be obtained from the helpstringdll,
7420 * using the _DLLGetDocumentation function, based on the supplied
7421 * lcid. Nice to do sometime...
7423 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7425 *pbstrHelpString=SysAllocString(This->Name);
7426 if(pdwHelpStringContext)
7427 *pdwHelpStringContext=This->dwHelpStringContext;
7428 if(pbstrHelpStringDll)
7429 *pbstrHelpStringDll=
7430 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7432 }else {/* for a member */
7433 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7434 if(pFDesc->funcdesc.memid==memid){
7436 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7437 if(pdwHelpStringContext)
7438 *pdwHelpStringContext=pFDesc->HelpStringContext;
7439 if(pbstrHelpStringDll)
7440 *pbstrHelpStringDll=
7441 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7444 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7445 if(pVDesc->vardesc.memid==memid){
7447 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7448 if(pdwHelpStringContext)
7449 *pdwHelpStringContext=pVDesc->HelpStringContext;
7450 if(pbstrHelpStringDll)
7451 *pbstrHelpStringDll=
7452 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7456 return TYPE_E_ELEMENTNOTFOUND;
7459 /* ITypeInfo2::GetAllCustData
7461 * Gets all custom data items for the Type info.
7464 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7466 CUSTDATA *pCustData)
7468 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7469 TLBCustData *pCData;
7472 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7474 pCustData->prgCustData = heap_alloc_zero(This->ctCustData * sizeof(CUSTDATAITEM));
7475 if(pCustData->prgCustData ){
7476 pCustData->cCustData=This->ctCustData;
7477 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7478 pCustData->prgCustData[i].guid=pCData->guid;
7479 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7482 ERR(" OUT OF MEMORY!\n");
7483 return E_OUTOFMEMORY;
7488 /* ITypeInfo2::GetAllFuncCustData
7490 * Gets all custom data items for the specified Function
7493 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7496 CUSTDATA *pCustData)
7498 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7499 TLBCustData *pCData;
7500 TLBFuncDesc * pFDesc;
7502 TRACE("(%p) index %d\n", This, index);
7503 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7504 pFDesc=pFDesc->next)
7507 pCustData->prgCustData =
7508 heap_alloc_zero(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7509 if(pCustData->prgCustData ){
7510 pCustData->cCustData=pFDesc->ctCustData;
7511 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7512 pCData = pCData->next){
7513 pCustData->prgCustData[i].guid=pCData->guid;
7514 VariantCopy(& pCustData->prgCustData[i].varValue,
7518 ERR(" OUT OF MEMORY!\n");
7519 return E_OUTOFMEMORY;
7523 return TYPE_E_ELEMENTNOTFOUND;
7526 /* ITypeInfo2::GetAllParamCustData
7528 * Gets all custom data items for the Functions
7531 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7532 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7534 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7535 TLBCustData *pCData=NULL;
7536 TLBFuncDesc * pFDesc;
7538 TRACE("(%p) index %d\n", This, indexFunc);
7539 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7540 pFDesc=pFDesc->next)
7542 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7543 pCustData->prgCustData =
7544 heap_alloc_zero(pFDesc->pParamDesc[indexParam].ctCustData *
7545 sizeof(CUSTDATAITEM));
7546 if(pCustData->prgCustData ){
7547 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7548 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7549 pCData; i++, pCData = pCData->next){
7550 pCustData->prgCustData[i].guid=pCData->guid;
7551 VariantCopy(& pCustData->prgCustData[i].varValue,
7555 ERR(" OUT OF MEMORY!\n");
7556 return E_OUTOFMEMORY;
7560 return TYPE_E_ELEMENTNOTFOUND;
7563 /* ITypeInfo2::GetAllVarCustData
7565 * Gets all custom data items for the specified Variable
7568 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7569 UINT index, CUSTDATA *pCustData)
7571 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7572 TLBCustData *pCData;
7573 TLBVarDesc * pVDesc;
7575 TRACE("(%p) index %d\n", This, index);
7576 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7577 pVDesc=pVDesc->next)
7580 pCustData->prgCustData =
7581 heap_alloc_zero(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7582 if(pCustData->prgCustData ){
7583 pCustData->cCustData=pVDesc->ctCustData;
7584 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7585 pCData = pCData->next){
7586 pCustData->prgCustData[i].guid=pCData->guid;
7587 VariantCopy(& pCustData->prgCustData[i].varValue,
7591 ERR(" OUT OF MEMORY!\n");
7592 return E_OUTOFMEMORY;
7596 return TYPE_E_ELEMENTNOTFOUND;
7599 /* ITypeInfo2::GetAllImplCustData
7601 * Gets all custom data items for the specified implementation type
7604 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7607 CUSTDATA *pCustData)
7609 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7610 TLBCustData *pCData;
7611 TLBImplType * pRDesc;
7613 TRACE("(%p) index %d\n", This, index);
7614 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7615 pRDesc=pRDesc->next)
7618 pCustData->prgCustData =
7619 heap_alloc_zero(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7620 if(pCustData->prgCustData ){
7621 pCustData->cCustData=pRDesc->ctCustData;
7622 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7623 pCData = pCData->next){
7624 pCustData->prgCustData[i].guid=pCData->guid;
7625 VariantCopy(& pCustData->prgCustData[i].varValue,
7629 ERR(" OUT OF MEMORY!\n");
7630 return E_OUTOFMEMORY;
7634 return TYPE_E_ELEMENTNOTFOUND;
7637 static const ITypeInfo2Vtbl tinfvt =
7640 ITypeInfo_fnQueryInterface,
7642 ITypeInfo_fnRelease,
7644 ITypeInfo_fnGetTypeAttr,
7645 ITypeInfo_fnGetTypeComp,
7646 ITypeInfo_fnGetFuncDesc,
7647 ITypeInfo_fnGetVarDesc,
7648 ITypeInfo_fnGetNames,
7649 ITypeInfo_fnGetRefTypeOfImplType,
7650 ITypeInfo_fnGetImplTypeFlags,
7651 ITypeInfo_fnGetIDsOfNames,
7653 ITypeInfo_fnGetDocumentation,
7654 ITypeInfo_fnGetDllEntry,
7655 ITypeInfo_fnGetRefTypeInfo,
7656 ITypeInfo_fnAddressOfMember,
7657 ITypeInfo_fnCreateInstance,
7658 ITypeInfo_fnGetMops,
7659 ITypeInfo_fnGetContainingTypeLib,
7660 ITypeInfo_fnReleaseTypeAttr,
7661 ITypeInfo_fnReleaseFuncDesc,
7662 ITypeInfo_fnReleaseVarDesc,
7664 ITypeInfo2_fnGetTypeKind,
7665 ITypeInfo2_fnGetTypeFlags,
7666 ITypeInfo2_fnGetFuncIndexOfMemId,
7667 ITypeInfo2_fnGetVarIndexOfMemId,
7668 ITypeInfo2_fnGetCustData,
7669 ITypeInfo2_fnGetFuncCustData,
7670 ITypeInfo2_fnGetParamCustData,
7671 ITypeInfo2_fnGetVarCustData,
7672 ITypeInfo2_fnGetImplTypeCustData,
7673 ITypeInfo2_fnGetDocumentation2,
7674 ITypeInfo2_fnGetAllCustData,
7675 ITypeInfo2_fnGetAllFuncCustData,
7676 ITypeInfo2_fnGetAllParamCustData,
7677 ITypeInfo2_fnGetAllVarCustData,
7678 ITypeInfo2_fnGetAllImplTypeCustData,
7681 /******************************************************************************
7682 * CreateDispTypeInfo [OLEAUT32.31]
7684 * Build type information for an object so it can be called through an
7685 * IDispatch interface.
7688 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7689 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7692 * This call allows an objects methods to be accessed through IDispatch, by
7693 * building an ITypeInfo object that IDispatch can use to call through.
7695 HRESULT WINAPI CreateDispTypeInfo(
7696 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7697 LCID lcid, /* [I] Locale Id */
7698 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7700 ITypeInfoImpl *pTIClass, *pTIIface;
7701 ITypeLibImpl *pTypeLibImpl;
7702 unsigned int param, func;
7703 TLBFuncDesc **ppFuncDesc;
7707 pTypeLibImpl = TypeLibImpl_Constructor();
7708 if (!pTypeLibImpl) return E_FAIL;
7710 pTIIface = ITypeInfoImpl_Constructor();
7711 pTIIface->pTypeLib = pTypeLibImpl;
7712 pTIIface->index = 0;
7713 pTIIface->Name = NULL;
7714 pTIIface->dwHelpContext = -1;
7715 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7716 pTIIface->TypeAttr.lcid = lcid;
7717 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7718 pTIIface->TypeAttr.wMajorVerNum = 0;
7719 pTIIface->TypeAttr.wMinorVerNum = 0;
7720 pTIIface->TypeAttr.cbAlignment = 2;
7721 pTIIface->TypeAttr.cbSizeInstance = -1;
7722 pTIIface->TypeAttr.cbSizeVft = -1;
7723 pTIIface->TypeAttr.cFuncs = 0;
7724 pTIIface->TypeAttr.cImplTypes = 0;
7725 pTIIface->TypeAttr.cVars = 0;
7726 pTIIface->TypeAttr.wTypeFlags = 0;
7728 ppFuncDesc = &pTIIface->funclist;
7729 for(func = 0; func < pidata->cMembers; func++) {
7730 METHODDATA *md = pidata->pmethdata + func;
7731 *ppFuncDesc = heap_alloc(sizeof(**ppFuncDesc));
7732 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7733 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7734 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7735 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7736 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7737 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7738 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7739 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7740 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7741 (*ppFuncDesc)->funcdesc.cScodes = 0;
7742 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7743 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7744 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7745 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7746 (*ppFuncDesc)->funcdesc.lprgelemdescParam = heap_alloc_zero(md->cArgs * sizeof(ELEMDESC));
7747 (*ppFuncDesc)->pParamDesc = heap_alloc_zero(md->cArgs * sizeof(TLBParDesc));
7748 for(param = 0; param < md->cArgs; param++) {
7749 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7750 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7752 (*ppFuncDesc)->helpcontext = 0;
7753 (*ppFuncDesc)->HelpStringContext = 0;
7754 (*ppFuncDesc)->HelpString = NULL;
7755 (*ppFuncDesc)->Entry = NULL;
7756 (*ppFuncDesc)->ctCustData = 0;
7757 (*ppFuncDesc)->pCustData = NULL;
7758 (*ppFuncDesc)->next = NULL;
7759 pTIIface->TypeAttr.cFuncs++;
7760 ppFuncDesc = &(*ppFuncDesc)->next;
7763 dump_TypeInfo(pTIIface);
7765 pTypeLibImpl->pTypeInfo = pTIIface;
7766 pTypeLibImpl->TypeInfoCount++;
7768 pTIClass = ITypeInfoImpl_Constructor();
7769 pTIClass->pTypeLib = pTypeLibImpl;
7770 pTIClass->index = 1;
7771 pTIClass->Name = NULL;
7772 pTIClass->dwHelpContext = -1;
7773 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7774 pTIClass->TypeAttr.lcid = lcid;
7775 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7776 pTIClass->TypeAttr.wMajorVerNum = 0;
7777 pTIClass->TypeAttr.wMinorVerNum = 0;
7778 pTIClass->TypeAttr.cbAlignment = 2;
7779 pTIClass->TypeAttr.cbSizeInstance = -1;
7780 pTIClass->TypeAttr.cbSizeVft = -1;
7781 pTIClass->TypeAttr.cFuncs = 0;
7782 pTIClass->TypeAttr.cImplTypes = 1;
7783 pTIClass->TypeAttr.cVars = 0;
7784 pTIClass->TypeAttr.wTypeFlags = 0;
7786 pTIClass->impltypelist = heap_alloc_zero(sizeof(*pTIClass->impltypelist));
7787 pTIClass->impltypelist->hRef = 0;
7789 ref = heap_alloc_zero(sizeof(*ref));
7792 ref->pImpTLInfo = TLB_REF_INTERNAL;
7793 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7795 dump_TypeInfo(pTIClass);
7797 pTIIface->next = pTIClass;
7798 pTypeLibImpl->TypeInfoCount++;
7800 *pptinfo = (ITypeInfo*)pTIClass;
7802 ITypeInfo_AddRef(*pptinfo);
7803 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7809 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7811 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7813 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7816 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7818 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7820 return ITypeInfo_AddRef((ITypeInfo *)This);
7823 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7825 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7827 return ITypeInfo_Release((ITypeInfo *)This);
7830 static HRESULT WINAPI ITypeComp_fnBind(
7835 ITypeInfo ** ppTInfo,
7836 DESCKIND * pDescKind,
7839 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7840 const TLBFuncDesc *pFDesc;
7841 const TLBVarDesc *pVDesc;
7842 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7844 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7846 *pDescKind = DESCKIND_NONE;
7847 pBindPtr->lpfuncdesc = NULL;
7850 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7851 if (!strcmpiW(pFDesc->Name, szName)) {
7852 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7855 /* name found, but wrong flags */
7856 hr = TYPE_E_TYPEMISMATCH;
7861 HRESULT hr = TLB_AllocAndInitFuncDesc(
7863 &pBindPtr->lpfuncdesc,
7864 This->TypeAttr.typekind == TKIND_DISPATCH);
7867 *pDescKind = DESCKIND_FUNCDESC;
7868 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7869 ITypeInfo_AddRef(*ppTInfo);
7872 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7873 if (!strcmpiW(pVDesc->Name, szName)) {
7874 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7877 *pDescKind = DESCKIND_VARDESC;
7878 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7879 ITypeInfo_AddRef(*ppTInfo);
7884 /* FIXME: search each inherited interface, not just the first */
7885 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7886 /* recursive search */
7890 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7893 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7894 ITypeInfo_Release(pTInfo);
7898 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7899 ITypeComp_Release(pTComp);
7902 WARN("Could not search inherited interface!\n");
7904 if (hr == DISP_E_MEMBERNOTFOUND)
7906 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7910 static HRESULT WINAPI ITypeComp_fnBindType(
7914 ITypeInfo ** ppTInfo,
7915 ITypeComp ** ppTComp)
7917 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7919 /* strange behaviour (does nothing) but like the
7922 if (!ppTInfo || !ppTComp)
7931 static const ITypeCompVtbl tcompvt =
7934 ITypeComp_fnQueryInterface,
7936 ITypeComp_fnRelease,
7939 ITypeComp_fnBindType