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
68 #include "wine/unicode.h"
71 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(ole);
75 WINE_DECLARE_DEBUG_CHANNEL(typelib);
77 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
78 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
80 /****************************************************************************
83 * Takes p_iVal (which is in little endian) and returns it
84 * in the host machine's byte order.
86 #ifdef WORDS_BIGENDIAN
87 static WORD FromLEWord(WORD p_iVal)
89 return (((p_iVal & 0x00FF) << 8) |
90 ((p_iVal & 0xFF00) >> 8));
94 static DWORD FromLEDWord(DWORD p_iVal)
96 return (((p_iVal & 0x000000FF) << 24) |
97 ((p_iVal & 0x0000FF00) << 8) |
98 ((p_iVal & 0x00FF0000) >> 8) |
99 ((p_iVal & 0xFF000000) >> 24));
102 #define FromLEWord(X) (X)
103 #define FromLEDWord(X) (X)
107 /****************************************************************************
110 * Fix byte order in any structure if necessary
112 #ifdef WORDS_BIGENDIAN
113 static void FromLEWords(void *p_Val, int p_iSize)
117 p_iSize /= sizeof(WORD);
120 *Val = FromLEWord(*Val);
127 static void FromLEDWords(void *p_Val, int p_iSize)
131 p_iSize /= sizeof(DWORD);
134 *Val = FromLEDWord(*Val);
140 #define FromLEWords(X,Y) /*nothing*/
141 #define FromLEDWords(X,Y) /*nothing*/
145 * Find a typelib key which matches a requested maj.min version.
147 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
149 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
156 memcpy( buffer, typelibW, sizeof(typelibW) );
157 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
159 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
162 len = sizeof(key_name);
164 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
168 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
170 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
177 break; /* exact match */
179 if (v_min > best_min) best_min = v_min;
182 len = sizeof(key_name);
193 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
194 /* buffer must be at least 60 characters long */
195 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
197 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
198 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
200 memcpy( buffer, TypelibW, sizeof(TypelibW) );
201 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
202 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
206 /* get the path of an interface key, in the form "Interface\\<guid>" */
207 /* buffer must be at least 50 characters long */
208 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
210 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
212 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
213 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
217 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
218 /* buffer must be at least 16 characters long */
219 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
221 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
222 static const WCHAR win16W[] = {'w','i','n','1','6',0};
223 static const WCHAR win32W[] = {'w','i','n','3','2',0};
225 sprintfW( buffer, LcidFormatW, lcid );
228 case SYS_WIN16: strcatW( buffer, win16W ); break;
229 case SYS_WIN32: strcatW( buffer, win32W ); break;
231 TRACE("Typelib is for unsupported syskind %i\n", syskind);
237 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
240 /****************************************************************************
241 * QueryPathOfRegTypeLib [OLEAUT32.164]
243 * Gets the path to a registered type library.
246 * guid [I] referenced guid
247 * wMaj [I] major version
248 * wMin [I] minor version
250 * path [O] path of typelib
254 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
255 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
258 HRESULT WINAPI QueryPathOfRegTypeLib(
265 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
269 WCHAR Path[MAX_PATH];
272 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
274 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
275 get_typelib_key( guid, wMaj, wMin, buffer );
277 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
278 if (res == ERROR_FILE_NOT_FOUND)
280 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
281 return TYPE_E_LIBNOTREGISTERED;
283 else if (res != ERROR_SUCCESS)
285 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
286 return TYPE_E_REGISTRYACCESS;
291 LONG dwPathLen = sizeof(Path);
293 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
295 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
299 else if (myLCID == lcid)
301 /* try with sub-langid */
302 myLCID = SUBLANGID(lcid);
304 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
306 /* try with system langid */
316 *path = SysAllocString( Path );
321 TRACE_(typelib)("-- 0x%08x\n", hr);
325 /******************************************************************************
326 * CreateTypeLib [OLEAUT32.160] creates a typelib
332 HRESULT WINAPI CreateTypeLib(
333 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
335 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
339 /******************************************************************************
340 * LoadTypeLib [OLEAUT32.161]
342 * Loads a type library
345 * szFile [I] Name of file to load from.
346 * pptLib [O] Pointer that receives ITypeLib object on success.
353 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
355 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
357 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
358 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
361 /******************************************************************************
362 * LoadTypeLibEx [OLEAUT32.183]
364 * Loads and optionally registers a type library
370 HRESULT WINAPI LoadTypeLibEx(
371 LPCOLESTR szFile, /* [in] Name of file to load from */
372 REGKIND regkind, /* [in] Specify kind of registration */
373 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
375 WCHAR szPath[MAX_PATH+1];
378 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
382 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
387 case REGKIND_DEFAULT:
388 /* don't register typelibs supplied with full path. Experimentation confirms the following */
389 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
390 (szFile[0] && (szFile[1] == ':'))) break;
391 /* else fall-through */
393 case REGKIND_REGISTER:
394 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
396 IUnknown_Release(*pptLib);
404 TRACE(" returns %08x\n",res);
408 /******************************************************************************
409 * LoadRegTypeLib [OLEAUT32.162]
411 * Loads a registered type library.
414 * rguid [I] GUID of the registered type library.
415 * wVerMajor [I] major version.
416 * wVerMinor [I] minor version.
417 * lcid [I] locale ID.
418 * ppTLib [O] pointer that receives an ITypeLib object on success.
422 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
425 HRESULT WINAPI LoadRegTypeLib(
437 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
441 res= LoadTypeLib(bstr, ppTLib);
445 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
451 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
452 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
453 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
454 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
455 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
456 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
458 /******************************************************************************
459 * RegisterTypeLib [OLEAUT32.163]
460 * Adds information about a type library to the System Registry
462 * Docs: ITypeLib FAR * ptlib
463 * Docs: OLECHAR FAR* szFullPath
464 * Docs: OLECHAR FAR* szHelpDir
470 HRESULT WINAPI RegisterTypeLib(
471 ITypeLib * ptlib, /* [in] Pointer to the library*/
472 OLECHAR * szFullPath, /* [in] full Path of the library*/
473 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
476 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
477 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
478 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
488 if (ptlib == NULL || szFullPath == NULL)
491 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
494 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
497 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
498 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
502 /* Set the human-readable name of the typelib */
503 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
505 if (RegSetValueExW(key, NULL, 0, REG_SZ,
506 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
514 /* Make up the name of the typelib path subkey */
515 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
517 /* Create the typelib path subkey */
518 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
519 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
521 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
522 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
530 /* Create the flags subkey */
531 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
532 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
534 /* FIXME: is %u correct? */
535 static const WCHAR formatW[] = {'%','u',0};
537 sprintfW(buf, formatW, attr->wLibFlags);
538 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
539 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
547 /* create the helpdir subkey */
548 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
549 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
551 BOOL freeHelpDir = FALSE;
554 /* if we created a new key, and helpDir was null, set the helpdir
555 to the directory which contains the typelib. However,
556 if we just opened an existing key, we leave the helpdir alone */
557 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
558 szHelpDir = SysAllocString(szFullPath);
559 pIndexStr = strrchrW(szHelpDir, '\\');
566 /* if we have an szHelpDir, set it! */
567 if (szHelpDir != NULL) {
568 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
569 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
575 if (freeHelpDir) SysFreeString(szHelpDir);
587 /* register OLE Automation-compatible interfaces for this typelib */
588 types = ITypeLib_GetTypeInfoCount(ptlib);
589 for (tidx=0; tidx<types; tidx++) {
590 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
591 LPOLESTR name = NULL;
592 ITypeInfo *tinfo = NULL;
594 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
597 case TKIND_INTERFACE:
598 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
599 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
603 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
604 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
608 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
613 TYPEATTR *tattr = NULL;
614 ITypeInfo_GetTypeAttr(tinfo, &tattr);
617 TRACE_(typelib)("guid=%s, flags=%04x (",
618 debugstr_guid(&tattr->guid),
621 if (TRACE_ON(typelib)) {
622 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
642 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
644 /* register interface<->typelib coupling */
645 get_interface_key( &tattr->guid, keyName );
646 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
647 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
650 RegSetValueExW(key, NULL, 0, REG_SZ,
651 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
653 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
654 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
655 RegSetValueExW(subKey, NULL, 0, REG_SZ,
656 (const BYTE *)PSOA, sizeof PSOA);
660 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
661 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
662 RegSetValueExW(subKey, NULL, 0, REG_SZ,
663 (const BYTE *)PSOA, sizeof PSOA);
667 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
668 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
671 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
672 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
674 StringFromGUID2(&attr->guid, buffer, 40);
675 RegSetValueExW(subKey, NULL, 0, REG_SZ,
676 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
677 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
678 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
679 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
687 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
690 ITypeInfo_Release(tinfo);
697 ITypeLib_ReleaseTLibAttr(ptlib, attr);
703 /******************************************************************************
704 * UnRegisterTypeLib [OLEAUT32.186]
705 * Removes information about a type library from the System Registry
712 HRESULT WINAPI UnRegisterTypeLib(
713 REFGUID libid, /* [in] Guid of the library */
714 WORD wVerMajor, /* [in] major version */
715 WORD wVerMinor, /* [in] minor version */
716 LCID lcid, /* [in] locale id */
719 BSTR tlibPath = NULL;
722 WCHAR subKeyName[50];
725 BOOL deleteOtherStuff;
728 TYPEATTR* typeAttr = NULL;
730 ITypeInfo* typeInfo = NULL;
731 ITypeLib* typeLib = NULL;
734 TRACE("(IID: %s)\n",debugstr_guid(libid));
736 /* Create the path to the key */
737 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
739 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
741 TRACE("Unsupported syskind %i\n", syskind);
742 result = E_INVALIDARG;
746 /* get the path to the typelib on disk */
747 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
748 result = E_INVALIDARG;
752 /* Try and open the key to the type library. */
753 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
754 result = E_INVALIDARG;
758 /* Try and load the type library */
759 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
760 result = TYPE_E_INVALIDSTATE;
764 /* remove any types registered with this typelib */
765 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
766 for (i=0; i<numTypes; i++) {
767 /* get the kind of type */
768 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
772 /* skip non-interfaces, and get type info for the type */
773 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
776 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
779 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
783 /* the path to the type */
784 get_interface_key( &typeAttr->guid, subKeyName );
786 /* Delete its bits */
787 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
790 RegDeleteKeyW(subKey, ProxyStubClsidW);
791 RegDeleteKeyW(subKey, ProxyStubClsid32W);
792 RegDeleteKeyW(subKey, TypeLibW);
795 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
798 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
800 if (typeInfo) ITypeInfo_Release(typeInfo);
804 /* Now, delete the type library path subkey */
805 get_lcid_subkey( lcid, syskind, subKeyName );
806 RegDeleteKeyW(key, subKeyName);
807 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
808 RegDeleteKeyW(key, subKeyName);
810 /* check if there is anything besides the FLAGS/HELPDIR keys.
811 If there is, we don't delete them */
812 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
813 deleteOtherStuff = TRUE;
815 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
816 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
818 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
819 if (!strcmpW(subKeyName, FLAGSW)) continue;
820 if (!strcmpW(subKeyName, HELPDIRW)) continue;
821 deleteOtherStuff = FALSE;
825 /* only delete the other parts of the key if we're absolutely sure */
826 if (deleteOtherStuff) {
827 RegDeleteKeyW(key, FLAGSW);
828 RegDeleteKeyW(key, HELPDIRW);
832 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
833 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
834 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
838 if (tlibPath) SysFreeString(tlibPath);
839 if (typeLib) ITypeLib_Release(typeLib);
840 if (subKey) RegCloseKey(subKey);
841 if (key) RegCloseKey(key);
845 /*======================= ITypeLib implementation =======================*/
847 typedef struct tagTLBCustData
851 struct tagTLBCustData* next;
854 /* data structure for import typelibs */
855 typedef struct tagTLBImpLib
857 int offset; /* offset in the file (MSFT)
858 offset in nametable (SLTG)
859 just used to identify library while reading
861 GUID guid; /* libid */
862 BSTR name; /* name */
864 LCID lcid; /* lcid of imported typelib */
866 WORD wVersionMajor; /* major version number */
867 WORD wVersionMinor; /* minor version number */
869 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
870 NULL if not yet loaded */
871 struct tagTLBImpLib * next;
874 /* internal ITypeLib data */
875 typedef struct tagITypeLibImpl
877 const ITypeLib2Vtbl *lpVtbl;
878 const ITypeCompVtbl *lpVtblTypeComp;
880 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
882 /* strings can be stored in tlb as multibyte strings BUT they are *always*
883 * exported to the application as a UNICODE string.
889 unsigned long dwHelpContext;
890 int TypeInfoCount; /* nr of typeinfo's in librarry */
891 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
892 int ctCustData; /* number of items in cust data list */
893 TLBCustData * pCustData; /* linked list to cust data */
894 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
895 int ctTypeDesc; /* number of items in type desc array */
896 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
897 library. Only used while read MSFT
900 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
901 struct tagITypeLibImpl *next, *prev;
906 static const ITypeLib2Vtbl tlbvt;
907 static const ITypeCompVtbl tlbtcvt;
909 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
911 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
914 /* ITypeLib methods */
915 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
916 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
918 /*======================= ITypeInfo implementation =======================*/
920 /* data for referenced types */
921 typedef struct tagTLBRefType
923 INT index; /* Type index for internal ref or for external ref
924 it the format is SLTG. -2 indicates to
927 GUID guid; /* guid of the referenced type */
928 /* if index == TLB_REF_USE_GUID */
930 HREFTYPE reference; /* The href of this ref */
931 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
932 TLB_REF_INTERNAL for internal refs
933 TLB_REF_NOT_FOUND for broken refs */
935 struct tagTLBRefType * next;
938 #define TLB_REF_USE_GUID -2
940 #define TLB_REF_INTERNAL (void*)-2
941 #define TLB_REF_NOT_FOUND (void*)-1
943 /* internal Parameter data */
944 typedef struct tagTLBParDesc
948 TLBCustData * pCustData; /* linked list to cust data */
951 /* internal Function data */
952 typedef struct tagTLBFuncDesc
954 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
955 BSTR Name; /* the name of this function */
956 TLBParDesc *pParamDesc; /* array with param names and custom data */
958 int HelpStringContext;
960 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
962 TLBCustData * pCustData; /* linked list to cust data; */
963 struct tagTLBFuncDesc * next;
966 /* internal Variable data */
967 typedef struct tagTLBVarDesc
969 VARDESC vardesc; /* lots of info on the variable and its attributes. */
970 BSTR Name; /* the name of this variable */
972 int HelpStringContext; /* FIXME: where? */
975 TLBCustData * pCustData;/* linked list to cust data; */
976 struct tagTLBVarDesc * next;
979 /* internal implemented interface data */
980 typedef struct tagTLBImplType
982 HREFTYPE hRef; /* hRef of interface */
983 int implflags; /* IMPLFLAG_*s */
985 TLBCustData * pCustData;/* linked list to custom data; */
986 struct tagTLBImplType *next;
989 /* internal TypeInfo data */
990 typedef struct tagITypeInfoImpl
992 const ITypeInfo2Vtbl *lpVtbl;
993 const ITypeCompVtbl *lpVtblTypeComp;
995 BOOL no_free_data; /* don't free data structurees */
996 TYPEATTR TypeAttr ; /* _lots_ of type information. */
997 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
998 int index; /* index in this typelib; */
999 HREFTYPE hreftype; /* hreftype for app object binding */
1000 /* type libs seem to store the doc strings in ascii
1001 * so why should we do it in unicode?
1006 unsigned long dwHelpContext;
1007 unsigned long dwHelpStringContext;
1010 TLBFuncDesc * funclist; /* linked list with function descriptions */
1013 TLBVarDesc * varlist; /* linked list with variable descriptions */
1015 /* Implemented Interfaces */
1016 TLBImplType * impltypelist;
1018 TLBRefType * reflist;
1020 TLBCustData * pCustData; /* linked list to cust data; */
1021 struct tagITypeInfoImpl * next;
1024 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1026 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1029 static const ITypeInfo2Vtbl tinfvt;
1030 static const ITypeCompVtbl tcompvt;
1032 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1034 typedef struct tagTLBContext
1036 unsigned int oStart; /* start of TLB in file */
1037 unsigned int pos; /* current pos */
1038 unsigned int length; /* total length */
1039 void *mapping; /* memory mapping */
1040 MSFT_SegDir * pTblDir;
1041 ITypeLibImpl* pLibInfo;
1045 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1050 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1051 if (pTD->vt & VT_RESERVED)
1052 szVarType += strlen(strcpy(szVarType, "reserved | "));
1053 if (pTD->vt & VT_BYREF)
1054 szVarType += strlen(strcpy(szVarType, "ref to "));
1055 if (pTD->vt & VT_ARRAY)
1056 szVarType += strlen(strcpy(szVarType, "array of "));
1057 if (pTD->vt & VT_VECTOR)
1058 szVarType += strlen(strcpy(szVarType, "vector of "));
1059 switch(pTD->vt & VT_TYPEMASK) {
1060 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1061 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1062 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1063 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1064 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1065 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1066 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1067 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1068 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1069 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1070 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1071 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1072 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1073 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1074 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1075 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1076 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1077 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1078 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1079 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1080 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1081 pTD->u.hreftype); break;
1082 case VT_PTR: sprintf(szVarType, "ptr to ");
1083 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1085 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1086 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1088 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1089 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1090 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1093 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1097 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1099 USHORT flags = edesc->u.paramdesc.wParamFlags;
1100 dump_TypeDesc(&edesc->tdesc,buf);
1101 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1102 MESSAGE("\t\tu.paramdesc.wParamFlags");
1103 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1104 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1105 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1106 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1107 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1108 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1109 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1110 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1111 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1113 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1115 MESSAGE("memid is %08x\n",funcdesc->memid);
1116 for (i=0;i<funcdesc->cParams;i++) {
1117 MESSAGE("Param %d:\n",i);
1118 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1120 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1121 switch (funcdesc->funckind) {
1122 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1123 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1124 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1125 case FUNC_STATIC: MESSAGE("static");break;
1126 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1127 default: MESSAGE("unknown");break;
1129 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1130 switch (funcdesc->invkind) {
1131 case INVOKE_FUNC: MESSAGE("func");break;
1132 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1133 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1134 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1136 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1137 switch (funcdesc->callconv) {
1138 case CC_CDECL: MESSAGE("cdecl");break;
1139 case CC_PASCAL: MESSAGE("pascal");break;
1140 case CC_STDCALL: MESSAGE("stdcall");break;
1141 case CC_SYSCALL: MESSAGE("syscall");break;
1144 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1145 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1146 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1148 MESSAGE("\telemdescFunc (return value type):\n");
1149 dump_ELEMDESC(&funcdesc->elemdescFunc);
1152 static const char * const typekind_desc[] =
1165 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1168 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1169 for (i=0;i<pfd->funcdesc.cParams;i++)
1170 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1173 dump_FUNCDESC(&(pfd->funcdesc));
1175 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1176 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1178 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1182 dump_TLBFuncDescOne(pfd);
1186 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1190 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1195 static void dump_TLBImpLib(const TLBImpLib *import)
1197 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1198 debugstr_w(import->name));
1199 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1200 import->wVersionMinor, import->lcid, import->offset);
1203 static void dump_TLBRefType(const TLBRefType * prt)
1207 TRACE_(typelib)("href:0x%08x\n", prt->reference);
1208 if(prt->index == -1)
1209 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1211 TRACE_(typelib)("type no: %d\n", prt->index);
1213 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1214 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1215 TRACE_(typelib)("in lib\n");
1216 dump_TLBImpLib(prt->pImpTLInfo);
1222 static void dump_TLBImplType(const TLBImplType * impl)
1226 "implementing/inheriting interface hRef = %x implflags %x\n",
1227 impl->hRef, impl->implflags);
1232 static void dump_Variant(const VARIANT * pvar)
1236 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1240 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1241 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1243 TRACE(",%p", V_BYREF(pvar));
1245 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1247 TRACE(",%p", V_ARRAY(pvar));
1249 else switch (V_TYPE(pvar))
1251 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1252 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1253 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1254 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1256 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1258 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1259 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1260 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1261 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1262 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1263 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1264 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1265 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1266 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1267 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1268 V_CY(pvar).s.Lo); break;
1270 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1271 TRACE(",<invalid>");
1273 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1274 st.wHour, st.wMinute, st.wSecond);
1278 case VT_USERDEFINED:
1280 case VT_NULL: break;
1281 default: TRACE(",?"); break;
1287 static void dump_DispParms(const DISPPARAMS * pdp)
1291 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1293 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1295 TRACE("named args:\n");
1296 for (index = 0; index < pdp->cNamedArgs; index++)
1297 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1300 if (pdp->cArgs && pdp->rgvarg)
1303 for (index = 0; index < pdp->cArgs; index++)
1304 dump_Variant( &pdp->rgvarg[index] );
1308 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1310 TRACE("%p ref=%u\n", pty, pty->ref);
1311 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1312 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1313 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1314 TRACE("fct:%u var:%u impl:%u\n",
1315 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1316 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1317 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1318 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1320 dump_TLBFuncDesc(pty->funclist);
1321 dump_TLBVarDesc(pty->varlist);
1322 dump_TLBImplType(pty->impltypelist);
1325 static void dump_VARDESC(const VARDESC *v)
1327 MESSAGE("memid %d\n",v->memid);
1328 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1329 MESSAGE("oInst %d\n",v->u.oInst);
1330 dump_ELEMDESC(&(v->elemdescVar));
1331 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1332 MESSAGE("varkind %d\n",v->varkind);
1335 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1337 /* VT_LPWSTR is largest type that */
1338 /* may appear in type description*/
1339 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1340 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1341 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1342 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1343 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1344 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1348 static void TLB_abort(void)
1352 static void * TLB_Alloc(unsigned size)
1355 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1357 ERR("cannot allocate memory\n");
1362 static void TLB_Free(void * ptr)
1364 HeapFree(GetProcessHeap(), 0, ptr);
1367 /* returns the size required for a deep copy of a typedesc into a
1369 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1373 if (alloc_initial_space)
1374 size += sizeof(TYPEDESC);
1380 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1383 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1384 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1390 /* deep copy a typedesc into a flat buffer */
1391 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1396 buffer = (char *)buffer + sizeof(TYPEDESC);
1405 dest->u.lptdesc = buffer;
1406 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1409 dest->u.lpadesc = buffer;
1410 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1411 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1412 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1418 /**********************************************************************
1420 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1422 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1427 static inline void MSFT_Seek(TLBContext *pcx, long where)
1429 if (where != DO_NOT_SEEK)
1431 where += pcx->oStart;
1432 if (where > pcx->length)
1435 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1443 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1445 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1446 pcx->pos, count, pcx->oStart, pcx->length, where);
1448 MSFT_Seek(pcx, where);
1449 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1450 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1455 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1460 ret = MSFT_Read(buffer, count, pcx, where);
1461 FromLEDWords(buffer, ret);
1466 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1471 ret = MSFT_Read(buffer, count, pcx, where);
1472 FromLEWords(buffer, ret);
1477 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1479 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1480 memset(pGuid,0, sizeof(GUID));
1483 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1484 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1485 pGuid->Data2 = FromLEWord(pGuid->Data2);
1486 pGuid->Data3 = FromLEWord(pGuid->Data3);
1487 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1490 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1492 MSFT_NameIntro niName;
1496 ERR_(typelib)("bad offset %d\n", offset);
1500 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1501 pcx->pTblDir->pNametab.offset+offset);
1503 return niName.hreftype;
1506 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1509 MSFT_NameIntro niName;
1511 BSTR bstrName = NULL;
1515 ERR_(typelib)("bad offset %d\n", offset);
1518 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1519 pcx->pTblDir->pNametab.offset+offset);
1520 niName.namelen &= 0xFF; /* FIXME: correct ? */
1521 name=TLB_Alloc((niName.namelen & 0xff) +1);
1522 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1523 name[niName.namelen & 0xff]='\0';
1525 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1528 /* no invalid characters in string */
1531 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1533 /* don't check for invalid character since this has been done previously */
1534 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1538 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1542 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1549 if(offset<0) return NULL;
1550 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1551 if(length <= 0) return 0;
1552 string=TLB_Alloc(length +1);
1553 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1554 string[length]='\0';
1556 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1557 string, -1, NULL, 0);
1559 /* no invalid characters in string */
1562 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1564 /* don't check for invalid character since this has been done previously */
1565 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1569 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1573 * read a value and fill a VARIANT structure
1575 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1579 TRACE_(typelib)("\n");
1581 if(offset <0) { /* data are packed in here */
1582 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1583 V_I4(pVar) = offset & 0x3ffffff;
1586 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1587 pcx->pTblDir->pCustData.offset + offset );
1588 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1589 switch (V_VT(pVar)){
1590 case VT_EMPTY: /* FIXME: is this right? */
1591 case VT_NULL: /* FIXME: is this right? */
1592 case VT_I2 : /* this should not happen */
1603 case VT_VOID : /* FIXME: is this right? */
1611 case VT_DECIMAL : /* FIXME: is this right? */
1614 /* pointer types with known behaviour */
1617 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1620 DWORD origPos = MSFT_Tell(pcx), nullPos;
1623 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1625 nullPos = MSFT_Tell(pcx);
1626 size = nullPos - origPos;
1627 MSFT_Seek(pcx, origPos);
1629 ptr=TLB_Alloc(size);/* allocate temp buffer */
1630 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1631 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1632 /* FIXME: do we need a AtoW conversion here? */
1633 V_UNION(pVar, bstrVal[size])=L'\0';
1634 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1638 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1645 case VT_USERDEFINED :
1651 case VT_STREAMED_OBJECT :
1652 case VT_STORED_OBJECT :
1653 case VT_BLOB_OBJECT :
1658 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1662 if(size>0) /* (big|small) endian correct? */
1663 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1667 * create a linked list with custom data
1669 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1675 TRACE_(typelib)("\n");
1679 pNew=TLB_Alloc(sizeof(TLBCustData));
1680 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1681 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1682 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1683 /* add new custom data at head of the list */
1684 pNew->next=*ppCustData;
1686 offset = entry.next;
1691 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1695 pTd->vt=type & VT_TYPEMASK;
1697 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1699 if(pTd->vt == VT_USERDEFINED)
1700 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1702 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1705 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1707 /* resolve referenced type if any */
1710 switch (lpTypeDesc->vt)
1713 lpTypeDesc = lpTypeDesc->u.lptdesc;
1717 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1720 case VT_USERDEFINED:
1721 MSFT_DoRefType(pcx, pTI,
1722 lpTypeDesc->u.hreftype);
1734 MSFT_DoFuncs(TLBContext* pcx,
1739 TLBFuncDesc** pptfd)
1742 * member information is stored in a data structure at offset
1743 * indicated by the memoffset field of the typeinfo structure
1744 * There are several distinctive parts.
1745 * The first part starts with a field that holds the total length
1746 * of this (first) part excluding this field. Then follow the records,
1747 * for each member there is one record.
1749 * The first entry is always the length of the record (including this
1751 * The rest of the record depends on the type of the member. If there is
1752 * a field indicating the member type (function, variable, interface, etc)
1753 * I have not found it yet. At this time we depend on the information
1754 * in the type info and the usual order how things are stored.
1756 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1759 * Third is an equal sized array with file offsets to the name entry
1762 * The fourth and last (?) part is an array with offsets to the records
1763 * in the first part of this file segment.
1766 int infolen, nameoffset, reclength, nrattributes, i;
1767 int recoffset = offset + sizeof(INT);
1769 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1770 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1771 TLBFuncDesc *ptfd_prev = NULL;
1773 TRACE_(typelib)("\n");
1775 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1777 for ( i = 0; i < cFuncs ; i++ )
1779 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1781 /* name, eventually add to a hash table */
1782 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1783 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1785 /* nameoffset is sometimes -1 on the second half of a propget/propput
1786 * pair of functions */
1787 if ((nameoffset == -1) && (i > 0))
1788 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1790 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1792 /* read the function information record */
1793 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1795 reclength &= 0xffff;
1797 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1799 /* do the attributes */
1800 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1803 if ( nrattributes > 0 )
1805 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1807 if ( nrattributes > 1 )
1809 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1810 pFuncRec->OptAttr[1]) ;
1812 if ( nrattributes > 2 )
1814 if ( pFuncRec->FKCCIC & 0x2000 )
1816 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1817 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1818 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1822 (*pptfd)->Entry = MSFT_ReadString(pcx,
1823 pFuncRec->OptAttr[2]);
1825 if( nrattributes > 5 )
1827 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1829 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1832 pFuncRec->OptAttr[6],
1833 &(*pptfd)->pCustData);
1839 (*pptfd)->Entry = (BSTR)-1;
1844 /* fill the FuncDesc Structure */
1845 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1846 offset + infolen + ( i + 1) * sizeof(INT));
1848 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1849 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1850 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1851 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1852 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1853 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1854 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1858 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1860 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1862 /* do the parameters/arguments */
1863 if(pFuncRec->nrargs)
1866 MSFT_ParameterInfo paraminfo;
1868 (*pptfd)->funcdesc.lprgelemdescParam =
1869 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1871 (*pptfd)->pParamDesc =
1872 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1874 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1875 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1877 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1879 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1886 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1889 if (paraminfo.oName == -1)
1890 /* this occurs for [propput] or [propget] methods, so
1891 * we should just set the name of the parameter to the
1892 * name of the method. */
1893 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1895 (*pptfd)->pParamDesc[j].Name =
1896 MSFT_ReadName( pcx, paraminfo.oName );
1897 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1899 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1902 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1903 (pFuncRec->FKCCIC & 0x1000) )
1905 INT* pInt = (INT *)((char *)pFuncRec +
1907 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1909 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1911 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1912 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1914 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1918 elemdesc->u.paramdesc.pparamdescex = NULL;
1920 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1923 pFuncRec->OptAttr[7+j],
1924 &(*pptfd)->pParamDesc[j].pCustData);
1927 /* SEEK value = jump to offset,
1928 * from there jump to the end of record,
1929 * go back by (j-1) arguments
1931 MSFT_ReadLEDWords( ¶minfo ,
1932 sizeof(MSFT_ParameterInfo), pcx,
1933 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1934 * sizeof(MSFT_ParameterInfo)));
1938 /* scode is not used: archaic win16 stuff FIXME: right? */
1939 (*pptfd)->funcdesc.cScodes = 0 ;
1940 (*pptfd)->funcdesc.lprgscode = NULL ;
1943 pptfd = & ((*pptfd)->next);
1944 recoffset += reclength;
1946 HeapFree(GetProcessHeap(), 0, recbuf);
1949 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1950 int cVars, int offset, TLBVarDesc ** pptvd)
1952 int infolen, nameoffset, reclength;
1954 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1958 TRACE_(typelib)("\n");
1960 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1961 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1962 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1963 recoffset += offset+sizeof(INT);
1964 for(i=0;i<cVars;i++){
1965 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1966 /* name, eventually add to a hash table */
1967 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1968 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1969 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1970 /* read the variable information record */
1971 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1973 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1975 if(reclength >(6*sizeof(INT)) )
1976 (*pptvd)->HelpContext=pVarRec->HelpContext;
1977 if(reclength >(7*sizeof(INT)) )
1978 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1979 if(reclength >(8*sizeof(INT)) )
1980 if(reclength >(9*sizeof(INT)) )
1981 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1982 /* fill the VarDesc Structure */
1983 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1984 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1985 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1986 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1987 MSFT_GetTdesc(pcx, pVarRec->DataType,
1988 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1989 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1990 if(pVarRec->VarKind == VAR_CONST ){
1991 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1992 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1993 pVarRec->OffsValue, pcx);
1995 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1996 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1997 pptvd=&((*pptvd)->next);
1998 recoffset += reclength;
2001 /* fill in data for a hreftype (offset). When the referenced type is contained
2002 * in the typelib, it's just an (file) offset in the type info base dir.
2003 * If comes from import, it's an offset+1 in the ImpInfo table
2005 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
2009 TLBRefType **ppRefType = &pTI->reflist;
2011 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2014 if((*ppRefType)->reference == offset)
2016 ppRefType = &(*ppRefType)->next;
2019 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2020 sizeof(**ppRefType));
2022 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2023 /* external typelib */
2024 MSFT_ImpInfo impinfo;
2025 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2027 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2029 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2030 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2031 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2032 if(pImpLib->offset==impinfo.oImpFile) break;
2033 pImpLib=pImpLib->next;
2036 (*ppRefType)->reference=offset;
2037 (*ppRefType)->pImpTLInfo = pImpLib;
2038 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2039 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2040 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
2041 (*ppRefType)->index = TLB_REF_USE_GUID;
2043 (*ppRefType)->index = impinfo.oGuid;
2045 ERR("Cannot find a reference\n");
2046 (*ppRefType)->reference=-1;
2047 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2050 /* in this typelib */
2051 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2052 (*ppRefType)->reference=offset;
2053 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2057 /* process Implemented Interfaces of a com class */
2058 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2062 MSFT_RefRecord refrec;
2063 TLBImplType **ppImpl = &pTI->impltypelist;
2065 TRACE_(typelib)("\n");
2067 for(i=0;i<count;i++){
2068 if(offset<0) break; /* paranoia */
2069 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2070 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2071 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2072 (*ppImpl)->hRef = refrec.reftype;
2073 (*ppImpl)->implflags=refrec.flags;
2074 (*ppImpl)->ctCustData=
2075 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2076 offset=refrec.onext;
2077 ppImpl=&((*ppImpl)->next);
2081 * process a typeinfo record
2083 static ITypeInfoImpl * MSFT_DoTypeInfo(
2087 ITypeLibImpl * pLibInfo)
2089 MSFT_TypeInfoBase tiBase;
2090 ITypeInfoImpl *ptiRet;
2092 TRACE_(typelib)("count=%u\n", count);
2094 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2095 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2096 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2098 /* this is where we are coming from */
2099 ptiRet->pTypeLib = pLibInfo;
2100 ptiRet->index=count;
2101 /* fill in the typeattr fields */
2103 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2104 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2105 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2106 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2107 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2108 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2109 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2110 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2111 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2112 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2113 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2114 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2115 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2116 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2117 MSFT_GetTdesc(pcx, tiBase.datatype1,
2118 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2121 /* IDLDESC idldescType; *//* never saw this one != zero */
2123 /* name, eventually add to a hash table */
2124 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2125 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2126 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2128 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2129 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2130 ptiRet->dwHelpContext=tiBase.helpcontext;
2132 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2133 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2135 /* note: InfoType's Help file and HelpStringDll come from the containing
2136 * library. Further HelpString and Docstring appear to be the same thing :(
2139 if(ptiRet->TypeAttr.cFuncs >0 )
2140 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2141 ptiRet->TypeAttr.cVars,
2142 tiBase.memoffset, & ptiRet->funclist);
2144 if(ptiRet->TypeAttr.cVars >0 )
2145 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2146 ptiRet->TypeAttr.cVars,
2147 tiBase.memoffset, & ptiRet->varlist);
2148 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2149 switch(ptiRet->TypeAttr.typekind)
2152 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2155 case TKIND_DISPATCH:
2156 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2158 if (tiBase.datatype1 != -1)
2160 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2161 ptiRet->impltypelist->hRef = tiBase.datatype1;
2165 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2166 ptiRet->impltypelist->hRef = dispatch_href;
2170 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2171 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2172 ptiRet->impltypelist->hRef = tiBase.datatype1;
2177 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2179 TRACE_(typelib)("%s guid: %s kind:%s\n",
2180 debugstr_w(ptiRet->Name),
2181 debugstr_guid(&ptiRet->TypeAttr.guid),
2182 typekind_desc[ptiRet->TypeAttr.typekind]);
2187 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2188 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2189 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2192 static ITypeLibImpl *tlb_cache_first;
2193 static CRITICAL_SECTION cache_section;
2194 static CRITICAL_SECTION_DEBUG cache_section_debug =
2196 0, 0, &cache_section,
2197 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2198 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2200 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2203 /****************************************************************************
2206 * find the type of the typelib file and map the typelib resource into
2209 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2210 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2211 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2213 ITypeLibImpl *entry;
2214 int ret = TYPE_E_CANTLOADLIBRARY;
2217 LPWSTR index_str, file = (LPWSTR)pszFileName;
2221 index_str = strrchrW(pszFileName, '\\');
2222 if(index_str && *++index_str != '\0')
2225 long idx = strtolW(index_str, &end_ptr, 10);
2226 if(*end_ptr == '\0')
2228 int str_len = index_str - pszFileName - 1;
2230 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2231 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2236 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2238 if(strchrW(file, '\\'))
2240 lstrcpyW(pszPath, file);
2244 int len = GetSystemDirectoryW(pszPath, cchPath);
2245 pszPath[len] = '\\';
2246 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2250 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2252 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2254 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2255 EnterCriticalSection(&cache_section);
2256 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2258 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2260 TRACE("cache hit\n");
2261 *ppTypeLib = (ITypeLib2*)entry;
2262 ITypeLib_AddRef(*ppTypeLib);
2263 LeaveCriticalSection(&cache_section);
2267 LeaveCriticalSection(&cache_section);
2269 /* now actually load and parse the typelib */
2271 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2272 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2276 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2277 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2280 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2283 LPVOID pBase = LockResource(hGlobal);
2284 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2288 /* try to load as incore resource */
2289 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2290 if (dwSignature == MSFT_SIGNATURE)
2291 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2292 else if (dwSignature == SLTG_SIGNATURE)
2293 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2295 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2297 FreeResource( hGlobal );
2300 FreeLibrary(hinstDLL);
2304 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2305 if (INVALID_HANDLE_VALUE != hFile)
2307 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2310 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2313 /* retrieve file size */
2314 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2315 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2317 if (dwSignature == MSFT_SIGNATURE)
2318 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2319 else if (dwSignature == SLTG_SIGNATURE)
2320 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2322 UnmapViewOfFile(pBase);
2324 CloseHandle(hMapping);
2331 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2333 TRACE("adding to cache\n");
2334 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2335 lstrcpyW(impl->path, pszPath);
2336 /* We should really canonicalise the path here. */
2337 impl->index = index;
2339 /* FIXME: check if it has added already in the meantime */
2340 EnterCriticalSection(&cache_section);
2341 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2343 tlb_cache_first = impl;
2344 LeaveCriticalSection(&cache_section);
2347 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2352 /*================== ITypeLib(2) Methods ===================================*/
2354 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2356 ITypeLibImpl* pTypeLibImpl;
2358 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2359 if (!pTypeLibImpl) return NULL;
2361 pTypeLibImpl->lpVtbl = &tlbvt;
2362 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2363 pTypeLibImpl->ref = 1;
2365 return pTypeLibImpl;
2368 /****************************************************************************
2369 * ITypeLib2_Constructor_MSFT
2371 * loading an MSFT typelib from an in-memory image
2373 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2377 MSFT_Header tlbHeader;
2378 MSFT_SegDir tlbSegDir;
2379 ITypeLibImpl * pTypeLibImpl;
2381 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2383 pTypeLibImpl = TypeLibImpl_Constructor();
2384 if (!pTypeLibImpl) return NULL;
2386 /* get pointer to beginning of typelib data */
2390 cx.pLibInfo = pTypeLibImpl;
2391 cx.length = dwTLBLength;
2394 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2395 TRACE_(typelib)("header:\n");
2396 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2397 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2398 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2401 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2403 /* there is a small amount of information here until the next important
2405 * the segment directory . Try to calculate the amount of data */
2406 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2408 /* now read the segment directory */
2409 TRACE("read segment directory (at %ld)\n",lPSegDir);
2410 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2411 cx.pTblDir = &tlbSegDir;
2413 /* just check two entries */
2414 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2416 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2417 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2421 /* now fill our internal data */
2422 /* TLIBATTR fields */
2423 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2425 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2426 /* Windows seems to have zero here, is this correct? */
2427 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2428 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2430 pTypeLibImpl->LibAttr.lcid = 0;
2432 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2433 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2434 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2435 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2437 /* name, eventually add to a hash table */
2438 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2441 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2442 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2444 if( tlbHeader.varflags & HELPDLLFLAG)
2447 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2448 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2451 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2454 if(tlbHeader.CustomDataOffset >= 0)
2456 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2459 /* fill in typedescriptions */
2460 if(tlbSegDir.pTypdescTab.length > 0)
2462 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2464 pTypeLibImpl->ctTypeDesc = cTD;
2465 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2466 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2469 /* FIXME: add several sanity checks here */
2470 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2471 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2473 /* FIXME: check safearray */
2475 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2477 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2479 else if(td[0] == VT_CARRAY)
2481 /* array descr table here */
2482 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2484 else if(td[0] == VT_USERDEFINED)
2486 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2488 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2491 /* second time around to fill the array subscript info */
2494 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2495 if(tlbSegDir.pArrayDescriptions.offset>0)
2497 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2498 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2501 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2503 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2505 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2507 for(j = 0; j<td[2]; j++)
2509 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2510 sizeof(INT), &cx, DO_NOT_SEEK);
2511 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2512 sizeof(INT), &cx, DO_NOT_SEEK);
2517 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2518 ERR("didn't find array description data\n");
2523 /* imported type libs */
2524 if(tlbSegDir.pImpFiles.offset>0)
2526 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2527 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2530 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2535 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2536 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2537 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2539 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2540 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2541 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2542 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2545 name = TLB_Alloc(size+1);
2546 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2547 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2548 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2549 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2552 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2553 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2555 ppImpLib = &(*ppImpLib)->next;
2560 if(tlbHeader.nrtypeinfos >= 0 )
2562 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2563 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2566 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2568 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2570 ppTI = &((*ppTI)->next);
2571 (pTypeLibImpl->TypeInfoCount)++;
2575 TRACE("(%p)\n", pTypeLibImpl);
2576 return (ITypeLib2*) pTypeLibImpl;
2580 static BSTR TLB_MultiByteToBSTR(char *ptr)
2586 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2587 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2588 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2589 ret = SysAllocString(nameW);
2590 HeapFree(GetProcessHeap(), 0, nameW);
2594 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2600 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2601 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2605 guid->Data4[0] = s >> 8;
2606 guid->Data4[1] = s & 0xff;
2609 for(i = 0; i < 6; i++) {
2610 memcpy(b, str + 24 + 2 * i, 2);
2611 guid->Data4[i + 2] = strtol(b, NULL, 16);
2616 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2623 bytelen = *(WORD*)ptr;
2624 if(bytelen == 0xffff) return 2;
2625 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2626 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2627 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2628 *pBstr = SysAllocStringLen(nameW, len);
2629 HeapFree(GetProcessHeap(), 0, nameW);
2633 static WORD SLTG_ReadStringA(char *ptr, char **str)
2638 bytelen = *(WORD*)ptr;
2639 if(bytelen == 0xffff) return 2;
2640 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2641 memcpy(*str, ptr + 2, bytelen);
2642 (*str)[bytelen] = '\0';
2646 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2648 char *ptr = pLibBlk;
2651 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2652 FIXME("libblk magic = %04x\n", w);
2657 if((w = *(WORD*)ptr) != 0xffff) {
2658 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2663 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2665 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2667 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2670 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2673 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2674 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2676 pTypeLibImpl->LibAttr.lcid = 0;
2679 ptr += 4; /* skip res12 */
2681 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2684 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2687 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2690 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2691 ptr += sizeof(GUID);
2693 return ptr - (char*)pLibBlk;
2696 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2701 if((*pType & 0xe00) == 0xe00) {
2703 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2705 pTD = pTD->u.lptdesc;
2707 switch(*pType & 0x3f) {
2710 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2712 pTD = pTD->u.lptdesc;
2715 case VT_USERDEFINED:
2716 pTD->vt = VT_USERDEFINED;
2717 pTD->u.hreftype = *(++pType) / 4;
2723 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2726 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2728 pTD->vt = VT_CARRAY;
2729 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2731 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2732 pTD->u.lpadesc->cDims = pSA->cDims;
2733 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2734 pSA->cDims * sizeof(SAFEARRAYBOUND));
2736 pTD = &pTD->u.lpadesc->tdescElem;
2742 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2746 pTD->vt = VT_SAFEARRAY;
2747 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2749 pTD = pTD->u.lptdesc;
2753 pTD->vt = *pType & 0x3f;
2762 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2764 /* Handle [in/out] first */
2765 if((*pType & 0xc000) == 0xc000)
2766 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2767 else if(*pType & 0x8000)
2768 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2769 else if(*pType & 0x4000)
2770 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2772 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2775 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2778 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2780 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2784 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2789 TLBRefType **ppRefType;
2791 if(pRef->magic != SLTG_REF_MAGIC) {
2792 FIXME("Ref magic = %x\n", pRef->magic);
2795 name = ( (char*)(&pRef->names) + pRef->number);
2797 ppRefType = &pTI->reflist;
2798 for(ref = 0; ref < pRef->number >> 3; ref++) {
2800 unsigned int lib_offs, type_num;
2802 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2803 sizeof(**ppRefType));
2805 name += SLTG_ReadStringA(name, &refname);
2806 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2807 FIXME("Can't sscanf ref\n");
2808 if(lib_offs != 0xffff) {
2809 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2812 if((*import)->offset == lib_offs)
2814 import = &(*import)->next;
2817 char fname[MAX_PATH+1];
2820 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2822 (*import)->offset = lib_offs;
2823 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2825 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2826 &(*import)->wVersionMajor,
2827 &(*import)->wVersionMinor,
2828 &(*import)->lcid, fname) != 4) {
2829 FIXME("can't sscanf ref %s\n",
2830 pNameTable + lib_offs + 40);
2832 len = strlen(fname);
2833 if(fname[len-1] != '#')
2834 FIXME("fname = %s\n", fname);
2835 fname[len-1] = '\0';
2836 (*import)->name = TLB_MultiByteToBSTR(fname);
2838 (*ppRefType)->pImpTLInfo = *import;
2839 } else { /* internal ref */
2840 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2842 (*ppRefType)->reference = ref;
2843 (*ppRefType)->index = type_num;
2845 HeapFree(GetProcessHeap(), 0, refname);
2846 ppRefType = &(*ppRefType)->next;
2848 if((BYTE)*name != SLTG_REF_MAGIC)
2849 FIXME("End of ref block magic = %x\n", *name);
2850 dump_TLBRefType(pTI->reflist);
2853 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2856 SLTG_ImplInfo *info;
2857 TLBImplType **ppImplType = &pTI->impltypelist;
2858 /* I don't really get this structure, usually it's 0x16 bytes
2859 long, but iuser.tlb contains some that are 0x18 bytes long.
2860 That's ok because we can use the next ptr to jump to the next
2861 one. But how do we know the length of the last one? The WORD
2862 at offs 0x8 might be the clue. For now I'm just assuming that
2863 the last one is the regular 0x16 bytes. */
2865 info = (SLTG_ImplInfo*)pBlk;
2867 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2868 sizeof(**ppImplType));
2869 (*ppImplType)->hRef = info->ref;
2870 (*ppImplType)->implflags = info->impltypeflags;
2871 pTI->TypeAttr.cImplTypes++;
2872 ppImplType = &(*ppImplType)->next;
2874 if(info->next == 0xffff)
2877 FIXME("Interface inheriting more than one interface\n");
2878 info = (SLTG_ImplInfo*)(pBlk + info->next);
2880 info++; /* see comment at top of function */
2884 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2886 TLBVarDesc **ppVarDesc = &pTI->varlist;
2887 BSTR bstrPrevName = NULL;
2888 SLTG_Variable *pItem;
2893 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2894 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2896 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2897 sizeof(**ppVarDesc));
2898 (*ppVarDesc)->vardesc.memid = pItem->memid;
2900 if (pItem->magic != SLTG_VAR_MAGIC &&
2901 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2902 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2906 if (pItem->name == 0xfffe)
2907 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2909 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2911 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2912 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2914 if (pItem->flags & 0x40) {
2915 TRACE_(typelib)("VAR_DISPATCH\n");
2916 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2918 else if (pItem->flags & 0x10) {
2919 TRACE_(typelib)("VAR_CONST\n");
2920 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2921 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2923 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2924 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2925 *(INT*)(pBlk + pItem->byte_offs);
2928 TRACE_(typelib)("VAR_PERINSTANCE\n");
2929 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2930 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2933 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2934 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2936 if (pItem->flags & 0x80)
2937 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2939 if(pItem->flags & 0x02)
2940 pType = &pItem->type;
2942 pType = (WORD*)(pBlk + pItem->type);
2944 if (pItem->flags & ~0xd2)
2945 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2947 SLTG_DoElem(pType, pBlk,
2948 &(*ppVarDesc)->vardesc.elemdescVar);
2950 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2952 bstrPrevName = (*ppVarDesc)->Name;
2953 ppVarDesc = &((*ppVarDesc)->next);
2955 pTI->TypeAttr.cVars = cVars;
2958 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2960 SLTG_Function *pFunc;
2962 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2964 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2965 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2970 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2971 sizeof(**ppFuncDesc));
2973 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2974 case SLTG_FUNCTION_MAGIC:
2975 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2977 case SLTG_DISPATCH_FUNCTION_MAGIC:
2978 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2980 case SLTG_STATIC_FUNCTION_MAGIC:
2981 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2984 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2985 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2989 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2991 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2992 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2993 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2994 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2995 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2996 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2998 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2999 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3001 if(pFunc->retnextopt & 0x80)
3002 pType = &pFunc->rettype;
3004 pType = (WORD*)(pBlk + pFunc->rettype);
3006 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
3008 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3009 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3010 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3011 (*ppFuncDesc)->pParamDesc =
3012 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3013 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3015 pArg = (WORD*)(pBlk + pFunc->arg_off);
3017 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3018 char *paramName = pNameTable + *pArg;
3020 /* If arg type follows then paramName points to the 2nd
3021 letter of the name, else the next WORD is an offset to
3022 the arg type and paramName points to the first letter.
3023 So let's take one char off paramName and see if we're
3024 pointing at an alpha-numeric char. However if *pArg is
3025 0xffff or 0xfffe then the param has no name, the former
3026 meaning that the next WORD is the type, the latter
3027 meaning the the next WORD is an offset to the type. */
3032 else if(*pArg == 0xfffe) {
3036 else if(paramName[-1] && !isalnum(paramName[-1]))
3041 if(HaveOffs) { /* the next word is an offset to type */
3042 pType = (WORD*)(pBlk + *pArg);
3043 SLTG_DoElem(pType, pBlk,
3044 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3049 pArg = SLTG_DoElem(pArg, pBlk,
3050 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3053 /* Are we an optional param ? */
3054 if((*ppFuncDesc)->funcdesc.cParams - param <=
3055 (*ppFuncDesc)->funcdesc.cParamsOpt)
3056 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3059 (*ppFuncDesc)->pParamDesc[param].Name =
3060 TLB_MultiByteToBSTR(paramName);
3064 ppFuncDesc = &((*ppFuncDesc)->next);
3065 if(pFunc->next == 0xffff) break;
3067 pTI->TypeAttr.cFuncs = cFuncs;
3070 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3071 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3072 SLTG_TypeInfoTail *pTITail)
3074 char *pFirstItem, *pNextItem;
3076 if(pTIHeader->href_table != 0xffffffff) {
3077 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3081 pFirstItem = pNextItem = pBlk;
3083 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3084 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3089 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3090 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3091 SLTG_TypeInfoTail *pTITail)
3093 char *pFirstItem, *pNextItem;
3095 if(pTIHeader->href_table != 0xffffffff) {
3096 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3100 pFirstItem = pNextItem = pBlk;
3102 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3103 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3106 if (pTITail->funcs_off != 0xffff)
3107 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3109 if (TRACE_ON(typelib))
3110 dump_TLBFuncDesc(pTI->funclist);
3113 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3114 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3115 SLTG_TypeInfoTail *pTITail)
3117 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3120 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3121 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3122 SLTG_TypeInfoTail *pTITail)
3126 if (pTITail->simple_alias) {
3127 /* if simple alias, no more processing required */
3128 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3132 if(pTIHeader->href_table != 0xffffffff) {
3133 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3137 /* otherwise it is an offset to a type */
3138 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3140 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3143 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3144 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3145 SLTG_TypeInfoTail *pTITail)
3147 if (pTIHeader->href_table != 0xffffffff)
3148 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3151 if (pTITail->vars_off != 0xffff)
3152 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3154 if (pTITail->funcs_off != 0xffff)
3155 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3157 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3158 * of dispinterface functons including the IDispatch ones, so
3159 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3160 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3162 if (TRACE_ON(typelib))
3163 dump_TLBFuncDesc(pTI->funclist);
3166 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3167 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3168 SLTG_TypeInfoTail *pTITail)
3170 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3173 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3174 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3175 SLTG_TypeInfoTail *pTITail)
3177 if (pTIHeader->href_table != 0xffffffff)
3178 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3181 if (pTITail->vars_off != 0xffff)
3182 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3184 if (pTITail->funcs_off != 0xffff)
3185 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3188 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3189 managable copy of it into this */
3202 } SLTG_InternalOtherTypeInfo;
3204 /****************************************************************************
3205 * ITypeLib2_Constructor_SLTG
3207 * loading a SLTG typelib from an in-memory image
3209 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3211 ITypeLibImpl *pTypeLibImpl;
3212 SLTG_Header *pHeader;
3213 SLTG_BlkEntry *pBlkEntry;
3217 LPVOID pBlk, pFirstBlk;
3218 SLTG_LibBlk *pLibBlk;
3219 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3220 char *pAfterOTIBlks = NULL;
3221 char *pNameTable, *ptr;
3224 ITypeInfoImpl **ppTypeInfoImpl;
3226 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3229 pTypeLibImpl = TypeLibImpl_Constructor();
3230 if (!pTypeLibImpl) return NULL;
3234 TRACE_(typelib)("header:\n");
3235 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3236 pHeader->nrOfFileBlks );
3237 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3238 FIXME("Header type magic 0x%08x not supported.\n",
3239 pHeader->SLTG_magic);
3243 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3244 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3246 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3247 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3249 /* Next we have a magic block */
3250 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3252 /* Let's see if we're still in sync */
3253 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3254 sizeof(SLTG_COMPOBJ_MAGIC))) {
3255 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3258 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3259 sizeof(SLTG_DIR_MAGIC))) {
3260 FIXME("dir magic = %s\n", pMagic->dir_magic);
3264 pIndex = (SLTG_Index*)(pMagic+1);
3266 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3268 pFirstBlk = (LPVOID)(pPad9 + 1);
3270 /* We'll set up a ptr to the main library block, which is the last one. */
3272 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3273 pBlkEntry[order].next != 0;
3274 order = pBlkEntry[order].next - 1, i++) {
3275 pBlk = (char*)pBlk + pBlkEntry[order].len;
3279 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3281 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3286 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3288 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3289 sizeof(*pOtherTypeInfoBlks) *
3290 pTypeLibImpl->TypeInfoCount);
3293 ptr = (char*)pLibBlk + len;
3295 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3299 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3301 w = *(WORD*)(ptr + 2);
3304 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3306 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3307 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3309 w = *(WORD*)(ptr + 4 + len);
3311 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3313 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3315 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3316 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3318 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3319 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3320 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3322 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3324 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3327 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3328 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3329 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3330 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3331 len += sizeof(SLTG_OtherTypeInfo);
3335 pAfterOTIBlks = ptr;
3337 /* Skip this WORD and get the next DWORD */
3338 len = *(DWORD*)(pAfterOTIBlks + 2);
3340 /* Now add this to pLibBLk look at what we're pointing at and
3341 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3342 dust and we should be pointing at the beginning of the name
3345 pNameTable = (char*)pLibBlk + len;
3347 switch(*(WORD*)pNameTable) {
3354 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3358 pNameTable += 0x216;
3362 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3364 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3367 /* Hopefully we now have enough ptrs set up to actually read in
3368 some TypeInfos. It's not clear which order to do them in, so
3369 I'll just follow the links along the BlkEntry chain and read
3370 them in the order in which they are in the file */
3372 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3374 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3375 pBlkEntry[order].next != 0;
3376 order = pBlkEntry[order].next - 1, i++) {
3378 SLTG_TypeInfoHeader *pTIHeader;
3379 SLTG_TypeInfoTail *pTITail;
3380 SLTG_MemberHeader *pMemHeader;
3382 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3383 pOtherTypeInfoBlks[i].index_name)) {
3384 FIXME("Index strings don't match\n");
3389 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3390 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3393 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3394 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3396 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3397 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3398 (*ppTypeInfoImpl)->index = i;
3399 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3400 pOtherTypeInfoBlks[i].name_offs +
3402 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3403 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3405 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3406 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3407 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3408 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3409 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3411 if((pTIHeader->typeflags1 & 7) != 2)
3412 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3413 if(pTIHeader->typeflags3 != 2)
3414 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3416 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3417 debugstr_w((*ppTypeInfoImpl)->Name),
3418 typekind_desc[pTIHeader->typekind],
3419 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3420 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3422 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3424 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3426 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3427 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3428 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3430 switch(pTIHeader->typekind) {
3432 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3433 pTIHeader, pTITail);
3437 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3438 pTIHeader, pTITail);
3441 case TKIND_INTERFACE:
3442 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3443 pTIHeader, pTITail);
3447 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3448 pTIHeader, pTITail);
3452 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3453 pTIHeader, pTITail);
3456 case TKIND_DISPATCH:
3457 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3458 pTIHeader, pTITail);
3462 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3463 pTIHeader, pTITail);
3467 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3472 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3473 but we've already set those */
3474 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3489 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3490 pBlk = (char*)pBlk + pBlkEntry[order].len;
3493 if(i != pTypeLibImpl->TypeInfoCount) {
3494 FIXME("Somehow processed %d TypeInfos\n", i);
3498 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3499 return (ITypeLib2*)pTypeLibImpl;
3502 /* ITypeLib::QueryInterface
3504 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3509 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3511 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3514 if(IsEqualIID(riid, &IID_IUnknown) ||
3515 IsEqualIID(riid,&IID_ITypeLib)||
3516 IsEqualIID(riid,&IID_ITypeLib2))
3523 ITypeLib2_AddRef(iface);
3524 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3527 TRACE("-- Interface: E_NOINTERFACE\n");
3528 return E_NOINTERFACE;
3533 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3535 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3536 ULONG ref = InterlockedIncrement(&This->ref);
3538 TRACE("(%p)->ref was %u\n",This, ref - 1);
3543 /* ITypeLib::Release
3545 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3547 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3548 ULONG ref = InterlockedDecrement(&This->ref);
3550 TRACE("(%p)->(%u)\n",This, ref);
3554 TLBImpLib *pImpLib, *pImpLibNext;
3555 TLBCustData *pCustData, *pCustDataNext;
3558 /* remove cache entry */
3561 TRACE("removing from cache list\n");
3562 EnterCriticalSection(&cache_section);
3563 if (This->next) This->next->prev = This->prev;
3564 if (This->prev) This->prev->next = This->next;
3565 else tlb_cache_first = This->next;
3566 LeaveCriticalSection(&cache_section);
3567 HeapFree(GetProcessHeap(), 0, This->path);
3569 TRACE(" destroying ITypeLib(%p)\n",This);
3573 SysFreeString(This->Name);
3577 if (This->DocString)
3579 SysFreeString(This->DocString);
3580 This->DocString = NULL;
3585 SysFreeString(This->HelpFile);
3586 This->HelpFile = NULL;
3589 if (This->HelpStringDll)
3591 SysFreeString(This->HelpStringDll);
3592 This->HelpStringDll = NULL;
3595 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3597 VariantClear(&pCustData->data);
3599 pCustDataNext = pCustData->next;
3600 TLB_Free(pCustData);
3603 for (i = 0; i < This->ctTypeDesc; i++)
3604 if (This->pTypeDesc[i].vt == VT_CARRAY)
3605 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3607 TLB_Free(This->pTypeDesc);
3609 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3611 if (pImpLib->pImpTypeLib)
3612 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3613 TLB_Free(pImpLib->name);
3615 pImpLibNext = pImpLib->next;
3619 if (This->pTypeInfo) /* can be NULL */
3620 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3621 HeapFree(GetProcessHeap(),0,This);
3628 /* ITypeLib::GetTypeInfoCount
3630 * Returns the number of type descriptions in the type library
3632 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3634 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3635 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3636 return This->TypeInfoCount;
3639 /* ITypeLib::GetTypeInfo
3641 * retrieves the specified type description in the library.
3643 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3646 ITypeInfo **ppTInfo)
3650 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3651 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3653 TRACE("(%p)->(index=%d)\n", This, index);
3655 if (!ppTInfo) return E_INVALIDARG;
3657 /* search element n in list */
3658 for(i=0; i < index; i++)
3660 pTypeInfo = pTypeInfo->next;
3663 TRACE("-- element not found\n");
3664 return TYPE_E_ELEMENTNOTFOUND;
3668 *ppTInfo = (ITypeInfo *) pTypeInfo;
3670 ITypeInfo_AddRef(*ppTInfo);
3671 TRACE("-- found (%p)\n",*ppTInfo);
3676 /* ITypeLibs::GetTypeInfoType
3678 * Retrieves the type of a type description.
3680 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3685 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3687 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3689 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3690 return TYPE_E_ELEMENTNOTFOUND;
3692 TRACE("(%p) index %d\n", This, index);
3694 if(!pTKind) return E_INVALIDARG;
3696 /* search element n in list */
3697 for(i=0; i < index; i++)
3701 TRACE("-- element not found\n");
3702 return TYPE_E_ELEMENTNOTFOUND;
3704 pTInfo = pTInfo->next;
3707 *pTKind = pTInfo->TypeAttr.typekind;
3708 TRACE("-- found Type (%d)\n", *pTKind);
3712 /* ITypeLib::GetTypeInfoOfGuid
3714 * Retrieves the type description that corresponds to the specified GUID.
3717 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3720 ITypeInfo **ppTInfo)
3722 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3723 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3725 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3729 WARN("-- element not found\n");
3730 return TYPE_E_ELEMENTNOTFOUND;
3733 /* search linked list for guid */
3734 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3736 pTypeInfo = pTypeInfo->next;
3740 /* end of list reached */
3741 WARN("-- element not found\n");
3742 return TYPE_E_ELEMENTNOTFOUND;
3746 TRACE("-- found (%p, %s)\n",
3748 debugstr_w(pTypeInfo->Name));
3750 *ppTInfo = (ITypeInfo*)pTypeInfo;
3751 ITypeInfo_AddRef(*ppTInfo);
3755 /* ITypeLib::GetLibAttr
3757 * Retrieves the structure that contains the library's attributes.
3760 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3762 LPTLIBATTR *ppTLibAttr)
3764 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3765 TRACE("(%p)\n",This);
3766 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3767 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3771 /* ITypeLib::GetTypeComp
3773 * Enables a client compiler to bind to a library's types, variables,
3774 * constants, and global functions.
3777 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3779 ITypeComp **ppTComp)
3781 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3783 TRACE("(%p)->(%p)\n",This,ppTComp);
3784 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3785 ITypeComp_AddRef(*ppTComp);
3790 /* ITypeLib::GetDocumentation
3792 * Retrieves the library's documentation string, the complete Help file name
3793 * and path, and the context identifier for the library Help topic in the Help
3796 * On a successful return all non-null BSTR pointers will have been set,
3799 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3803 BSTR *pBstrDocString,
3804 DWORD *pdwHelpContext,
3805 BSTR *pBstrHelpFile)
3807 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3809 HRESULT result = E_INVALIDARG;
3814 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3816 pBstrName, pBstrDocString,
3817 pdwHelpContext, pBstrHelpFile);
3821 /* documentation for the typelib */
3826 if(!(*pBstrName = SysAllocString(This->Name)))
3834 if (This->DocString)
3836 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3839 else if (This->Name)
3841 if(!(*pBstrDocString = SysAllocString(This->Name)))
3845 *pBstrDocString = NULL;
3849 *pdwHelpContext = This->dwHelpContext;
3855 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3859 *pBstrHelpFile = NULL;
3866 /* for a typeinfo */
3867 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3869 if(SUCCEEDED(result))
3871 result = ITypeInfo_GetDocumentation(pTInfo,
3875 pdwHelpContext, pBstrHelpFile);
3877 ITypeInfo_Release(pTInfo);
3882 if (pBstrDocString) SysFreeString (*pBstrDocString);
3884 if (pBstrName) SysFreeString (*pBstrName);
3886 return STG_E_INSUFFICIENTMEMORY;
3891 * Indicates whether a passed-in string contains the name of a type or member
3892 * described in the library.
3895 static HRESULT WINAPI ITypeLib2_fnIsName(
3901 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3902 ITypeInfoImpl *pTInfo;
3903 TLBFuncDesc *pFInfo;
3906 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3908 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3912 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3913 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3914 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3915 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3916 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3917 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3918 goto ITypeLib2_fnIsName_exit;
3920 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3921 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3926 ITypeLib2_fnIsName_exit:
3927 TRACE("(%p)slow! search for %s: %s found!\n", This,
3928 debugstr_w(szNameBuf), *pfName?"NOT":"");
3933 /* ITypeLib::FindName
3935 * Finds occurrences of a type description in a type library. This may be used
3936 * to quickly verify that a name exists in a type library.
3939 static HRESULT WINAPI ITypeLib2_fnFindName(
3943 ITypeInfo **ppTInfo,
3947 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3948 ITypeInfoImpl *pTInfo;
3949 TLBFuncDesc *pFInfo;
3952 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3954 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3955 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3956 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3957 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3958 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3959 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3960 goto ITypeLib2_fnFindName_exit;
3963 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3964 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3966 ITypeLib2_fnFindName_exit:
3967 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3968 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3971 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3972 This, *pcFound, debugstr_w(szNameBuf), j);
3979 /* ITypeLib::ReleaseTLibAttr
3981 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3984 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3986 TLIBATTR *pTLibAttr)
3988 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3989 TRACE("freeing (%p)\n",This);
3990 HeapFree(GetProcessHeap(),0,pTLibAttr);
3994 /* ITypeLib2::GetCustData
3996 * gets the custom data
3998 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4003 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4004 TLBCustData *pCData;
4006 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4008 if( IsEqualIID(guid, &pCData->guid)) break;
4011 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4015 VariantInit( pVarVal);
4016 VariantCopy( pVarVal, &pCData->data);
4019 return E_INVALIDARG; /* FIXME: correct? */
4022 /* ITypeLib2::GetLibStatistics
4024 * Returns statistics about a type library that are required for efficient
4025 * sizing of hash tables.
4028 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4030 ULONG *pcUniqueNames,
4031 ULONG *pcchUniqueNames)
4033 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4035 FIXME("(%p): stub!\n", This);
4037 if(pcUniqueNames) *pcUniqueNames=1;
4038 if(pcchUniqueNames) *pcchUniqueNames=1;
4042 /* ITypeLib2::GetDocumentation2
4044 * Retrieves the library's documentation string, the complete Help file name
4045 * and path, the localization context to use, and the context ID for the
4046 * library Help topic in the Help file.
4049 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4053 BSTR *pbstrHelpString,
4054 DWORD *pdwHelpStringContext,
4055 BSTR *pbstrHelpStringDll)
4057 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4061 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4063 /* the help string should be obtained from the helpstringdll,
4064 * using the _DLLGetDocumentation function, based on the supplied
4065 * lcid. Nice to do sometime...
4069 /* documentation for the typelib */
4071 *pbstrHelpString=SysAllocString(This->DocString);
4072 if(pdwHelpStringContext)
4073 *pdwHelpStringContext=This->dwHelpContext;
4074 if(pbstrHelpStringDll)
4075 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4081 /* for a typeinfo */
4082 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4084 if(SUCCEEDED(result))
4086 ITypeInfo2 * pTInfo2;
4087 result = ITypeInfo_QueryInterface(pTInfo,
4089 (LPVOID*) &pTInfo2);
4091 if(SUCCEEDED(result))
4093 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4097 pdwHelpStringContext,
4098 pbstrHelpStringDll);
4100 ITypeInfo2_Release(pTInfo2);
4103 ITypeInfo_Release(pTInfo);
4109 /* ITypeLib2::GetAllCustData
4111 * Gets all custom data items for the library.
4114 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4116 CUSTDATA *pCustData)
4118 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4119 TLBCustData *pCData;
4121 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4122 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4123 if(pCustData->prgCustData ){
4124 pCustData->cCustData=This->ctCustData;
4125 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4126 pCustData->prgCustData[i].guid=pCData->guid;
4127 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4130 ERR(" OUT OF MEMORY!\n");
4131 return E_OUTOFMEMORY;
4136 static const ITypeLib2Vtbl tlbvt = {
4137 ITypeLib2_fnQueryInterface,
4139 ITypeLib2_fnRelease,
4140 ITypeLib2_fnGetTypeInfoCount,
4141 ITypeLib2_fnGetTypeInfo,
4142 ITypeLib2_fnGetTypeInfoType,
4143 ITypeLib2_fnGetTypeInfoOfGuid,
4144 ITypeLib2_fnGetLibAttr,
4145 ITypeLib2_fnGetTypeComp,
4146 ITypeLib2_fnGetDocumentation,
4148 ITypeLib2_fnFindName,
4149 ITypeLib2_fnReleaseTLibAttr,
4151 ITypeLib2_fnGetCustData,
4152 ITypeLib2_fnGetLibStatistics,
4153 ITypeLib2_fnGetDocumentation2,
4154 ITypeLib2_fnGetAllCustData
4158 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4160 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4162 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4165 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4167 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4169 return ITypeLib2_AddRef((ITypeLib2 *)This);
4172 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4174 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4176 return ITypeLib2_Release((ITypeLib2 *)This);
4179 static HRESULT WINAPI ITypeLibComp_fnBind(
4184 ITypeInfo ** ppTInfo,
4185 DESCKIND * pDescKind,
4188 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4189 ITypeInfoImpl *pTypeInfo;
4191 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4193 *pDescKind = DESCKIND_NONE;
4194 pBindPtr->lptcomp = NULL;
4197 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4199 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4201 /* FIXME: check wFlags here? */
4202 /* FIXME: we should use a hash table to look this info up using lHash
4203 * instead of an O(n) search */
4204 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4205 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4207 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4209 *pDescKind = DESCKIND_TYPECOMP;
4210 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4211 ITypeComp_AddRef(pBindPtr->lptcomp);
4212 TRACE("module or enum: %s\n", debugstr_w(szName));
4217 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4218 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4220 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4223 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4224 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4226 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4231 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4232 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4234 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4236 ITypeInfo *subtypeinfo;
4238 DESCKIND subdesckind;
4240 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4241 &subtypeinfo, &subdesckind, &subbindptr);
4242 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4244 TYPEDESC tdesc_appobject =
4247 (TYPEDESC *)pTypeInfo->hreftype
4251 const VARDESC vardesc_appobject =
4254 NULL, /* lpstrSchema */
4269 VAR_STATIC /* varkind */
4272 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4274 /* cleanup things filled in by Bind call so we can put our
4275 * application object data in there instead */
4276 switch (subdesckind)
4278 case DESCKIND_FUNCDESC:
4279 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4281 case DESCKIND_VARDESC:
4282 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4287 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4289 if (pTypeInfo->hreftype == -1)
4290 FIXME("no hreftype for interface %p\n", pTypeInfo);
4292 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4296 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4297 *ppTInfo = (ITypeInfo *)pTypeInfo;
4298 ITypeInfo_AddRef(*ppTInfo);
4304 TRACE("name not found %s\n", debugstr_w(szName));
4308 static HRESULT WINAPI ITypeLibComp_fnBindType(
4312 ITypeInfo ** ppTInfo,
4313 ITypeComp ** ppTComp)
4315 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4319 static const ITypeCompVtbl tlbtcvt =
4322 ITypeLibComp_fnQueryInterface,
4323 ITypeLibComp_fnAddRef,
4324 ITypeLibComp_fnRelease,
4326 ITypeLibComp_fnBind,
4327 ITypeLibComp_fnBindType
4330 /*================== ITypeInfo(2) Methods ===================================*/
4331 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4333 ITypeInfoImpl * pTypeInfoImpl;
4335 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4338 pTypeInfoImpl->lpVtbl = &tinfvt;
4339 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4340 pTypeInfoImpl->ref=1;
4341 pTypeInfoImpl->hreftype = -1;
4342 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4343 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4345 TRACE("(%p)\n", pTypeInfoImpl);
4346 return (ITypeInfo2*) pTypeInfoImpl;
4349 /* ITypeInfo::QueryInterface
4351 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4356 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4358 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4361 if(IsEqualIID(riid, &IID_IUnknown) ||
4362 IsEqualIID(riid,&IID_ITypeInfo)||
4363 IsEqualIID(riid,&IID_ITypeInfo2))
4367 ITypeInfo_AddRef(iface);
4368 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4371 TRACE("-- Interface: E_NOINTERFACE\n");
4372 return E_NOINTERFACE;
4375 /* ITypeInfo::AddRef
4377 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4379 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4380 ULONG ref = InterlockedIncrement(&This->ref);
4382 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4384 TRACE("(%p)->ref is %u\n",This, ref);
4388 /* ITypeInfo::Release
4390 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4392 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4393 ULONG ref = InterlockedDecrement(&This->ref);
4395 TRACE("(%p)->(%u)\n",This, ref);
4398 /* We don't release ITypeLib when ref=0 because
4399 it means that function is called by ITypeLib2_Release */
4400 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4402 TLBFuncDesc *pFInfo, *pFInfoNext;
4403 TLBVarDesc *pVInfo, *pVInfoNext;
4404 TLBImplType *pImpl, *pImplNext;
4405 TLBRefType *pRefType,*pRefTypeNext;
4406 TLBCustData *pCustData, *pCustDataNext;
4408 TRACE("destroying ITypeInfo(%p)\n",This);
4410 if (This->no_free_data)
4415 SysFreeString(This->Name);
4419 if (This->DocString)
4421 SysFreeString(This->DocString);
4422 This->DocString = 0;
4427 SysFreeString(This->DllName);
4431 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4434 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4436 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4437 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4439 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4440 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4442 SysFreeString(pFInfo->pParamDesc[i].Name);
4444 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4445 TLB_Free(pFInfo->pParamDesc);
4446 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4448 VariantClear(&pCustData->data);
4450 pCustDataNext = pCustData->next;
4451 TLB_Free(pCustData);
4453 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4454 SysFreeString(pFInfo->Entry);
4455 SysFreeString(pFInfo->HelpString);
4456 SysFreeString(pFInfo->Name);
4458 pFInfoNext = pFInfo->next;
4461 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4463 if (pVInfo->vardesc.varkind == VAR_CONST)
4465 VariantClear(pVInfo->vardesc.u.lpvarValue);
4466 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4468 SysFreeString(pVInfo->Name);
4469 pVInfoNext = pVInfo->next;
4472 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4474 for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4476 VariantClear(&pCustData->data);
4478 pCustDataNext = pCustData->next;
4479 TLB_Free(pCustData);
4481 pImplNext = pImpl->next;
4484 for(pRefType = This->reflist; pRefType; pRefType = pRefTypeNext)
4486 pRefTypeNext = pRefType->next;
4489 TLB_Free(This->pCustData);
4494 ITypeInfo_Release((ITypeInfo*)This->next);
4497 HeapFree(GetProcessHeap(),0,This);
4503 /* ITypeInfo::GetTypeAttr
4505 * Retrieves a TYPEATTR structure that contains the attributes of the type
4509 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4510 LPTYPEATTR *ppTypeAttr)
4512 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4515 TRACE("(%p)\n",This);
4517 size = sizeof(**ppTypeAttr);
4518 if (This->TypeAttr.typekind == TKIND_ALIAS)
4519 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4521 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4523 return E_OUTOFMEMORY;
4525 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4527 if (This->TypeAttr.typekind == TKIND_ALIAS)
4528 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4529 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4531 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4532 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4534 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4535 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4540 /* ITypeInfo::GetTypeComp
4542 * Retrieves the ITypeComp interface for the type description, which enables a
4543 * client compiler to bind to the type description's members.
4546 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4547 ITypeComp * *ppTComp)
4549 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4551 TRACE("(%p)->(%p)\n", This, ppTComp);
4553 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4554 ITypeComp_AddRef(*ppTComp);
4558 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4560 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4561 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4562 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4566 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4568 memcpy(dest, src, sizeof(ELEMDESC));
4569 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4570 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4572 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4573 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4574 *buffer += sizeof(PARAMDESCEX);
4575 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4576 VariantInit(&pparamdescex_dest->varDefaultValue);
4577 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4578 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4581 dest->u.paramdesc.pparamdescex = NULL;
4585 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4587 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4588 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4591 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4595 SIZE_T size = sizeof(*src);
4599 size += sizeof(*src->lprgscode) * src->cScodes;
4600 size += TLB_SizeElemDesc(&src->elemdescFunc);
4601 for (i = 0; i < src->cParams; i++)
4603 size += sizeof(ELEMDESC);
4604 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4607 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4608 if (!dest) return E_OUTOFMEMORY;
4610 memcpy(dest, src, sizeof(FUNCDESC));
4611 buffer = (char *)(dest + 1);
4613 dest->lprgscode = (SCODE *)buffer;
4614 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4615 buffer += sizeof(*src->lprgscode) * src->cScodes;
4617 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4620 SysFreeString((BSTR)dest);
4624 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4625 buffer += sizeof(ELEMDESC) * src->cParams;
4626 for (i = 0; i < src->cParams; i++)
4628 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4634 /* undo the above actions */
4635 for (i = i - 1; i >= 0; i--)
4636 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4637 TLB_FreeElemDesc(&dest->elemdescFunc);
4638 SysFreeString((BSTR)dest);
4642 /* special treatment for dispinterfaces: this makes functions appear
4643 * to return their [retval] value when it is really returning an
4645 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4647 if (dest->cParams &&
4648 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4650 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4651 if (elemdesc->tdesc.vt != VT_PTR)
4653 ERR("elemdesc should have started with VT_PTR instead of:\n");
4655 dump_ELEMDESC(elemdesc);
4656 return E_UNEXPECTED;
4659 /* copy last parameter to the return value. we are using a flat
4660 * buffer so there is no danger of leaking memory in
4662 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4664 /* remove the last parameter */
4668 /* otherwise this function is made to appear to have no return
4670 dest->elemdescFunc.tdesc.vt = VT_VOID;
4678 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4680 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4681 const TLBFuncDesc *pFDesc;
4684 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4689 *ppFuncDesc = &pFDesc->funcdesc;
4693 return E_INVALIDARG;
4696 /* internal function to make the inherited interfaces' methods appear
4697 * part of the interface */
4698 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4699 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs)
4701 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4704 UINT implemented_funcs = 0;
4709 for (i = 0; i < This->TypeAttr.cImplTypes; i++)
4712 ITypeInfo *pSubTypeInfo;
4715 hr = ITypeInfo_GetRefTypeOfImplType(iface, i, &href);
4718 hr = ITypeInfo_GetRefTypeInfo(iface, href, &pSubTypeInfo);
4722 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4726 implemented_funcs += sub_funcs;
4727 ITypeInfo_Release(pSubTypeInfo);
4733 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4735 if (index < implemented_funcs)
4736 return E_INVALIDARG;
4737 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4741 /* ITypeInfo::GetFuncDesc
4743 * Retrieves the FUNCDESC structure that contains information about a
4744 * specified function.
4747 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4748 LPFUNCDESC *ppFuncDesc)
4750 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4751 const FUNCDESC *internal_funcdesc;
4754 TRACE("(%p) index %d\n", This, index);
4756 if ((This->TypeAttr.typekind == TKIND_DISPATCH) &&
4757 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4758 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4759 &internal_funcdesc, NULL);
4761 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4762 &internal_funcdesc);
4765 WARN("description for function %d not found\n", index);
4769 return TLB_AllocAndInitFuncDesc(
4772 This->TypeAttr.typekind == TKIND_DISPATCH);
4775 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4779 SIZE_T size = sizeof(*src);
4782 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4783 if (src->varkind == VAR_CONST)
4784 size += sizeof(VARIANT);
4785 size += TLB_SizeElemDesc(&src->elemdescVar);
4787 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4788 if (!dest) return E_OUTOFMEMORY;
4791 buffer = (char *)(dest + 1);
4792 if (src->lpstrSchema)
4795 dest->lpstrSchema = (LPOLESTR)buffer;
4796 len = strlenW(src->lpstrSchema);
4797 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4798 buffer += (len + 1) * sizeof(WCHAR);
4801 if (src->varkind == VAR_CONST)
4805 dest->u.lpvarValue = (VARIANT *)buffer;
4806 *dest->u.lpvarValue = *src->u.lpvarValue;
4807 buffer += sizeof(VARIANT);
4808 VariantInit(dest->u.lpvarValue);
4809 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4812 SysFreeString((BSTR)dest_ptr);
4816 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4819 if (src->varkind == VAR_CONST)
4820 VariantClear(dest->u.lpvarValue);
4821 SysFreeString((BSTR)dest);
4828 /* ITypeInfo::GetVarDesc
4830 * Retrieves a VARDESC structure that describes the specified variable.
4833 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4834 LPVARDESC *ppVarDesc)
4836 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4838 const TLBVarDesc *pVDesc;
4840 TRACE("(%p) index %d\n", This, index);
4842 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4846 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4848 return E_INVALIDARG;
4851 /* ITypeInfo_GetNames
4853 * Retrieves the variable with the specified member ID (or the name of the
4854 * property or method and its parameters) that correspond to the specified
4857 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4858 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4860 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4861 const TLBFuncDesc *pFDesc;
4862 const TLBVarDesc *pVDesc;
4864 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4865 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4868 /* function found, now return function and parameter names */
4869 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4872 *rgBstrNames=SysAllocString(pFDesc->Name);
4874 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4880 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4883 *rgBstrNames=SysAllocString(pVDesc->Name);
4888 if(This->TypeAttr.cImplTypes &&
4889 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4890 /* recursive search */
4893 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4895 if(SUCCEEDED(result))
4897 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4898 ITypeInfo_Release(pTInfo);
4901 WARN("Could not search inherited interface!\n");
4905 WARN("no names found\n");
4908 return TYPE_E_ELEMENTNOTFOUND;
4915 /* ITypeInfo::GetRefTypeOfImplType
4917 * If a type description describes a COM class, it retrieves the type
4918 * description of the implemented interface types. For an interface,
4919 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4923 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4928 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4931 const TLBImplType *pImpl = This->impltypelist;
4933 TRACE("(%p) index %d\n", This, index);
4934 if (TRACE_ON(ole)) dump_TypeInfo(This);
4938 /* only valid on dual interfaces;
4939 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4941 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4943 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4944 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4950 hr = TYPE_E_ELEMENTNOTFOUND;
4955 /* get element n from linked list */
4956 for(i=0; pImpl && i<index; i++)
4958 pImpl = pImpl->next;
4962 *pRefType = pImpl->hRef;
4964 hr = TYPE_E_ELEMENTNOTFOUND;
4970 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
4972 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
4978 /* ITypeInfo::GetImplTypeFlags
4980 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4981 * or base interface in a type description.
4983 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4984 UINT index, INT *pImplTypeFlags)
4986 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4990 TRACE("(%p) index %d\n", This, index);
4991 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4992 i++, pImpl=pImpl->next)
4994 if(i==index && pImpl){
4995 *pImplTypeFlags=pImpl->implflags;
4999 return TYPE_E_ELEMENTNOTFOUND;
5003 * Maps between member names and member IDs, and parameter names and
5006 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5007 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5009 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5010 const TLBFuncDesc *pFDesc;
5011 const TLBVarDesc *pVDesc;
5015 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5018 /* init out parameters in case of failure */
5019 for (i = 0; i < cNames; i++)
5020 pMemId[i] = MEMBERID_NIL;
5022 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5024 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5025 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5026 for(i=1; i < cNames; i++){
5027 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5028 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5030 if( j<pFDesc->funcdesc.cParams)
5033 ret=DISP_E_UNKNOWNNAME;
5035 TRACE("-- 0x%08x\n", ret);
5039 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5040 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5041 if(cNames) *pMemId=pVDesc->vardesc.memid;
5045 /* not found, see if it can be found in an inherited interface */
5046 if(This->TypeAttr.cImplTypes) {
5047 /* recursive search */
5049 ret=ITypeInfo_GetRefTypeInfo(iface,
5050 This->impltypelist->hRef, &pTInfo);
5052 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5053 ITypeInfo_Release(pTInfo);
5056 WARN("Could not search inherited interface!\n");
5058 WARN("no names found\n");
5059 return DISP_E_UNKNOWNNAME;
5062 /* ITypeInfo::Invoke
5064 * Invokes a method, or accesses a property of an object, that implements the
5065 * interface described by the type description.
5068 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5071 if (TRACE_ON(ole)) {
5073 TRACE("Calling %p(",func);
5074 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5086 res = func(args[0]);
5089 res = func(args[0],args[1]);
5092 res = func(args[0],args[1],args[2]);
5095 res = func(args[0],args[1],args[2],args[3]);
5098 res = func(args[0],args[1],args[2],args[3],args[4]);
5101 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5104 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5107 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5110 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5113 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5116 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5119 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
5122 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
5125 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
5128 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5131 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5134 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5137 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5140 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5143 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5146 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5149 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5152 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5155 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5161 FIXME("unsupported calling convention %d\n",callconv);
5165 TRACE("returns %08x\n",res);
5169 extern int _argsize(DWORD vt);
5171 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5174 ITypeInfo *tinfo2 = NULL;
5175 TYPEATTR *tattr = NULL;
5177 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5180 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5182 tdesc->u.hreftype, hr);
5185 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5188 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5189 ITypeInfo_Release(tinfo2);
5193 switch (tattr->typekind)
5200 tdesc = &tattr->tdescAlias;
5201 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5204 case TKIND_INTERFACE:
5205 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5211 case TKIND_DISPATCH:
5220 FIXME("TKIND_RECORD unhandled.\n");
5225 FIXME("TKIND_UNION unhandled.\n");
5230 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5234 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5235 ITypeInfo_Release(tinfo2);
5239 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5243 /* enforce only one level of pointer indirection */
5244 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5246 tdesc = tdesc->u.lptdesc;
5248 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5249 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5250 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5251 if ((tdesc->vt == VT_USERDEFINED) ||
5252 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5254 VARTYPE vt_userdefined = 0;
5255 const TYPEDESC *tdesc_userdefined = tdesc;
5256 if (tdesc->vt == VT_PTR)
5258 vt_userdefined = VT_BYREF;
5259 tdesc_userdefined = tdesc->u.lptdesc;
5261 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5263 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5264 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5266 *vt |= vt_userdefined;
5278 case VT_USERDEFINED:
5279 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5286 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5287 hr = DISP_E_BADVARTYPE;
5291 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5300 /***********************************************************************
5301 * DispCallFunc (OLEAUT32.@)
5303 * Invokes a function of the specifed calling convention, passing the
5304 * specified arguments and returns the result.
5307 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5308 * oVft [I] The offset in the vtable. See notes.
5309 * cc [I] Calling convention of the function to call.
5310 * vtReturn [I] The return type of the function.
5311 * cActuals [I] Number of parameters.
5312 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5313 * prgpvarg [I] The arguments to pass.
5314 * pvargResult [O] The return value of the function. Can be NULL.
5318 * Failure: HRESULT code.
5321 * The HRESULT return value of this function is not affected by the return
5322 * value of the user supplied function, which is returned in pvargResult.
5324 * If pvInstance is NULL then a non-object function is to be called and oVft
5325 * is the address of the function to call.
5327 * The cc parameter can be one of the following values:
5340 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5341 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5343 int i, argsize, argspos;
5347 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5348 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5349 pvargResult, V_VT(pvargResult));
5353 argsize++; /* for This pointer */
5355 for (i=0;i<cActuals;i++)
5357 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5358 dump_Variant(prgpvarg[i]);
5359 argsize += _argsize(prgvt[i]);
5361 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5366 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5370 for (i=0;i<cActuals;i++)
5372 VARIANT *arg = prgpvarg[i];
5373 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5374 if (prgvt[i] == VT_VARIANT)
5375 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5377 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5378 argspos += _argsize(prgvt[i]);
5383 FARPROC *vtable = *(FARPROC**)pvInstance;
5384 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5387 /* if we aren't invoking an object then the function pointer is stored
5389 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5391 if (pvargResult && (vtReturn != VT_EMPTY))
5393 TRACE("Method returned 0x%08x\n",hres);
5394 V_VT(pvargResult) = vtReturn;
5395 V_UI4(pvargResult) = hres;
5398 HeapFree(GetProcessHeap(),0,args);
5402 #define INVBUF_ELEMENT_SIZE \
5403 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5404 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5405 ((VARIANTARG *)(buffer))
5406 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5407 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5408 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5409 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5410 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5411 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5413 static HRESULT WINAPI ITypeInfo_fnInvoke(
5418 DISPPARAMS *pDispParams,
5419 VARIANT *pVarResult,
5420 EXCEPINFO *pExcepInfo,
5423 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5425 unsigned int var_index;
5428 const TLBFuncDesc *pFuncInfo;
5430 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5431 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5436 ERR("NULL pDispParams not allowed\n");
5437 return E_INVALIDARG;
5440 dump_DispParms(pDispParams);
5442 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5444 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5445 pDispParams->cNamedArgs, pDispParams->cArgs);
5446 return E_INVALIDARG;
5449 /* we do this instead of using GetFuncDesc since it will return a fake
5450 * FUNCDESC for dispinterfaces and we want the real function description */
5451 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5452 if ((memid == pFuncInfo->funcdesc.memid) &&
5453 (wFlags & pFuncInfo->funcdesc.invkind))
5457 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5461 TRACE("invoking:\n");
5462 dump_TLBFuncDescOne(pFuncInfo);
5465 switch (func_desc->funckind) {
5466 case FUNC_PUREVIRTUAL:
5467 case FUNC_VIRTUAL: {
5468 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5470 VARIANT retval; /* pointer for storing byref retvals in */
5471 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5472 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5473 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5474 UINT cNamedArgs = pDispParams->cNamedArgs;
5475 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5479 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5481 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5483 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5484 hres = DISP_E_PARAMNOTFOUND;
5487 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5489 rgdispidNamedArgs++;
5492 for (i = 0; i < func_desc->cParams; i++)
5494 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5495 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5500 TRACE("changing args\n");
5501 for (i = 0; i < func_desc->cParams; i++)
5503 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5504 VARIANTARG *src_arg;
5510 for (j = 0; j < cNamedArgs; j++)
5511 if (rgdispidNamedArgs[j] == i)
5513 src_arg = &pDispParams->rgvarg[j];
5518 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5520 if (wParamFlags & PARAMFLAG_FRETVAL)
5522 /* under most conditions the caller is not allowed to
5523 * pass in a dispparam arg in the index of what would be
5524 * the retval parameter. however, there is an exception
5525 * where the extra parameter is used in an extra
5526 * IDispatch::Invoke below */
5527 if ((i < pDispParams->cArgs) &&
5528 ((func_desc->cParams != 1) || !pVarResult ||
5529 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5531 hres = DISP_E_BADPARAMCOUNT;
5535 /* note: this check is placed so that if the caller passes
5536 * in a VARIANTARG for the retval we just ignore it, like
5538 if (i == func_desc->cParams - 1)
5541 arg = prgpvarg[i] = &rgvarg[i];
5542 memset(arg, 0, sizeof(*arg));
5543 V_VT(arg) = rgvt[i];
5544 memset(&retval, 0, sizeof(retval));
5545 V_BYREF(arg) = &retval;
5549 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5550 hres = E_UNEXPECTED;
5556 dump_Variant(src_arg);
5558 if (rgvt[i] == VT_VARIANT)
5559 hres = VariantCopy(&rgvarg[i], src_arg);
5560 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5562 if (rgvt[i] == V_VT(src_arg))
5563 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5566 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5567 hres = VariantCopy(&missing_arg[i], src_arg);
5568 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5570 V_VT(&rgvarg[i]) = rgvt[i];
5572 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5574 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5575 V_VT(&missing_arg[i]) = V_VT(src_arg);
5576 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5577 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5578 V_VT(&rgvarg[i]) = rgvt[i];
5580 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5582 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5583 V_VT(&rgvarg[i]) = rgvt[i];
5587 /* FIXME: this doesn't work for VT_BYREF arguments if
5588 * they are not the same type as in the paramdesc */
5589 V_VT(&rgvarg[i]) = V_VT(src_arg);
5590 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5591 V_VT(&rgvarg[i]) = rgvt[i];
5596 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5597 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5598 debugstr_VT(src_arg), debugstr_VF(src_arg));
5601 prgpvarg[i] = &rgvarg[i];
5603 else if (wParamFlags & PARAMFLAG_FOPT)
5606 arg = prgpvarg[i] = &rgvarg[i];
5607 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5609 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5615 VARIANTARG *missing_arg;
5616 /* if the function wants a pointer to a variant then
5617 * set that up, otherwise just pass the VT_ERROR in
5618 * the argument by value */
5619 if (rgvt[i] & VT_BYREF)
5621 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5622 V_VT(arg) = VT_VARIANT | VT_BYREF;
5623 V_VARIANTREF(arg) = missing_arg;
5627 V_VT(missing_arg) = VT_ERROR;
5628 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5633 hres = DISP_E_BADPARAMCOUNT;
5637 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5638 if (func_desc->cParamsOpt < 0)
5640 FIXME("Does not support safearray optional parameters\n");
5641 hres = DISP_E_BADPARAMCOUNT;
5642 goto func_fail; /* FIXME: we don't free changed types here */
5645 /* VT_VOID is a special case for return types, so it is not
5646 * handled in the general function */
5647 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5648 V_VT(&varresult) = VT_EMPTY;
5651 V_VT(&varresult) = 0;
5652 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5653 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5656 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5657 V_VT(&varresult), func_desc->cParams, rgvt,
5658 prgpvarg, &varresult);
5660 for (i = 0; i < func_desc->cParams; i++)
5662 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5663 if (wParamFlags & PARAMFLAG_FRETVAL)
5667 TRACE("[retval] value: ");
5668 dump_Variant(prgpvarg[i]);
5673 VariantInit(pVarResult);
5674 /* deref return value */
5675 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5678 /* free data stored in varresult. Note that
5679 * VariantClear doesn't do what we want because we are
5680 * working with byref types. */
5681 /* FIXME: clear safearrays, bstrs, records and
5682 * variants here too */
5683 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5684 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5686 if(*V_UNKNOWNREF(prgpvarg[i]))
5687 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5691 else if (i < pDispParams->cArgs)
5693 if (wParamFlags & PARAMFLAG_FOUT)
5695 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5697 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5698 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5702 ERR("failed to convert param %d to vt %d\n", i,
5703 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5707 VariantClear(&rgvarg[i]);
5709 else if (wParamFlags & PARAMFLAG_FOPT)
5711 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5712 VariantClear(&rgvarg[i]);
5716 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5718 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5719 hres = DISP_E_EXCEPTION;
5722 IErrorInfo *pErrorInfo;
5723 pExcepInfo->scode = V_ERROR(&varresult);
5724 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
5726 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
5727 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
5728 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
5729 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
5731 IErrorInfo_Release(pErrorInfo);
5735 if (V_VT(&varresult) != VT_ERROR)
5737 TRACE("varresult value: ");
5738 dump_Variant(&varresult);
5742 VariantClear(pVarResult);
5743 *pVarResult = varresult;
5746 VariantClear(&varresult);
5749 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
5750 (wFlags == INVOKE_PROPERTYGET) &&
5751 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
5752 (pDispParams->cArgs != 0))
5754 if (V_VT(pVarResult) == VT_DISPATCH)
5756 IDispatch *pDispatch = V_DISPATCH(pVarResult);
5757 /* Note: not VariantClear; we still need the dispatch
5758 * pointer to be valid */
5759 VariantInit(pVarResult);
5760 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
5761 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
5762 pDispParams, pVarResult, pExcepInfo, pArgErr);
5763 IDispatch_Release(pDispatch);
5767 VariantClear(pVarResult);
5768 hres = DISP_E_NOTACOLLECTION;
5773 HeapFree(GetProcessHeap(), 0, buffer);
5776 case FUNC_DISPATCH: {
5779 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5780 if (SUCCEEDED(hres)) {
5781 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5782 hres = IDispatch_Invoke(
5783 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5784 pVarResult,pExcepInfo,pArgErr
5787 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5788 IDispatch_Release(disp);
5790 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5794 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5799 TRACE("-- 0x%08x\n", hres);
5802 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5805 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5806 if(FAILED(hres)) return hres;
5808 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5809 dump_VARDESC(var_desc);
5810 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5814 /* not found, look for it in inherited interfaces */
5815 ITypeInfo2_GetTypeKind(iface, &type_kind);
5816 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5818 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5819 /* recursive search */
5821 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5822 if(SUCCEEDED(hres)){
5823 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5824 ITypeInfo_Release(pTInfo);
5827 WARN("Could not search inherited interface!\n");
5830 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
5831 return DISP_E_MEMBERNOTFOUND;
5834 /* ITypeInfo::GetDocumentation
5836 * Retrieves the documentation string, the complete Help file name and path,
5837 * and the context ID for the Help topic for a specified type description.
5839 * (Can be tested by the Visual Basic Editor in Word for instance.)
5841 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5842 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5843 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5845 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5846 const TLBFuncDesc *pFDesc;
5847 const TLBVarDesc *pVDesc;
5848 TRACE("(%p) memid %d Name(%p) DocString(%p)"
5849 " HelpContext(%p) HelpFile(%p)\n",
5850 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5851 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5853 *pBstrName=SysAllocString(This->Name);
5855 *pBstrDocString=SysAllocString(This->DocString);
5857 *pdwHelpContext=This->dwHelpContext;
5859 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5861 }else {/* for a member */
5862 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5863 if(pFDesc->funcdesc.memid==memid){
5865 *pBstrName = SysAllocString(pFDesc->Name);
5867 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5869 *pdwHelpContext=pFDesc->helpcontext;
5872 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5873 if(pVDesc->vardesc.memid==memid){
5875 *pBstrName = SysAllocString(pVDesc->Name);
5877 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5879 *pdwHelpContext=pVDesc->HelpContext;
5884 if(This->TypeAttr.cImplTypes &&
5885 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5886 /* recursive search */
5889 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5891 if(SUCCEEDED(result)) {
5892 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
5893 pBstrDocString, pdwHelpContext, pBstrHelpFile);
5894 ITypeInfo_Release(pTInfo);
5897 WARN("Could not search inherited interface!\n");
5900 WARN("member %d not found\n", memid);
5901 return TYPE_E_ELEMENTNOTFOUND;
5904 /* ITypeInfo::GetDllEntry
5906 * Retrieves a description or specification of an entry point for a function
5909 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5910 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5913 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5914 const TLBFuncDesc *pFDesc;
5916 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5918 if (pBstrDllName) *pBstrDllName = NULL;
5919 if (pBstrName) *pBstrName = NULL;
5920 if (pwOrdinal) *pwOrdinal = 0;
5922 if (This->TypeAttr.typekind != TKIND_MODULE)
5923 return TYPE_E_BADMODULEKIND;
5925 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5926 if(pFDesc->funcdesc.memid==memid){
5927 dump_TypeInfo(This);
5929 dump_TLBFuncDescOne(pFDesc);
5932 *pBstrDllName = SysAllocString(This->DllName);
5934 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5936 *pBstrName = SysAllocString(pFDesc->Entry);
5944 *pwOrdinal = (DWORD)pFDesc->Entry;
5947 return TYPE_E_ELEMENTNOTFOUND;
5950 /* ITypeInfo::GetRefTypeInfo
5952 * If a type description references other type descriptions, it retrieves
5953 * the referenced type descriptions.
5955 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5958 ITypeInfo **ppTInfo)
5960 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5961 HRESULT result = E_FAIL;
5963 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5965 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5966 ITypeInfo_AddRef(*ppTInfo);
5969 else if (hRefType == -1 &&
5970 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5971 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5973 /* when we meet a DUAL dispinterface, we must create the interface
5976 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5979 /* the interface version contains the same information as the dispinterface
5980 * copy the contents of the structs.
5982 *pTypeInfoImpl = *This;
5983 pTypeInfoImpl->ref = 0;
5985 /* change the type to interface */
5986 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5988 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5990 /* we use data structures from This, so we need to keep a reference
5991 * to it to stop it being destroyed and signal to the new instance to
5992 * not free its data structures when it is destroyed */
5993 pTypeInfoImpl->no_free_data = TRUE;
5994 pTypeInfoImpl->next = This;
5995 ITypeInfo_AddRef((ITypeInfo*) This);
5997 ITypeInfo_AddRef(*ppTInfo);
6002 TLBRefType *pRefType;
6003 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
6004 if(pRefType->reference == hRefType)
6008 FIXME("Can't find pRefType for ref %x\n", hRefType);
6009 if(pRefType && hRefType != -1) {
6010 ITypeLib *pTLib = NULL;
6012 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
6014 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6016 if(pRefType->pImpTLInfo->pImpTypeLib) {
6017 TRACE("typeinfo in imported typelib that is already loaded\n");
6018 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
6019 ITypeLib2_AddRef((ITypeLib*) pTLib);
6022 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6023 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
6024 pRefType->pImpTLInfo->wVersionMajor,
6025 pRefType->pImpTLInfo->wVersionMinor,
6026 pRefType->pImpTLInfo->lcid,
6029 if(!SUCCEEDED(result)) {
6030 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
6031 result=LoadTypeLib(libnam, &pTLib);
6032 SysFreeString(libnam);
6034 if(SUCCEEDED(result)) {
6035 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6036 ITypeLib2_AddRef(pTLib);
6040 if(SUCCEEDED(result)) {
6041 if(pRefType->index == TLB_REF_USE_GUID)
6042 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6046 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
6050 ITypeLib2_Release(pTLib);
6054 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6055 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6059 /* ITypeInfo::AddressOfMember
6061 * Retrieves the addresses of static functions or variables, such as those
6064 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6065 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6067 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6073 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6075 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6079 module = LoadLibraryW(dll);
6082 ERR("couldn't load %s\n", debugstr_w(dll));
6084 if (entry) SysFreeString(entry);
6085 return STG_E_FILENOTFOUND;
6087 /* FIXME: store library somewhere where we can free it */
6092 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6093 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6094 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6096 *ppv = GetProcAddress(module, entryA);
6098 ERR("function not found %s\n", debugstr_a(entryA));
6100 HeapFree(GetProcessHeap(), 0, entryA);
6104 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6106 ERR("function not found %d\n", ordinal);
6110 if (entry) SysFreeString(entry);
6113 return TYPE_E_DLLFUNCTIONNOTFOUND;
6118 /* ITypeInfo::CreateInstance
6120 * Creates a new instance of a type that describes a component object class
6123 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6124 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6126 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6130 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6136 WARN("Not able to aggregate\n");
6137 return CLASS_E_NOAGGREGATION;
6140 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6141 if(FAILED(hr)) return hr;
6143 if(pTA->typekind != TKIND_COCLASS)
6145 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6151 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6154 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6155 TRACE("GetActiveObject rets %08x\n", hr);
6158 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6159 IUnknown_Release(pUnk);
6164 hr = CoCreateInstance(&pTA->guid, NULL,
6165 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6169 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6173 /* ITypeInfo::GetMops
6175 * Retrieves marshalling information.
6177 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6180 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6181 FIXME("(%p) stub!\n", This);
6185 /* ITypeInfo::GetContainingTypeLib
6187 * Retrieves the containing type library and the index of the type description
6188 * within that type library.
6190 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6191 ITypeLib * *ppTLib, UINT *pIndex)
6193 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6195 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6197 *pIndex=This->index;
6198 TRACE("returning pIndex=%d\n", *pIndex);
6202 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6203 ITypeLib2_AddRef(*ppTLib);
6204 TRACE("returning ppTLib=%p\n", *ppTLib);
6210 /* ITypeInfo::ReleaseTypeAttr
6212 * Releases a TYPEATTR previously returned by GetTypeAttr.
6215 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6216 TYPEATTR* pTypeAttr)
6218 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6219 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6220 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6223 /* ITypeInfo::ReleaseFuncDesc
6225 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6227 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6229 FUNCDESC *pFuncDesc)
6231 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6234 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6236 for (i = 0; i < pFuncDesc->cParams; i++)
6237 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6238 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6240 SysFreeString((BSTR)pFuncDesc);
6243 /* ITypeInfo::ReleaseVarDesc
6245 * Releases a VARDESC previously returned by GetVarDesc.
6247 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6251 TRACE("(%p)->(%p)\n", This, pVarDesc);
6253 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6254 if (pVarDesc->varkind == VAR_CONST)
6255 VariantClear(pVarDesc->u.lpvarValue);
6256 SysFreeString((BSTR)pVarDesc);
6259 /* ITypeInfo2::GetTypeKind
6261 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6264 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6265 TYPEKIND *pTypeKind)
6267 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6268 *pTypeKind=This->TypeAttr.typekind;
6269 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6273 /* ITypeInfo2::GetTypeFlags
6275 * Returns the type flags without any allocations. This returns a DWORD type
6276 * flag, which expands the type flags without growing the TYPEATTR (type
6280 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6282 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6283 *pTypeFlags=This->TypeAttr.wTypeFlags;
6284 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6288 /* ITypeInfo2::GetFuncIndexOfMemId
6289 * Binds to a specific member based on a known DISPID, where the member name
6290 * is not known (for example, when binding to a default member).
6293 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6294 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6296 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6297 const TLBFuncDesc *pFuncInfo;
6301 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6302 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6308 result = TYPE_E_ELEMENTNOTFOUND;
6310 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6311 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6315 /* TypeInfo2::GetVarIndexOfMemId
6317 * Binds to a specific member based on a known DISPID, where the member name
6318 * is not known (for example, when binding to a default member).
6321 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6322 MEMBERID memid, UINT *pVarIndex)
6324 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6325 TLBVarDesc *pVarInfo;
6328 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6329 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6335 result = TYPE_E_ELEMENTNOTFOUND;
6337 TRACE("(%p) memid 0x%08x -> %s\n", This,
6338 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6342 /* ITypeInfo2::GetCustData
6344 * Gets the custom data
6346 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6351 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6352 TLBCustData *pCData;
6354 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6355 if( IsEqualIID(guid, &pCData->guid)) break;
6357 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6361 VariantInit( pVarVal);
6362 VariantCopy( pVarVal, &pCData->data);
6365 return E_INVALIDARG; /* FIXME: correct? */
6368 /* ITypeInfo2::GetFuncCustData
6370 * Gets the custom data
6372 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6378 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6379 TLBCustData *pCData=NULL;
6380 TLBFuncDesc * pFDesc;
6382 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6383 pFDesc=pFDesc->next);
6386 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6387 if( IsEqualIID(guid, &pCData->guid)) break;
6389 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6392 VariantInit( pVarVal);
6393 VariantCopy( pVarVal, &pCData->data);
6396 return E_INVALIDARG; /* FIXME: correct? */
6399 /* ITypeInfo2::GetParamCustData
6401 * Gets the custom data
6403 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6410 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6411 TLBCustData *pCData=NULL;
6412 TLBFuncDesc * pFDesc;
6415 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6417 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6418 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6419 pCData = pCData->next)
6420 if( IsEqualIID(guid, &pCData->guid)) break;
6422 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6426 VariantInit( pVarVal);
6427 VariantCopy( pVarVal, &pCData->data);
6430 return E_INVALIDARG; /* FIXME: correct? */
6433 /* ITypeInfo2::GetVarCustData
6435 * Gets the custom data
6437 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6443 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6444 TLBCustData *pCData=NULL;
6445 TLBVarDesc * pVDesc;
6448 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6452 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6454 if( IsEqualIID(guid, &pCData->guid)) break;
6458 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6462 VariantInit( pVarVal);
6463 VariantCopy( pVarVal, &pCData->data);
6466 return E_INVALIDARG; /* FIXME: correct? */
6469 /* ITypeInfo2::GetImplCustData
6471 * Gets the custom data
6473 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6479 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6480 TLBCustData *pCData=NULL;
6481 TLBImplType * pRDesc;
6484 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6488 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6490 if( IsEqualIID(guid, &pCData->guid)) break;
6494 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6498 VariantInit( pVarVal);
6499 VariantCopy( pVarVal, &pCData->data);
6502 return E_INVALIDARG; /* FIXME: correct? */
6505 /* ITypeInfo2::GetDocumentation2
6507 * Retrieves the documentation string, the complete Help file name and path,
6508 * the localization context to use, and the context ID for the library Help
6509 * topic in the Help file.
6512 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6516 BSTR *pbstrHelpString,
6517 DWORD *pdwHelpStringContext,
6518 BSTR *pbstrHelpStringDll)
6520 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6521 const TLBFuncDesc *pFDesc;
6522 const TLBVarDesc *pVDesc;
6523 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6524 "HelpStringContext(%p) HelpStringDll(%p)\n",
6525 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6526 pbstrHelpStringDll );
6527 /* the help string should be obtained from the helpstringdll,
6528 * using the _DLLGetDocumentation function, based on the supplied
6529 * lcid. Nice to do sometime...
6531 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6533 *pbstrHelpString=SysAllocString(This->Name);
6534 if(pdwHelpStringContext)
6535 *pdwHelpStringContext=This->dwHelpStringContext;
6536 if(pbstrHelpStringDll)
6537 *pbstrHelpStringDll=
6538 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6540 }else {/* for a member */
6541 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6542 if(pFDesc->funcdesc.memid==memid){
6544 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6545 if(pdwHelpStringContext)
6546 *pdwHelpStringContext=pFDesc->HelpStringContext;
6547 if(pbstrHelpStringDll)
6548 *pbstrHelpStringDll=
6549 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6552 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6553 if(pVDesc->vardesc.memid==memid){
6555 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6556 if(pdwHelpStringContext)
6557 *pdwHelpStringContext=pVDesc->HelpStringContext;
6558 if(pbstrHelpStringDll)
6559 *pbstrHelpStringDll=
6560 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6564 return TYPE_E_ELEMENTNOTFOUND;
6567 /* ITypeInfo2::GetAllCustData
6569 * Gets all custom data items for the Type info.
6572 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6574 CUSTDATA *pCustData)
6576 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6577 TLBCustData *pCData;
6580 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6582 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6583 if(pCustData->prgCustData ){
6584 pCustData->cCustData=This->ctCustData;
6585 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6586 pCustData->prgCustData[i].guid=pCData->guid;
6587 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6590 ERR(" OUT OF MEMORY!\n");
6591 return E_OUTOFMEMORY;
6596 /* ITypeInfo2::GetAllFuncCustData
6598 * Gets all custom data items for the specified Function
6601 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6604 CUSTDATA *pCustData)
6606 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6607 TLBCustData *pCData;
6608 TLBFuncDesc * pFDesc;
6610 TRACE("(%p) index %d\n", This, index);
6611 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6612 pFDesc=pFDesc->next)
6615 pCustData->prgCustData =
6616 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6617 if(pCustData->prgCustData ){
6618 pCustData->cCustData=pFDesc->ctCustData;
6619 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6620 pCData = pCData->next){
6621 pCustData->prgCustData[i].guid=pCData->guid;
6622 VariantCopy(& pCustData->prgCustData[i].varValue,
6626 ERR(" OUT OF MEMORY!\n");
6627 return E_OUTOFMEMORY;
6631 return TYPE_E_ELEMENTNOTFOUND;
6634 /* ITypeInfo2::GetAllParamCustData
6636 * Gets all custom data items for the Functions
6639 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6640 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6642 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6643 TLBCustData *pCData=NULL;
6644 TLBFuncDesc * pFDesc;
6646 TRACE("(%p) index %d\n", This, indexFunc);
6647 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6648 pFDesc=pFDesc->next)
6650 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6651 pCustData->prgCustData =
6652 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6653 sizeof(CUSTDATAITEM));
6654 if(pCustData->prgCustData ){
6655 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6656 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6657 pCData; i++, pCData = pCData->next){
6658 pCustData->prgCustData[i].guid=pCData->guid;
6659 VariantCopy(& pCustData->prgCustData[i].varValue,
6663 ERR(" OUT OF MEMORY!\n");
6664 return E_OUTOFMEMORY;
6668 return TYPE_E_ELEMENTNOTFOUND;
6671 /* ITypeInfo2::GetAllVarCustData
6673 * Gets all custom data items for the specified Variable
6676 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6677 UINT index, CUSTDATA *pCustData)
6679 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6680 TLBCustData *pCData;
6681 TLBVarDesc * pVDesc;
6683 TRACE("(%p) index %d\n", This, index);
6684 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6685 pVDesc=pVDesc->next)
6688 pCustData->prgCustData =
6689 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6690 if(pCustData->prgCustData ){
6691 pCustData->cCustData=pVDesc->ctCustData;
6692 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6693 pCData = pCData->next){
6694 pCustData->prgCustData[i].guid=pCData->guid;
6695 VariantCopy(& pCustData->prgCustData[i].varValue,
6699 ERR(" OUT OF MEMORY!\n");
6700 return E_OUTOFMEMORY;
6704 return TYPE_E_ELEMENTNOTFOUND;
6707 /* ITypeInfo2::GetAllImplCustData
6709 * Gets all custom data items for the specified implementation type
6712 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6715 CUSTDATA *pCustData)
6717 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6718 TLBCustData *pCData;
6719 TLBImplType * pRDesc;
6721 TRACE("(%p) index %d\n", This, index);
6722 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6723 pRDesc=pRDesc->next)
6726 pCustData->prgCustData =
6727 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6728 if(pCustData->prgCustData ){
6729 pCustData->cCustData=pRDesc->ctCustData;
6730 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6731 pCData = pCData->next){
6732 pCustData->prgCustData[i].guid=pCData->guid;
6733 VariantCopy(& pCustData->prgCustData[i].varValue,
6737 ERR(" OUT OF MEMORY!\n");
6738 return E_OUTOFMEMORY;
6742 return TYPE_E_ELEMENTNOTFOUND;
6745 static const ITypeInfo2Vtbl tinfvt =
6748 ITypeInfo_fnQueryInterface,
6750 ITypeInfo_fnRelease,
6752 ITypeInfo_fnGetTypeAttr,
6753 ITypeInfo_fnGetTypeComp,
6754 ITypeInfo_fnGetFuncDesc,
6755 ITypeInfo_fnGetVarDesc,
6756 ITypeInfo_fnGetNames,
6757 ITypeInfo_fnGetRefTypeOfImplType,
6758 ITypeInfo_fnGetImplTypeFlags,
6759 ITypeInfo_fnGetIDsOfNames,
6761 ITypeInfo_fnGetDocumentation,
6762 ITypeInfo_fnGetDllEntry,
6763 ITypeInfo_fnGetRefTypeInfo,
6764 ITypeInfo_fnAddressOfMember,
6765 ITypeInfo_fnCreateInstance,
6766 ITypeInfo_fnGetMops,
6767 ITypeInfo_fnGetContainingTypeLib,
6768 ITypeInfo_fnReleaseTypeAttr,
6769 ITypeInfo_fnReleaseFuncDesc,
6770 ITypeInfo_fnReleaseVarDesc,
6772 ITypeInfo2_fnGetTypeKind,
6773 ITypeInfo2_fnGetTypeFlags,
6774 ITypeInfo2_fnGetFuncIndexOfMemId,
6775 ITypeInfo2_fnGetVarIndexOfMemId,
6776 ITypeInfo2_fnGetCustData,
6777 ITypeInfo2_fnGetFuncCustData,
6778 ITypeInfo2_fnGetParamCustData,
6779 ITypeInfo2_fnGetVarCustData,
6780 ITypeInfo2_fnGetImplTypeCustData,
6781 ITypeInfo2_fnGetDocumentation2,
6782 ITypeInfo2_fnGetAllCustData,
6783 ITypeInfo2_fnGetAllFuncCustData,
6784 ITypeInfo2_fnGetAllParamCustData,
6785 ITypeInfo2_fnGetAllVarCustData,
6786 ITypeInfo2_fnGetAllImplTypeCustData,
6789 /******************************************************************************
6790 * CreateDispTypeInfo [OLEAUT32.31]
6792 * Build type information for an object so it can be called through an
6793 * IDispatch interface.
6796 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6797 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6800 * This call allows an objects methods to be accessed through IDispatch, by
6801 * building an ITypeInfo object that IDispatch can use to call through.
6803 HRESULT WINAPI CreateDispTypeInfo(
6804 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6805 LCID lcid, /* [I] Locale Id */
6806 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6808 ITypeInfoImpl *pTIClass, *pTIIface;
6809 ITypeLibImpl *pTypeLibImpl;
6811 TLBFuncDesc **ppFuncDesc;
6814 pTypeLibImpl = TypeLibImpl_Constructor();
6815 if (!pTypeLibImpl) return E_FAIL;
6817 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6818 pTIIface->pTypeLib = pTypeLibImpl;
6819 pTIIface->index = 0;
6820 pTIIface->Name = NULL;
6821 pTIIface->dwHelpContext = -1;
6822 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6823 pTIIface->TypeAttr.lcid = lcid;
6824 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6825 pTIIface->TypeAttr.wMajorVerNum = 0;
6826 pTIIface->TypeAttr.wMinorVerNum = 0;
6827 pTIIface->TypeAttr.cbAlignment = 2;
6828 pTIIface->TypeAttr.cbSizeInstance = -1;
6829 pTIIface->TypeAttr.cbSizeVft = -1;
6830 pTIIface->TypeAttr.cFuncs = 0;
6831 pTIIface->TypeAttr.cImplTypes = 0;
6832 pTIIface->TypeAttr.cVars = 0;
6833 pTIIface->TypeAttr.wTypeFlags = 0;
6835 ppFuncDesc = &pTIIface->funclist;
6836 for(func = 0; func < pidata->cMembers; func++) {
6837 METHODDATA *md = pidata->pmethdata + func;
6838 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6839 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6840 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6841 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
6842 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6843 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6844 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6845 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6846 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6847 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6848 (*ppFuncDesc)->funcdesc.cScodes = 0;
6849 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6850 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6851 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6852 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6853 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6854 md->cArgs * sizeof(ELEMDESC));
6855 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6856 md->cArgs * sizeof(TLBParDesc));
6857 for(param = 0; param < md->cArgs; param++) {
6858 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6859 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6861 (*ppFuncDesc)->helpcontext = 0;
6862 (*ppFuncDesc)->HelpStringContext = 0;
6863 (*ppFuncDesc)->HelpString = NULL;
6864 (*ppFuncDesc)->Entry = NULL;
6865 (*ppFuncDesc)->ctCustData = 0;
6866 (*ppFuncDesc)->pCustData = NULL;
6867 (*ppFuncDesc)->next = NULL;
6868 ppFuncDesc = &(*ppFuncDesc)->next;
6871 dump_TypeInfo(pTIIface);
6873 pTypeLibImpl->pTypeInfo = pTIIface;
6874 pTypeLibImpl->TypeInfoCount++;
6876 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6877 pTIClass->pTypeLib = pTypeLibImpl;
6878 pTIClass->index = 1;
6879 pTIClass->Name = NULL;
6880 pTIClass->dwHelpContext = -1;
6881 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6882 pTIClass->TypeAttr.lcid = lcid;
6883 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6884 pTIClass->TypeAttr.wMajorVerNum = 0;
6885 pTIClass->TypeAttr.wMinorVerNum = 0;
6886 pTIClass->TypeAttr.cbAlignment = 2;
6887 pTIClass->TypeAttr.cbSizeInstance = -1;
6888 pTIClass->TypeAttr.cbSizeVft = -1;
6889 pTIClass->TypeAttr.cFuncs = 0;
6890 pTIClass->TypeAttr.cImplTypes = 1;
6891 pTIClass->TypeAttr.cVars = 0;
6892 pTIClass->TypeAttr.wTypeFlags = 0;
6894 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6895 pTIClass->impltypelist->hRef = 1;
6897 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6898 pTIClass->reflist->index = 0;
6899 pTIClass->reflist->reference = 1;
6900 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6902 dump_TypeInfo(pTIClass);
6904 pTIIface->next = pTIClass;
6905 pTypeLibImpl->TypeInfoCount++;
6907 *pptinfo = (ITypeInfo*)pTIClass;
6909 ITypeInfo_AddRef(*pptinfo);
6910 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
6916 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6918 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6920 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6923 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6925 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6927 return ITypeInfo_AddRef((ITypeInfo *)This);
6930 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6932 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6934 return ITypeInfo_Release((ITypeInfo *)This);
6937 static HRESULT WINAPI ITypeComp_fnBind(
6942 ITypeInfo ** ppTInfo,
6943 DESCKIND * pDescKind,
6946 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6947 const TLBFuncDesc *pFDesc;
6948 const TLBVarDesc *pVDesc;
6949 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6951 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6953 *pDescKind = DESCKIND_NONE;
6954 pBindPtr->lpfuncdesc = NULL;
6957 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6958 if (!strcmpiW(pFDesc->Name, szName)) {
6959 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6962 /* name found, but wrong flags */
6963 hr = TYPE_E_TYPEMISMATCH;
6968 HRESULT hr = TLB_AllocAndInitFuncDesc(
6970 &pBindPtr->lpfuncdesc,
6971 This->TypeAttr.typekind == TKIND_DISPATCH);
6974 *pDescKind = DESCKIND_FUNCDESC;
6975 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6976 ITypeInfo_AddRef(*ppTInfo);
6979 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6980 if (!strcmpiW(pVDesc->Name, szName)) {
6981 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6984 *pDescKind = DESCKIND_VARDESC;
6985 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6986 ITypeInfo_AddRef(*ppTInfo);
6991 /* FIXME: search each inherited interface, not just the first */
6992 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6993 /* recursive search */
6997 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7000 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7001 ITypeInfo_Release(pTInfo);
7005 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7006 ITypeComp_Release(pTComp);
7009 WARN("Could not search inherited interface!\n");
7011 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7015 static HRESULT WINAPI ITypeComp_fnBindType(
7019 ITypeInfo ** ppTInfo,
7020 ITypeComp ** ppTComp)
7022 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7024 /* strange behaviour (does nothing) but like the
7027 if (!ppTInfo || !ppTComp)
7036 static const ITypeCompVtbl tcompvt =
7039 ITypeComp_fnQueryInterface,
7041 ITypeComp_fnRelease,
7044 ITypeComp_fnBindType