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)) {
822 result = TYPE_E_INVALIDSTATE;
826 /* remove any types registered with this typelib */
827 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
828 for (i=0; i<numTypes; i++) {
829 /* get the kind of type */
830 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
834 /* skip non-interfaces, and get type info for the type */
835 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
838 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
841 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
845 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
846 kind == TKIND_DISPATCH)
848 /* the path to the type */
849 get_interface_key( &typeAttr->guid, subKeyName );
851 /* Delete its bits */
852 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
855 RegDeleteKeyW(subKey, ProxyStubClsidW);
856 RegDeleteKeyW(subKey, ProxyStubClsid32W);
857 RegDeleteKeyW(subKey, TypeLibW);
860 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
864 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
866 if (typeInfo) ITypeInfo_Release(typeInfo);
870 /* Now, delete the type library path subkey */
871 get_lcid_subkey( lcid, syskind, subKeyName );
872 RegDeleteKeyW(key, subKeyName);
873 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
874 RegDeleteKeyW(key, subKeyName);
876 /* check if there is anything besides the FLAGS/HELPDIR keys.
877 If there is, we don't delete them */
878 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
879 deleteOtherStuff = TRUE;
881 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
882 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
884 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
885 if (!strcmpW(subKeyName, FLAGSW)) continue;
886 if (!strcmpW(subKeyName, HELPDIRW)) continue;
887 deleteOtherStuff = FALSE;
891 /* only delete the other parts of the key if we're absolutely sure */
892 if (deleteOtherStuff) {
893 RegDeleteKeyW(key, FLAGSW);
894 RegDeleteKeyW(key, HELPDIRW);
898 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
899 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
900 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
904 SysFreeString(tlibPath);
905 if (typeLib) ITypeLib_Release(typeLib);
906 if (subKey) RegCloseKey(subKey);
907 if (key) RegCloseKey(key);
911 /******************************************************************************
912 * RegisterTypeLibForUser [OLEAUT32.442]
913 * Adds information about a type library to the user registry
915 * Docs: ITypeLib FAR * ptlib
916 * Docs: OLECHAR FAR* szFullPath
917 * Docs: OLECHAR FAR* szHelpDir
923 HRESULT WINAPI RegisterTypeLibForUser(
924 ITypeLib * ptlib, /* [in] Pointer to the library*/
925 OLECHAR * szFullPath, /* [in] full Path of the library*/
926 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
929 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
930 debugstr_w(szFullPath), debugstr_w(szHelpDir));
931 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
934 /******************************************************************************
935 * UnRegisterTypeLibForUser [OLEAUT32.443]
936 * Removes information about a type library from the user registry
942 HRESULT WINAPI UnRegisterTypeLibForUser(
943 REFGUID libid, /* [in] GUID of the library */
944 WORD wVerMajor, /* [in] major version */
945 WORD wVerMinor, /* [in] minor version */
946 LCID lcid, /* [in] locale id */
949 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
950 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
951 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
954 /*======================= ITypeLib implementation =======================*/
956 typedef struct tagTLBCustData
960 struct tagTLBCustData* next;
963 /* data structure for import typelibs */
964 typedef struct tagTLBImpLib
966 int offset; /* offset in the file (MSFT)
967 offset in nametable (SLTG)
968 just used to identify library while reading
970 GUID guid; /* libid */
971 BSTR name; /* name */
973 LCID lcid; /* lcid of imported typelib */
975 WORD wVersionMajor; /* major version number */
976 WORD wVersionMinor; /* minor version number */
978 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
979 NULL if not yet loaded */
980 struct tagTLBImpLib * next;
983 /* internal ITypeLib data */
984 typedef struct tagITypeLibImpl
986 const ITypeLib2Vtbl *lpVtbl;
987 const ITypeCompVtbl *lpVtblTypeComp;
989 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
992 /* strings can be stored in tlb as multibyte strings BUT they are *always*
993 * exported to the application as a UNICODE string.
1000 int TypeInfoCount; /* nr of typeinfo's in librarry */
1001 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
1002 int ctCustData; /* number of items in cust data list */
1003 TLBCustData * pCustData; /* linked list to cust data */
1004 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
1005 int ctTypeDesc; /* number of items in type desc array */
1006 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1007 library. Only used while reading MSFT
1009 struct list ref_list; /* list of ref types in this typelib */
1010 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1013 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1014 struct tagITypeLibImpl *next, *prev;
1019 static const ITypeLib2Vtbl tlbvt;
1020 static const ITypeCompVtbl tlbtcvt;
1022 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1024 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1027 /* ITypeLib methods */
1028 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1029 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1031 /*======================= ITypeInfo implementation =======================*/
1033 /* data for referenced types */
1034 typedef struct tagTLBRefType
1036 INT index; /* Type index for internal ref or for external ref
1037 it the format is SLTG. -2 indicates to
1040 GUID guid; /* guid of the referenced type */
1041 /* if index == TLB_REF_USE_GUID */
1043 HREFTYPE reference; /* The href of this ref */
1044 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1045 TLB_REF_INTERNAL for internal refs
1046 TLB_REF_NOT_FOUND for broken refs */
1051 #define TLB_REF_USE_GUID -2
1053 #define TLB_REF_INTERNAL (void*)-2
1054 #define TLB_REF_NOT_FOUND (void*)-1
1056 /* internal Parameter data */
1057 typedef struct tagTLBParDesc
1061 TLBCustData * pCustData; /* linked list to cust data */
1064 /* internal Function data */
1065 typedef struct tagTLBFuncDesc
1067 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1068 BSTR Name; /* the name of this function */
1069 TLBParDesc *pParamDesc; /* array with param names and custom data */
1071 int HelpStringContext;
1073 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1075 TLBCustData * pCustData; /* linked list to cust data; */
1076 struct tagTLBFuncDesc * next;
1079 /* internal Variable data */
1080 typedef struct tagTLBVarDesc
1082 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1083 BSTR Name; /* the name of this variable */
1085 int HelpStringContext; /* FIXME: where? */
1088 TLBCustData * pCustData;/* linked list to cust data; */
1089 struct tagTLBVarDesc * next;
1092 /* internal implemented interface data */
1093 typedef struct tagTLBImplType
1095 HREFTYPE hRef; /* hRef of interface */
1096 int implflags; /* IMPLFLAG_*s */
1098 TLBCustData * pCustData;/* linked list to custom data; */
1099 struct tagTLBImplType *next;
1102 /* internal TypeInfo data */
1103 typedef struct tagITypeInfoImpl
1105 const ITypeInfo2Vtbl *lpVtbl;
1106 const ITypeCompVtbl *lpVtblTypeComp;
1108 BOOL not_attached_to_typelib;
1109 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1110 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1111 int index; /* index in this typelib; */
1112 HREFTYPE hreftype; /* hreftype for app object binding */
1113 /* type libs seem to store the doc strings in ascii
1114 * so why should we do it in unicode?
1119 DWORD dwHelpContext;
1120 DWORD dwHelpStringContext;
1123 TLBFuncDesc * funclist; /* linked list with function descriptions */
1126 TLBVarDesc * varlist; /* linked list with variable descriptions */
1128 /* Implemented Interfaces */
1129 TLBImplType * impltypelist;
1132 TLBCustData * pCustData; /* linked list to cust data; */
1133 struct tagITypeInfoImpl * next;
1136 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1138 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1141 static const ITypeInfo2Vtbl tinfvt;
1142 static const ITypeCompVtbl tcompvt;
1144 static ITypeInfo2 * ITypeInfo_Constructor(void);
1145 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This);
1147 typedef struct tagTLBContext
1149 unsigned int oStart; /* start of TLB in file */
1150 unsigned int pos; /* current pos */
1151 unsigned int length; /* total length */
1152 void *mapping; /* memory mapping */
1153 MSFT_SegDir * pTblDir;
1154 ITypeLibImpl* pLibInfo;
1158 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1163 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1164 if (pTD->vt & VT_RESERVED)
1165 szVarType += strlen(strcpy(szVarType, "reserved | "));
1166 if (pTD->vt & VT_BYREF)
1167 szVarType += strlen(strcpy(szVarType, "ref to "));
1168 if (pTD->vt & VT_ARRAY)
1169 szVarType += strlen(strcpy(szVarType, "array of "));
1170 if (pTD->vt & VT_VECTOR)
1171 szVarType += strlen(strcpy(szVarType, "vector of "));
1172 switch(pTD->vt & VT_TYPEMASK) {
1173 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1174 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1175 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1176 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1177 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1178 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1179 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1180 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1181 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1182 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1183 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1184 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1185 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1186 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1187 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1188 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1189 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1190 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1191 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1192 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1193 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1194 pTD->u.hreftype); break;
1195 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1196 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1197 case VT_PTR: sprintf(szVarType, "ptr to ");
1198 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1200 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1201 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1203 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1204 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1205 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1208 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1212 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1214 USHORT flags = edesc->u.paramdesc.wParamFlags;
1215 dump_TypeDesc(&edesc->tdesc,buf);
1216 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1217 MESSAGE("\t\tu.paramdesc.wParamFlags");
1218 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1219 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1220 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1221 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1222 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1223 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1224 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1225 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1226 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1228 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1230 MESSAGE("memid is %08x\n",funcdesc->memid);
1231 for (i=0;i<funcdesc->cParams;i++) {
1232 MESSAGE("Param %d:\n",i);
1233 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1235 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1236 switch (funcdesc->funckind) {
1237 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1238 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1239 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1240 case FUNC_STATIC: MESSAGE("static");break;
1241 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1242 default: MESSAGE("unknown");break;
1244 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1245 switch (funcdesc->invkind) {
1246 case INVOKE_FUNC: MESSAGE("func");break;
1247 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1248 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1249 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1251 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1252 switch (funcdesc->callconv) {
1253 case CC_CDECL: MESSAGE("cdecl");break;
1254 case CC_PASCAL: MESSAGE("pascal");break;
1255 case CC_STDCALL: MESSAGE("stdcall");break;
1256 case CC_SYSCALL: MESSAGE("syscall");break;
1259 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1260 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1261 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1263 MESSAGE("\telemdescFunc (return value type):\n");
1264 dump_ELEMDESC(&funcdesc->elemdescFunc);
1267 static const char * const typekind_desc[] =
1280 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1283 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1284 for (i=0;i<pfd->funcdesc.cParams;i++)
1285 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1288 dump_FUNCDESC(&(pfd->funcdesc));
1290 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1291 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1293 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1297 dump_TLBFuncDescOne(pfd);
1301 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1305 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1310 static void dump_TLBImpLib(const TLBImpLib *import)
1312 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1313 debugstr_w(import->name));
1314 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1315 import->wVersionMinor, import->lcid, import->offset);
1318 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1322 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1324 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1325 if(ref->index == -1)
1326 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1328 TRACE_(typelib)("type no: %d\n", ref->index);
1330 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1332 TRACE_(typelib)("in lib\n");
1333 dump_TLBImpLib(ref->pImpTLInfo);
1338 static void dump_TLBImplType(const TLBImplType * impl)
1342 "implementing/inheriting interface hRef = %x implflags %x\n",
1343 impl->hRef, impl->implflags);
1348 static void dump_Variant(const VARIANT * pvar)
1352 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1356 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1357 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1359 TRACE(",%p", V_BYREF(pvar));
1361 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1363 TRACE(",%p", V_ARRAY(pvar));
1365 else switch (V_TYPE(pvar))
1367 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1368 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1369 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1370 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1372 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1374 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1375 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1376 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1377 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1378 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1379 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1380 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1381 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1382 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1383 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1384 V_CY(pvar).s.Lo); break;
1386 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1387 TRACE(",<invalid>");
1389 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1390 st.wHour, st.wMinute, st.wSecond);
1394 case VT_USERDEFINED:
1396 case VT_NULL: break;
1397 default: TRACE(",?"); break;
1403 static void dump_DispParms(const DISPPARAMS * pdp)
1407 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1409 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1411 TRACE("named args:\n");
1412 for (index = 0; index < pdp->cNamedArgs; index++)
1413 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1416 if (pdp->cArgs && pdp->rgvarg)
1419 for (index = 0; index < pdp->cArgs; index++)
1420 dump_Variant( &pdp->rgvarg[index] );
1424 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1426 TRACE("%p ref=%u\n", pty, pty->ref);
1427 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1428 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1429 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1430 TRACE("fct:%u var:%u impl:%u\n",
1431 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1432 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1433 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1434 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1436 dump_TLBFuncDesc(pty->funclist);
1437 dump_TLBVarDesc(pty->varlist);
1438 dump_TLBImplType(pty->impltypelist);
1441 static void dump_VARDESC(const VARDESC *v)
1443 MESSAGE("memid %d\n",v->memid);
1444 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1445 MESSAGE("oInst %d\n",v->u.oInst);
1446 dump_ELEMDESC(&(v->elemdescVar));
1447 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1448 MESSAGE("varkind %d\n",v->varkind);
1451 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1453 /* VT_LPWSTR is largest type that */
1454 /* may appear in type description*/
1455 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1456 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1457 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1458 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1459 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1460 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1464 static void TLB_abort(void)
1469 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1470 static void * TLB_Alloc(unsigned size)
1473 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1475 ERR("cannot allocate memory\n");
1480 static void TLB_Free(void * ptr)
1482 HeapFree(GetProcessHeap(), 0, ptr);
1485 /* returns the size required for a deep copy of a typedesc into a
1487 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1491 if (alloc_initial_space)
1492 size += sizeof(TYPEDESC);
1498 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1501 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1502 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1508 /* deep copy a typedesc into a flat buffer */
1509 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1514 buffer = (char *)buffer + sizeof(TYPEDESC);
1523 dest->u.lptdesc = buffer;
1524 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1527 dest->u.lpadesc = buffer;
1528 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1529 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1530 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1536 /* free custom data allocated by MSFT_CustData */
1537 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1539 TLBCustData *pCustDataNext;
1540 for (; pCustData; pCustData = pCustDataNext)
1542 VariantClear(&pCustData->data);
1544 pCustDataNext = pCustData->next;
1545 TLB_Free(pCustData);
1549 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1554 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1555 ret = SysAllocStringLen(NULL, len - 1);
1556 if (!ret) return ret;
1557 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1561 /**********************************************************************
1563 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1565 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1570 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1572 if (where != DO_NOT_SEEK)
1574 where += pcx->oStart;
1575 if (where > pcx->length)
1578 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1586 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1588 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1589 pcx->pos, count, pcx->oStart, pcx->length, where);
1591 MSFT_Seek(pcx, where);
1592 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1593 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1598 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1603 ret = MSFT_Read(buffer, count, pcx, where);
1604 FromLEDWords(buffer, ret);
1609 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1614 ret = MSFT_Read(buffer, count, pcx, where);
1615 FromLEWords(buffer, ret);
1620 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1622 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1623 memset(pGuid,0, sizeof(GUID));
1626 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1627 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1628 pGuid->Data2 = FromLEWord(pGuid->Data2);
1629 pGuid->Data3 = FromLEWord(pGuid->Data3);
1630 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1633 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1635 MSFT_NameIntro niName;
1639 ERR_(typelib)("bad offset %d\n", offset);
1643 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1644 pcx->pTblDir->pNametab.offset+offset);
1646 return niName.hreftype;
1649 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1652 MSFT_NameIntro niName;
1654 BSTR bstrName = NULL;
1658 ERR_(typelib)("bad offset %d\n", offset);
1661 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1662 pcx->pTblDir->pNametab.offset+offset);
1663 niName.namelen &= 0xFF; /* FIXME: correct ? */
1664 name=TLB_Alloc((niName.namelen & 0xff) +1);
1665 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1666 name[niName.namelen & 0xff]='\0';
1668 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1671 /* no invalid characters in string */
1674 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1676 /* don't check for invalid character since this has been done previously */
1677 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1681 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1685 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1692 if(offset<0) return NULL;
1693 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1694 if(length <= 0) return 0;
1695 string=TLB_Alloc(length +1);
1696 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1697 string[length]='\0';
1699 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1700 string, -1, NULL, 0);
1702 /* no invalid characters in string */
1705 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1707 /* don't check for invalid character since this has been done previously */
1708 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1712 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1716 * read a value and fill a VARIANT structure
1718 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1722 TRACE_(typelib)("\n");
1724 if(offset <0) { /* data are packed in here */
1725 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1726 V_I4(pVar) = offset & 0x3ffffff;
1729 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1730 pcx->pTblDir->pCustData.offset + offset );
1731 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1732 switch (V_VT(pVar)){
1733 case VT_EMPTY: /* FIXME: is this right? */
1734 case VT_NULL: /* FIXME: is this right? */
1735 case VT_I2 : /* this should not happen */
1746 case VT_VOID : /* FIXME: is this right? */
1754 case VT_DECIMAL : /* FIXME: is this right? */
1757 /* pointer types with known behaviour */
1760 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1763 DWORD origPos = MSFT_Tell(pcx), nullPos;
1766 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1768 nullPos = MSFT_Tell(pcx);
1769 size = nullPos - origPos;
1770 MSFT_Seek(pcx, origPos);
1772 ptr=TLB_Alloc(size);/* allocate temp buffer */
1773 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1774 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1775 /* FIXME: do we need a AtoW conversion here? */
1776 V_UNION(pVar, bstrVal[size])='\0';
1777 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1781 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1788 case VT_USERDEFINED :
1794 case VT_STREAMED_OBJECT :
1795 case VT_STORED_OBJECT :
1796 case VT_BLOB_OBJECT :
1801 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1805 if(size>0) /* (big|small) endian correct? */
1806 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1810 * create a linked list with custom data
1812 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1818 TRACE_(typelib)("\n");
1822 pNew=TLB_Alloc(sizeof(TLBCustData));
1823 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1824 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1825 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1826 /* add new custom data at head of the list */
1827 pNew->next=*ppCustData;
1829 offset = entry.next;
1834 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1838 pTd->vt=type & VT_TYPEMASK;
1840 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1842 if(pTd->vt == VT_USERDEFINED)
1843 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1845 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1848 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1850 /* resolve referenced type if any */
1853 switch (lpTypeDesc->vt)
1856 lpTypeDesc = lpTypeDesc->u.lptdesc;
1860 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1863 case VT_USERDEFINED:
1864 MSFT_DoRefType(pcx, pTI->pTypeLib,
1865 lpTypeDesc->u.hreftype);
1877 MSFT_DoFuncs(TLBContext* pcx,
1882 TLBFuncDesc** pptfd)
1885 * member information is stored in a data structure at offset
1886 * indicated by the memoffset field of the typeinfo structure
1887 * There are several distinctive parts.
1888 * The first part starts with a field that holds the total length
1889 * of this (first) part excluding this field. Then follow the records,
1890 * for each member there is one record.
1892 * The first entry is always the length of the record (including this
1894 * The rest of the record depends on the type of the member. If there is
1895 * a field indicating the member type (function, variable, interface, etc)
1896 * I have not found it yet. At this time we depend on the information
1897 * in the type info and the usual order how things are stored.
1899 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1902 * Third is an equal sized array with file offsets to the name entry
1905 * The fourth and last (?) part is an array with offsets to the records
1906 * in the first part of this file segment.
1909 int infolen, nameoffset, reclength, i;
1910 int recoffset = offset + sizeof(INT);
1912 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1913 MSFT_FuncRecord *pFuncRec = (MSFT_FuncRecord*)recbuf;
1914 TLBFuncDesc *ptfd_prev = NULL;
1916 TRACE_(typelib)("\n");
1918 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1920 for ( i = 0; i < cFuncs ; i++ )
1924 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1926 /* name, eventually add to a hash table */
1927 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1928 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1930 /* nameoffset is sometimes -1 on the second half of a propget/propput
1931 * pair of functions */
1932 if ((nameoffset == -1) && (i > 0))
1933 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1935 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1937 /* read the function information record */
1938 MSFT_ReadLEDWords(&reclength, sizeof(pFuncRec->Info), pcx, recoffset);
1940 reclength &= 0xffff;
1942 MSFT_ReadLEDWords(&pFuncRec->DataType, reclength - FIELD_OFFSET(MSFT_FuncRecord, DataType), pcx, DO_NOT_SEEK);
1944 /* size without argument data */
1945 optional = reclength - pFuncRec->nrargs*sizeof(MSFT_ParameterInfo);
1947 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpContext))
1948 (*pptfd)->helpcontext = pFuncRec->HelpContext;
1950 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oHelpString))
1951 (*pptfd)->HelpString = MSFT_ReadString(pcx, pFuncRec->oHelpString);
1953 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oEntry))
1955 if (pFuncRec->FKCCIC & 0x2000 )
1957 if (!IS_INTRESOURCE(pFuncRec->oEntry))
1958 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->oEntry);
1959 (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->oEntry);
1962 (*pptfd)->Entry = MSFT_ReadString(pcx, pFuncRec->oEntry);
1965 (*pptfd)->Entry = (BSTR)-1;
1967 if (optional > FIELD_OFFSET(MSFT_FuncRecord, HelpStringContext))
1968 (*pptfd)->HelpStringContext = pFuncRec->HelpStringContext;
1970 if (optional > FIELD_OFFSET(MSFT_FuncRecord, oCustData) && pFuncRec->FKCCIC & 0x80)
1971 MSFT_CustData(pcx, pFuncRec->oCustData, &(*pptfd)->pCustData);
1973 /* fill the FuncDesc Structure */
1974 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1975 offset + infolen + ( i + 1) * sizeof(INT));
1977 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1978 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1979 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1980 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1981 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1982 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1983 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1987 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1989 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1991 /* do the parameters/arguments */
1992 if(pFuncRec->nrargs)
1995 MSFT_ParameterInfo paraminfo;
1997 (*pptfd)->funcdesc.lprgelemdescParam =
1998 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
2000 (*pptfd)->pParamDesc =
2001 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
2003 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
2004 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2006 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2008 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
2015 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2018 if (paraminfo.oName == -1)
2019 /* this occurs for [propput] or [propget] methods, so
2020 * we should just set the name of the parameter to the
2021 * name of the method. */
2022 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
2024 (*pptfd)->pParamDesc[j].Name =
2025 MSFT_ReadName( pcx, paraminfo.oName );
2026 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
2028 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2031 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2032 (pFuncRec->FKCCIC & 0x1000) )
2034 INT* pInt = (INT *)((char *)pFuncRec +
2036 (pFuncRec->nrargs * 4) * sizeof(INT) );
2038 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2040 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
2041 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2043 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2047 elemdesc->u.paramdesc.pparamdescex = NULL;
2050 if (optional > (FIELD_OFFSET(MSFT_FuncRecord, oArgCustData) +
2051 j*sizeof(pFuncRec->oArgCustData[0])) &&
2052 pFuncRec->FKCCIC & 0x80 )
2055 pFuncRec->oArgCustData[j],
2056 &(*pptfd)->pParamDesc[j].pCustData);
2059 /* SEEK value = jump to offset,
2060 * from there jump to the end of record,
2061 * go back by (j-1) arguments
2063 MSFT_ReadLEDWords( ¶minfo ,
2064 sizeof(MSFT_ParameterInfo), pcx,
2065 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2066 * sizeof(MSFT_ParameterInfo)));
2070 /* scode is not used: archaic win16 stuff FIXME: right? */
2071 (*pptfd)->funcdesc.cScodes = 0 ;
2072 (*pptfd)->funcdesc.lprgscode = NULL ;
2075 pptfd = & ((*pptfd)->next);
2076 recoffset += reclength;
2078 HeapFree(GetProcessHeap(), 0, recbuf);
2081 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2082 int cVars, int offset, TLBVarDesc ** pptvd)
2084 int infolen, nameoffset, reclength;
2086 MSFT_VarRecord *pVarRec = (MSFT_VarRecord*)recbuf;
2090 TRACE_(typelib)("\n");
2092 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2093 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2094 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2095 recoffset += offset+sizeof(INT);
2096 for(i=0;i<cVars;i++){
2097 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2098 /* name, eventually add to a hash table */
2099 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2100 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2101 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2102 /* read the variable information record */
2103 MSFT_ReadLEDWords(&reclength, sizeof(pVarRec->Info), pcx, recoffset);
2105 MSFT_ReadLEDWords(&pVarRec->DataType, reclength - FIELD_OFFSET(MSFT_VarRecord, DataType), pcx, DO_NOT_SEEK);
2108 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpContext))
2109 (*pptvd)->HelpContext = pVarRec->HelpContext;
2111 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpString))
2112 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->HelpString);
2114 if(reclength > FIELD_OFFSET(MSFT_VarRecord, HelpStringContext))
2115 (*pptvd)->HelpStringContext = pVarRec->HelpStringContext;
2117 /* fill the VarDesc Structure */
2118 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2119 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2120 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2121 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2122 MSFT_GetTdesc(pcx, pVarRec->DataType,
2123 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2124 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2125 if(pVarRec->VarKind == VAR_CONST ){
2126 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2127 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2128 pVarRec->OffsValue, pcx);
2130 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2131 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2132 pptvd=&((*pptvd)->next);
2133 recoffset += reclength;
2136 /* fill in data for a hreftype (offset). When the referenced type is contained
2137 * in the typelib, it's just an (file) offset in the type info base dir.
2138 * If comes from import, it's an offset+1 in the ImpInfo table
2140 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2145 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2147 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2149 if(ref->reference == offset) return;
2152 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2153 list_add_tail(&pTL->ref_list, &ref->entry);
2155 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2156 /* external typelib */
2157 MSFT_ImpInfo impinfo;
2158 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2160 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2162 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2163 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2164 while (pImpLib){ /* search the known offsets of all import libraries */
2165 if(pImpLib->offset==impinfo.oImpFile) break;
2166 pImpLib=pImpLib->next;
2169 ref->reference = offset;
2170 ref->pImpTLInfo = pImpLib;
2171 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2172 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2173 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2174 ref->index = TLB_REF_USE_GUID;
2176 ref->index = impinfo.oGuid;
2178 ERR("Cannot find a reference\n");
2179 ref->reference = -1;
2180 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2183 /* in this typelib */
2184 ref->index = MSFT_HREFTYPE_INDEX(offset);
2185 ref->reference = offset;
2186 ref->pImpTLInfo = TLB_REF_INTERNAL;
2190 /* process Implemented Interfaces of a com class */
2191 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2195 MSFT_RefRecord refrec;
2196 TLBImplType **ppImpl = &pTI->impltypelist;
2198 TRACE_(typelib)("\n");
2200 for(i=0;i<count;i++){
2201 if(offset<0) break; /* paranoia */
2202 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2203 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2204 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2205 (*ppImpl)->hRef = refrec.reftype;
2206 (*ppImpl)->implflags=refrec.flags;
2207 (*ppImpl)->ctCustData=
2208 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2209 offset=refrec.onext;
2210 ppImpl=&((*ppImpl)->next);
2214 * process a typeinfo record
2216 static ITypeInfoImpl * MSFT_DoTypeInfo(
2219 ITypeLibImpl * pLibInfo)
2221 MSFT_TypeInfoBase tiBase;
2222 ITypeInfoImpl *ptiRet;
2224 TRACE_(typelib)("count=%u\n", count);
2226 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2227 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2228 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2230 /* this is where we are coming from */
2231 ptiRet->pTypeLib = pLibInfo;
2232 ptiRet->index=count;
2233 /* fill in the typeattr fields */
2235 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2236 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2237 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2238 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2239 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2240 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2241 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2242 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2243 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2244 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2245 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2246 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2247 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2248 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2249 MSFT_GetTdesc(pcx, tiBase.datatype1,
2250 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2253 /* IDLDESC idldescType; *//* never saw this one != zero */
2255 /* name, eventually add to a hash table */
2256 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2257 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2258 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2260 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2261 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2262 ptiRet->dwHelpContext=tiBase.helpcontext;
2264 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2265 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2267 /* note: InfoType's Help file and HelpStringDll come from the containing
2268 * library. Further HelpString and Docstring appear to be the same thing :(
2271 if(ptiRet->TypeAttr.cFuncs >0 )
2272 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2273 ptiRet->TypeAttr.cVars,
2274 tiBase.memoffset, & ptiRet->funclist);
2276 if(ptiRet->TypeAttr.cVars >0 )
2277 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2278 ptiRet->TypeAttr.cVars,
2279 tiBase.memoffset, & ptiRet->varlist);
2280 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2281 switch(ptiRet->TypeAttr.typekind)
2284 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2287 case TKIND_DISPATCH:
2288 /* This is not -1 when the interface is a non-base dual interface or
2289 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2290 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2294 if (tiBase.datatype1 != -1)
2296 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2297 ptiRet->impltypelist->hRef = tiBase.datatype1;
2298 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2302 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2303 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2304 ptiRet->impltypelist->hRef = tiBase.datatype1;
2309 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2311 TRACE_(typelib)("%s guid: %s kind:%s\n",
2312 debugstr_w(ptiRet->Name),
2313 debugstr_guid(&ptiRet->TypeAttr.guid),
2314 typekind_desc[ptiRet->TypeAttr.typekind]);
2315 if (TRACE_ON(typelib))
2316 dump_TypeInfo(ptiRet);
2321 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2322 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2323 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2326 static ITypeLibImpl *tlb_cache_first;
2327 static CRITICAL_SECTION cache_section;
2328 static CRITICAL_SECTION_DEBUG cache_section_debug =
2330 0, 0, &cache_section,
2331 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2332 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2334 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2337 typedef struct TLB_PEFile
2339 const IUnknownVtbl *lpvtbl;
2342 HRSRC typelib_resource;
2343 HGLOBAL typelib_global;
2344 LPVOID typelib_base;
2347 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2349 if (IsEqualIID(riid, &IID_IUnknown))
2352 IUnknown_AddRef(iface);
2356 return E_NOINTERFACE;
2359 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2361 TLB_PEFile *This = (TLB_PEFile *)iface;
2362 return InterlockedIncrement(&This->refs);
2365 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2367 TLB_PEFile *This = (TLB_PEFile *)iface;
2368 ULONG refs = InterlockedDecrement(&This->refs);
2371 if (This->typelib_global)
2372 FreeResource(This->typelib_global);
2374 FreeLibrary(This->dll);
2375 HeapFree(GetProcessHeap(), 0, This);
2380 static const IUnknownVtbl TLB_PEFile_Vtable =
2382 TLB_PEFile_QueryInterface,
2387 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2391 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2393 return E_OUTOFMEMORY;
2395 This->lpvtbl = &TLB_PEFile_Vtable;
2398 This->typelib_resource = NULL;
2399 This->typelib_global = NULL;
2400 This->typelib_base = NULL;
2402 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2403 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2407 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2408 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2409 if (This->typelib_resource)
2411 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2412 if (This->typelib_global)
2414 This->typelib_base = LockResource(This->typelib_global);
2416 if (This->typelib_base)
2418 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2419 *ppBase = This->typelib_base;
2420 *ppFile = (IUnknown *)&This->lpvtbl;
2427 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2428 return TYPE_E_CANTLOADLIBRARY;
2431 typedef struct TLB_NEFile
2433 const IUnknownVtbl *lpvtbl;
2435 LPVOID typelib_base;
2438 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2440 if (IsEqualIID(riid, &IID_IUnknown))
2443 IUnknown_AddRef(iface);
2447 return E_NOINTERFACE;
2450 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2452 TLB_NEFile *This = (TLB_NEFile *)iface;
2453 return InterlockedIncrement(&This->refs);
2456 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2458 TLB_NEFile *This = (TLB_NEFile *)iface;
2459 ULONG refs = InterlockedDecrement(&This->refs);
2462 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2463 HeapFree(GetProcessHeap(), 0, This);
2468 static const IUnknownVtbl TLB_NEFile_Vtable =
2470 TLB_NEFile_QueryInterface,
2475 /***********************************************************************
2476 * read_xx_header [internal]
2478 static int read_xx_header( HFILE lzfd )
2480 IMAGE_DOS_HEADER mzh;
2483 LZSeek( lzfd, 0, SEEK_SET );
2484 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2486 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2489 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2490 if ( 2 != LZRead( lzfd, magic, 2 ) )
2493 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2495 if ( magic[0] == 'N' && magic[1] == 'E' )
2496 return IMAGE_OS2_SIGNATURE;
2497 if ( magic[0] == 'P' && magic[1] == 'E' )
2498 return IMAGE_NT_SIGNATURE;
2501 WARN("Can't handle %s files.\n", magic );
2506 /***********************************************************************
2507 * find_ne_resource [internal]
2509 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2510 DWORD *resLen, DWORD *resOff )
2512 IMAGE_OS2_HEADER nehd;
2513 NE_TYPEINFO *typeInfo;
2514 NE_NAMEINFO *nameInfo;
2520 /* Read in NE header */
2521 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2522 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2524 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2527 TRACE("No resources in NE dll\n" );
2531 /* Read in resource table */
2532 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2533 if ( !resTab ) return FALSE;
2535 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2536 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2538 HeapFree( GetProcessHeap(), 0, resTab );
2543 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2545 if (!IS_INTRESOURCE(typeid)) /* named type */
2547 BYTE len = strlen( typeid );
2548 while (typeInfo->type_id)
2550 if (!(typeInfo->type_id & 0x8000))
2552 BYTE *p = resTab + typeInfo->type_id;
2553 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2555 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2556 typeInfo->count * sizeof(NE_NAMEINFO));
2559 else /* numeric type id */
2561 WORD id = LOWORD(typeid) | 0x8000;
2562 while (typeInfo->type_id)
2564 if (typeInfo->type_id == id) goto found_type;
2565 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2566 typeInfo->count * sizeof(NE_NAMEINFO));
2569 TRACE("No typeid entry found for %p\n", typeid );
2570 HeapFree( GetProcessHeap(), 0, resTab );
2574 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2576 if (!IS_INTRESOURCE(resid)) /* named resource */
2578 BYTE len = strlen( resid );
2579 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2581 BYTE *p = resTab + nameInfo->id;
2582 if (nameInfo->id & 0x8000) continue;
2583 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2586 else /* numeric resource id */
2588 WORD id = LOWORD(resid) | 0x8000;
2589 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2590 if (nameInfo->id == id) goto found_name;
2592 TRACE("No resid entry found for %p\n", typeid );
2593 HeapFree( GetProcessHeap(), 0, resTab );
2597 /* Return resource data */
2598 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2599 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2601 HeapFree( GetProcessHeap(), 0, resTab );
2605 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2609 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2610 TLB_NEFile *This = NULL;
2612 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2613 if (!This) return E_OUTOFMEMORY;
2615 This->lpvtbl = &TLB_NEFile_Vtable;
2617 This->typelib_base = NULL;
2619 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2620 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2622 DWORD reslen, offset;
2623 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2625 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2626 if( !This->typelib_base )
2630 LZSeek( lzfd, offset, SEEK_SET );
2631 reslen = LZRead( lzfd, This->typelib_base, reslen );
2633 *ppBase = This->typelib_base;
2634 *pdwTLBLength = reslen;
2635 *ppFile = (IUnknown *)&This->lpvtbl;
2641 if( lzfd >= 0) LZClose( lzfd );
2642 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2646 typedef struct TLB_Mapping
2648 const IUnknownVtbl *lpvtbl;
2652 LPVOID typelib_base;
2655 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2657 if (IsEqualIID(riid, &IID_IUnknown))
2660 IUnknown_AddRef(iface);
2664 return E_NOINTERFACE;
2667 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2669 TLB_Mapping *This = (TLB_Mapping *)iface;
2670 return InterlockedIncrement(&This->refs);
2673 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2675 TLB_Mapping *This = (TLB_Mapping *)iface;
2676 ULONG refs = InterlockedDecrement(&This->refs);
2679 if (This->typelib_base)
2680 UnmapViewOfFile(This->typelib_base);
2682 CloseHandle(This->mapping);
2683 if (This->file != INVALID_HANDLE_VALUE)
2684 CloseHandle(This->file);
2685 HeapFree(GetProcessHeap(), 0, This);
2690 static const IUnknownVtbl TLB_Mapping_Vtable =
2692 TLB_Mapping_QueryInterface,
2697 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2701 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2703 return E_OUTOFMEMORY;
2705 This->lpvtbl = &TLB_Mapping_Vtable;
2707 This->file = INVALID_HANDLE_VALUE;
2708 This->mapping = NULL;
2709 This->typelib_base = NULL;
2711 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2712 if (INVALID_HANDLE_VALUE != This->file)
2714 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2717 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2718 if(This->typelib_base)
2720 /* retrieve file size */
2721 *pdwTLBLength = GetFileSize(This->file, NULL);
2722 *ppBase = This->typelib_base;
2723 *ppFile = (IUnknown *)&This->lpvtbl;
2729 IUnknown_Release((IUnknown *)&This->lpvtbl);
2730 return TYPE_E_CANTLOADLIBRARY;
2733 /****************************************************************************
2736 * find the type of the typelib file and map the typelib resource into
2740 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2741 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2743 ITypeLibImpl *entry;
2746 LPWSTR index_str, file = (LPWSTR)pszFileName;
2747 LPVOID pBase = NULL;
2748 DWORD dwTLBLength = 0;
2749 IUnknown *pFile = NULL;
2753 index_str = strrchrW(pszFileName, '\\');
2754 if(index_str && *++index_str != '\0')
2757 LONG idx = strtolW(index_str, &end_ptr, 10);
2758 if(*end_ptr == '\0')
2760 int str_len = index_str - pszFileName - 1;
2762 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2763 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2768 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2770 if(strchrW(file, '\\'))
2772 lstrcpyW(pszPath, file);
2776 int len = GetSystemDirectoryW(pszPath, cchPath);
2777 pszPath[len] = '\\';
2778 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2782 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2784 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2786 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2787 EnterCriticalSection(&cache_section);
2788 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2790 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2792 TRACE("cache hit\n");
2793 *ppTypeLib = (ITypeLib2*)entry;
2794 ITypeLib_AddRef(*ppTypeLib);
2795 LeaveCriticalSection(&cache_section);
2799 LeaveCriticalSection(&cache_section);
2801 /* now actually load and parse the typelib */
2803 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2804 if (ret == TYPE_E_CANTLOADLIBRARY)
2805 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2806 if (ret == TYPE_E_CANTLOADLIBRARY)
2807 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2810 if (dwTLBLength >= 4)
2812 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2813 if (dwSignature == MSFT_SIGNATURE)
2814 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2815 else if (dwSignature == SLTG_SIGNATURE)
2816 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2819 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2820 ret = TYPE_E_CANTLOADLIBRARY;
2824 ret = TYPE_E_CANTLOADLIBRARY;
2825 IUnknown_Release(pFile);
2829 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2831 TRACE("adding to cache\n");
2832 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2833 lstrcpyW(impl->path, pszPath);
2834 /* We should really canonicalise the path here. */
2835 impl->index = index;
2837 /* FIXME: check if it has added already in the meantime */
2838 EnterCriticalSection(&cache_section);
2839 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2841 tlb_cache_first = impl;
2842 LeaveCriticalSection(&cache_section);
2845 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2850 /*================== ITypeLib(2) Methods ===================================*/
2852 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2854 ITypeLibImpl* pTypeLibImpl;
2856 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2857 if (!pTypeLibImpl) return NULL;
2859 pTypeLibImpl->lpVtbl = &tlbvt;
2860 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2861 pTypeLibImpl->ref = 1;
2863 list_init(&pTypeLibImpl->ref_list);
2864 pTypeLibImpl->dispatch_href = -1;
2866 return pTypeLibImpl;
2869 /****************************************************************************
2870 * ITypeLib2_Constructor_MSFT
2872 * loading an MSFT typelib from an in-memory image
2874 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2878 MSFT_Header tlbHeader;
2879 MSFT_SegDir tlbSegDir;
2880 ITypeLibImpl * pTypeLibImpl;
2882 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2884 pTypeLibImpl = TypeLibImpl_Constructor();
2885 if (!pTypeLibImpl) return NULL;
2887 /* get pointer to beginning of typelib data */
2891 cx.pLibInfo = pTypeLibImpl;
2892 cx.length = dwTLBLength;
2895 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2896 TRACE_(typelib)("header:\n");
2897 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2898 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2899 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2902 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2904 /* there is a small amount of information here until the next important
2906 * the segment directory . Try to calculate the amount of data */
2907 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2909 /* now read the segment directory */
2910 TRACE("read segment directory (at %d)\n",lPSegDir);
2911 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2912 cx.pTblDir = &tlbSegDir;
2914 /* just check two entries */
2915 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2917 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
2918 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2922 /* now fill our internal data */
2923 /* TLIBATTR fields */
2924 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2926 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2927 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2928 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2929 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2930 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2932 pTypeLibImpl->lcid = tlbHeader.lcid;
2934 /* name, eventually add to a hash table */
2935 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2938 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2939 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2941 if( tlbHeader.varflags & HELPDLLFLAG)
2944 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2945 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2948 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2951 if(tlbHeader.CustomDataOffset >= 0)
2953 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2956 /* fill in type descriptions */
2957 if(tlbSegDir.pTypdescTab.length > 0)
2959 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2961 pTypeLibImpl->ctTypeDesc = cTD;
2962 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2963 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2966 /* FIXME: add several sanity checks here */
2967 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2968 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2970 /* FIXME: check safearray */
2972 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2974 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2976 else if(td[0] == VT_CARRAY)
2978 /* array descr table here */
2979 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
2981 else if(td[0] == VT_USERDEFINED)
2983 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2985 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2988 /* second time around to fill the array subscript info */
2991 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2992 if(tlbSegDir.pArrayDescriptions.offset>0)
2994 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2995 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2998 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3000 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3002 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3004 for(j = 0; j<td[2]; j++)
3006 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3007 sizeof(INT), &cx, DO_NOT_SEEK);
3008 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3009 sizeof(INT), &cx, DO_NOT_SEEK);
3014 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3015 ERR("didn't find array description data\n");
3020 /* imported type libs */
3021 if(tlbSegDir.pImpFiles.offset>0)
3023 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
3024 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3027 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3031 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
3032 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
3033 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3035 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3036 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3037 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3038 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3041 name = TLB_Alloc(size+1);
3042 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3043 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3046 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3047 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3049 ppImpLib = &(*ppImpLib)->next;
3053 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3054 if(pTypeLibImpl->dispatch_href != -1)
3055 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3058 if(tlbHeader.nrtypeinfos >= 0 )
3060 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3061 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3064 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3066 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3068 ppTI = &((*ppTI)->next);
3069 (pTypeLibImpl->TypeInfoCount)++;
3073 TRACE("(%p)\n", pTypeLibImpl);
3074 return (ITypeLib2*) pTypeLibImpl;
3078 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3084 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3085 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3089 guid->Data4[0] = s >> 8;
3090 guid->Data4[1] = s & 0xff;
3093 for(i = 0; i < 6; i++) {
3094 memcpy(b, str + 24 + 2 * i, 2);
3095 guid->Data4[i + 2] = strtol(b, NULL, 16);
3100 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3106 bytelen = *(const WORD*)ptr;
3107 if(bytelen == 0xffff) return 2;
3108 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3109 *pBstr = SysAllocStringLen(NULL, len);
3111 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3115 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3120 bytelen = *(const WORD*)ptr;
3121 if(bytelen == 0xffff) return 2;
3122 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3123 memcpy(*str, ptr + 2, bytelen);
3124 (*str)[bytelen] = '\0';
3128 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3130 char *ptr = pLibBlk;
3133 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3134 FIXME("libblk magic = %04x\n", w);
3139 if((w = *(WORD*)ptr) != 0xffff) {
3140 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3145 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3147 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3149 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3152 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3155 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3156 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3158 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3161 ptr += 4; /* skip res12 */
3163 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3166 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3169 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3172 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3173 ptr += sizeof(GUID);
3175 return ptr - (char*)pLibBlk;
3178 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3183 } sltg_ref_lookup_t;
3185 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3186 HREFTYPE *typelib_ref)
3188 if(table && typeinfo_ref < table->num)
3190 *typelib_ref = table->refs[typeinfo_ref];
3194 ERR_(typelib)("Unable to find reference\n");
3199 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3204 if((*pType & 0xe00) == 0xe00) {
3206 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3208 pTD = pTD->u.lptdesc;
3210 switch(*pType & 0x3f) {
3213 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3215 pTD = pTD->u.lptdesc;
3218 case VT_USERDEFINED:
3219 pTD->vt = VT_USERDEFINED;
3220 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3226 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3229 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3231 pTD->vt = VT_CARRAY;
3232 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3234 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3235 pTD->u.lpadesc->cDims = pSA->cDims;
3236 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3237 pSA->cDims * sizeof(SAFEARRAYBOUND));
3239 pTD = &pTD->u.lpadesc->tdescElem;
3245 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3249 pTD->vt = VT_SAFEARRAY;
3250 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3252 pTD = pTD->u.lptdesc;
3256 pTD->vt = *pType & 0x3f;
3265 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3266 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3268 /* Handle [in/out] first */
3269 if((*pType & 0xc000) == 0xc000)
3270 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3271 else if(*pType & 0x8000)
3272 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3273 else if(*pType & 0x4000)
3274 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3276 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3279 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3282 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3284 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3288 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3293 TLBRefType *ref_type;
3294 sltg_ref_lookup_t *table;
3295 HREFTYPE typelib_ref;
3297 if(pRef->magic != SLTG_REF_MAGIC) {
3298 FIXME("Ref magic = %x\n", pRef->magic);
3301 name = ( (char*)pRef->names + pRef->number);
3303 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3304 table->num = pRef->number >> 3;
3306 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3308 /* We don't want the first href to be 0 */
3309 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3311 for(ref = 0; ref < pRef->number >> 3; ref++) {
3313 unsigned int lib_offs, type_num;
3315 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3317 name += SLTG_ReadStringA(name, &refname);
3318 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3319 FIXME_(typelib)("Can't sscanf ref\n");
3320 if(lib_offs != 0xffff) {
3321 TLBImpLib **import = &pTL->pImpLibs;
3324 if((*import)->offset == lib_offs)
3326 import = &(*import)->next;
3329 char fname[MAX_PATH+1];
3332 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3334 (*import)->offset = lib_offs;
3335 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3337 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3338 &(*import)->wVersionMajor,
3339 &(*import)->wVersionMinor,
3340 &(*import)->lcid, fname) != 4) {
3341 FIXME_(typelib)("can't sscanf ref %s\n",
3342 pNameTable + lib_offs + 40);
3344 len = strlen(fname);
3345 if(fname[len-1] != '#')
3346 FIXME("fname = %s\n", fname);
3347 fname[len-1] = '\0';
3348 (*import)->name = TLB_MultiByteToBSTR(fname);
3350 ref_type->pImpTLInfo = *import;
3352 /* Store a reference to IDispatch */
3353 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3354 pTL->dispatch_href = typelib_ref;
3356 } else { /* internal ref */
3357 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3359 ref_type->reference = typelib_ref;
3360 ref_type->index = type_num;
3362 HeapFree(GetProcessHeap(), 0, refname);
3363 list_add_tail(&pTL->ref_list, &ref_type->entry);
3365 table->refs[ref] = typelib_ref;
3368 if((BYTE)*name != SLTG_REF_MAGIC)
3369 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3370 dump_TLBRefType(pTL);
3374 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3375 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3377 SLTG_ImplInfo *info;
3378 TLBImplType **ppImplType = &pTI->impltypelist;
3379 /* I don't really get this structure, usually it's 0x16 bytes
3380 long, but iuser.tlb contains some that are 0x18 bytes long.
3381 That's ok because we can use the next ptr to jump to the next
3382 one. But how do we know the length of the last one? The WORD
3383 at offs 0x8 might be the clue. For now I'm just assuming that
3384 the last one is the regular 0x16 bytes. */
3386 info = (SLTG_ImplInfo*)pBlk;
3388 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3389 sizeof(**ppImplType));
3390 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3391 (*ppImplType)->implflags = info->impltypeflags;
3392 pTI->TypeAttr.cImplTypes++;
3393 ppImplType = &(*ppImplType)->next;
3395 if(info->next == 0xffff)
3398 FIXME_(typelib)("Interface inheriting more than one interface\n");
3399 info = (SLTG_ImplInfo*)(pBlk + info->next);
3401 info++; /* see comment at top of function */
3405 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3406 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3408 TLBVarDesc **ppVarDesc = &pTI->varlist;
3409 BSTR bstrPrevName = NULL;
3410 SLTG_Variable *pItem;
3414 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3415 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3417 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3418 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 = HeapAlloc(GetProcessHeap(), 0,
3462 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3463 if (pItem->flags & 0x08)
3464 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3466 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3472 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3474 TRACE_(typelib)("len = %u\n", len);
3475 if (len == 0xffff) {
3478 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3479 str = SysAllocStringLen(NULL, alloc_len);
3480 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3482 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3483 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3492 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3493 *(INT*)(pBlk + pItem->byte_offs);
3496 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3501 TRACE_(typelib)("VAR_PERINSTANCE\n");
3502 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3503 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3506 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3507 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3509 if (pItem->flags & 0x80)
3510 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3512 bstrPrevName = (*ppVarDesc)->Name;
3513 ppVarDesc = &((*ppVarDesc)->next);
3515 pTI->TypeAttr.cVars = cVars;
3518 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3519 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3521 SLTG_Function *pFunc;
3523 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3525 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3526 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3531 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3532 sizeof(**ppFuncDesc));
3534 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3535 case SLTG_FUNCTION_MAGIC:
3536 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3538 case SLTG_DISPATCH_FUNCTION_MAGIC:
3539 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3541 case SLTG_STATIC_FUNCTION_MAGIC:
3542 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3545 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3546 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3550 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3552 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3553 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3554 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3555 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3556 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3557 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3559 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3560 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3562 if(pFunc->retnextopt & 0x80)
3563 pType = &pFunc->rettype;
3565 pType = (WORD*)(pBlk + pFunc->rettype);
3567 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3569 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3570 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3571 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3572 (*ppFuncDesc)->pParamDesc =
3573 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3574 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3576 pArg = (WORD*)(pBlk + pFunc->arg_off);
3578 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3579 char *paramName = pNameTable + *pArg;
3581 /* If arg type follows then paramName points to the 2nd
3582 letter of the name, else the next WORD is an offset to
3583 the arg type and paramName points to the first letter.
3584 So let's take one char off paramName and see if we're
3585 pointing at an alpha-numeric char. However if *pArg is
3586 0xffff or 0xfffe then the param has no name, the former
3587 meaning that the next WORD is the type, the latter
3588 meaning that the next WORD is an offset to the type. */
3593 else if(*pArg == 0xfffe) {
3597 else if(paramName[-1] && !isalnum(paramName[-1]))
3602 if(HaveOffs) { /* the next word is an offset to type */
3603 pType = (WORD*)(pBlk + *pArg);
3604 SLTG_DoElem(pType, pBlk,
3605 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3610 pArg = SLTG_DoElem(pArg, pBlk,
3611 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3614 /* Are we an optional param ? */
3615 if((*ppFuncDesc)->funcdesc.cParams - param <=
3616 (*ppFuncDesc)->funcdesc.cParamsOpt)
3617 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3620 (*ppFuncDesc)->pParamDesc[param].Name =
3621 TLB_MultiByteToBSTR(paramName);
3623 (*ppFuncDesc)->pParamDesc[param].Name =
3624 SysAllocString((*ppFuncDesc)->Name);
3628 ppFuncDesc = &((*ppFuncDesc)->next);
3629 if(pFunc->next == 0xffff) break;
3631 pTI->TypeAttr.cFuncs = cFuncs;
3634 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3635 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3636 SLTG_TypeInfoTail *pTITail)
3639 sltg_ref_lookup_t *ref_lookup = NULL;
3641 if(pTIHeader->href_table != 0xffffffff) {
3642 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3648 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3649 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3651 HeapFree(GetProcessHeap(), 0, ref_lookup);
3655 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3656 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3657 const SLTG_TypeInfoTail *pTITail)
3660 sltg_ref_lookup_t *ref_lookup = NULL;
3662 if(pTIHeader->href_table != 0xffffffff) {
3663 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3669 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3670 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3673 if (pTITail->funcs_off != 0xffff)
3674 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3676 HeapFree(GetProcessHeap(), 0, ref_lookup);
3678 if (TRACE_ON(typelib))
3679 dump_TLBFuncDesc(pTI->funclist);
3682 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3683 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3684 const SLTG_TypeInfoTail *pTITail)
3686 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3689 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3690 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3691 const SLTG_TypeInfoTail *pTITail)
3694 sltg_ref_lookup_t *ref_lookup = NULL;
3696 if (pTITail->simple_alias) {
3697 /* if simple alias, no more processing required */
3698 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3702 if(pTIHeader->href_table != 0xffffffff) {
3703 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3707 /* otherwise it is an offset to a type */
3708 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3710 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3712 HeapFree(GetProcessHeap(), 0, ref_lookup);
3715 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3716 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3717 const SLTG_TypeInfoTail *pTITail)
3719 sltg_ref_lookup_t *ref_lookup = NULL;
3720 if (pTIHeader->href_table != 0xffffffff)
3721 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3724 if (pTITail->vars_off != 0xffff)
3725 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3727 if (pTITail->funcs_off != 0xffff)
3728 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3730 if (pTITail->impls_off != 0xffff)
3731 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3733 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3734 * of dispinterface functions including the IDispatch ones, so
3735 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3736 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3738 HeapFree(GetProcessHeap(), 0, ref_lookup);
3739 if (TRACE_ON(typelib))
3740 dump_TLBFuncDesc(pTI->funclist);
3743 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3744 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3745 const SLTG_TypeInfoTail *pTITail)
3747 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3750 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3751 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3752 const SLTG_TypeInfoTail *pTITail)
3754 sltg_ref_lookup_t *ref_lookup = NULL;
3755 if (pTIHeader->href_table != 0xffffffff)
3756 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3759 if (pTITail->vars_off != 0xffff)
3760 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3762 if (pTITail->funcs_off != 0xffff)
3763 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3764 HeapFree(GetProcessHeap(), 0, ref_lookup);
3765 if (TRACE_ON(typelib))
3769 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3770 managable copy of it into this */
3783 } SLTG_InternalOtherTypeInfo;
3785 /****************************************************************************
3786 * ITypeLib2_Constructor_SLTG
3788 * loading a SLTG typelib from an in-memory image
3790 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3792 ITypeLibImpl *pTypeLibImpl;
3793 SLTG_Header *pHeader;
3794 SLTG_BlkEntry *pBlkEntry;
3798 LPVOID pBlk, pFirstBlk;
3799 SLTG_LibBlk *pLibBlk;
3800 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3801 char *pAfterOTIBlks = NULL;
3802 char *pNameTable, *ptr;
3805 ITypeInfoImpl **ppTypeInfoImpl;
3807 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3810 pTypeLibImpl = TypeLibImpl_Constructor();
3811 if (!pTypeLibImpl) return NULL;
3815 TRACE_(typelib)("header:\n");
3816 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3817 pHeader->nrOfFileBlks );
3818 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3819 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3820 pHeader->SLTG_magic);
3824 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3825 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3827 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3828 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3830 /* Next we have a magic block */
3831 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3833 /* Let's see if we're still in sync */
3834 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3835 sizeof(SLTG_COMPOBJ_MAGIC))) {
3836 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3839 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3840 sizeof(SLTG_DIR_MAGIC))) {
3841 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3845 pIndex = (SLTG_Index*)(pMagic+1);
3847 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3849 pFirstBlk = pPad9 + 1;
3851 /* We'll set up a ptr to the main library block, which is the last one. */
3853 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3854 pBlkEntry[order].next != 0;
3855 order = pBlkEntry[order].next - 1, i++) {
3856 pBlk = (char*)pBlk + pBlkEntry[order].len;
3860 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3862 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3867 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3869 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3870 sizeof(*pOtherTypeInfoBlks) *
3871 pTypeLibImpl->TypeInfoCount);
3874 ptr = (char*)pLibBlk + len;
3876 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3880 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3882 w = *(WORD*)(ptr + 2);
3885 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3887 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3888 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3890 w = *(WORD*)(ptr + 4 + len);
3892 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3894 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3896 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3897 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3899 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3900 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3901 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3903 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3905 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3908 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3909 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3910 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3911 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3912 len += sizeof(SLTG_OtherTypeInfo);
3916 pAfterOTIBlks = ptr;
3918 /* Skip this WORD and get the next DWORD */
3919 len = *(DWORD*)(pAfterOTIBlks + 2);
3921 /* Now add this to pLibBLk look at what we're pointing at and
3922 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3923 dust and we should be pointing at the beginning of the name
3926 pNameTable = (char*)pLibBlk + len;
3928 switch(*(WORD*)pNameTable) {
3935 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3939 pNameTable += 0x216;
3943 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3945 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3948 /* Hopefully we now have enough ptrs set up to actually read in
3949 some TypeInfos. It's not clear which order to do them in, so
3950 I'll just follow the links along the BlkEntry chain and read
3951 them in the order in which they are in the file */
3953 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3955 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3956 pBlkEntry[order].next != 0;
3957 order = pBlkEntry[order].next - 1, i++) {
3959 SLTG_TypeInfoHeader *pTIHeader;
3960 SLTG_TypeInfoTail *pTITail;
3961 SLTG_MemberHeader *pMemHeader;
3963 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3964 pOtherTypeInfoBlks[i].index_name)) {
3965 FIXME_(typelib)("Index strings don't match\n");
3970 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3971 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3974 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3975 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3976 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3978 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3979 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3980 (*ppTypeInfoImpl)->index = i;
3981 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3982 pOtherTypeInfoBlks[i].name_offs +
3984 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3985 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3986 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3987 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3988 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3989 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3990 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3992 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3993 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3995 if((pTIHeader->typeflags1 & 7) != 2)
3996 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3997 if(pTIHeader->typeflags3 != 2)
3998 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4000 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4001 debugstr_w((*ppTypeInfoImpl)->Name),
4002 typekind_desc[pTIHeader->typekind],
4003 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4004 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4006 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4008 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4010 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4011 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4012 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4014 switch(pTIHeader->typekind) {
4016 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4017 pTIHeader, pTITail);
4021 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4022 pTIHeader, pTITail);
4025 case TKIND_INTERFACE:
4026 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4027 pTIHeader, pTITail);
4031 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4032 pTIHeader, pTITail);
4036 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4037 pTIHeader, pTITail);
4040 case TKIND_DISPATCH:
4041 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4042 pTIHeader, pTITail);
4046 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4047 pTIHeader, pTITail);
4051 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4056 /* could get cFuncs, cVars and cImplTypes from here
4057 but we've already set those */
4058 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4073 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4074 pBlk = (char*)pBlk + pBlkEntry[order].len;
4077 if(i != pTypeLibImpl->TypeInfoCount) {
4078 FIXME("Somehow processed %d TypeInfos\n", i);
4082 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4083 return (ITypeLib2*)pTypeLibImpl;
4086 /* ITypeLib::QueryInterface
4088 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4093 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4095 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4098 if(IsEqualIID(riid, &IID_IUnknown) ||
4099 IsEqualIID(riid,&IID_ITypeLib)||
4100 IsEqualIID(riid,&IID_ITypeLib2))
4107 ITypeLib2_AddRef(iface);
4108 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4111 TRACE("-- Interface: E_NOINTERFACE\n");
4112 return E_NOINTERFACE;
4117 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4119 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4120 ULONG ref = InterlockedIncrement(&This->ref);
4122 TRACE("(%p)->ref was %u\n",This, ref - 1);
4127 /* ITypeLib::Release
4129 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4131 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4132 ULONG ref = InterlockedDecrement(&This->ref);
4134 TRACE("(%p)->(%u)\n",This, ref);
4138 TLBImpLib *pImpLib, *pImpLibNext;
4139 TLBCustData *pCustData, *pCustDataNext;
4140 TLBRefType *ref_type;
4143 ITypeInfoImpl *pTI, *pTINext;
4145 /* remove cache entry */
4148 TRACE("removing from cache list\n");
4149 EnterCriticalSection(&cache_section);
4150 if (This->next) This->next->prev = This->prev;
4151 if (This->prev) This->prev->next = This->next;
4152 else tlb_cache_first = This->next;
4153 LeaveCriticalSection(&cache_section);
4154 HeapFree(GetProcessHeap(), 0, This->path);
4156 TRACE(" destroying ITypeLib(%p)\n",This);
4158 SysFreeString(This->Name);
4161 SysFreeString(This->DocString);
4162 This->DocString = NULL;
4164 SysFreeString(This->HelpFile);
4165 This->HelpFile = NULL;
4167 SysFreeString(This->HelpStringDll);
4168 This->HelpStringDll = NULL;
4170 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4172 VariantClear(&pCustData->data);
4174 pCustDataNext = pCustData->next;
4175 TLB_Free(pCustData);
4178 for (i = 0; i < This->ctTypeDesc; i++)
4179 if (This->pTypeDesc[i].vt == VT_CARRAY)
4180 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4182 TLB_Free(This->pTypeDesc);
4184 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4186 if (pImpLib->pImpTypeLib)
4187 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4188 SysFreeString(pImpLib->name);
4190 pImpLibNext = pImpLib->next;
4194 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4196 list_remove(&ref_type->entry);
4200 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4202 pTINext = pTI->next;
4203 ITypeInfo_fnDestroy(pTI);
4205 HeapFree(GetProcessHeap(),0,This);
4212 /* ITypeLib::GetTypeInfoCount
4214 * Returns the number of type descriptions in the type library
4216 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4218 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4219 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4220 return This->TypeInfoCount;
4223 /* ITypeLib::GetTypeInfo
4225 * retrieves the specified type description in the library.
4227 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4230 ITypeInfo **ppTInfo)
4234 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4235 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4237 TRACE("(%p)->(index=%d)\n", This, index);
4239 if (!ppTInfo) return E_INVALIDARG;
4241 /* search element n in list */
4242 for(i=0; i < index; i++)
4244 pTypeInfo = pTypeInfo->next;
4247 TRACE("-- element not found\n");
4248 return TYPE_E_ELEMENTNOTFOUND;
4252 *ppTInfo = (ITypeInfo *) pTypeInfo;
4254 ITypeInfo_AddRef(*ppTInfo);
4255 TRACE("-- found (%p)\n",*ppTInfo);
4260 /* ITypeLibs::GetTypeInfoType
4262 * Retrieves the type of a type description.
4264 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4269 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4271 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4273 TRACE("(%p, %d, %p)\n", This, index, pTKind);
4275 if(!pTKind) return E_INVALIDARG;
4277 if(ITypeLib2_GetTypeInfoCount(iface) <= index)
4278 return TYPE_E_ELEMENTNOTFOUND;
4280 /* search element n in list */
4281 for(i=0; i < index; i++)
4285 TRACE("-- element not found\n");
4286 return TYPE_E_ELEMENTNOTFOUND;
4288 pTInfo = pTInfo->next;
4291 *pTKind = pTInfo->TypeAttr.typekind;
4292 TRACE("-- found Type (%d)\n", *pTKind);
4296 /* ITypeLib::GetTypeInfoOfGuid
4298 * Retrieves the type description that corresponds to the specified GUID.
4301 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4304 ITypeInfo **ppTInfo)
4306 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4307 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4309 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4313 WARN("-- element not found\n");
4314 return TYPE_E_ELEMENTNOTFOUND;
4317 /* search linked list for guid */
4318 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4320 pTypeInfo = pTypeInfo->next;
4324 /* end of list reached */
4325 WARN("-- element not found\n");
4326 return TYPE_E_ELEMENTNOTFOUND;
4330 TRACE("-- found (%p, %s)\n",
4332 debugstr_w(pTypeInfo->Name));
4334 *ppTInfo = (ITypeInfo*)pTypeInfo;
4335 ITypeInfo_AddRef(*ppTInfo);
4339 /* ITypeLib::GetLibAttr
4341 * Retrieves the structure that contains the library's attributes.
4344 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4348 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4350 TRACE("(%p, %p)\n", This, attr);
4352 if (!attr) return E_INVALIDARG;
4354 *attr = HeapAlloc(GetProcessHeap(), 0, sizeof(**attr));
4355 if (!*attr) return E_OUTOFMEMORY;
4357 **attr = This->LibAttr;
4361 /* ITypeLib::GetTypeComp
4363 * Enables a client compiler to bind to a library's types, variables,
4364 * constants, and global functions.
4367 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4369 ITypeComp **ppTComp)
4371 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4373 TRACE("(%p)->(%p)\n",This,ppTComp);
4374 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4375 ITypeComp_AddRef(*ppTComp);
4380 /* ITypeLib::GetDocumentation
4382 * Retrieves the library's documentation string, the complete Help file name
4383 * and path, and the context identifier for the library Help topic in the Help
4386 * On a successful return all non-null BSTR pointers will have been set,
4389 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4393 BSTR *pBstrDocString,
4394 DWORD *pdwHelpContext,
4395 BSTR *pBstrHelpFile)
4397 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4399 HRESULT result = E_INVALIDARG;
4404 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4406 pBstrName, pBstrDocString,
4407 pdwHelpContext, pBstrHelpFile);
4411 /* documentation for the typelib */
4416 if(!(*pBstrName = SysAllocString(This->Name)))
4424 if (This->DocString)
4426 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4429 else if (This->Name)
4431 if(!(*pBstrDocString = SysAllocString(This->Name)))
4435 *pBstrDocString = NULL;
4439 *pdwHelpContext = This->dwHelpContext;
4445 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4449 *pBstrHelpFile = NULL;
4456 /* for a typeinfo */
4457 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4459 if(SUCCEEDED(result))
4461 result = ITypeInfo_GetDocumentation(pTInfo,
4465 pdwHelpContext, pBstrHelpFile);
4467 ITypeInfo_Release(pTInfo);
4472 if (pBstrDocString) SysFreeString (*pBstrDocString);
4474 if (pBstrName) SysFreeString (*pBstrName);
4476 return STG_E_INSUFFICIENTMEMORY;
4481 * Indicates whether a passed-in string contains the name of a type or member
4482 * described in the library.
4485 static HRESULT WINAPI ITypeLib2_fnIsName(
4491 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4492 ITypeInfoImpl *pTInfo;
4493 TLBFuncDesc *pFInfo;
4496 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4498 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4502 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4503 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4504 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4505 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4506 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4507 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4508 goto ITypeLib2_fnIsName_exit;
4510 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4511 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4516 ITypeLib2_fnIsName_exit:
4517 TRACE("(%p)slow! search for %s: %s found!\n", This,
4518 debugstr_w(szNameBuf), *pfName?"NOT":"");
4523 /* ITypeLib::FindName
4525 * Finds occurrences of a type description in a type library. This may be used
4526 * to quickly verify that a name exists in a type library.
4529 static HRESULT WINAPI ITypeLib2_fnFindName(
4533 ITypeInfo **ppTInfo,
4537 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4538 ITypeInfoImpl *pTInfo;
4539 TLBFuncDesc *pFInfo;
4542 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4544 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4545 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4546 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4547 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4548 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4549 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4550 goto ITypeLib2_fnFindName_exit;
4553 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4554 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4556 ITypeLib2_fnFindName_exit:
4557 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4558 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4561 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4562 This, *pcFound, debugstr_w(szNameBuf), j);
4569 /* ITypeLib::ReleaseTLibAttr
4571 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4574 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4576 TLIBATTR *pTLibAttr)
4578 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4579 TRACE("freeing (%p)\n",This);
4580 HeapFree(GetProcessHeap(),0,pTLibAttr);
4584 /* ITypeLib2::GetCustData
4586 * gets the custom data
4588 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4593 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4594 TLBCustData *pCData;
4596 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4598 if( IsEqualIID(guid, &pCData->guid)) break;
4601 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4605 VariantInit( pVarVal);
4606 VariantCopy( pVarVal, &pCData->data);
4609 return E_INVALIDARG; /* FIXME: correct? */
4612 /* ITypeLib2::GetLibStatistics
4614 * Returns statistics about a type library that are required for efficient
4615 * sizing of hash tables.
4618 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4620 ULONG *pcUniqueNames,
4621 ULONG *pcchUniqueNames)
4623 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4625 FIXME("(%p): stub!\n", This);
4627 if(pcUniqueNames) *pcUniqueNames=1;
4628 if(pcchUniqueNames) *pcchUniqueNames=1;
4632 /* ITypeLib2::GetDocumentation2
4634 * Retrieves the library's documentation string, the complete Help file name
4635 * and path, the localization context to use, and the context ID for the
4636 * library Help topic in the Help file.
4639 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4643 BSTR *pbstrHelpString,
4644 DWORD *pdwHelpStringContext,
4645 BSTR *pbstrHelpStringDll)
4647 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4651 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4653 /* the help string should be obtained from the helpstringdll,
4654 * using the _DLLGetDocumentation function, based on the supplied
4655 * lcid. Nice to do sometime...
4659 /* documentation for the typelib */
4661 *pbstrHelpString=SysAllocString(This->DocString);
4662 if(pdwHelpStringContext)
4663 *pdwHelpStringContext=This->dwHelpContext;
4664 if(pbstrHelpStringDll)
4665 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4671 /* for a typeinfo */
4672 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4674 if(SUCCEEDED(result))
4676 ITypeInfo2 * pTInfo2;
4677 result = ITypeInfo_QueryInterface(pTInfo,
4679 (LPVOID*) &pTInfo2);
4681 if(SUCCEEDED(result))
4683 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4687 pdwHelpStringContext,
4688 pbstrHelpStringDll);
4690 ITypeInfo2_Release(pTInfo2);
4693 ITypeInfo_Release(pTInfo);
4699 /* ITypeLib2::GetAllCustData
4701 * Gets all custom data items for the library.
4704 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4706 CUSTDATA *pCustData)
4708 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4709 TLBCustData *pCData;
4711 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4712 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4713 if(pCustData->prgCustData ){
4714 pCustData->cCustData=This->ctCustData;
4715 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4716 pCustData->prgCustData[i].guid=pCData->guid;
4717 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4720 ERR(" OUT OF MEMORY!\n");
4721 return E_OUTOFMEMORY;
4726 static const ITypeLib2Vtbl tlbvt = {
4727 ITypeLib2_fnQueryInterface,
4729 ITypeLib2_fnRelease,
4730 ITypeLib2_fnGetTypeInfoCount,
4731 ITypeLib2_fnGetTypeInfo,
4732 ITypeLib2_fnGetTypeInfoType,
4733 ITypeLib2_fnGetTypeInfoOfGuid,
4734 ITypeLib2_fnGetLibAttr,
4735 ITypeLib2_fnGetTypeComp,
4736 ITypeLib2_fnGetDocumentation,
4738 ITypeLib2_fnFindName,
4739 ITypeLib2_fnReleaseTLibAttr,
4741 ITypeLib2_fnGetCustData,
4742 ITypeLib2_fnGetLibStatistics,
4743 ITypeLib2_fnGetDocumentation2,
4744 ITypeLib2_fnGetAllCustData
4748 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4750 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4752 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4755 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4757 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4759 return ITypeLib2_AddRef((ITypeLib2 *)This);
4762 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4764 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4766 return ITypeLib2_Release((ITypeLib2 *)This);
4769 static HRESULT WINAPI ITypeLibComp_fnBind(
4774 ITypeInfo ** ppTInfo,
4775 DESCKIND * pDescKind,
4778 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4779 ITypeInfoImpl *pTypeInfo;
4782 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4784 *pDescKind = DESCKIND_NONE;
4785 pBindPtr->lptcomp = NULL;
4788 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4790 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4792 /* FIXME: check wFlags here? */
4793 /* FIXME: we should use a hash table to look this info up using lHash
4794 * instead of an O(n) search */
4795 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4796 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4798 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4800 *pDescKind = DESCKIND_TYPECOMP;
4801 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4802 ITypeComp_AddRef(pBindPtr->lptcomp);
4803 TRACE("module or enum: %s\n", debugstr_w(szName));
4808 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4809 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4811 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4814 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4815 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4817 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4820 else if (hr == TYPE_E_TYPEMISMATCH)
4824 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4825 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4827 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4829 ITypeInfo *subtypeinfo;
4831 DESCKIND subdesckind;
4833 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4834 &subtypeinfo, &subdesckind, &subbindptr);
4835 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4837 TYPEDESC tdesc_appobject;
4838 const VARDESC vardesc_appobject =
4841 NULL, /* lpstrSchema */
4856 VAR_STATIC /* varkind */
4859 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4860 tdesc_appobject.vt = VT_USERDEFINED;
4862 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4864 /* cleanup things filled in by Bind call so we can put our
4865 * application object data in there instead */
4866 switch (subdesckind)
4868 case DESCKIND_FUNCDESC:
4869 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4871 case DESCKIND_VARDESC:
4872 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4877 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4879 if (pTypeInfo->hreftype == -1)
4880 FIXME("no hreftype for interface %p\n", pTypeInfo);
4882 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4886 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4887 *ppTInfo = (ITypeInfo *)pTypeInfo;
4888 ITypeInfo_AddRef(*ppTInfo);
4891 else if (hr == TYPE_E_TYPEMISMATCH)
4898 TRACE("type mismatch %s\n", debugstr_w(szName));
4899 return TYPE_E_TYPEMISMATCH;
4903 TRACE("name not found %s\n", debugstr_w(szName));
4908 static HRESULT WINAPI ITypeLibComp_fnBindType(
4912 ITypeInfo ** ppTInfo,
4913 ITypeComp ** ppTComp)
4915 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4916 ITypeInfoImpl *pTypeInfo;
4918 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4920 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4922 /* FIXME: should use lHash to do the search */
4923 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4925 TRACE("returning %p\n", pTypeInfo);
4926 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4927 ITypeInfo_AddRef(*ppTInfo);
4928 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4929 ITypeComp_AddRef(*ppTComp);
4934 TRACE("not found\n");
4940 static const ITypeCompVtbl tlbtcvt =
4943 ITypeLibComp_fnQueryInterface,
4944 ITypeLibComp_fnAddRef,
4945 ITypeLibComp_fnRelease,
4947 ITypeLibComp_fnBind,
4948 ITypeLibComp_fnBindType
4951 /*================== ITypeInfo(2) Methods ===================================*/
4952 static ITypeInfo2 * ITypeInfo_Constructor(void)
4954 ITypeInfoImpl * pTypeInfoImpl;
4956 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4959 pTypeInfoImpl->lpVtbl = &tinfvt;
4960 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4961 pTypeInfoImpl->ref = 0;
4962 pTypeInfoImpl->hreftype = -1;
4963 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4964 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4966 TRACE("(%p)\n", pTypeInfoImpl);
4967 return (ITypeInfo2*) pTypeInfoImpl;
4970 /* ITypeInfo::QueryInterface
4972 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4977 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4979 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4982 if(IsEqualIID(riid, &IID_IUnknown) ||
4983 IsEqualIID(riid,&IID_ITypeInfo)||
4984 IsEqualIID(riid,&IID_ITypeInfo2))
4988 ITypeInfo_AddRef(iface);
4989 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4992 TRACE("-- Interface: E_NOINTERFACE\n");
4993 return E_NOINTERFACE;
4996 /* ITypeInfo::AddRef
4998 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
5000 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5001 ULONG ref = InterlockedIncrement(&This->ref);
5003 TRACE("(%p)->ref is %u\n",This, ref);
5005 if (ref == 1 /* incremented from 0 */)
5006 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
5011 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This)
5013 TLBFuncDesc *pFInfo, *pFInfoNext;
5014 TLBVarDesc *pVInfo, *pVInfoNext;
5015 TLBImplType *pImpl, *pImplNext;
5017 TRACE("destroying ITypeInfo(%p)\n",This);
5019 SysFreeString(This->Name);
5022 SysFreeString(This->DocString);
5023 This->DocString = NULL;
5025 SysFreeString(This->DllName);
5026 This->DllName = NULL;
5028 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
5031 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
5033 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
5034 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5036 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5037 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
5039 SysFreeString(pFInfo->pParamDesc[i].Name);
5041 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
5042 TLB_Free(pFInfo->pParamDesc);
5043 TLB_FreeCustData(pFInfo->pCustData);
5044 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5045 SysFreeString(pFInfo->Entry);
5046 SysFreeString(pFInfo->HelpString);
5047 SysFreeString(pFInfo->Name);
5049 pFInfoNext = pFInfo->next;
5052 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5054 if (pVInfo->vardesc.varkind == VAR_CONST)
5056 VariantClear(pVInfo->vardesc.u.lpvarValue);
5057 TLB_Free(pVInfo->vardesc.u.lpvarValue);
5059 TLB_FreeCustData(pVInfo->pCustData);
5060 SysFreeString(pVInfo->Name);
5061 pVInfoNext = pVInfo->next;
5064 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5066 TLB_FreeCustData(pImpl->pCustData);
5067 pImplNext = pImpl->next;
5070 TLB_FreeCustData(This->pCustData);
5072 HeapFree(GetProcessHeap(), 0, This);
5075 /* ITypeInfo::Release
5077 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5079 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5080 ULONG ref = InterlockedDecrement(&This->ref);
5082 TRACE("(%p)->(%u)\n",This, ref);
5086 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5087 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5088 if (not_attached_to_typelib)
5089 HeapFree(GetProcessHeap(), 0, This);
5090 /* otherwise This will be freed when typelib is freed */
5096 /* ITypeInfo::GetTypeAttr
5098 * Retrieves a TYPEATTR structure that contains the attributes of the type
5102 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5103 LPTYPEATTR *ppTypeAttr)
5105 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5108 TRACE("(%p)\n",This);
5110 size = sizeof(**ppTypeAttr);
5111 if (This->TypeAttr.typekind == TKIND_ALIAS)
5112 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5114 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5116 return E_OUTOFMEMORY;
5118 **ppTypeAttr = This->TypeAttr;
5120 if (This->TypeAttr.typekind == TKIND_ALIAS)
5121 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5122 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5124 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5125 /* This should include all the inherited funcs */
5126 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5127 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5128 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5133 /* ITypeInfo::GetTypeComp
5135 * Retrieves the ITypeComp interface for the type description, which enables a
5136 * client compiler to bind to the type description's members.
5139 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5140 ITypeComp * *ppTComp)
5142 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5144 TRACE("(%p)->(%p)\n", This, ppTComp);
5146 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5147 ITypeComp_AddRef(*ppTComp);
5151 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5153 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5154 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5155 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5159 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5162 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5163 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5165 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5166 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5167 *buffer += sizeof(PARAMDESCEX);
5168 *pparamdescex_dest = *pparamdescex_src;
5169 VariantInit(&pparamdescex_dest->varDefaultValue);
5170 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5171 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5174 dest->u.paramdesc.pparamdescex = NULL;
5178 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5180 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5181 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5184 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5188 SIZE_T size = sizeof(*src);
5192 size += sizeof(*src->lprgscode) * src->cScodes;
5193 size += TLB_SizeElemDesc(&src->elemdescFunc);
5194 for (i = 0; i < src->cParams; i++)
5196 size += sizeof(ELEMDESC);
5197 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5200 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5201 if (!dest) return E_OUTOFMEMORY;
5204 if (dispinterface) /* overwrite funckind */
5205 dest->funckind = FUNC_DISPATCH;
5206 buffer = (char *)(dest + 1);
5208 dest->lprgscode = (SCODE *)buffer;
5209 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5210 buffer += sizeof(*src->lprgscode) * src->cScodes;
5212 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5215 SysFreeString((BSTR)dest);
5219 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5220 buffer += sizeof(ELEMDESC) * src->cParams;
5221 for (i = 0; i < src->cParams; i++)
5223 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5229 /* undo the above actions */
5230 for (i = i - 1; i >= 0; i--)
5231 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5232 TLB_FreeElemDesc(&dest->elemdescFunc);
5233 SysFreeString((BSTR)dest);
5237 /* special treatment for dispinterfaces: this makes functions appear
5238 * to return their [retval] value when it is really returning an
5240 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5242 if (dest->cParams &&
5243 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5245 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5246 if (elemdesc->tdesc.vt != VT_PTR)
5248 ERR("elemdesc should have started with VT_PTR instead of:\n");
5250 dump_ELEMDESC(elemdesc);
5251 return E_UNEXPECTED;
5254 /* copy last parameter to the return value. we are using a flat
5255 * buffer so there is no danger of leaking memory in
5257 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5259 /* remove the last parameter */
5263 /* otherwise this function is made to appear to have no return
5265 dest->elemdescFunc.tdesc.vt = VT_VOID;
5273 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5275 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5276 const TLBFuncDesc *pFDesc;
5279 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5284 *ppFuncDesc = &pFDesc->funcdesc;
5288 return TYPE_E_ELEMENTNOTFOUND;
5291 /* internal function to make the inherited interfaces' methods appear
5292 * part of the interface */
5293 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5294 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5296 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5298 UINT implemented_funcs = 0;
5303 *hrefoffset = DISPATCH_HREF_OFFSET;
5305 if(This->impltypelist)
5307 ITypeInfo *pSubTypeInfo;
5310 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5314 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5317 &sub_funcs, hrefoffset);
5318 implemented_funcs += sub_funcs;
5319 ITypeInfo_Release(pSubTypeInfo);
5322 *hrefoffset += DISPATCH_HREF_OFFSET;
5326 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5330 if (index < implemented_funcs)
5331 return E_INVALIDARG;
5332 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5336 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5338 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5341 switch (pTypeDesc->vt)
5343 case VT_USERDEFINED:
5344 pTypeDesc->u.hreftype += hrefoffset;
5348 pTypeDesc = pTypeDesc->u.lptdesc;
5351 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5359 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5362 for (i = 0; i < pFuncDesc->cParams; i++)
5363 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5364 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5367 /* ITypeInfo::GetFuncDesc
5369 * Retrieves the FUNCDESC structure that contains information about a
5370 * specified function.
5373 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5374 LPFUNCDESC *ppFuncDesc)
5376 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5377 const FUNCDESC *internal_funcdesc;
5379 UINT hrefoffset = 0;
5381 TRACE("(%p) index %d\n", This, index);
5383 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5384 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5385 &internal_funcdesc, NULL,
5388 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5389 &internal_funcdesc);
5392 WARN("description for function %d not found\n", index);
5396 hr = TLB_AllocAndInitFuncDesc(
5399 This->TypeAttr.typekind == TKIND_DISPATCH);
5401 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5402 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5404 TRACE("-- 0x%08x\n", hr);
5408 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5412 SIZE_T size = sizeof(*src);
5415 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5416 if (src->varkind == VAR_CONST)
5417 size += sizeof(VARIANT);
5418 size += TLB_SizeElemDesc(&src->elemdescVar);
5420 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5421 if (!dest) return E_OUTOFMEMORY;
5424 buffer = (char *)(dest + 1);
5425 if (src->lpstrSchema)
5428 dest->lpstrSchema = (LPOLESTR)buffer;
5429 len = strlenW(src->lpstrSchema);
5430 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5431 buffer += (len + 1) * sizeof(WCHAR);
5434 if (src->varkind == VAR_CONST)
5438 dest->u.lpvarValue = (VARIANT *)buffer;
5439 *dest->u.lpvarValue = *src->u.lpvarValue;
5440 buffer += sizeof(VARIANT);
5441 VariantInit(dest->u.lpvarValue);
5442 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5445 SysFreeString((BSTR)dest);
5449 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5452 if (src->varkind == VAR_CONST)
5453 VariantClear(dest->u.lpvarValue);
5454 SysFreeString((BSTR)dest);
5461 /* ITypeInfo::GetVarDesc
5463 * Retrieves a VARDESC structure that describes the specified variable.
5466 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5467 LPVARDESC *ppVarDesc)
5469 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5471 const TLBVarDesc *pVDesc;
5473 TRACE("(%p) index %d\n", This, index);
5475 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5479 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5481 return E_INVALIDARG;
5484 /* ITypeInfo_GetNames
5486 * Retrieves the variable with the specified member ID (or the name of the
5487 * property or method and its parameters) that correspond to the specified
5490 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5491 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5493 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5494 const TLBFuncDesc *pFDesc;
5495 const TLBVarDesc *pVDesc;
5497 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5498 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5501 /* function found, now return function and parameter names */
5502 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5505 *rgBstrNames=SysAllocString(pFDesc->Name);
5507 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5513 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5516 *rgBstrNames=SysAllocString(pVDesc->Name);
5521 if(This->impltypelist &&
5522 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5523 /* recursive search */
5526 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5528 if(SUCCEEDED(result))
5530 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5531 ITypeInfo_Release(pTInfo);
5534 WARN("Could not search inherited interface!\n");
5538 WARN("no names found\n");
5541 return TYPE_E_ELEMENTNOTFOUND;
5548 /* ITypeInfo::GetRefTypeOfImplType
5550 * If a type description describes a COM class, it retrieves the type
5551 * description of the implemented interface types. For an interface,
5552 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5556 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5561 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5564 const TLBImplType *pImpl = This->impltypelist;
5566 TRACE("(%p) index %d\n", This, index);
5567 if (TRACE_ON(ole)) dump_TypeInfo(This);
5571 /* only valid on dual interfaces;
5572 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5574 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5576 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5582 hr = TYPE_E_ELEMENTNOTFOUND;
5585 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5587 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5588 *pRefType = This->pTypeLib->dispatch_href;
5592 /* get element n from linked list */
5593 for(i=0; pImpl && i<index; i++)
5595 pImpl = pImpl->next;
5599 *pRefType = pImpl->hRef;
5601 hr = TYPE_E_ELEMENTNOTFOUND;
5607 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5609 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5615 /* ITypeInfo::GetImplTypeFlags
5617 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5618 * or base interface in a type description.
5620 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5621 UINT index, INT *pImplTypeFlags)
5623 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5627 TRACE("(%p) index %d\n", This, index);
5628 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5629 i++, pImpl=pImpl->next)
5631 if(i==index && pImpl){
5632 *pImplTypeFlags=pImpl->implflags;
5637 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5640 WARN("ImplType %d not found\n", index);
5641 return TYPE_E_ELEMENTNOTFOUND;
5645 * Maps between member names and member IDs, and parameter names and
5648 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5649 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5651 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5652 const TLBFuncDesc *pFDesc;
5653 const TLBVarDesc *pVDesc;
5657 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5660 /* init out parameters in case of failure */
5661 for (i = 0; i < cNames; i++)
5662 pMemId[i] = MEMBERID_NIL;
5664 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5666 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5667 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5668 for(i=1; i < cNames; i++){
5669 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5670 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5672 if( j<pFDesc->funcdesc.cParams)
5675 ret=DISP_E_UNKNOWNNAME;
5677 TRACE("-- 0x%08x\n", ret);
5681 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5682 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5683 if(cNames) *pMemId=pVDesc->vardesc.memid;
5687 /* not found, see if it can be found in an inherited interface */
5688 if(This->impltypelist) {
5689 /* recursive search */
5691 ret=ITypeInfo_GetRefTypeInfo(iface,
5692 This->impltypelist->hRef, &pTInfo);
5694 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5695 ITypeInfo_Release(pTInfo);
5698 WARN("Could not search inherited interface!\n");
5700 WARN("no names found\n");
5701 return DISP_E_UNKNOWNNAME;
5707 extern LONGLONG call_method( void *func, int nb_args, const DWORD *args, int *stack_offset );
5708 __ASM_GLOBAL_FUNC( call_method,
5710 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5711 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5712 "movl %esp,%ebp\n\t"
5713 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5715 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5717 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5718 "movl 12(%ebp),%edx\n\t"
5719 "movl %esp,%edi\n\t"
5722 "subl %edx,%edi\n\t"
5723 "andl $~15,%edi\n\t"
5724 "movl %edi,%esp\n\t"
5725 "movl 12(%ebp),%ecx\n\t"
5726 "movl 16(%ebp),%esi\n\t"
5729 "1:\tcall *8(%ebp)\n\t"
5730 "subl %esp,%edi\n\t"
5731 "movl 20(%ebp),%ecx\n\t"
5732 "movl %edi,(%ecx)\n\t"
5733 "leal -8(%ebp),%esp\n\t"
5735 __ASM_CFI(".cfi_same_value %edi\n\t")
5737 __ASM_CFI(".cfi_same_value %esi\n\t")
5739 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5740 __ASM_CFI(".cfi_same_value %ebp\n\t")
5743 /* same function but returning floating point */
5744 static double (* const call_double_method)(void*,int,const DWORD*,int*) = (void *)call_method;
5746 /* ITypeInfo::Invoke
5748 * Invokes a method, or accesses a property of an object, that implements the
5749 * interface described by the type description.
5752 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5756 if (TRACE_ON(ole)) {
5758 TRACE("Calling %p(",func);
5759 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5760 if (nrargs > 30) TRACE("...");
5767 res = call_method( func, nrargs, args, &stack_offset );
5770 FIXME("unsupported calling convention %d\n",callconv);
5774 TRACE("returns %08x\n",res);
5778 #elif defined(__x86_64__)
5780 extern DWORD_PTR CDECL call_method( void *func, int nb_args, const DWORD_PTR *args );
5781 __ASM_GLOBAL_FUNC( call_method,
5783 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5784 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5785 "movq %rsp,%rbp\n\t"
5786 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5788 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5790 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5791 "movq %rcx,%rax\n\t"
5794 "cmovgq %rdx,%rcx\n\t"
5795 "leaq 0(,%rcx,8),%rdx\n\t"
5796 "subq %rdx,%rsp\n\t"
5797 "andq $~15,%rsp\n\t"
5798 "movq %rsp,%rdi\n\t"
5801 "movq 0(%rsp),%rcx\n\t"
5802 "movq 8(%rsp),%rdx\n\t"
5803 "movq 16(%rsp),%r8\n\t"
5804 "movq 24(%rsp),%r9\n\t"
5805 "movq %rcx,%xmm0\n\t"
5806 "movq %rdx,%xmm1\n\t"
5807 "movq %r8,%xmm2\n\t"
5808 "movq %r9,%xmm3\n\t"
5810 "leaq -16(%rbp),%rsp\n\t"
5812 __ASM_CFI(".cfi_same_value %rdi\n\t")
5814 __ASM_CFI(".cfi_same_value %rsi\n\t")
5815 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5817 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5818 __ASM_CFI(".cfi_same_value %rbp\n\t")
5821 /* same function but returning floating point */
5822 static double (CDECL * const call_double_method)(void*,int,const DWORD_PTR*) = (void *)call_method;
5824 #endif /* __x86_64__ */
5826 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5829 ITypeInfo *tinfo2 = NULL;
5830 TYPEATTR *tattr = NULL;
5832 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5835 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5837 tdesc->u.hreftype, hr);
5840 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5843 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5844 ITypeInfo_Release(tinfo2);
5848 switch (tattr->typekind)
5855 tdesc = &tattr->tdescAlias;
5856 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5859 case TKIND_INTERFACE:
5860 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5866 case TKIND_DISPATCH:
5875 FIXME("TKIND_RECORD unhandled.\n");
5880 FIXME("TKIND_UNION unhandled.\n");
5885 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5889 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5890 ITypeInfo_Release(tinfo2);
5894 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5898 /* enforce only one level of pointer indirection */
5899 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5901 tdesc = tdesc->u.lptdesc;
5903 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5904 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5905 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5906 if ((tdesc->vt == VT_USERDEFINED) ||
5907 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5909 VARTYPE vt_userdefined = 0;
5910 const TYPEDESC *tdesc_userdefined = tdesc;
5911 if (tdesc->vt == VT_PTR)
5913 vt_userdefined = VT_BYREF;
5914 tdesc_userdefined = tdesc->u.lptdesc;
5916 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5918 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5919 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5921 *vt |= vt_userdefined;
5933 case VT_USERDEFINED:
5934 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5941 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5942 hr = DISP_E_BADVARTYPE;
5946 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5961 /***********************************************************************
5962 * DispCallFunc (OLEAUT32.@)
5964 * Invokes a function of the specified calling convention, passing the
5965 * specified arguments and returns the result.
5968 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5969 * oVft [I] The offset in the vtable. See notes.
5970 * cc [I] Calling convention of the function to call.
5971 * vtReturn [I] The return type of the function.
5972 * cActuals [I] Number of parameters.
5973 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5974 * prgpvarg [I] The arguments to pass.
5975 * pvargResult [O] The return value of the function. Can be NULL.
5979 * Failure: HRESULT code.
5982 * The HRESULT return value of this function is not affected by the return
5983 * value of the user supplied function, which is returned in pvargResult.
5985 * If pvInstance is NULL then a non-object function is to be called and oVft
5986 * is the address of the function to call.
5988 * The cc parameter can be one of the following values:
6001 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
6002 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
6005 int argspos, stack_offset;
6010 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6011 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6012 pvargResult, V_VT(pvargResult));
6014 if (cc != CC_STDCALL && cc != CC_CDECL)
6016 FIXME("unsupported calling convention %d\n",cc);
6017 return E_INVALIDARG;
6020 /* maximum size for an argument is sizeof(VARIANT) */
6021 args = HeapAlloc( GetProcessHeap(), 0, sizeof(VARIANT) * cActuals + sizeof(DWORD) * 2 );
6023 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6027 const FARPROC *vtable = *(FARPROC **)pvInstance;
6028 func = vtable[oVft/sizeof(void *)];
6029 args[argspos++] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6031 else func = (void *)oVft;
6033 for (i = 0; i < cActuals; i++)
6035 VARIANT *arg = prgpvarg[i];
6046 memcpy( &args[argspos], &V_I8(arg), sizeof(V_I8(arg)) );
6047 argspos += sizeof(V_I8(arg)) / sizeof(DWORD);
6051 memcpy( &args[argspos], arg, sizeof(*arg) );
6052 argspos += sizeof(*arg) / sizeof(DWORD);
6054 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6055 args[argspos++] = V_BOOL(arg);
6058 args[argspos++] = V_UI4(arg);
6061 TRACE("arg %u: type %d\n",i,prgvt[i]);
6068 call_method( func, argspos - 1, args + 1, &stack_offset );
6071 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6075 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1, &stack_offset );
6079 args[0] = (DWORD)pvargResult; /* arg 0 is a pointer to the result */
6080 call_method( func, argspos, args, &stack_offset );
6085 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6088 V_UI4(pvargResult) = call_method( func, argspos - 1, args + 1, &stack_offset );
6091 HeapFree( GetProcessHeap(), 0, args );
6092 if (stack_offset && cc == CC_STDCALL)
6094 WARN( "stack pointer off by %d\n", stack_offset );
6095 return DISP_E_BADCALLEE;
6097 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6098 TRACE("retval: "); dump_Variant(pvargResult);
6101 #elif defined(__x86_64__)
6107 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6108 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
6109 pvargResult, V_VT(pvargResult));
6111 if (cc != CC_STDCALL && cc != CC_CDECL)
6113 FIXME("unsupported calling convention %d\n",cc);
6114 return E_INVALIDARG;
6117 /* maximum size for an argument is sizeof(DWORD_PTR) */
6118 args = HeapAlloc( GetProcessHeap(), 0, sizeof(DWORD_PTR) * (cActuals + 2) );
6120 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6124 const FARPROC *vtable = *(FARPROC **)pvInstance;
6125 func = vtable[oVft/sizeof(void *)];
6126 args[argspos++] = (DWORD_PTR)pvInstance; /* the This pointer is always the first parameter */
6128 else func = (void *)oVft;
6130 for (i = 0; i < cActuals; i++)
6132 VARIANT *arg = prgpvarg[i];
6138 args[argspos++] = (ULONG_PTR)arg;
6140 case VT_BOOL: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6141 args[argspos++] = V_BOOL(arg);
6144 args[argspos++] = V_UI8(arg);
6147 TRACE("arg %u: type %d\n",i,prgvt[i]);
6154 V_R4(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6158 V_R8(pvargResult) = call_double_method( func, argspos - 1, args + 1 );
6162 args[0] = (DWORD_PTR)pvargResult; /* arg 0 is a pointer to the result */
6163 call_method( func, argspos, args );
6166 V_UI8(pvargResult) = call_method( func, argspos - 1, args + 1 );
6169 HeapFree( GetProcessHeap(), 0, args );
6170 if (vtReturn != VT_VARIANT) V_VT(pvargResult) = vtReturn;
6171 TRACE("retval: "); dump_Variant(pvargResult);
6175 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6176 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6181 #define INVBUF_ELEMENT_SIZE \
6182 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6183 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6184 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6185 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6186 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6187 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6188 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6189 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6191 static HRESULT WINAPI ITypeInfo_fnInvoke(
6196 DISPPARAMS *pDispParams,
6197 VARIANT *pVarResult,
6198 EXCEPINFO *pExcepInfo,
6201 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6203 unsigned int var_index;
6206 const TLBFuncDesc *pFuncInfo;
6208 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6209 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6212 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6213 return DISP_E_MEMBERNOTFOUND;
6217 ERR("NULL pDispParams not allowed\n");
6218 return E_INVALIDARG;
6221 dump_DispParms(pDispParams);
6223 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6225 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6226 pDispParams->cNamedArgs, pDispParams->cArgs);
6227 return E_INVALIDARG;
6230 /* we do this instead of using GetFuncDesc since it will return a fake
6231 * FUNCDESC for dispinterfaces and we want the real function description */
6232 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6233 if ((memid == pFuncInfo->funcdesc.memid) &&
6234 (wFlags & pFuncInfo->funcdesc.invkind) &&
6235 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6239 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6243 TRACE("invoking:\n");
6244 dump_TLBFuncDescOne(pFuncInfo);
6247 switch (func_desc->funckind) {
6248 case FUNC_PUREVIRTUAL:
6249 case FUNC_VIRTUAL: {
6250 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6252 VARIANT retval; /* pointer for storing byref retvals in */
6253 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6254 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6255 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6256 UINT cNamedArgs = pDispParams->cNamedArgs;
6257 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6258 UINT vargs_converted=0;
6262 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6264 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6266 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6267 hres = DISP_E_PARAMNOTFOUND;
6272 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6274 ERR("functions with the vararg attribute do not support named arguments\n");
6275 hres = DISP_E_NONAMEDARGS;
6279 for (i = 0; i < func_desc->cParams; i++)
6281 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6282 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6287 TRACE("changing args\n");
6288 for (i = 0; i < func_desc->cParams; i++)
6290 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6291 VARIANTARG *src_arg;
6293 if (wParamFlags & PARAMFLAG_FLCID)
6296 arg = prgpvarg[i] = &rgvarg[i];
6298 V_I4(arg) = This->pTypeLib->lcid;
6307 for (j = 0; j < cNamedArgs; j++)
6308 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6310 src_arg = &pDispParams->rgvarg[j];
6315 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6317 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6321 if (wParamFlags & PARAMFLAG_FRETVAL)
6323 /* under most conditions the caller is not allowed to
6324 * pass in a dispparam arg in the index of what would be
6325 * the retval parameter. however, there is an exception
6326 * where the extra parameter is used in an extra
6327 * IDispatch::Invoke below */
6328 if ((i < pDispParams->cArgs) &&
6329 ((func_desc->cParams != 1) || !pVarResult ||
6330 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6332 hres = DISP_E_BADPARAMCOUNT;
6336 /* note: this check is placed so that if the caller passes
6337 * in a VARIANTARG for the retval we just ignore it, like
6339 if (i == func_desc->cParams - 1)
6342 arg = prgpvarg[i] = &rgvarg[i];
6343 memset(arg, 0, sizeof(*arg));
6344 V_VT(arg) = rgvt[i];
6345 memset(&retval, 0, sizeof(retval));
6346 V_BYREF(arg) = &retval;
6350 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6351 hres = E_UNEXPECTED;
6357 dump_Variant(src_arg);
6359 if (rgvt[i] == VT_VARIANT)
6360 hres = VariantCopy(&rgvarg[i], src_arg);
6361 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6363 if (rgvt[i] == V_VT(src_arg))
6364 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6367 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6368 if (wParamFlags & PARAMFLAG_FIN)
6369 hres = VariantCopy(&missing_arg[i], src_arg);
6370 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6372 V_VT(&rgvarg[i]) = rgvt[i];
6374 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6377 SAFEARRAYBOUND bound;
6381 bound.cElements = pDispParams->cArgs-i;
6382 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6384 ERR("SafeArrayCreate failed\n");
6387 hres = SafeArrayAccessData(a, (LPVOID)&v);
6390 ERR("SafeArrayAccessData failed with %x\n", hres);
6393 for (j = 0; j < bound.cElements; j++)
6394 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6395 hres = SafeArrayUnaccessData(a);
6398 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6401 V_ARRAY(&rgvarg[i]) = a;
6402 V_VT(&rgvarg[i]) = rgvt[i];
6404 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6406 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6407 if (wParamFlags & PARAMFLAG_FIN)
6408 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6410 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6411 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6412 V_VT(&rgvarg[i]) = rgvt[i];
6414 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6416 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6417 V_VT(&rgvarg[i]) = rgvt[i];
6421 /* FIXME: this doesn't work for VT_BYREF arguments if
6422 * they are not the same type as in the paramdesc */
6423 V_VT(&rgvarg[i]) = V_VT(src_arg);
6424 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6425 V_VT(&rgvarg[i]) = rgvt[i];
6430 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6431 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6432 debugstr_VT(src_arg), debugstr_VF(src_arg));
6435 prgpvarg[i] = &rgvarg[i];
6437 else if (wParamFlags & PARAMFLAG_FOPT)
6440 arg = prgpvarg[i] = &rgvarg[i];
6441 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6443 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6449 VARIANTARG *missing_arg;
6450 /* if the function wants a pointer to a variant then
6451 * set that up, otherwise just pass the VT_ERROR in
6452 * the argument by value */
6453 if (rgvt[i] & VT_BYREF)
6455 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6456 V_VT(arg) = VT_VARIANT | VT_BYREF;
6457 V_VARIANTREF(arg) = missing_arg;
6461 V_VT(missing_arg) = VT_ERROR;
6462 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6467 hres = DISP_E_BADPARAMCOUNT;
6471 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6473 /* VT_VOID is a special case for return types, so it is not
6474 * handled in the general function */
6475 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6476 V_VT(&varresult) = VT_EMPTY;
6479 V_VT(&varresult) = 0;
6480 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6481 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6484 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6485 V_VT(&varresult), func_desc->cParams, rgvt,
6486 prgpvarg, &varresult);
6488 vargs_converted = 0;
6490 for (i = 0; i < func_desc->cParams; i++)
6492 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6493 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6495 if (wParamFlags & PARAMFLAG_FLCID)
6497 else if (wParamFlags & PARAMFLAG_FRETVAL)
6501 TRACE("[retval] value: ");
6502 dump_Variant(prgpvarg[i]);
6507 VariantInit(pVarResult);
6508 /* deref return value */
6509 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6512 VARIANT_ClearInd(prgpvarg[i]);
6514 else if (vargs_converted < pDispParams->cArgs)
6516 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6517 if (wParamFlags & PARAMFLAG_FOUT)
6519 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6521 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6525 ERR("failed to convert param %d to vt %d\n", i,
6526 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6531 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6532 func_desc->cParamsOpt < 0 &&
6533 i == func_desc->cParams-1)
6535 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6538 hres = SafeArrayGetUBound(a, 1, &ubound);
6541 ERR("SafeArrayGetUBound failed with %x\n", hres);
6544 hres = SafeArrayAccessData(a, (LPVOID)&v);
6547 ERR("SafeArrayAccessData failed with %x\n", hres);
6550 for (j = 0; j <= ubound; j++)
6551 VariantClear(&v[j]);
6552 hres = SafeArrayUnaccessData(a);
6555 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6559 VariantClear(&rgvarg[i]);
6562 else if (wParamFlags & PARAMFLAG_FOPT)
6564 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6565 VariantClear(&rgvarg[i]);
6568 VariantClear(&missing_arg[i]);
6571 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6573 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6574 hres = DISP_E_EXCEPTION;
6577 IErrorInfo *pErrorInfo;
6578 pExcepInfo->scode = V_ERROR(&varresult);
6579 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6581 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6582 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6583 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6584 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6586 IErrorInfo_Release(pErrorInfo);
6590 if (V_VT(&varresult) != VT_ERROR)
6592 TRACE("varresult value: ");
6593 dump_Variant(&varresult);
6597 VariantClear(pVarResult);
6598 *pVarResult = varresult;
6601 VariantClear(&varresult);
6604 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6605 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6606 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6607 (pDispParams->cArgs != 0))
6609 if (V_VT(pVarResult) == VT_DISPATCH)
6611 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6612 /* Note: not VariantClear; we still need the dispatch
6613 * pointer to be valid */
6614 VariantInit(pVarResult);
6615 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6616 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6617 pDispParams, pVarResult, pExcepInfo, pArgErr);
6618 IDispatch_Release(pDispatch);
6622 VariantClear(pVarResult);
6623 hres = DISP_E_NOTACOLLECTION;
6628 HeapFree(GetProcessHeap(), 0, buffer);
6631 case FUNC_DISPATCH: {
6634 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6635 if (SUCCEEDED(hres)) {
6636 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6637 hres = IDispatch_Invoke(
6638 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6639 pVarResult,pExcepInfo,pArgErr
6642 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6643 IDispatch_Release(disp);
6645 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6649 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6654 TRACE("-- 0x%08x\n", hres);
6657 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6660 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6661 if(FAILED(hres)) return hres;
6663 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6664 dump_VARDESC(var_desc);
6665 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6669 /* not found, look for it in inherited interfaces */
6670 ITypeInfo2_GetTypeKind(iface, &type_kind);
6671 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6672 if(This->impltypelist) {
6673 /* recursive search */
6675 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6676 if(SUCCEEDED(hres)){
6677 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6678 ITypeInfo_Release(pTInfo);
6681 WARN("Could not search inherited interface!\n");
6684 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6685 return DISP_E_MEMBERNOTFOUND;
6688 /* ITypeInfo::GetDocumentation
6690 * Retrieves the documentation string, the complete Help file name and path,
6691 * and the context ID for the Help topic for a specified type description.
6693 * (Can be tested by the Visual Basic Editor in Word for instance.)
6695 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6696 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6697 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6699 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6700 const TLBFuncDesc *pFDesc;
6701 const TLBVarDesc *pVDesc;
6702 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6703 " HelpContext(%p) HelpFile(%p)\n",
6704 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6705 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6707 *pBstrName=SysAllocString(This->Name);
6709 *pBstrDocString=SysAllocString(This->DocString);
6711 *pdwHelpContext=This->dwHelpContext;
6713 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6715 }else {/* for a member */
6716 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6717 if(pFDesc->funcdesc.memid==memid){
6719 *pBstrName = SysAllocString(pFDesc->Name);
6721 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6723 *pdwHelpContext=pFDesc->helpcontext;
6726 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6727 if(pVDesc->vardesc.memid==memid){
6729 *pBstrName = SysAllocString(pVDesc->Name);
6731 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6733 *pdwHelpContext=pVDesc->HelpContext;
6738 if(This->impltypelist &&
6739 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6740 /* recursive search */
6743 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6745 if(SUCCEEDED(result)) {
6746 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6747 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6748 ITypeInfo_Release(pTInfo);
6751 WARN("Could not search inherited interface!\n");
6754 WARN("member %d not found\n", memid);
6755 return TYPE_E_ELEMENTNOTFOUND;
6758 /* ITypeInfo::GetDllEntry
6760 * Retrieves a description or specification of an entry point for a function
6763 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6764 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6767 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6768 const TLBFuncDesc *pFDesc;
6770 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6772 if (pBstrDllName) *pBstrDllName = NULL;
6773 if (pBstrName) *pBstrName = NULL;
6774 if (pwOrdinal) *pwOrdinal = 0;
6776 if (This->TypeAttr.typekind != TKIND_MODULE)
6777 return TYPE_E_BADMODULEKIND;
6779 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6780 if(pFDesc->funcdesc.memid==memid){
6781 dump_TypeInfo(This);
6783 dump_TLBFuncDescOne(pFDesc);
6786 *pBstrDllName = SysAllocString(This->DllName);
6788 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6790 *pBstrName = SysAllocString(pFDesc->Entry);
6798 *pwOrdinal = LOWORD(pFDesc->Entry);
6801 return TYPE_E_ELEMENTNOTFOUND;
6804 /* internal function to make the inherited interfaces' methods appear
6805 * part of the interface */
6806 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6807 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6809 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6812 TRACE("%p, 0x%x\n", iface, *hRefType);
6814 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6816 ITypeInfo *pSubTypeInfo;
6818 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6822 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6824 ITypeInfo_Release(pSubTypeInfo);
6828 *hRefType -= DISPATCH_HREF_OFFSET;
6830 if (!(*hRefType & DISPATCH_HREF_MASK))
6831 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6836 /* ITypeInfo::GetRefTypeInfo
6838 * If a type description references other type descriptions, it retrieves
6839 * the referenced type descriptions.
6841 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6844 ITypeInfo **ppTInfo)
6846 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6847 HRESULT result = E_FAIL;
6849 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6851 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6852 ITypeInfo_AddRef(*ppTInfo);
6855 else if (hRefType == -1 &&
6856 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6857 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6859 /* when we meet a DUAL dispinterface, we must create the interface
6862 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6865 /* the interface version contains the same information as the dispinterface
6866 * copy the contents of the structs.
6868 *pTypeInfoImpl = *This;
6869 pTypeInfoImpl->ref = 0;
6871 /* change the type to interface */
6872 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6874 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6876 /* the AddRef implicitly adds a reference to the parent typelib, which
6877 * stops the copied data from being destroyed until the new typeinfo's
6878 * refcount goes to zero, but we need to signal to the new instance to
6879 * not free its data structures when it is destroyed */
6880 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6882 ITypeInfo_AddRef(*ppTInfo);
6886 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6887 (This->TypeAttr.typekind == TKIND_DISPATCH))
6889 HREFTYPE href_dispatch = hRefType;
6890 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6892 TLBRefType *ref_type;
6893 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6895 if(ref_type->reference == hRefType)
6898 if(&ref_type->entry == &This->pTypeLib->ref_list)
6900 FIXME("Can't find pRefType for ref %x\n", hRefType);
6903 if(hRefType != -1) {
6904 ITypeLib *pTLib = NULL;
6906 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6908 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6910 if(ref_type->pImpTLInfo->pImpTypeLib) {
6911 TRACE("typeinfo in imported typelib that is already loaded\n");
6912 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6913 ITypeLib2_AddRef(pTLib);
6916 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6917 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6918 ref_type->pImpTLInfo->wVersionMajor,
6919 ref_type->pImpTLInfo->wVersionMinor,
6920 ref_type->pImpTLInfo->lcid,
6923 if(FAILED(result)) {
6924 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6925 result=LoadTypeLib(libnam, &pTLib);
6926 SysFreeString(libnam);
6928 if(SUCCEEDED(result)) {
6929 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6930 ITypeLib2_AddRef(pTLib);
6934 if(SUCCEEDED(result)) {
6935 if(ref_type->index == TLB_REF_USE_GUID)
6936 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6940 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6944 ITypeLib2_Release(pTLib);
6949 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6950 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6954 /* ITypeInfo::AddressOfMember
6956 * Retrieves the addresses of static functions or variables, such as those
6959 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6960 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6962 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6968 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6970 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6974 module = LoadLibraryW(dll);
6977 ERR("couldn't load %s\n", debugstr_w(dll));
6979 SysFreeString(entry);
6980 return STG_E_FILENOTFOUND;
6982 /* FIXME: store library somewhere where we can free it */
6987 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6988 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6989 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6991 *ppv = GetProcAddress(module, entryA);
6993 ERR("function not found %s\n", debugstr_a(entryA));
6995 HeapFree(GetProcessHeap(), 0, entryA);
6999 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
7001 ERR("function not found %d\n", ordinal);
7005 SysFreeString(entry);
7008 return TYPE_E_DLLFUNCTIONNOTFOUND;
7013 /* ITypeInfo::CreateInstance
7015 * Creates a new instance of a type that describes a component object class
7018 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
7019 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
7021 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7025 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
7031 WARN("Not able to aggregate\n");
7032 return CLASS_E_NOAGGREGATION;
7035 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
7036 if(FAILED(hr)) return hr;
7038 if(pTA->typekind != TKIND_COCLASS)
7040 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
7046 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
7049 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
7050 TRACE("GetActiveObject rets %08x\n", hr);
7053 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
7054 IUnknown_Release(pUnk);
7059 hr = CoCreateInstance(&pTA->guid, NULL,
7060 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
7064 ITypeInfo_ReleaseTypeAttr(iface, pTA);
7068 /* ITypeInfo::GetMops
7070 * Retrieves marshalling information.
7072 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
7075 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7076 FIXME("(%p %d) stub!\n", This, memid);
7081 /* ITypeInfo::GetContainingTypeLib
7083 * Retrieves the containing type library and the index of the type description
7084 * within that type library.
7086 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
7087 ITypeLib * *ppTLib, UINT *pIndex)
7089 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7091 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7093 *pIndex=This->index;
7094 TRACE("returning pIndex=%d\n", *pIndex);
7098 *ppTLib=(LPTYPELIB )(This->pTypeLib);
7099 ITypeLib2_AddRef(*ppTLib);
7100 TRACE("returning ppTLib=%p\n", *ppTLib);
7106 /* ITypeInfo::ReleaseTypeAttr
7108 * Releases a TYPEATTR previously returned by GetTypeAttr.
7111 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
7112 TYPEATTR* pTypeAttr)
7114 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7115 TRACE("(%p)->(%p)\n", This, pTypeAttr);
7116 HeapFree(GetProcessHeap(), 0, pTypeAttr);
7119 /* ITypeInfo::ReleaseFuncDesc
7121 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7123 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
7125 FUNCDESC *pFuncDesc)
7127 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7130 TRACE("(%p)->(%p)\n", This, pFuncDesc);
7132 for (i = 0; i < pFuncDesc->cParams; i++)
7133 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
7134 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
7136 SysFreeString((BSTR)pFuncDesc);
7139 /* ITypeInfo::ReleaseVarDesc
7141 * Releases a VARDESC previously returned by GetVarDesc.
7143 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7146 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7147 TRACE("(%p)->(%p)\n", This, pVarDesc);
7149 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7150 if (pVarDesc->varkind == VAR_CONST)
7151 VariantClear(pVarDesc->u.lpvarValue);
7152 SysFreeString((BSTR)pVarDesc);
7155 /* ITypeInfo2::GetTypeKind
7157 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7160 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7161 TYPEKIND *pTypeKind)
7163 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7164 *pTypeKind=This->TypeAttr.typekind;
7165 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7169 /* ITypeInfo2::GetTypeFlags
7171 * Returns the type flags without any allocations. This returns a DWORD type
7172 * flag, which expands the type flags without growing the TYPEATTR (type
7176 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7178 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7179 *pTypeFlags=This->TypeAttr.wTypeFlags;
7180 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7184 /* ITypeInfo2::GetFuncIndexOfMemId
7185 * Binds to a specific member based on a known DISPID, where the member name
7186 * is not known (for example, when binding to a default member).
7189 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7190 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7192 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7193 const TLBFuncDesc *pFuncInfo;
7197 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7198 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7204 result = TYPE_E_ELEMENTNOTFOUND;
7206 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7207 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7211 /* TypeInfo2::GetVarIndexOfMemId
7213 * Binds to a specific member based on a known DISPID, where the member name
7214 * is not known (for example, when binding to a default member).
7217 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7218 MEMBERID memid, UINT *pVarIndex)
7220 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7221 TLBVarDesc *pVarInfo;
7224 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7225 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7231 result = TYPE_E_ELEMENTNOTFOUND;
7233 TRACE("(%p) memid 0x%08x -> %s\n", This,
7234 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7238 /* ITypeInfo2::GetCustData
7240 * Gets the custom data
7242 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7247 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7248 TLBCustData *pCData;
7250 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7251 if( IsEqualIID(guid, &pCData->guid)) break;
7253 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7255 VariantInit( pVarVal);
7257 VariantCopy( pVarVal, &pCData->data);
7259 VariantClear( pVarVal );
7263 /* ITypeInfo2::GetFuncCustData
7265 * Gets the custom data
7267 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7273 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7274 TLBCustData *pCData=NULL;
7275 TLBFuncDesc * pFDesc;
7277 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7278 pFDesc=pFDesc->next);
7281 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7282 if( IsEqualIID(guid, &pCData->guid)) break;
7284 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7287 VariantInit( pVarVal);
7288 VariantCopy( pVarVal, &pCData->data);
7291 return E_INVALIDARG; /* FIXME: correct? */
7294 /* ITypeInfo2::GetParamCustData
7296 * Gets the custom data
7298 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7305 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7306 TLBCustData *pCData=NULL;
7307 TLBFuncDesc * pFDesc;
7310 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7312 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7313 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7314 pCData = pCData->next)
7315 if( IsEqualIID(guid, &pCData->guid)) break;
7317 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7321 VariantInit( pVarVal);
7322 VariantCopy( pVarVal, &pCData->data);
7325 return E_INVALIDARG; /* FIXME: correct? */
7328 /* ITypeInfo2::GetVarCustData
7330 * Gets the custom data
7332 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7338 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7339 TLBCustData *pCData=NULL;
7340 TLBVarDesc * pVDesc;
7343 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7347 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7349 if( IsEqualIID(guid, &pCData->guid)) break;
7353 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7357 VariantInit( pVarVal);
7358 VariantCopy( pVarVal, &pCData->data);
7361 return E_INVALIDARG; /* FIXME: correct? */
7364 /* ITypeInfo2::GetImplCustData
7366 * Gets the custom data
7368 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7374 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7375 TLBCustData *pCData=NULL;
7376 TLBImplType * pRDesc;
7379 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7383 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7385 if( IsEqualIID(guid, &pCData->guid)) break;
7389 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7393 VariantInit( pVarVal);
7394 VariantCopy( pVarVal, &pCData->data);
7397 return E_INVALIDARG; /* FIXME: correct? */
7400 /* ITypeInfo2::GetDocumentation2
7402 * Retrieves the documentation string, the complete Help file name and path,
7403 * the localization context to use, and the context ID for the library Help
7404 * topic in the Help file.
7407 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7411 BSTR *pbstrHelpString,
7412 DWORD *pdwHelpStringContext,
7413 BSTR *pbstrHelpStringDll)
7415 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7416 const TLBFuncDesc *pFDesc;
7417 const TLBVarDesc *pVDesc;
7418 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7419 "HelpStringContext(%p) HelpStringDll(%p)\n",
7420 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7421 pbstrHelpStringDll );
7422 /* the help string should be obtained from the helpstringdll,
7423 * using the _DLLGetDocumentation function, based on the supplied
7424 * lcid. Nice to do sometime...
7426 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7428 *pbstrHelpString=SysAllocString(This->Name);
7429 if(pdwHelpStringContext)
7430 *pdwHelpStringContext=This->dwHelpStringContext;
7431 if(pbstrHelpStringDll)
7432 *pbstrHelpStringDll=
7433 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7435 }else {/* for a member */
7436 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7437 if(pFDesc->funcdesc.memid==memid){
7439 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7440 if(pdwHelpStringContext)
7441 *pdwHelpStringContext=pFDesc->HelpStringContext;
7442 if(pbstrHelpStringDll)
7443 *pbstrHelpStringDll=
7444 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7447 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7448 if(pVDesc->vardesc.memid==memid){
7450 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7451 if(pdwHelpStringContext)
7452 *pdwHelpStringContext=pVDesc->HelpStringContext;
7453 if(pbstrHelpStringDll)
7454 *pbstrHelpStringDll=
7455 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7459 return TYPE_E_ELEMENTNOTFOUND;
7462 /* ITypeInfo2::GetAllCustData
7464 * Gets all custom data items for the Type info.
7467 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7469 CUSTDATA *pCustData)
7471 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7472 TLBCustData *pCData;
7475 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7477 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7478 if(pCustData->prgCustData ){
7479 pCustData->cCustData=This->ctCustData;
7480 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7481 pCustData->prgCustData[i].guid=pCData->guid;
7482 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7485 ERR(" OUT OF MEMORY!\n");
7486 return E_OUTOFMEMORY;
7491 /* ITypeInfo2::GetAllFuncCustData
7493 * Gets all custom data items for the specified Function
7496 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7499 CUSTDATA *pCustData)
7501 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7502 TLBCustData *pCData;
7503 TLBFuncDesc * pFDesc;
7505 TRACE("(%p) index %d\n", This, index);
7506 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7507 pFDesc=pFDesc->next)
7510 pCustData->prgCustData =
7511 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7512 if(pCustData->prgCustData ){
7513 pCustData->cCustData=pFDesc->ctCustData;
7514 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7515 pCData = pCData->next){
7516 pCustData->prgCustData[i].guid=pCData->guid;
7517 VariantCopy(& pCustData->prgCustData[i].varValue,
7521 ERR(" OUT OF MEMORY!\n");
7522 return E_OUTOFMEMORY;
7526 return TYPE_E_ELEMENTNOTFOUND;
7529 /* ITypeInfo2::GetAllParamCustData
7531 * Gets all custom data items for the Functions
7534 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7535 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7537 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7538 TLBCustData *pCData=NULL;
7539 TLBFuncDesc * pFDesc;
7541 TRACE("(%p) index %d\n", This, indexFunc);
7542 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7543 pFDesc=pFDesc->next)
7545 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7546 pCustData->prgCustData =
7547 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7548 sizeof(CUSTDATAITEM));
7549 if(pCustData->prgCustData ){
7550 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7551 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7552 pCData; i++, pCData = pCData->next){
7553 pCustData->prgCustData[i].guid=pCData->guid;
7554 VariantCopy(& pCustData->prgCustData[i].varValue,
7558 ERR(" OUT OF MEMORY!\n");
7559 return E_OUTOFMEMORY;
7563 return TYPE_E_ELEMENTNOTFOUND;
7566 /* ITypeInfo2::GetAllVarCustData
7568 * Gets all custom data items for the specified Variable
7571 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7572 UINT index, CUSTDATA *pCustData)
7574 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7575 TLBCustData *pCData;
7576 TLBVarDesc * pVDesc;
7578 TRACE("(%p) index %d\n", This, index);
7579 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7580 pVDesc=pVDesc->next)
7583 pCustData->prgCustData =
7584 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7585 if(pCustData->prgCustData ){
7586 pCustData->cCustData=pVDesc->ctCustData;
7587 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7588 pCData = pCData->next){
7589 pCustData->prgCustData[i].guid=pCData->guid;
7590 VariantCopy(& pCustData->prgCustData[i].varValue,
7594 ERR(" OUT OF MEMORY!\n");
7595 return E_OUTOFMEMORY;
7599 return TYPE_E_ELEMENTNOTFOUND;
7602 /* ITypeInfo2::GetAllImplCustData
7604 * Gets all custom data items for the specified implementation type
7607 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7610 CUSTDATA *pCustData)
7612 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7613 TLBCustData *pCData;
7614 TLBImplType * pRDesc;
7616 TRACE("(%p) index %d\n", This, index);
7617 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7618 pRDesc=pRDesc->next)
7621 pCustData->prgCustData =
7622 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7623 if(pCustData->prgCustData ){
7624 pCustData->cCustData=pRDesc->ctCustData;
7625 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7626 pCData = pCData->next){
7627 pCustData->prgCustData[i].guid=pCData->guid;
7628 VariantCopy(& pCustData->prgCustData[i].varValue,
7632 ERR(" OUT OF MEMORY!\n");
7633 return E_OUTOFMEMORY;
7637 return TYPE_E_ELEMENTNOTFOUND;
7640 static const ITypeInfo2Vtbl tinfvt =
7643 ITypeInfo_fnQueryInterface,
7645 ITypeInfo_fnRelease,
7647 ITypeInfo_fnGetTypeAttr,
7648 ITypeInfo_fnGetTypeComp,
7649 ITypeInfo_fnGetFuncDesc,
7650 ITypeInfo_fnGetVarDesc,
7651 ITypeInfo_fnGetNames,
7652 ITypeInfo_fnGetRefTypeOfImplType,
7653 ITypeInfo_fnGetImplTypeFlags,
7654 ITypeInfo_fnGetIDsOfNames,
7656 ITypeInfo_fnGetDocumentation,
7657 ITypeInfo_fnGetDllEntry,
7658 ITypeInfo_fnGetRefTypeInfo,
7659 ITypeInfo_fnAddressOfMember,
7660 ITypeInfo_fnCreateInstance,
7661 ITypeInfo_fnGetMops,
7662 ITypeInfo_fnGetContainingTypeLib,
7663 ITypeInfo_fnReleaseTypeAttr,
7664 ITypeInfo_fnReleaseFuncDesc,
7665 ITypeInfo_fnReleaseVarDesc,
7667 ITypeInfo2_fnGetTypeKind,
7668 ITypeInfo2_fnGetTypeFlags,
7669 ITypeInfo2_fnGetFuncIndexOfMemId,
7670 ITypeInfo2_fnGetVarIndexOfMemId,
7671 ITypeInfo2_fnGetCustData,
7672 ITypeInfo2_fnGetFuncCustData,
7673 ITypeInfo2_fnGetParamCustData,
7674 ITypeInfo2_fnGetVarCustData,
7675 ITypeInfo2_fnGetImplTypeCustData,
7676 ITypeInfo2_fnGetDocumentation2,
7677 ITypeInfo2_fnGetAllCustData,
7678 ITypeInfo2_fnGetAllFuncCustData,
7679 ITypeInfo2_fnGetAllParamCustData,
7680 ITypeInfo2_fnGetAllVarCustData,
7681 ITypeInfo2_fnGetAllImplTypeCustData,
7684 /******************************************************************************
7685 * CreateDispTypeInfo [OLEAUT32.31]
7687 * Build type information for an object so it can be called through an
7688 * IDispatch interface.
7691 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7692 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7695 * This call allows an objects methods to be accessed through IDispatch, by
7696 * building an ITypeInfo object that IDispatch can use to call through.
7698 HRESULT WINAPI CreateDispTypeInfo(
7699 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7700 LCID lcid, /* [I] Locale Id */
7701 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7703 ITypeInfoImpl *pTIClass, *pTIIface;
7704 ITypeLibImpl *pTypeLibImpl;
7705 unsigned int param, func;
7706 TLBFuncDesc **ppFuncDesc;
7710 pTypeLibImpl = TypeLibImpl_Constructor();
7711 if (!pTypeLibImpl) return E_FAIL;
7713 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7714 pTIIface->pTypeLib = pTypeLibImpl;
7715 pTIIface->index = 0;
7716 pTIIface->Name = NULL;
7717 pTIIface->dwHelpContext = -1;
7718 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7719 pTIIface->TypeAttr.lcid = lcid;
7720 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7721 pTIIface->TypeAttr.wMajorVerNum = 0;
7722 pTIIface->TypeAttr.wMinorVerNum = 0;
7723 pTIIface->TypeAttr.cbAlignment = 2;
7724 pTIIface->TypeAttr.cbSizeInstance = -1;
7725 pTIIface->TypeAttr.cbSizeVft = -1;
7726 pTIIface->TypeAttr.cFuncs = 0;
7727 pTIIface->TypeAttr.cImplTypes = 0;
7728 pTIIface->TypeAttr.cVars = 0;
7729 pTIIface->TypeAttr.wTypeFlags = 0;
7731 ppFuncDesc = &pTIIface->funclist;
7732 for(func = 0; func < pidata->cMembers; func++) {
7733 METHODDATA *md = pidata->pmethdata + func;
7734 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7735 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7736 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7737 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7738 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7739 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7740 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7741 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7742 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7743 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7744 (*ppFuncDesc)->funcdesc.cScodes = 0;
7745 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7746 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7747 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7748 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7749 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7750 md->cArgs * sizeof(ELEMDESC));
7751 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7752 md->cArgs * sizeof(TLBParDesc));
7753 for(param = 0; param < md->cArgs; param++) {
7754 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7755 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7757 (*ppFuncDesc)->helpcontext = 0;
7758 (*ppFuncDesc)->HelpStringContext = 0;
7759 (*ppFuncDesc)->HelpString = NULL;
7760 (*ppFuncDesc)->Entry = NULL;
7761 (*ppFuncDesc)->ctCustData = 0;
7762 (*ppFuncDesc)->pCustData = NULL;
7763 (*ppFuncDesc)->next = NULL;
7764 pTIIface->TypeAttr.cFuncs++;
7765 ppFuncDesc = &(*ppFuncDesc)->next;
7768 dump_TypeInfo(pTIIface);
7770 pTypeLibImpl->pTypeInfo = pTIIface;
7771 pTypeLibImpl->TypeInfoCount++;
7773 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7774 pTIClass->pTypeLib = pTypeLibImpl;
7775 pTIClass->index = 1;
7776 pTIClass->Name = NULL;
7777 pTIClass->dwHelpContext = -1;
7778 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7779 pTIClass->TypeAttr.lcid = lcid;
7780 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7781 pTIClass->TypeAttr.wMajorVerNum = 0;
7782 pTIClass->TypeAttr.wMinorVerNum = 0;
7783 pTIClass->TypeAttr.cbAlignment = 2;
7784 pTIClass->TypeAttr.cbSizeInstance = -1;
7785 pTIClass->TypeAttr.cbSizeVft = -1;
7786 pTIClass->TypeAttr.cFuncs = 0;
7787 pTIClass->TypeAttr.cImplTypes = 1;
7788 pTIClass->TypeAttr.cVars = 0;
7789 pTIClass->TypeAttr.wTypeFlags = 0;
7791 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7792 pTIClass->impltypelist->hRef = 0;
7794 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7797 ref->pImpTLInfo = TLB_REF_INTERNAL;
7798 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7800 dump_TypeInfo(pTIClass);
7802 pTIIface->next = pTIClass;
7803 pTypeLibImpl->TypeInfoCount++;
7805 *pptinfo = (ITypeInfo*)pTIClass;
7807 ITypeInfo_AddRef(*pptinfo);
7808 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7814 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7816 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7818 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7821 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7823 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7825 return ITypeInfo_AddRef((ITypeInfo *)This);
7828 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7830 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7832 return ITypeInfo_Release((ITypeInfo *)This);
7835 static HRESULT WINAPI ITypeComp_fnBind(
7840 ITypeInfo ** ppTInfo,
7841 DESCKIND * pDescKind,
7844 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7845 const TLBFuncDesc *pFDesc;
7846 const TLBVarDesc *pVDesc;
7847 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7849 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7851 *pDescKind = DESCKIND_NONE;
7852 pBindPtr->lpfuncdesc = NULL;
7855 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7856 if (!strcmpiW(pFDesc->Name, szName)) {
7857 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7860 /* name found, but wrong flags */
7861 hr = TYPE_E_TYPEMISMATCH;
7866 HRESULT hr = TLB_AllocAndInitFuncDesc(
7868 &pBindPtr->lpfuncdesc,
7869 This->TypeAttr.typekind == TKIND_DISPATCH);
7872 *pDescKind = DESCKIND_FUNCDESC;
7873 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7874 ITypeInfo_AddRef(*ppTInfo);
7877 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7878 if (!strcmpiW(pVDesc->Name, szName)) {
7879 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7882 *pDescKind = DESCKIND_VARDESC;
7883 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7884 ITypeInfo_AddRef(*ppTInfo);
7889 /* FIXME: search each inherited interface, not just the first */
7890 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7891 /* recursive search */
7895 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7898 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7899 ITypeInfo_Release(pTInfo);
7903 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7904 ITypeComp_Release(pTComp);
7907 WARN("Could not search inherited interface!\n");
7909 if (hr == DISP_E_MEMBERNOTFOUND)
7911 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7915 static HRESULT WINAPI ITypeComp_fnBindType(
7919 ITypeInfo ** ppTInfo,
7920 ITypeComp ** ppTComp)
7922 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7924 /* strange behaviour (does nothing) but like the
7927 if (!ppTInfo || !ppTComp)
7936 static const ITypeCompVtbl tcompvt =
7939 ITypeComp_fnQueryInterface,
7941 ITypeComp_fnRelease,
7944 ITypeComp_fnBindType