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"
73 #include "wine/list.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
79 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
81 /****************************************************************************
84 * Takes p_iVal (which is in little endian) and returns it
85 * in the host machine's byte order.
87 #ifdef WORDS_BIGENDIAN
88 static WORD FromLEWord(WORD p_iVal)
90 return (((p_iVal & 0x00FF) << 8) |
91 ((p_iVal & 0xFF00) >> 8));
95 static DWORD FromLEDWord(DWORD p_iVal)
97 return (((p_iVal & 0x000000FF) << 24) |
98 ((p_iVal & 0x0000FF00) << 8) |
99 ((p_iVal & 0x00FF0000) >> 8) |
100 ((p_iVal & 0xFF000000) >> 24));
103 #define FromLEWord(X) (X)
104 #define FromLEDWord(X) (X)
108 /****************************************************************************
111 * Fix byte order in any structure if necessary
113 #ifdef WORDS_BIGENDIAN
114 static void FromLEWords(void *p_Val, int p_iSize)
118 p_iSize /= sizeof(WORD);
121 *Val = FromLEWord(*Val);
128 static void FromLEDWords(void *p_Val, int p_iSize)
132 p_iSize /= sizeof(DWORD);
135 *Val = FromLEDWord(*Val);
141 #define FromLEWords(X,Y) /*nothing*/
142 #define FromLEDWords(X,Y) /*nothing*/
146 * Find a typelib key which matches a requested maj.min version.
148 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
150 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
157 memcpy( buffer, typelibW, sizeof(typelibW) );
158 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
160 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
163 len = sizeof(key_name);
165 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
169 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
171 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
178 break; /* exact match */
180 if (v_min > best_min) best_min = v_min;
183 len = sizeof(key_name);
194 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
195 /* buffer must be at least 60 characters long */
196 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
198 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
199 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
201 memcpy( buffer, TypelibW, sizeof(TypelibW) );
202 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
203 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
207 /* get the path of an interface key, in the form "Interface\\<guid>" */
208 /* buffer must be at least 50 characters long */
209 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
211 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
213 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
214 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
218 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
219 /* buffer must be at least 16 characters long */
220 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
222 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
223 static const WCHAR win16W[] = {'w','i','n','1','6',0};
224 static const WCHAR win32W[] = {'w','i','n','3','2',0};
226 sprintfW( buffer, LcidFormatW, lcid );
229 case SYS_WIN16: strcatW( buffer, win16W ); break;
230 case SYS_WIN32: strcatW( buffer, win32W ); break;
232 TRACE("Typelib is for unsupported syskind %i\n", syskind);
238 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
241 /****************************************************************************
242 * QueryPathOfRegTypeLib [OLEAUT32.164]
244 * Gets the path to a registered type library.
247 * guid [I] referenced guid
248 * wMaj [I] major version
249 * wMin [I] minor version
251 * path [O] path of typelib
255 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
256 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
259 HRESULT WINAPI QueryPathOfRegTypeLib(
266 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
270 WCHAR Path[MAX_PATH];
273 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
275 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
276 get_typelib_key( guid, wMaj, wMin, buffer );
278 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
279 if (res == ERROR_FILE_NOT_FOUND)
281 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
282 return TYPE_E_LIBNOTREGISTERED;
284 else if (res != ERROR_SUCCESS)
286 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
287 return TYPE_E_REGISTRYACCESS;
292 LONG dwPathLen = sizeof(Path);
294 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
296 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
300 else if (myLCID == lcid)
302 /* try with sub-langid */
303 myLCID = SUBLANGID(lcid);
305 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
307 /* try with system langid */
317 *path = SysAllocString( Path );
322 TRACE_(typelib)("-- 0x%08x\n", hr);
326 /******************************************************************************
327 * CreateTypeLib [OLEAUT32.160] creates a typelib
333 HRESULT WINAPI CreateTypeLib(
334 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
336 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
340 /******************************************************************************
341 * LoadTypeLib [OLEAUT32.161]
343 * Loads a type library
346 * szFile [I] Name of file to load from.
347 * pptLib [O] Pointer that receives ITypeLib object on success.
354 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
356 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
358 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
359 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
362 /******************************************************************************
363 * LoadTypeLibEx [OLEAUT32.183]
365 * Loads and optionally registers a type library
371 HRESULT WINAPI LoadTypeLibEx(
372 LPCOLESTR szFile, /* [in] Name of file to load from */
373 REGKIND regkind, /* [in] Specify kind of registration */
374 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
376 WCHAR szPath[MAX_PATH+1];
379 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
383 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
388 case REGKIND_DEFAULT:
389 /* don't register typelibs supplied with full path. Experimentation confirms the following */
390 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
391 (szFile[0] && (szFile[1] == ':'))) break;
392 /* else fall-through */
394 case REGKIND_REGISTER:
395 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
397 IUnknown_Release(*pptLib);
405 TRACE(" returns %08x\n",res);
409 /******************************************************************************
410 * LoadRegTypeLib [OLEAUT32.162]
412 * Loads a registered type library.
415 * rguid [I] GUID of the registered type library.
416 * wVerMajor [I] major version.
417 * wVerMinor [I] minor version.
418 * lcid [I] locale ID.
419 * ppTLib [O] pointer that receives an ITypeLib object on success.
423 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
426 HRESULT WINAPI LoadRegTypeLib(
438 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
442 res= LoadTypeLib(bstr, ppTLib);
446 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
452 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
453 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
454 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
455 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
456 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
457 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
459 /******************************************************************************
460 * RegisterTypeLib [OLEAUT32.163]
461 * Adds information about a type library to the System Registry
463 * Docs: ITypeLib FAR * ptlib
464 * Docs: OLECHAR FAR* szFullPath
465 * Docs: OLECHAR FAR* szHelpDir
471 HRESULT WINAPI RegisterTypeLib(
472 ITypeLib * ptlib, /* [in] Pointer to the library*/
473 OLECHAR * szFullPath, /* [in] full Path of the library*/
474 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
477 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
478 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
479 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
489 if (ptlib == NULL || szFullPath == NULL)
492 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
495 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
498 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
499 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
503 /* Set the human-readable name of the typelib */
504 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
506 if (RegSetValueExW(key, NULL, 0, REG_SZ,
507 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
515 /* Make up the name of the typelib path subkey */
516 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
518 /* Create the typelib path subkey */
519 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
520 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
522 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
523 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
531 /* Create the flags subkey */
532 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
533 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
535 /* FIXME: is %u correct? */
536 static const WCHAR formatW[] = {'%','u',0};
538 sprintfW(buf, formatW, attr->wLibFlags);
539 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
540 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
548 /* create the helpdir subkey */
549 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
550 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
552 BOOL freeHelpDir = FALSE;
555 /* if we created a new key, and helpDir was null, set the helpdir
556 to the directory which contains the typelib. However,
557 if we just opened an existing key, we leave the helpdir alone */
558 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
559 szHelpDir = SysAllocString(szFullPath);
560 pIndexStr = strrchrW(szHelpDir, '\\');
567 /* if we have an szHelpDir, set it! */
568 if (szHelpDir != NULL) {
569 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
570 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
576 if (freeHelpDir) SysFreeString(szHelpDir);
588 /* register OLE Automation-compatible interfaces for this typelib */
589 types = ITypeLib_GetTypeInfoCount(ptlib);
590 for (tidx=0; tidx<types; tidx++) {
591 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
592 LPOLESTR name = NULL;
593 ITypeInfo *tinfo = NULL;
595 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
598 case TKIND_INTERFACE:
599 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
600 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
604 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
605 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
609 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
614 TYPEATTR *tattr = NULL;
615 ITypeInfo_GetTypeAttr(tinfo, &tattr);
618 TRACE_(typelib)("guid=%s, flags=%04x (",
619 debugstr_guid(&tattr->guid),
622 if (TRACE_ON(typelib)) {
623 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
643 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
645 /* register interface<->typelib coupling */
646 get_interface_key( &tattr->guid, keyName );
647 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
648 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
651 RegSetValueExW(key, NULL, 0, REG_SZ,
652 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
654 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
655 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
656 RegSetValueExW(subKey, NULL, 0, REG_SZ,
657 (const BYTE *)PSOA, sizeof PSOA);
661 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
662 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
663 RegSetValueExW(subKey, NULL, 0, REG_SZ,
664 (const BYTE *)PSOA, sizeof PSOA);
668 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
669 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
672 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
673 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
675 StringFromGUID2(&attr->guid, buffer, 40);
676 RegSetValueExW(subKey, NULL, 0, REG_SZ,
677 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
678 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
679 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
680 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
688 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
691 ITypeInfo_Release(tinfo);
698 ITypeLib_ReleaseTLibAttr(ptlib, attr);
704 /******************************************************************************
705 * UnRegisterTypeLib [OLEAUT32.186]
706 * Removes information about a type library from the System Registry
713 HRESULT WINAPI UnRegisterTypeLib(
714 REFGUID libid, /* [in] Guid of the library */
715 WORD wVerMajor, /* [in] major version */
716 WORD wVerMinor, /* [in] minor version */
717 LCID lcid, /* [in] locale id */
720 BSTR tlibPath = NULL;
723 WCHAR subKeyName[50];
726 BOOL deleteOtherStuff;
729 TYPEATTR* typeAttr = NULL;
731 ITypeInfo* typeInfo = NULL;
732 ITypeLib* typeLib = NULL;
735 TRACE("(IID: %s)\n",debugstr_guid(libid));
737 /* Create the path to the key */
738 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
740 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
742 TRACE("Unsupported syskind %i\n", syskind);
743 result = E_INVALIDARG;
747 /* get the path to the typelib on disk */
748 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
749 result = E_INVALIDARG;
753 /* Try and open the key to the type library. */
754 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
755 result = E_INVALIDARG;
759 /* Try and load the type library */
760 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
761 result = TYPE_E_INVALIDSTATE;
765 /* remove any types registered with this typelib */
766 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
767 for (i=0; i<numTypes; i++) {
768 /* get the kind of type */
769 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
773 /* skip non-interfaces, and get type info for the type */
774 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
777 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
780 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
784 /* the path to the type */
785 get_interface_key( &typeAttr->guid, subKeyName );
787 /* Delete its bits */
788 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
791 RegDeleteKeyW(subKey, ProxyStubClsidW);
792 RegDeleteKeyW(subKey, ProxyStubClsid32W);
793 RegDeleteKeyW(subKey, TypeLibW);
796 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
799 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
801 if (typeInfo) ITypeInfo_Release(typeInfo);
805 /* Now, delete the type library path subkey */
806 get_lcid_subkey( lcid, syskind, subKeyName );
807 RegDeleteKeyW(key, subKeyName);
808 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
809 RegDeleteKeyW(key, subKeyName);
811 /* check if there is anything besides the FLAGS/HELPDIR keys.
812 If there is, we don't delete them */
813 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
814 deleteOtherStuff = TRUE;
816 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
817 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
819 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
820 if (!strcmpW(subKeyName, FLAGSW)) continue;
821 if (!strcmpW(subKeyName, HELPDIRW)) continue;
822 deleteOtherStuff = FALSE;
826 /* only delete the other parts of the key if we're absolutely sure */
827 if (deleteOtherStuff) {
828 RegDeleteKeyW(key, FLAGSW);
829 RegDeleteKeyW(key, HELPDIRW);
833 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
834 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
835 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
839 if (tlibPath) SysFreeString(tlibPath);
840 if (typeLib) ITypeLib_Release(typeLib);
841 if (subKey) RegCloseKey(subKey);
842 if (key) RegCloseKey(key);
846 /*======================= ITypeLib implementation =======================*/
848 typedef struct tagTLBCustData
852 struct tagTLBCustData* next;
855 /* data structure for import typelibs */
856 typedef struct tagTLBImpLib
858 int offset; /* offset in the file (MSFT)
859 offset in nametable (SLTG)
860 just used to identify library while reading
862 GUID guid; /* libid */
863 BSTR name; /* name */
865 LCID lcid; /* lcid of imported typelib */
867 WORD wVersionMajor; /* major version number */
868 WORD wVersionMinor; /* minor version number */
870 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
871 NULL if not yet loaded */
872 struct tagTLBImpLib * next;
875 /* internal ITypeLib data */
876 typedef struct tagITypeLibImpl
878 const ITypeLib2Vtbl *lpVtbl;
879 const ITypeCompVtbl *lpVtblTypeComp;
881 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
883 /* strings can be stored in tlb as multibyte strings BUT they are *always*
884 * exported to the application as a UNICODE string.
890 unsigned long dwHelpContext;
891 int TypeInfoCount; /* nr of typeinfo's in librarry */
892 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
893 int ctCustData; /* number of items in cust data list */
894 TLBCustData * pCustData; /* linked list to cust data */
895 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
896 int ctTypeDesc; /* number of items in type desc array */
897 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
898 library. Only used while reading MSFT
900 struct list ref_list; /* list of ref types in this typelib */
901 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
902 struct tagITypeLibImpl *next, *prev;
907 static const ITypeLib2Vtbl tlbvt;
908 static const ITypeCompVtbl tlbtcvt;
910 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
912 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
915 /* ITypeLib methods */
916 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
917 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
919 /*======================= ITypeInfo implementation =======================*/
921 /* data for referenced types */
922 typedef struct tagTLBRefType
924 INT index; /* Type index for internal ref or for external ref
925 it the format is SLTG. -2 indicates to
928 GUID guid; /* guid of the referenced type */
929 /* if index == TLB_REF_USE_GUID */
931 HREFTYPE reference; /* The href of this ref */
932 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
933 TLB_REF_INTERNAL for internal refs
934 TLB_REF_NOT_FOUND for broken refs */
939 #define TLB_REF_USE_GUID -2
941 #define TLB_REF_INTERNAL (void*)-2
942 #define TLB_REF_NOT_FOUND (void*)-1
944 /* internal Parameter data */
945 typedef struct tagTLBParDesc
949 TLBCustData * pCustData; /* linked list to cust data */
952 /* internal Function data */
953 typedef struct tagTLBFuncDesc
955 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
956 BSTR Name; /* the name of this function */
957 TLBParDesc *pParamDesc; /* array with param names and custom data */
959 int HelpStringContext;
961 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
963 TLBCustData * pCustData; /* linked list to cust data; */
964 struct tagTLBFuncDesc * next;
967 /* internal Variable data */
968 typedef struct tagTLBVarDesc
970 VARDESC vardesc; /* lots of info on the variable and its attributes. */
971 BSTR Name; /* the name of this variable */
973 int HelpStringContext; /* FIXME: where? */
976 TLBCustData * pCustData;/* linked list to cust data; */
977 struct tagTLBVarDesc * next;
980 /* internal implemented interface data */
981 typedef struct tagTLBImplType
983 HREFTYPE hRef; /* hRef of interface */
984 int implflags; /* IMPLFLAG_*s */
986 TLBCustData * pCustData;/* linked list to custom data; */
987 struct tagTLBImplType *next;
990 /* internal TypeInfo data */
991 typedef struct tagITypeInfoImpl
993 const ITypeInfo2Vtbl *lpVtbl;
994 const ITypeCompVtbl *lpVtblTypeComp;
996 BOOL no_free_data; /* don't free data structurees */
997 TYPEATTR TypeAttr ; /* _lots_ of type information. */
998 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
999 int index; /* index in this typelib; */
1000 HREFTYPE hreftype; /* hreftype for app object binding */
1001 /* type libs seem to store the doc strings in ascii
1002 * so why should we do it in unicode?
1007 unsigned long dwHelpContext;
1008 unsigned long dwHelpStringContext;
1011 TLBFuncDesc * funclist; /* linked list with function descriptions */
1014 TLBVarDesc * varlist; /* linked list with variable descriptions */
1016 /* Implemented Interfaces */
1017 TLBImplType * impltypelist;
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, ITypeLibImpl *pTL, 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 ITypeLibImpl *pTL)
1207 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1209 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1210 if(ref->index == -1)
1211 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1213 TRACE_(typelib)("type no: %d\n", ref->index);
1215 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1217 TRACE_(typelib)("in lib\n");
1218 dump_TLBImpLib(ref->pImpTLInfo);
1223 static void dump_TLBImplType(const TLBImplType * impl)
1227 "implementing/inheriting interface hRef = %x implflags %x\n",
1228 impl->hRef, impl->implflags);
1233 static void dump_Variant(const VARIANT * pvar)
1237 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1241 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1242 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1244 TRACE(",%p", V_BYREF(pvar));
1246 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1248 TRACE(",%p", V_ARRAY(pvar));
1250 else switch (V_TYPE(pvar))
1252 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1253 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1254 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1255 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1257 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1259 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1260 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1261 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1262 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1263 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1264 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1265 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1266 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1267 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1268 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1269 V_CY(pvar).s.Lo); break;
1271 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1272 TRACE(",<invalid>");
1274 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1275 st.wHour, st.wMinute, st.wSecond);
1279 case VT_USERDEFINED:
1281 case VT_NULL: break;
1282 default: TRACE(",?"); break;
1288 static void dump_DispParms(const DISPPARAMS * pdp)
1292 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1294 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1296 TRACE("named args:\n");
1297 for (index = 0; index < pdp->cNamedArgs; index++)
1298 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1301 if (pdp->cArgs && pdp->rgvarg)
1304 for (index = 0; index < pdp->cArgs; index++)
1305 dump_Variant( &pdp->rgvarg[index] );
1309 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1311 TRACE("%p ref=%u\n", pty, pty->ref);
1312 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1313 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1314 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1315 TRACE("fct:%u var:%u impl:%u\n",
1316 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1317 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1318 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1319 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1321 dump_TLBFuncDesc(pty->funclist);
1322 dump_TLBVarDesc(pty->varlist);
1323 dump_TLBImplType(pty->impltypelist);
1326 static void dump_VARDESC(const VARDESC *v)
1328 MESSAGE("memid %d\n",v->memid);
1329 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1330 MESSAGE("oInst %d\n",v->u.oInst);
1331 dump_ELEMDESC(&(v->elemdescVar));
1332 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1333 MESSAGE("varkind %d\n",v->varkind);
1336 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1338 /* VT_LPWSTR is largest type that */
1339 /* may appear in type description*/
1340 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1341 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1342 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1343 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1344 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1345 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1349 static void TLB_abort(void)
1353 static void * TLB_Alloc(unsigned size)
1356 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1358 ERR("cannot allocate memory\n");
1363 static void TLB_Free(void * ptr)
1365 HeapFree(GetProcessHeap(), 0, ptr);
1368 /* returns the size required for a deep copy of a typedesc into a
1370 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1374 if (alloc_initial_space)
1375 size += sizeof(TYPEDESC);
1381 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1384 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1385 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1391 /* deep copy a typedesc into a flat buffer */
1392 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1397 buffer = (char *)buffer + sizeof(TYPEDESC);
1406 dest->u.lptdesc = buffer;
1407 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1410 dest->u.lpadesc = buffer;
1411 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1412 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1413 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1419 /**********************************************************************
1421 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1423 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1428 static inline void MSFT_Seek(TLBContext *pcx, long where)
1430 if (where != DO_NOT_SEEK)
1432 where += pcx->oStart;
1433 if (where > pcx->length)
1436 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1444 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1446 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1447 pcx->pos, count, pcx->oStart, pcx->length, where);
1449 MSFT_Seek(pcx, where);
1450 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1451 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1456 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1461 ret = MSFT_Read(buffer, count, pcx, where);
1462 FromLEDWords(buffer, ret);
1467 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1472 ret = MSFT_Read(buffer, count, pcx, where);
1473 FromLEWords(buffer, ret);
1478 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1480 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1481 memset(pGuid,0, sizeof(GUID));
1484 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1485 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1486 pGuid->Data2 = FromLEWord(pGuid->Data2);
1487 pGuid->Data3 = FromLEWord(pGuid->Data3);
1488 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1491 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1493 MSFT_NameIntro niName;
1497 ERR_(typelib)("bad offset %d\n", offset);
1501 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1502 pcx->pTblDir->pNametab.offset+offset);
1504 return niName.hreftype;
1507 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1510 MSFT_NameIntro niName;
1512 BSTR bstrName = NULL;
1516 ERR_(typelib)("bad offset %d\n", offset);
1519 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1520 pcx->pTblDir->pNametab.offset+offset);
1521 niName.namelen &= 0xFF; /* FIXME: correct ? */
1522 name=TLB_Alloc((niName.namelen & 0xff) +1);
1523 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1524 name[niName.namelen & 0xff]='\0';
1526 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1529 /* no invalid characters in string */
1532 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1534 /* don't check for invalid character since this has been done previously */
1535 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1539 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1543 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1550 if(offset<0) return NULL;
1551 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1552 if(length <= 0) return 0;
1553 string=TLB_Alloc(length +1);
1554 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1555 string[length]='\0';
1557 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1558 string, -1, NULL, 0);
1560 /* no invalid characters in string */
1563 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1565 /* don't check for invalid character since this has been done previously */
1566 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1570 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1574 * read a value and fill a VARIANT structure
1576 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1580 TRACE_(typelib)("\n");
1582 if(offset <0) { /* data are packed in here */
1583 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1584 V_I4(pVar) = offset & 0x3ffffff;
1587 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1588 pcx->pTblDir->pCustData.offset + offset );
1589 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1590 switch (V_VT(pVar)){
1591 case VT_EMPTY: /* FIXME: is this right? */
1592 case VT_NULL: /* FIXME: is this right? */
1593 case VT_I2 : /* this should not happen */
1604 case VT_VOID : /* FIXME: is this right? */
1612 case VT_DECIMAL : /* FIXME: is this right? */
1615 /* pointer types with known behaviour */
1618 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1621 DWORD origPos = MSFT_Tell(pcx), nullPos;
1624 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1626 nullPos = MSFT_Tell(pcx);
1627 size = nullPos - origPos;
1628 MSFT_Seek(pcx, origPos);
1630 ptr=TLB_Alloc(size);/* allocate temp buffer */
1631 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1632 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1633 /* FIXME: do we need a AtoW conversion here? */
1634 V_UNION(pVar, bstrVal[size])=L'\0';
1635 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1639 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1646 case VT_USERDEFINED :
1652 case VT_STREAMED_OBJECT :
1653 case VT_STORED_OBJECT :
1654 case VT_BLOB_OBJECT :
1659 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1663 if(size>0) /* (big|small) endian correct? */
1664 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1668 * create a linked list with custom data
1670 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1676 TRACE_(typelib)("\n");
1680 pNew=TLB_Alloc(sizeof(TLBCustData));
1681 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1682 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1683 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1684 /* add new custom data at head of the list */
1685 pNew->next=*ppCustData;
1687 offset = entry.next;
1692 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1696 pTd->vt=type & VT_TYPEMASK;
1698 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1700 if(pTd->vt == VT_USERDEFINED)
1701 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1703 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1706 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1708 /* resolve referenced type if any */
1711 switch (lpTypeDesc->vt)
1714 lpTypeDesc = lpTypeDesc->u.lptdesc;
1718 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1721 case VT_USERDEFINED:
1722 MSFT_DoRefType(pcx, pTI->pTypeLib,
1723 lpTypeDesc->u.hreftype);
1735 MSFT_DoFuncs(TLBContext* pcx,
1740 TLBFuncDesc** pptfd)
1743 * member information is stored in a data structure at offset
1744 * indicated by the memoffset field of the typeinfo structure
1745 * There are several distinctive parts.
1746 * The first part starts with a field that holds the total length
1747 * of this (first) part excluding this field. Then follow the records,
1748 * for each member there is one record.
1750 * The first entry is always the length of the record (including this
1752 * The rest of the record depends on the type of the member. If there is
1753 * a field indicating the member type (function, variable, interface, etc)
1754 * I have not found it yet. At this time we depend on the information
1755 * in the type info and the usual order how things are stored.
1757 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1760 * Third is an equal sized array with file offsets to the name entry
1763 * The fourth and last (?) part is an array with offsets to the records
1764 * in the first part of this file segment.
1767 int infolen, nameoffset, reclength, nrattributes, i;
1768 int recoffset = offset + sizeof(INT);
1770 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1771 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1772 TLBFuncDesc *ptfd_prev = NULL;
1774 TRACE_(typelib)("\n");
1776 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1778 for ( i = 0; i < cFuncs ; i++ )
1780 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1782 /* name, eventually add to a hash table */
1783 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1784 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1786 /* nameoffset is sometimes -1 on the second half of a propget/propput
1787 * pair of functions */
1788 if ((nameoffset == -1) && (i > 0))
1789 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1791 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1793 /* read the function information record */
1794 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1796 reclength &= 0xffff;
1798 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1800 /* do the attributes */
1801 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1804 if ( nrattributes > 0 )
1806 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1808 if ( nrattributes > 1 )
1810 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1811 pFuncRec->OptAttr[1]) ;
1813 if ( nrattributes > 2 )
1815 if ( pFuncRec->FKCCIC & 0x2000 )
1817 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1818 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1819 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1823 (*pptfd)->Entry = MSFT_ReadString(pcx,
1824 pFuncRec->OptAttr[2]);
1826 if( nrattributes > 5 )
1828 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1830 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1833 pFuncRec->OptAttr[6],
1834 &(*pptfd)->pCustData);
1840 (*pptfd)->Entry = (BSTR)-1;
1845 /* fill the FuncDesc Structure */
1846 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1847 offset + infolen + ( i + 1) * sizeof(INT));
1849 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1850 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1851 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1852 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1853 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1854 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1855 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1859 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1861 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1863 /* do the parameters/arguments */
1864 if(pFuncRec->nrargs)
1867 MSFT_ParameterInfo paraminfo;
1869 (*pptfd)->funcdesc.lprgelemdescParam =
1870 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1872 (*pptfd)->pParamDesc =
1873 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1875 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1876 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1878 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1880 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1887 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1890 if (paraminfo.oName == -1)
1891 /* this occurs for [propput] or [propget] methods, so
1892 * we should just set the name of the parameter to the
1893 * name of the method. */
1894 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1896 (*pptfd)->pParamDesc[j].Name =
1897 MSFT_ReadName( pcx, paraminfo.oName );
1898 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1900 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1903 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1904 (pFuncRec->FKCCIC & 0x1000) )
1906 INT* pInt = (INT *)((char *)pFuncRec +
1908 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1910 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1912 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1913 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1915 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1919 elemdesc->u.paramdesc.pparamdescex = NULL;
1921 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1924 pFuncRec->OptAttr[7+j],
1925 &(*pptfd)->pParamDesc[j].pCustData);
1928 /* SEEK value = jump to offset,
1929 * from there jump to the end of record,
1930 * go back by (j-1) arguments
1932 MSFT_ReadLEDWords( ¶minfo ,
1933 sizeof(MSFT_ParameterInfo), pcx,
1934 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1935 * sizeof(MSFT_ParameterInfo)));
1939 /* scode is not used: archaic win16 stuff FIXME: right? */
1940 (*pptfd)->funcdesc.cScodes = 0 ;
1941 (*pptfd)->funcdesc.lprgscode = NULL ;
1944 pptfd = & ((*pptfd)->next);
1945 recoffset += reclength;
1947 HeapFree(GetProcessHeap(), 0, recbuf);
1950 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1951 int cVars, int offset, TLBVarDesc ** pptvd)
1953 int infolen, nameoffset, reclength;
1955 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1959 TRACE_(typelib)("\n");
1961 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1962 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1963 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1964 recoffset += offset+sizeof(INT);
1965 for(i=0;i<cVars;i++){
1966 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1967 /* name, eventually add to a hash table */
1968 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1969 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1970 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1971 /* read the variable information record */
1972 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1974 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1976 if(reclength >(6*sizeof(INT)) )
1977 (*pptvd)->HelpContext=pVarRec->HelpContext;
1978 if(reclength >(7*sizeof(INT)) )
1979 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1980 if(reclength >(8*sizeof(INT)) )
1981 if(reclength >(9*sizeof(INT)) )
1982 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1983 /* fill the VarDesc Structure */
1984 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1985 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1986 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1987 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1988 MSFT_GetTdesc(pcx, pVarRec->DataType,
1989 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1990 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1991 if(pVarRec->VarKind == VAR_CONST ){
1992 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1993 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1994 pVarRec->OffsValue, pcx);
1996 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1997 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1998 pptvd=&((*pptvd)->next);
1999 recoffset += reclength;
2002 /* fill in data for a hreftype (offset). When the referenced type is contained
2003 * in the typelib, it's just an (file) offset in the type info base dir.
2004 * If comes from import, it's an offset+1 in the ImpInfo table
2006 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2012 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2014 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2016 if(ref->reference == offset) return;
2019 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2020 list_add_tail(&pTL->ref_list, &ref->entry);
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 ref->reference = offset;
2037 ref->pImpTLInfo = pImpLib;
2038 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2039 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2040 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2041 ref->index = TLB_REF_USE_GUID;
2043 ref->index = impinfo.oGuid;
2045 ERR("Cannot find a reference\n");
2046 ref->reference = -1;
2047 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2050 /* in this typelib */
2051 ref->index = MSFT_HREFTYPE_INDEX(offset);
2052 ref->reference = offset;
2053 ref->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->pTypeLib, 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, pLibInfo, tiBase.datatype1);
2161 ptiRet->impltypelist->hRef = tiBase.datatype1;
2165 MSFT_DoRefType(pcx, pLibInfo, dispatch_href);
2166 ptiRet->impltypelist->hRef = dispatch_href;
2170 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2171 MSFT_DoRefType(pcx, pLibInfo, 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 list_init(&pTypeLibImpl->ref_list);
2367 return pTypeLibImpl;
2370 /****************************************************************************
2371 * ITypeLib2_Constructor_MSFT
2373 * loading an MSFT typelib from an in-memory image
2375 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2379 MSFT_Header tlbHeader;
2380 MSFT_SegDir tlbSegDir;
2381 ITypeLibImpl * pTypeLibImpl;
2383 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2385 pTypeLibImpl = TypeLibImpl_Constructor();
2386 if (!pTypeLibImpl) return NULL;
2388 /* get pointer to beginning of typelib data */
2392 cx.pLibInfo = pTypeLibImpl;
2393 cx.length = dwTLBLength;
2396 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2397 TRACE_(typelib)("header:\n");
2398 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2399 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2400 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2403 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2405 /* there is a small amount of information here until the next important
2407 * the segment directory . Try to calculate the amount of data */
2408 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2410 /* now read the segment directory */
2411 TRACE("read segment directory (at %ld)\n",lPSegDir);
2412 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2413 cx.pTblDir = &tlbSegDir;
2415 /* just check two entries */
2416 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2418 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2419 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2423 /* now fill our internal data */
2424 /* TLIBATTR fields */
2425 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2427 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2428 /* Windows seems to have zero here, is this correct? */
2429 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2430 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2432 pTypeLibImpl->LibAttr.lcid = 0;
2434 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2435 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2436 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2437 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2439 /* name, eventually add to a hash table */
2440 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2443 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2444 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2446 if( tlbHeader.varflags & HELPDLLFLAG)
2449 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2450 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2453 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2456 if(tlbHeader.CustomDataOffset >= 0)
2458 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2461 /* fill in typedescriptions */
2462 if(tlbSegDir.pTypdescTab.length > 0)
2464 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2466 pTypeLibImpl->ctTypeDesc = cTD;
2467 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2468 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2471 /* FIXME: add several sanity checks here */
2472 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2473 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2475 /* FIXME: check safearray */
2477 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2479 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2481 else if(td[0] == VT_CARRAY)
2483 /* array descr table here */
2484 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2486 else if(td[0] == VT_USERDEFINED)
2488 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2490 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2493 /* second time around to fill the array subscript info */
2496 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2497 if(tlbSegDir.pArrayDescriptions.offset>0)
2499 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2500 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2503 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2505 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2507 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2509 for(j = 0; j<td[2]; j++)
2511 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2512 sizeof(INT), &cx, DO_NOT_SEEK);
2513 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2514 sizeof(INT), &cx, DO_NOT_SEEK);
2519 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2520 ERR("didn't find array description data\n");
2525 /* imported type libs */
2526 if(tlbSegDir.pImpFiles.offset>0)
2528 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2529 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2532 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2537 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2538 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2539 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2541 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2542 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2543 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2544 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2547 name = TLB_Alloc(size+1);
2548 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2549 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2550 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2551 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2554 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2555 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2557 ppImpLib = &(*ppImpLib)->next;
2562 if(tlbHeader.nrtypeinfos >= 0 )
2564 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2565 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2568 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2570 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2572 ppTI = &((*ppTI)->next);
2573 (pTypeLibImpl->TypeInfoCount)++;
2577 TRACE("(%p)\n", pTypeLibImpl);
2578 return (ITypeLib2*) pTypeLibImpl;
2582 static BSTR TLB_MultiByteToBSTR(char *ptr)
2588 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2589 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2590 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2591 ret = SysAllocString(nameW);
2592 HeapFree(GetProcessHeap(), 0, nameW);
2596 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2602 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2603 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2607 guid->Data4[0] = s >> 8;
2608 guid->Data4[1] = s & 0xff;
2611 for(i = 0; i < 6; i++) {
2612 memcpy(b, str + 24 + 2 * i, 2);
2613 guid->Data4[i + 2] = strtol(b, NULL, 16);
2618 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2625 bytelen = *(WORD*)ptr;
2626 if(bytelen == 0xffff) return 2;
2627 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2628 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2629 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2630 *pBstr = SysAllocStringLen(nameW, len);
2631 HeapFree(GetProcessHeap(), 0, nameW);
2635 static WORD SLTG_ReadStringA(char *ptr, char **str)
2640 bytelen = *(WORD*)ptr;
2641 if(bytelen == 0xffff) return 2;
2642 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2643 memcpy(*str, ptr + 2, bytelen);
2644 (*str)[bytelen] = '\0';
2648 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2650 char *ptr = pLibBlk;
2653 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2654 FIXME("libblk magic = %04x\n", w);
2659 if((w = *(WORD*)ptr) != 0xffff) {
2660 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2665 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2667 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2669 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2672 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2675 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2676 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2678 pTypeLibImpl->LibAttr.lcid = 0;
2681 ptr += 4; /* skip res12 */
2683 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2686 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2689 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2692 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2693 ptr += sizeof(GUID);
2695 return ptr - (char*)pLibBlk;
2698 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2703 if((*pType & 0xe00) == 0xe00) {
2705 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2707 pTD = pTD->u.lptdesc;
2709 switch(*pType & 0x3f) {
2712 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2714 pTD = pTD->u.lptdesc;
2717 case VT_USERDEFINED:
2718 pTD->vt = VT_USERDEFINED;
2719 pTD->u.hreftype = *(++pType) / 4;
2725 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2728 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2730 pTD->vt = VT_CARRAY;
2731 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2733 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2734 pTD->u.lpadesc->cDims = pSA->cDims;
2735 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2736 pSA->cDims * sizeof(SAFEARRAYBOUND));
2738 pTD = &pTD->u.lpadesc->tdescElem;
2744 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2748 pTD->vt = VT_SAFEARRAY;
2749 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2751 pTD = pTD->u.lptdesc;
2755 pTD->vt = *pType & 0x3f;
2764 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2766 /* Handle [in/out] first */
2767 if((*pType & 0xc000) == 0xc000)
2768 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2769 else if(*pType & 0x8000)
2770 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2771 else if(*pType & 0x4000)
2772 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2774 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2777 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2780 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2782 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2786 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2791 TLBRefType *ref_type;
2793 if(pRef->magic != SLTG_REF_MAGIC) {
2794 FIXME("Ref magic = %x\n", pRef->magic);
2797 name = ( (char*)(&pRef->names) + pRef->number);
2799 for(ref = 0; ref < pRef->number >> 3; ref++) {
2801 unsigned int lib_offs, type_num;
2803 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
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 = &pTL->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 ref_type->pImpTLInfo = *import;
2839 } else { /* internal ref */
2840 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
2842 ref_type->reference = ref;
2843 ref_type->index = type_num;
2845 HeapFree(GetProcessHeap(), 0, refname);
2846 list_add_tail(&pTL->ref_list, &ref_type->entry);
2848 if((BYTE)*name != SLTG_REF_MAGIC)
2849 FIXME("End of ref block magic = %x\n", *name);
2850 dump_TLBRefType(pTL);
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->pTypeLib,
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->pTypeLib,
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->pTypeLib,
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->pTypeLib,
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->pTypeLib,
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;
3556 TLBRefType *ref_type;
3560 /* remove cache entry */
3563 TRACE("removing from cache list\n");
3564 EnterCriticalSection(&cache_section);
3565 if (This->next) This->next->prev = This->prev;
3566 if (This->prev) This->prev->next = This->next;
3567 else tlb_cache_first = This->next;
3568 LeaveCriticalSection(&cache_section);
3569 HeapFree(GetProcessHeap(), 0, This->path);
3571 TRACE(" destroying ITypeLib(%p)\n",This);
3575 SysFreeString(This->Name);
3579 if (This->DocString)
3581 SysFreeString(This->DocString);
3582 This->DocString = NULL;
3587 SysFreeString(This->HelpFile);
3588 This->HelpFile = NULL;
3591 if (This->HelpStringDll)
3593 SysFreeString(This->HelpStringDll);
3594 This->HelpStringDll = NULL;
3597 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3599 VariantClear(&pCustData->data);
3601 pCustDataNext = pCustData->next;
3602 TLB_Free(pCustData);
3605 for (i = 0; i < This->ctTypeDesc; i++)
3606 if (This->pTypeDesc[i].vt == VT_CARRAY)
3607 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3609 TLB_Free(This->pTypeDesc);
3611 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3613 if (pImpLib->pImpTypeLib)
3614 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3615 TLB_Free(pImpLib->name);
3617 pImpLibNext = pImpLib->next;
3621 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3623 list_remove(&ref_type->entry);
3627 if (This->pTypeInfo) /* can be NULL */
3628 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3629 HeapFree(GetProcessHeap(),0,This);
3636 /* ITypeLib::GetTypeInfoCount
3638 * Returns the number of type descriptions in the type library
3640 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3642 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3643 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3644 return This->TypeInfoCount;
3647 /* ITypeLib::GetTypeInfo
3649 * retrieves the specified type description in the library.
3651 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3654 ITypeInfo **ppTInfo)
3658 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3659 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3661 TRACE("(%p)->(index=%d)\n", This, index);
3663 if (!ppTInfo) return E_INVALIDARG;
3665 /* search element n in list */
3666 for(i=0; i < index; i++)
3668 pTypeInfo = pTypeInfo->next;
3671 TRACE("-- element not found\n");
3672 return TYPE_E_ELEMENTNOTFOUND;
3676 *ppTInfo = (ITypeInfo *) pTypeInfo;
3678 ITypeInfo_AddRef(*ppTInfo);
3679 TRACE("-- found (%p)\n",*ppTInfo);
3684 /* ITypeLibs::GetTypeInfoType
3686 * Retrieves the type of a type description.
3688 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3693 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3695 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3697 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3698 return TYPE_E_ELEMENTNOTFOUND;
3700 TRACE("(%p) index %d\n", This, index);
3702 if(!pTKind) return E_INVALIDARG;
3704 /* search element n in list */
3705 for(i=0; i < index; i++)
3709 TRACE("-- element not found\n");
3710 return TYPE_E_ELEMENTNOTFOUND;
3712 pTInfo = pTInfo->next;
3715 *pTKind = pTInfo->TypeAttr.typekind;
3716 TRACE("-- found Type (%d)\n", *pTKind);
3720 /* ITypeLib::GetTypeInfoOfGuid
3722 * Retrieves the type description that corresponds to the specified GUID.
3725 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3728 ITypeInfo **ppTInfo)
3730 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3731 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3733 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3737 WARN("-- element not found\n");
3738 return TYPE_E_ELEMENTNOTFOUND;
3741 /* search linked list for guid */
3742 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3744 pTypeInfo = pTypeInfo->next;
3748 /* end of list reached */
3749 WARN("-- element not found\n");
3750 return TYPE_E_ELEMENTNOTFOUND;
3754 TRACE("-- found (%p, %s)\n",
3756 debugstr_w(pTypeInfo->Name));
3758 *ppTInfo = (ITypeInfo*)pTypeInfo;
3759 ITypeInfo_AddRef(*ppTInfo);
3763 /* ITypeLib::GetLibAttr
3765 * Retrieves the structure that contains the library's attributes.
3768 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3770 LPTLIBATTR *ppTLibAttr)
3772 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3773 TRACE("(%p)\n",This);
3774 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3775 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3779 /* ITypeLib::GetTypeComp
3781 * Enables a client compiler to bind to a library's types, variables,
3782 * constants, and global functions.
3785 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3787 ITypeComp **ppTComp)
3789 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3791 TRACE("(%p)->(%p)\n",This,ppTComp);
3792 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3793 ITypeComp_AddRef(*ppTComp);
3798 /* ITypeLib::GetDocumentation
3800 * Retrieves the library's documentation string, the complete Help file name
3801 * and path, and the context identifier for the library Help topic in the Help
3804 * On a successful return all non-null BSTR pointers will have been set,
3807 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3811 BSTR *pBstrDocString,
3812 DWORD *pdwHelpContext,
3813 BSTR *pBstrHelpFile)
3815 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3817 HRESULT result = E_INVALIDARG;
3822 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3824 pBstrName, pBstrDocString,
3825 pdwHelpContext, pBstrHelpFile);
3829 /* documentation for the typelib */
3834 if(!(*pBstrName = SysAllocString(This->Name)))
3842 if (This->DocString)
3844 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3847 else if (This->Name)
3849 if(!(*pBstrDocString = SysAllocString(This->Name)))
3853 *pBstrDocString = NULL;
3857 *pdwHelpContext = This->dwHelpContext;
3863 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3867 *pBstrHelpFile = NULL;
3874 /* for a typeinfo */
3875 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3877 if(SUCCEEDED(result))
3879 result = ITypeInfo_GetDocumentation(pTInfo,
3883 pdwHelpContext, pBstrHelpFile);
3885 ITypeInfo_Release(pTInfo);
3890 if (pBstrDocString) SysFreeString (*pBstrDocString);
3892 if (pBstrName) SysFreeString (*pBstrName);
3894 return STG_E_INSUFFICIENTMEMORY;
3899 * Indicates whether a passed-in string contains the name of a type or member
3900 * described in the library.
3903 static HRESULT WINAPI ITypeLib2_fnIsName(
3909 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3910 ITypeInfoImpl *pTInfo;
3911 TLBFuncDesc *pFInfo;
3914 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3916 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3920 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3921 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3922 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3923 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3924 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3925 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3926 goto ITypeLib2_fnIsName_exit;
3928 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3929 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3934 ITypeLib2_fnIsName_exit:
3935 TRACE("(%p)slow! search for %s: %s found!\n", This,
3936 debugstr_w(szNameBuf), *pfName?"NOT":"");
3941 /* ITypeLib::FindName
3943 * Finds occurrences of a type description in a type library. This may be used
3944 * to quickly verify that a name exists in a type library.
3947 static HRESULT WINAPI ITypeLib2_fnFindName(
3951 ITypeInfo **ppTInfo,
3955 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3956 ITypeInfoImpl *pTInfo;
3957 TLBFuncDesc *pFInfo;
3960 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3962 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3963 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3964 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3965 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3966 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3967 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3968 goto ITypeLib2_fnFindName_exit;
3971 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3972 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3974 ITypeLib2_fnFindName_exit:
3975 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3976 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3979 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3980 This, *pcFound, debugstr_w(szNameBuf), j);
3987 /* ITypeLib::ReleaseTLibAttr
3989 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3992 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3994 TLIBATTR *pTLibAttr)
3996 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3997 TRACE("freeing (%p)\n",This);
3998 HeapFree(GetProcessHeap(),0,pTLibAttr);
4002 /* ITypeLib2::GetCustData
4004 * gets the custom data
4006 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4011 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4012 TLBCustData *pCData;
4014 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4016 if( IsEqualIID(guid, &pCData->guid)) break;
4019 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4023 VariantInit( pVarVal);
4024 VariantCopy( pVarVal, &pCData->data);
4027 return E_INVALIDARG; /* FIXME: correct? */
4030 /* ITypeLib2::GetLibStatistics
4032 * Returns statistics about a type library that are required for efficient
4033 * sizing of hash tables.
4036 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4038 ULONG *pcUniqueNames,
4039 ULONG *pcchUniqueNames)
4041 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4043 FIXME("(%p): stub!\n", This);
4045 if(pcUniqueNames) *pcUniqueNames=1;
4046 if(pcchUniqueNames) *pcchUniqueNames=1;
4050 /* ITypeLib2::GetDocumentation2
4052 * Retrieves the library's documentation string, the complete Help file name
4053 * and path, the localization context to use, and the context ID for the
4054 * library Help topic in the Help file.
4057 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4061 BSTR *pbstrHelpString,
4062 DWORD *pdwHelpStringContext,
4063 BSTR *pbstrHelpStringDll)
4065 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4069 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4071 /* the help string should be obtained from the helpstringdll,
4072 * using the _DLLGetDocumentation function, based on the supplied
4073 * lcid. Nice to do sometime...
4077 /* documentation for the typelib */
4079 *pbstrHelpString=SysAllocString(This->DocString);
4080 if(pdwHelpStringContext)
4081 *pdwHelpStringContext=This->dwHelpContext;
4082 if(pbstrHelpStringDll)
4083 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4089 /* for a typeinfo */
4090 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4092 if(SUCCEEDED(result))
4094 ITypeInfo2 * pTInfo2;
4095 result = ITypeInfo_QueryInterface(pTInfo,
4097 (LPVOID*) &pTInfo2);
4099 if(SUCCEEDED(result))
4101 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4105 pdwHelpStringContext,
4106 pbstrHelpStringDll);
4108 ITypeInfo2_Release(pTInfo2);
4111 ITypeInfo_Release(pTInfo);
4117 /* ITypeLib2::GetAllCustData
4119 * Gets all custom data items for the library.
4122 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4124 CUSTDATA *pCustData)
4126 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4127 TLBCustData *pCData;
4129 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4130 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4131 if(pCustData->prgCustData ){
4132 pCustData->cCustData=This->ctCustData;
4133 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4134 pCustData->prgCustData[i].guid=pCData->guid;
4135 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4138 ERR(" OUT OF MEMORY!\n");
4139 return E_OUTOFMEMORY;
4144 static const ITypeLib2Vtbl tlbvt = {
4145 ITypeLib2_fnQueryInterface,
4147 ITypeLib2_fnRelease,
4148 ITypeLib2_fnGetTypeInfoCount,
4149 ITypeLib2_fnGetTypeInfo,
4150 ITypeLib2_fnGetTypeInfoType,
4151 ITypeLib2_fnGetTypeInfoOfGuid,
4152 ITypeLib2_fnGetLibAttr,
4153 ITypeLib2_fnGetTypeComp,
4154 ITypeLib2_fnGetDocumentation,
4156 ITypeLib2_fnFindName,
4157 ITypeLib2_fnReleaseTLibAttr,
4159 ITypeLib2_fnGetCustData,
4160 ITypeLib2_fnGetLibStatistics,
4161 ITypeLib2_fnGetDocumentation2,
4162 ITypeLib2_fnGetAllCustData
4166 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4168 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4170 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4173 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4175 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4177 return ITypeLib2_AddRef((ITypeLib2 *)This);
4180 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4182 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4184 return ITypeLib2_Release((ITypeLib2 *)This);
4187 static HRESULT WINAPI ITypeLibComp_fnBind(
4192 ITypeInfo ** ppTInfo,
4193 DESCKIND * pDescKind,
4196 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4197 ITypeInfoImpl *pTypeInfo;
4199 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4201 *pDescKind = DESCKIND_NONE;
4202 pBindPtr->lptcomp = NULL;
4205 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4207 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4209 /* FIXME: check wFlags here? */
4210 /* FIXME: we should use a hash table to look this info up using lHash
4211 * instead of an O(n) search */
4212 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4213 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4215 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4217 *pDescKind = DESCKIND_TYPECOMP;
4218 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4219 ITypeComp_AddRef(pBindPtr->lptcomp);
4220 TRACE("module or enum: %s\n", debugstr_w(szName));
4225 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4226 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4228 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4231 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4232 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4234 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4239 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4240 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4242 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4244 ITypeInfo *subtypeinfo;
4246 DESCKIND subdesckind;
4248 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4249 &subtypeinfo, &subdesckind, &subbindptr);
4250 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4252 TYPEDESC tdesc_appobject =
4255 (TYPEDESC *)pTypeInfo->hreftype
4259 const VARDESC vardesc_appobject =
4262 NULL, /* lpstrSchema */
4277 VAR_STATIC /* varkind */
4280 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4282 /* cleanup things filled in by Bind call so we can put our
4283 * application object data in there instead */
4284 switch (subdesckind)
4286 case DESCKIND_FUNCDESC:
4287 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4289 case DESCKIND_VARDESC:
4290 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4295 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4297 if (pTypeInfo->hreftype == -1)
4298 FIXME("no hreftype for interface %p\n", pTypeInfo);
4300 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4304 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4305 *ppTInfo = (ITypeInfo *)pTypeInfo;
4306 ITypeInfo_AddRef(*ppTInfo);
4312 TRACE("name not found %s\n", debugstr_w(szName));
4316 static HRESULT WINAPI ITypeLibComp_fnBindType(
4320 ITypeInfo ** ppTInfo,
4321 ITypeComp ** ppTComp)
4323 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4327 static const ITypeCompVtbl tlbtcvt =
4330 ITypeLibComp_fnQueryInterface,
4331 ITypeLibComp_fnAddRef,
4332 ITypeLibComp_fnRelease,
4334 ITypeLibComp_fnBind,
4335 ITypeLibComp_fnBindType
4338 /*================== ITypeInfo(2) Methods ===================================*/
4339 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4341 ITypeInfoImpl * pTypeInfoImpl;
4343 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4346 pTypeInfoImpl->lpVtbl = &tinfvt;
4347 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4348 pTypeInfoImpl->ref=1;
4349 pTypeInfoImpl->hreftype = -1;
4350 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4351 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4353 TRACE("(%p)\n", pTypeInfoImpl);
4354 return (ITypeInfo2*) pTypeInfoImpl;
4357 /* ITypeInfo::QueryInterface
4359 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4364 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4366 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4369 if(IsEqualIID(riid, &IID_IUnknown) ||
4370 IsEqualIID(riid,&IID_ITypeInfo)||
4371 IsEqualIID(riid,&IID_ITypeInfo2))
4375 ITypeInfo_AddRef(iface);
4376 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4379 TRACE("-- Interface: E_NOINTERFACE\n");
4380 return E_NOINTERFACE;
4383 /* ITypeInfo::AddRef
4385 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4387 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4388 ULONG ref = InterlockedIncrement(&This->ref);
4390 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4392 TRACE("(%p)->ref is %u\n",This, ref);
4396 /* ITypeInfo::Release
4398 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4400 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4401 ULONG ref = InterlockedDecrement(&This->ref);
4403 TRACE("(%p)->(%u)\n",This, ref);
4406 /* We don't release ITypeLib when ref=0 because
4407 it means that function is called by ITypeLib2_Release */
4408 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4410 TLBFuncDesc *pFInfo, *pFInfoNext;
4411 TLBVarDesc *pVInfo, *pVInfoNext;
4412 TLBImplType *pImpl, *pImplNext;
4413 TLBCustData *pCustData, *pCustDataNext;
4415 TRACE("destroying ITypeInfo(%p)\n",This);
4417 if (This->no_free_data)
4422 SysFreeString(This->Name);
4426 if (This->DocString)
4428 SysFreeString(This->DocString);
4429 This->DocString = 0;
4434 SysFreeString(This->DllName);
4438 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4441 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4443 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4444 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4446 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4447 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4449 SysFreeString(pFInfo->pParamDesc[i].Name);
4451 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4452 TLB_Free(pFInfo->pParamDesc);
4453 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4455 VariantClear(&pCustData->data);
4457 pCustDataNext = pCustData->next;
4458 TLB_Free(pCustData);
4460 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4461 SysFreeString(pFInfo->Entry);
4462 SysFreeString(pFInfo->HelpString);
4463 SysFreeString(pFInfo->Name);
4465 pFInfoNext = pFInfo->next;
4468 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4470 if (pVInfo->vardesc.varkind == VAR_CONST)
4472 VariantClear(pVInfo->vardesc.u.lpvarValue);
4473 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4475 SysFreeString(pVInfo->Name);
4476 pVInfoNext = pVInfo->next;
4479 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4481 for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4483 VariantClear(&pCustData->data);
4485 pCustDataNext = pCustData->next;
4486 TLB_Free(pCustData);
4488 pImplNext = pImpl->next;
4491 TLB_Free(This->pCustData);
4496 ITypeInfo_Release((ITypeInfo*)This->next);
4499 HeapFree(GetProcessHeap(),0,This);
4505 /* ITypeInfo::GetTypeAttr
4507 * Retrieves a TYPEATTR structure that contains the attributes of the type
4511 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4512 LPTYPEATTR *ppTypeAttr)
4514 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4517 TRACE("(%p)\n",This);
4519 size = sizeof(**ppTypeAttr);
4520 if (This->TypeAttr.typekind == TKIND_ALIAS)
4521 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4523 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4525 return E_OUTOFMEMORY;
4527 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4529 if (This->TypeAttr.typekind == TKIND_ALIAS)
4530 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4531 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4533 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4534 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4536 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4537 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4542 /* ITypeInfo::GetTypeComp
4544 * Retrieves the ITypeComp interface for the type description, which enables a
4545 * client compiler to bind to the type description's members.
4548 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4549 ITypeComp * *ppTComp)
4551 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4553 TRACE("(%p)->(%p)\n", This, ppTComp);
4555 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4556 ITypeComp_AddRef(*ppTComp);
4560 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4562 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4563 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4564 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4568 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4570 memcpy(dest, src, sizeof(ELEMDESC));
4571 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4572 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4574 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4575 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4576 *buffer += sizeof(PARAMDESCEX);
4577 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4578 VariantInit(&pparamdescex_dest->varDefaultValue);
4579 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4580 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4583 dest->u.paramdesc.pparamdescex = NULL;
4587 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4589 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4590 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4593 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4597 SIZE_T size = sizeof(*src);
4601 size += sizeof(*src->lprgscode) * src->cScodes;
4602 size += TLB_SizeElemDesc(&src->elemdescFunc);
4603 for (i = 0; i < src->cParams; i++)
4605 size += sizeof(ELEMDESC);
4606 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4609 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4610 if (!dest) return E_OUTOFMEMORY;
4612 memcpy(dest, src, sizeof(FUNCDESC));
4613 buffer = (char *)(dest + 1);
4615 dest->lprgscode = (SCODE *)buffer;
4616 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4617 buffer += sizeof(*src->lprgscode) * src->cScodes;
4619 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4622 SysFreeString((BSTR)dest);
4626 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4627 buffer += sizeof(ELEMDESC) * src->cParams;
4628 for (i = 0; i < src->cParams; i++)
4630 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4636 /* undo the above actions */
4637 for (i = i - 1; i >= 0; i--)
4638 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4639 TLB_FreeElemDesc(&dest->elemdescFunc);
4640 SysFreeString((BSTR)dest);
4644 /* special treatment for dispinterfaces: this makes functions appear
4645 * to return their [retval] value when it is really returning an
4647 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4649 if (dest->cParams &&
4650 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4652 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4653 if (elemdesc->tdesc.vt != VT_PTR)
4655 ERR("elemdesc should have started with VT_PTR instead of:\n");
4657 dump_ELEMDESC(elemdesc);
4658 return E_UNEXPECTED;
4661 /* copy last parameter to the return value. we are using a flat
4662 * buffer so there is no danger of leaking memory in
4664 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4666 /* remove the last parameter */
4670 /* otherwise this function is made to appear to have no return
4672 dest->elemdescFunc.tdesc.vt = VT_VOID;
4680 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4682 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4683 const TLBFuncDesc *pFDesc;
4686 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4691 *ppFuncDesc = &pFDesc->funcdesc;
4695 return E_INVALIDARG;
4698 /* internal function to make the inherited interfaces' methods appear
4699 * part of the interface */
4700 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4701 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs)
4703 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4706 UINT implemented_funcs = 0;
4711 for (i = 0; i < This->TypeAttr.cImplTypes; i++)
4714 ITypeInfo *pSubTypeInfo;
4717 hr = ITypeInfo_GetRefTypeOfImplType(iface, i, &href);
4720 hr = ITypeInfo_GetRefTypeInfo(iface, href, &pSubTypeInfo);
4724 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4728 implemented_funcs += sub_funcs;
4729 ITypeInfo_Release(pSubTypeInfo);
4735 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4737 if (index < implemented_funcs)
4738 return E_INVALIDARG;
4739 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4743 /* ITypeInfo::GetFuncDesc
4745 * Retrieves the FUNCDESC structure that contains information about a
4746 * specified function.
4749 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4750 LPFUNCDESC *ppFuncDesc)
4752 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4753 const FUNCDESC *internal_funcdesc;
4756 TRACE("(%p) index %d\n", This, index);
4758 if ((This->TypeAttr.typekind == TKIND_DISPATCH) &&
4759 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4760 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4761 &internal_funcdesc, NULL);
4763 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4764 &internal_funcdesc);
4767 WARN("description for function %d not found\n", index);
4771 return TLB_AllocAndInitFuncDesc(
4774 This->TypeAttr.typekind == TKIND_DISPATCH);
4777 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4781 SIZE_T size = sizeof(*src);
4784 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4785 if (src->varkind == VAR_CONST)
4786 size += sizeof(VARIANT);
4787 size += TLB_SizeElemDesc(&src->elemdescVar);
4789 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4790 if (!dest) return E_OUTOFMEMORY;
4793 buffer = (char *)(dest + 1);
4794 if (src->lpstrSchema)
4797 dest->lpstrSchema = (LPOLESTR)buffer;
4798 len = strlenW(src->lpstrSchema);
4799 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4800 buffer += (len + 1) * sizeof(WCHAR);
4803 if (src->varkind == VAR_CONST)
4807 dest->u.lpvarValue = (VARIANT *)buffer;
4808 *dest->u.lpvarValue = *src->u.lpvarValue;
4809 buffer += sizeof(VARIANT);
4810 VariantInit(dest->u.lpvarValue);
4811 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4814 SysFreeString((BSTR)dest_ptr);
4818 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4821 if (src->varkind == VAR_CONST)
4822 VariantClear(dest->u.lpvarValue);
4823 SysFreeString((BSTR)dest);
4830 /* ITypeInfo::GetVarDesc
4832 * Retrieves a VARDESC structure that describes the specified variable.
4835 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4836 LPVARDESC *ppVarDesc)
4838 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4840 const TLBVarDesc *pVDesc;
4842 TRACE("(%p) index %d\n", This, index);
4844 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4848 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4850 return E_INVALIDARG;
4853 /* ITypeInfo_GetNames
4855 * Retrieves the variable with the specified member ID (or the name of the
4856 * property or method and its parameters) that correspond to the specified
4859 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4860 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4862 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4863 const TLBFuncDesc *pFDesc;
4864 const TLBVarDesc *pVDesc;
4866 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4867 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4870 /* function found, now return function and parameter names */
4871 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4874 *rgBstrNames=SysAllocString(pFDesc->Name);
4876 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4882 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4885 *rgBstrNames=SysAllocString(pVDesc->Name);
4890 if(This->TypeAttr.cImplTypes &&
4891 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4892 /* recursive search */
4895 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4897 if(SUCCEEDED(result))
4899 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4900 ITypeInfo_Release(pTInfo);
4903 WARN("Could not search inherited interface!\n");
4907 WARN("no names found\n");
4910 return TYPE_E_ELEMENTNOTFOUND;
4917 /* ITypeInfo::GetRefTypeOfImplType
4919 * If a type description describes a COM class, it retrieves the type
4920 * description of the implemented interface types. For an interface,
4921 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4925 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4930 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4933 const TLBImplType *pImpl = This->impltypelist;
4935 TRACE("(%p) index %d\n", This, index);
4936 if (TRACE_ON(ole)) dump_TypeInfo(This);
4940 /* only valid on dual interfaces;
4941 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4943 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4945 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4946 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4952 hr = TYPE_E_ELEMENTNOTFOUND;
4957 /* get element n from linked list */
4958 for(i=0; pImpl && i<index; i++)
4960 pImpl = pImpl->next;
4964 *pRefType = pImpl->hRef;
4966 hr = TYPE_E_ELEMENTNOTFOUND;
4972 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
4974 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
4980 /* ITypeInfo::GetImplTypeFlags
4982 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4983 * or base interface in a type description.
4985 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4986 UINT index, INT *pImplTypeFlags)
4988 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4992 TRACE("(%p) index %d\n", This, index);
4993 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4994 i++, pImpl=pImpl->next)
4996 if(i==index && pImpl){
4997 *pImplTypeFlags=pImpl->implflags;
5001 return TYPE_E_ELEMENTNOTFOUND;
5005 * Maps between member names and member IDs, and parameter names and
5008 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5009 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5011 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5012 const TLBFuncDesc *pFDesc;
5013 const TLBVarDesc *pVDesc;
5017 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5020 /* init out parameters in case of failure */
5021 for (i = 0; i < cNames; i++)
5022 pMemId[i] = MEMBERID_NIL;
5024 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5026 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5027 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5028 for(i=1; i < cNames; i++){
5029 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5030 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5032 if( j<pFDesc->funcdesc.cParams)
5035 ret=DISP_E_UNKNOWNNAME;
5037 TRACE("-- 0x%08x\n", ret);
5041 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5042 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5043 if(cNames) *pMemId=pVDesc->vardesc.memid;
5047 /* not found, see if it can be found in an inherited interface */
5048 if(This->TypeAttr.cImplTypes) {
5049 /* recursive search */
5051 ret=ITypeInfo_GetRefTypeInfo(iface,
5052 This->impltypelist->hRef, &pTInfo);
5054 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5055 ITypeInfo_Release(pTInfo);
5058 WARN("Could not search inherited interface!\n");
5060 WARN("no names found\n");
5061 return DISP_E_UNKNOWNNAME;
5064 /* ITypeInfo::Invoke
5066 * Invokes a method, or accesses a property of an object, that implements the
5067 * interface described by the type description.
5070 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5073 if (TRACE_ON(ole)) {
5075 TRACE("Calling %p(",func);
5076 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5088 res = func(args[0]);
5091 res = func(args[0],args[1]);
5094 res = func(args[0],args[1],args[2]);
5097 res = func(args[0],args[1],args[2],args[3]);
5100 res = func(args[0],args[1],args[2],args[3],args[4]);
5103 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5106 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5109 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5112 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5115 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5118 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5121 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]);
5124 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]);
5127 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]);
5130 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]);
5133 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]);
5136 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]);
5139 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]);
5142 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]);
5145 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]);
5148 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]);
5151 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]);
5154 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]);
5157 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5163 FIXME("unsupported calling convention %d\n",callconv);
5167 TRACE("returns %08x\n",res);
5171 extern int _argsize(DWORD vt);
5173 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5176 ITypeInfo *tinfo2 = NULL;
5177 TYPEATTR *tattr = NULL;
5179 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5182 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5184 tdesc->u.hreftype, hr);
5187 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5190 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5191 ITypeInfo_Release(tinfo2);
5195 switch (tattr->typekind)
5202 tdesc = &tattr->tdescAlias;
5203 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5206 case TKIND_INTERFACE:
5207 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5213 case TKIND_DISPATCH:
5222 FIXME("TKIND_RECORD unhandled.\n");
5227 FIXME("TKIND_UNION unhandled.\n");
5232 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5236 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5237 ITypeInfo_Release(tinfo2);
5241 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5245 /* enforce only one level of pointer indirection */
5246 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5248 tdesc = tdesc->u.lptdesc;
5250 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5251 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5252 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5253 if ((tdesc->vt == VT_USERDEFINED) ||
5254 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5256 VARTYPE vt_userdefined = 0;
5257 const TYPEDESC *tdesc_userdefined = tdesc;
5258 if (tdesc->vt == VT_PTR)
5260 vt_userdefined = VT_BYREF;
5261 tdesc_userdefined = tdesc->u.lptdesc;
5263 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5265 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5266 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5268 *vt |= vt_userdefined;
5280 case VT_USERDEFINED:
5281 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5288 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5289 hr = DISP_E_BADVARTYPE;
5293 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5302 /***********************************************************************
5303 * DispCallFunc (OLEAUT32.@)
5305 * Invokes a function of the specifed calling convention, passing the
5306 * specified arguments and returns the result.
5309 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5310 * oVft [I] The offset in the vtable. See notes.
5311 * cc [I] Calling convention of the function to call.
5312 * vtReturn [I] The return type of the function.
5313 * cActuals [I] Number of parameters.
5314 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5315 * prgpvarg [I] The arguments to pass.
5316 * pvargResult [O] The return value of the function. Can be NULL.
5320 * Failure: HRESULT code.
5323 * The HRESULT return value of this function is not affected by the return
5324 * value of the user supplied function, which is returned in pvargResult.
5326 * If pvInstance is NULL then a non-object function is to be called and oVft
5327 * is the address of the function to call.
5329 * The cc parameter can be one of the following values:
5342 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5343 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5345 int i, argsize, argspos;
5349 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5350 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5351 pvargResult, V_VT(pvargResult));
5355 argsize++; /* for This pointer */
5357 for (i=0;i<cActuals;i++)
5359 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5360 dump_Variant(prgpvarg[i]);
5361 argsize += _argsize(prgvt[i]);
5363 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5368 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5372 for (i=0;i<cActuals;i++)
5374 VARIANT *arg = prgpvarg[i];
5375 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5376 if (prgvt[i] == VT_VARIANT)
5377 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5379 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5380 argspos += _argsize(prgvt[i]);
5385 FARPROC *vtable = *(FARPROC**)pvInstance;
5386 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5389 /* if we aren't invoking an object then the function pointer is stored
5391 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5393 if (pvargResult && (vtReturn != VT_EMPTY))
5395 TRACE("Method returned 0x%08x\n",hres);
5396 V_VT(pvargResult) = vtReturn;
5397 V_UI4(pvargResult) = hres;
5400 HeapFree(GetProcessHeap(),0,args);
5404 #define INVBUF_ELEMENT_SIZE \
5405 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5406 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5407 ((VARIANTARG *)(buffer))
5408 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5409 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5410 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5411 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5412 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5413 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5415 static HRESULT WINAPI ITypeInfo_fnInvoke(
5420 DISPPARAMS *pDispParams,
5421 VARIANT *pVarResult,
5422 EXCEPINFO *pExcepInfo,
5425 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5427 unsigned int var_index;
5430 const TLBFuncDesc *pFuncInfo;
5432 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5433 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5438 ERR("NULL pDispParams not allowed\n");
5439 return E_INVALIDARG;
5442 dump_DispParms(pDispParams);
5444 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5446 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5447 pDispParams->cNamedArgs, pDispParams->cArgs);
5448 return E_INVALIDARG;
5451 /* we do this instead of using GetFuncDesc since it will return a fake
5452 * FUNCDESC for dispinterfaces and we want the real function description */
5453 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5454 if ((memid == pFuncInfo->funcdesc.memid) &&
5455 (wFlags & pFuncInfo->funcdesc.invkind))
5459 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5463 TRACE("invoking:\n");
5464 dump_TLBFuncDescOne(pFuncInfo);
5467 switch (func_desc->funckind) {
5468 case FUNC_PUREVIRTUAL:
5469 case FUNC_VIRTUAL: {
5470 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5472 VARIANT retval; /* pointer for storing byref retvals in */
5473 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5474 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5475 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5476 UINT cNamedArgs = pDispParams->cNamedArgs;
5477 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5481 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5483 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5485 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5486 hres = DISP_E_PARAMNOTFOUND;
5489 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5491 rgdispidNamedArgs++;
5494 for (i = 0; i < func_desc->cParams; i++)
5496 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5497 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5502 TRACE("changing args\n");
5503 for (i = 0; i < func_desc->cParams; i++)
5505 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5506 VARIANTARG *src_arg;
5512 for (j = 0; j < cNamedArgs; j++)
5513 if (rgdispidNamedArgs[j] == i)
5515 src_arg = &pDispParams->rgvarg[j];
5520 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5522 if (wParamFlags & PARAMFLAG_FRETVAL)
5524 /* under most conditions the caller is not allowed to
5525 * pass in a dispparam arg in the index of what would be
5526 * the retval parameter. however, there is an exception
5527 * where the extra parameter is used in an extra
5528 * IDispatch::Invoke below */
5529 if ((i < pDispParams->cArgs) &&
5530 ((func_desc->cParams != 1) || !pVarResult ||
5531 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5533 hres = DISP_E_BADPARAMCOUNT;
5537 /* note: this check is placed so that if the caller passes
5538 * in a VARIANTARG for the retval we just ignore it, like
5540 if (i == func_desc->cParams - 1)
5543 arg = prgpvarg[i] = &rgvarg[i];
5544 memset(arg, 0, sizeof(*arg));
5545 V_VT(arg) = rgvt[i];
5546 memset(&retval, 0, sizeof(retval));
5547 V_BYREF(arg) = &retval;
5551 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5552 hres = E_UNEXPECTED;
5558 dump_Variant(src_arg);
5560 if (rgvt[i] == VT_VARIANT)
5561 hres = VariantCopy(&rgvarg[i], src_arg);
5562 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5564 if (rgvt[i] == V_VT(src_arg))
5565 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5568 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5569 hres = VariantCopy(&missing_arg[i], src_arg);
5570 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5572 V_VT(&rgvarg[i]) = rgvt[i];
5574 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5576 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5577 V_VT(&missing_arg[i]) = V_VT(src_arg);
5578 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5579 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5580 V_VT(&rgvarg[i]) = rgvt[i];
5582 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5584 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5585 V_VT(&rgvarg[i]) = rgvt[i];
5589 /* FIXME: this doesn't work for VT_BYREF arguments if
5590 * they are not the same type as in the paramdesc */
5591 V_VT(&rgvarg[i]) = V_VT(src_arg);
5592 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5593 V_VT(&rgvarg[i]) = rgvt[i];
5598 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5599 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5600 debugstr_VT(src_arg), debugstr_VF(src_arg));
5603 prgpvarg[i] = &rgvarg[i];
5605 else if (wParamFlags & PARAMFLAG_FOPT)
5608 arg = prgpvarg[i] = &rgvarg[i];
5609 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5611 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5617 VARIANTARG *missing_arg;
5618 /* if the function wants a pointer to a variant then
5619 * set that up, otherwise just pass the VT_ERROR in
5620 * the argument by value */
5621 if (rgvt[i] & VT_BYREF)
5623 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5624 V_VT(arg) = VT_VARIANT | VT_BYREF;
5625 V_VARIANTREF(arg) = missing_arg;
5629 V_VT(missing_arg) = VT_ERROR;
5630 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5635 hres = DISP_E_BADPARAMCOUNT;
5639 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5640 if (func_desc->cParamsOpt < 0)
5642 FIXME("Does not support safearray optional parameters\n");
5643 hres = DISP_E_BADPARAMCOUNT;
5644 goto func_fail; /* FIXME: we don't free changed types here */
5647 /* VT_VOID is a special case for return types, so it is not
5648 * handled in the general function */
5649 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5650 V_VT(&varresult) = VT_EMPTY;
5653 V_VT(&varresult) = 0;
5654 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5655 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5658 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5659 V_VT(&varresult), func_desc->cParams, rgvt,
5660 prgpvarg, &varresult);
5662 for (i = 0; i < func_desc->cParams; i++)
5664 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5665 if (wParamFlags & PARAMFLAG_FRETVAL)
5669 TRACE("[retval] value: ");
5670 dump_Variant(prgpvarg[i]);
5675 VariantInit(pVarResult);
5676 /* deref return value */
5677 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5680 /* free data stored in varresult. Note that
5681 * VariantClear doesn't do what we want because we are
5682 * working with byref types. */
5683 /* FIXME: clear safearrays, bstrs, records and
5684 * variants here too */
5685 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5686 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5688 if(*V_UNKNOWNREF(prgpvarg[i]))
5689 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5693 else if (i < pDispParams->cArgs)
5695 if (wParamFlags & PARAMFLAG_FOUT)
5697 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5699 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5700 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5704 ERR("failed to convert param %d to vt %d\n", i,
5705 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5709 VariantClear(&rgvarg[i]);
5711 else if (wParamFlags & PARAMFLAG_FOPT)
5713 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5714 VariantClear(&rgvarg[i]);
5718 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5720 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5721 hres = DISP_E_EXCEPTION;
5724 IErrorInfo *pErrorInfo;
5725 pExcepInfo->scode = V_ERROR(&varresult);
5726 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
5728 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
5729 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
5730 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
5731 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
5733 IErrorInfo_Release(pErrorInfo);
5737 if (V_VT(&varresult) != VT_ERROR)
5739 TRACE("varresult value: ");
5740 dump_Variant(&varresult);
5744 VariantClear(pVarResult);
5745 *pVarResult = varresult;
5748 VariantClear(&varresult);
5751 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
5752 (wFlags == INVOKE_PROPERTYGET) &&
5753 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
5754 (pDispParams->cArgs != 0))
5756 if (V_VT(pVarResult) == VT_DISPATCH)
5758 IDispatch *pDispatch = V_DISPATCH(pVarResult);
5759 /* Note: not VariantClear; we still need the dispatch
5760 * pointer to be valid */
5761 VariantInit(pVarResult);
5762 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
5763 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
5764 pDispParams, pVarResult, pExcepInfo, pArgErr);
5765 IDispatch_Release(pDispatch);
5769 VariantClear(pVarResult);
5770 hres = DISP_E_NOTACOLLECTION;
5775 HeapFree(GetProcessHeap(), 0, buffer);
5778 case FUNC_DISPATCH: {
5781 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5782 if (SUCCEEDED(hres)) {
5783 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5784 hres = IDispatch_Invoke(
5785 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5786 pVarResult,pExcepInfo,pArgErr
5789 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5790 IDispatch_Release(disp);
5792 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5796 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5801 TRACE("-- 0x%08x\n", hres);
5804 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5807 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5808 if(FAILED(hres)) return hres;
5810 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5811 dump_VARDESC(var_desc);
5812 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5816 /* not found, look for it in inherited interfaces */
5817 ITypeInfo2_GetTypeKind(iface, &type_kind);
5818 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5820 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5821 /* recursive search */
5823 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5824 if(SUCCEEDED(hres)){
5825 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5826 ITypeInfo_Release(pTInfo);
5829 WARN("Could not search inherited interface!\n");
5832 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
5833 return DISP_E_MEMBERNOTFOUND;
5836 /* ITypeInfo::GetDocumentation
5838 * Retrieves the documentation string, the complete Help file name and path,
5839 * and the context ID for the Help topic for a specified type description.
5841 * (Can be tested by the Visual Basic Editor in Word for instance.)
5843 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5844 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5845 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5847 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5848 const TLBFuncDesc *pFDesc;
5849 const TLBVarDesc *pVDesc;
5850 TRACE("(%p) memid %d Name(%p) DocString(%p)"
5851 " HelpContext(%p) HelpFile(%p)\n",
5852 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5853 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5855 *pBstrName=SysAllocString(This->Name);
5857 *pBstrDocString=SysAllocString(This->DocString);
5859 *pdwHelpContext=This->dwHelpContext;
5861 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5863 }else {/* for a member */
5864 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5865 if(pFDesc->funcdesc.memid==memid){
5867 *pBstrName = SysAllocString(pFDesc->Name);
5869 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5871 *pdwHelpContext=pFDesc->helpcontext;
5874 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5875 if(pVDesc->vardesc.memid==memid){
5877 *pBstrName = SysAllocString(pVDesc->Name);
5879 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5881 *pdwHelpContext=pVDesc->HelpContext;
5886 if(This->TypeAttr.cImplTypes &&
5887 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5888 /* recursive search */
5891 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5893 if(SUCCEEDED(result)) {
5894 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
5895 pBstrDocString, pdwHelpContext, pBstrHelpFile);
5896 ITypeInfo_Release(pTInfo);
5899 WARN("Could not search inherited interface!\n");
5902 WARN("member %d not found\n", memid);
5903 return TYPE_E_ELEMENTNOTFOUND;
5906 /* ITypeInfo::GetDllEntry
5908 * Retrieves a description or specification of an entry point for a function
5911 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5912 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5915 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5916 const TLBFuncDesc *pFDesc;
5918 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5920 if (pBstrDllName) *pBstrDllName = NULL;
5921 if (pBstrName) *pBstrName = NULL;
5922 if (pwOrdinal) *pwOrdinal = 0;
5924 if (This->TypeAttr.typekind != TKIND_MODULE)
5925 return TYPE_E_BADMODULEKIND;
5927 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5928 if(pFDesc->funcdesc.memid==memid){
5929 dump_TypeInfo(This);
5931 dump_TLBFuncDescOne(pFDesc);
5934 *pBstrDllName = SysAllocString(This->DllName);
5936 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5938 *pBstrName = SysAllocString(pFDesc->Entry);
5946 *pwOrdinal = (DWORD)pFDesc->Entry;
5949 return TYPE_E_ELEMENTNOTFOUND;
5952 /* ITypeInfo::GetRefTypeInfo
5954 * If a type description references other type descriptions, it retrieves
5955 * the referenced type descriptions.
5957 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5960 ITypeInfo **ppTInfo)
5962 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5963 HRESULT result = E_FAIL;
5965 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5967 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5968 ITypeInfo_AddRef(*ppTInfo);
5971 else if (hRefType == -1 &&
5972 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5973 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5975 /* when we meet a DUAL dispinterface, we must create the interface
5978 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5981 /* the interface version contains the same information as the dispinterface
5982 * copy the contents of the structs.
5984 *pTypeInfoImpl = *This;
5985 pTypeInfoImpl->ref = 0;
5987 /* change the type to interface */
5988 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5990 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5992 /* we use data structures from This, so we need to keep a reference
5993 * to it to stop it being destroyed and signal to the new instance to
5994 * not free its data structures when it is destroyed */
5995 pTypeInfoImpl->no_free_data = TRUE;
5996 pTypeInfoImpl->next = This;
5997 ITypeInfo_AddRef((ITypeInfo*) This);
5999 ITypeInfo_AddRef(*ppTInfo);
6004 TLBRefType *ref_type;
6005 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6007 if(ref_type->reference == hRefType)
6010 if(&ref_type->entry == &This->pTypeLib->ref_list)
6012 FIXME("Can't find pRefType for ref %x\n", hRefType);
6015 if(hRefType != -1) {
6016 ITypeLib *pTLib = NULL;
6018 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6020 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6022 if(ref_type->pImpTLInfo->pImpTypeLib) {
6023 TRACE("typeinfo in imported typelib that is already loaded\n");
6024 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6025 ITypeLib2_AddRef((ITypeLib*) pTLib);
6028 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6029 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6030 ref_type->pImpTLInfo->wVersionMajor,
6031 ref_type->pImpTLInfo->wVersionMinor,
6032 ref_type->pImpTLInfo->lcid,
6035 if(!SUCCEEDED(result)) {
6036 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6037 result=LoadTypeLib(libnam, &pTLib);
6038 SysFreeString(libnam);
6040 if(SUCCEEDED(result)) {
6041 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6042 ITypeLib2_AddRef(pTLib);
6046 if(SUCCEEDED(result)) {
6047 if(ref_type->index == TLB_REF_USE_GUID)
6048 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6052 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6056 ITypeLib2_Release(pTLib);
6061 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6062 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6066 /* ITypeInfo::AddressOfMember
6068 * Retrieves the addresses of static functions or variables, such as those
6071 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6072 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6074 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6080 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6082 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6086 module = LoadLibraryW(dll);
6089 ERR("couldn't load %s\n", debugstr_w(dll));
6091 if (entry) SysFreeString(entry);
6092 return STG_E_FILENOTFOUND;
6094 /* FIXME: store library somewhere where we can free it */
6099 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6100 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6101 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6103 *ppv = GetProcAddress(module, entryA);
6105 ERR("function not found %s\n", debugstr_a(entryA));
6107 HeapFree(GetProcessHeap(), 0, entryA);
6111 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6113 ERR("function not found %d\n", ordinal);
6117 if (entry) SysFreeString(entry);
6120 return TYPE_E_DLLFUNCTIONNOTFOUND;
6125 /* ITypeInfo::CreateInstance
6127 * Creates a new instance of a type that describes a component object class
6130 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6131 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6133 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6137 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6143 WARN("Not able to aggregate\n");
6144 return CLASS_E_NOAGGREGATION;
6147 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6148 if(FAILED(hr)) return hr;
6150 if(pTA->typekind != TKIND_COCLASS)
6152 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6158 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6161 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6162 TRACE("GetActiveObject rets %08x\n", hr);
6165 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6166 IUnknown_Release(pUnk);
6171 hr = CoCreateInstance(&pTA->guid, NULL,
6172 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6176 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6180 /* ITypeInfo::GetMops
6182 * Retrieves marshalling information.
6184 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6187 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6188 FIXME("(%p) stub!\n", This);
6192 /* ITypeInfo::GetContainingTypeLib
6194 * Retrieves the containing type library and the index of the type description
6195 * within that type library.
6197 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6198 ITypeLib * *ppTLib, UINT *pIndex)
6200 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6202 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6204 *pIndex=This->index;
6205 TRACE("returning pIndex=%d\n", *pIndex);
6209 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6210 ITypeLib2_AddRef(*ppTLib);
6211 TRACE("returning ppTLib=%p\n", *ppTLib);
6217 /* ITypeInfo::ReleaseTypeAttr
6219 * Releases a TYPEATTR previously returned by GetTypeAttr.
6222 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6223 TYPEATTR* pTypeAttr)
6225 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6226 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6227 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6230 /* ITypeInfo::ReleaseFuncDesc
6232 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6234 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6236 FUNCDESC *pFuncDesc)
6238 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6241 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6243 for (i = 0; i < pFuncDesc->cParams; i++)
6244 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6245 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6247 SysFreeString((BSTR)pFuncDesc);
6250 /* ITypeInfo::ReleaseVarDesc
6252 * Releases a VARDESC previously returned by GetVarDesc.
6254 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6257 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6258 TRACE("(%p)->(%p)\n", This, pVarDesc);
6260 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6261 if (pVarDesc->varkind == VAR_CONST)
6262 VariantClear(pVarDesc->u.lpvarValue);
6263 SysFreeString((BSTR)pVarDesc);
6266 /* ITypeInfo2::GetTypeKind
6268 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6271 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6272 TYPEKIND *pTypeKind)
6274 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6275 *pTypeKind=This->TypeAttr.typekind;
6276 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6280 /* ITypeInfo2::GetTypeFlags
6282 * Returns the type flags without any allocations. This returns a DWORD type
6283 * flag, which expands the type flags without growing the TYPEATTR (type
6287 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6289 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6290 *pTypeFlags=This->TypeAttr.wTypeFlags;
6291 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6295 /* ITypeInfo2::GetFuncIndexOfMemId
6296 * Binds to a specific member based on a known DISPID, where the member name
6297 * is not known (for example, when binding to a default member).
6300 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6301 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6303 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6304 const TLBFuncDesc *pFuncInfo;
6308 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6309 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6315 result = TYPE_E_ELEMENTNOTFOUND;
6317 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6318 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6322 /* TypeInfo2::GetVarIndexOfMemId
6324 * Binds to a specific member based on a known DISPID, where the member name
6325 * is not known (for example, when binding to a default member).
6328 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6329 MEMBERID memid, UINT *pVarIndex)
6331 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6332 TLBVarDesc *pVarInfo;
6335 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6336 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6342 result = TYPE_E_ELEMENTNOTFOUND;
6344 TRACE("(%p) memid 0x%08x -> %s\n", This,
6345 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6349 /* ITypeInfo2::GetCustData
6351 * Gets the custom data
6353 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6358 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6359 TLBCustData *pCData;
6361 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6362 if( IsEqualIID(guid, &pCData->guid)) break;
6364 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6368 VariantInit( pVarVal);
6369 VariantCopy( pVarVal, &pCData->data);
6372 return E_INVALIDARG; /* FIXME: correct? */
6375 /* ITypeInfo2::GetFuncCustData
6377 * Gets the custom data
6379 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6385 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6386 TLBCustData *pCData=NULL;
6387 TLBFuncDesc * pFDesc;
6389 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6390 pFDesc=pFDesc->next);
6393 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6394 if( IsEqualIID(guid, &pCData->guid)) break;
6396 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6399 VariantInit( pVarVal);
6400 VariantCopy( pVarVal, &pCData->data);
6403 return E_INVALIDARG; /* FIXME: correct? */
6406 /* ITypeInfo2::GetParamCustData
6408 * Gets the custom data
6410 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6417 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6418 TLBCustData *pCData=NULL;
6419 TLBFuncDesc * pFDesc;
6422 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6424 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6425 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6426 pCData = pCData->next)
6427 if( IsEqualIID(guid, &pCData->guid)) break;
6429 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6433 VariantInit( pVarVal);
6434 VariantCopy( pVarVal, &pCData->data);
6437 return E_INVALIDARG; /* FIXME: correct? */
6440 /* ITypeInfo2::GetVarCustData
6442 * Gets the custom data
6444 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6450 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6451 TLBCustData *pCData=NULL;
6452 TLBVarDesc * pVDesc;
6455 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6459 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6461 if( IsEqualIID(guid, &pCData->guid)) break;
6465 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6469 VariantInit( pVarVal);
6470 VariantCopy( pVarVal, &pCData->data);
6473 return E_INVALIDARG; /* FIXME: correct? */
6476 /* ITypeInfo2::GetImplCustData
6478 * Gets the custom data
6480 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6486 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6487 TLBCustData *pCData=NULL;
6488 TLBImplType * pRDesc;
6491 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6495 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6497 if( IsEqualIID(guid, &pCData->guid)) break;
6501 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6505 VariantInit( pVarVal);
6506 VariantCopy( pVarVal, &pCData->data);
6509 return E_INVALIDARG; /* FIXME: correct? */
6512 /* ITypeInfo2::GetDocumentation2
6514 * Retrieves the documentation string, the complete Help file name and path,
6515 * the localization context to use, and the context ID for the library Help
6516 * topic in the Help file.
6519 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6523 BSTR *pbstrHelpString,
6524 DWORD *pdwHelpStringContext,
6525 BSTR *pbstrHelpStringDll)
6527 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6528 const TLBFuncDesc *pFDesc;
6529 const TLBVarDesc *pVDesc;
6530 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6531 "HelpStringContext(%p) HelpStringDll(%p)\n",
6532 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6533 pbstrHelpStringDll );
6534 /* the help string should be obtained from the helpstringdll,
6535 * using the _DLLGetDocumentation function, based on the supplied
6536 * lcid. Nice to do sometime...
6538 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6540 *pbstrHelpString=SysAllocString(This->Name);
6541 if(pdwHelpStringContext)
6542 *pdwHelpStringContext=This->dwHelpStringContext;
6543 if(pbstrHelpStringDll)
6544 *pbstrHelpStringDll=
6545 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6547 }else {/* for a member */
6548 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6549 if(pFDesc->funcdesc.memid==memid){
6551 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6552 if(pdwHelpStringContext)
6553 *pdwHelpStringContext=pFDesc->HelpStringContext;
6554 if(pbstrHelpStringDll)
6555 *pbstrHelpStringDll=
6556 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6559 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6560 if(pVDesc->vardesc.memid==memid){
6562 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6563 if(pdwHelpStringContext)
6564 *pdwHelpStringContext=pVDesc->HelpStringContext;
6565 if(pbstrHelpStringDll)
6566 *pbstrHelpStringDll=
6567 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6571 return TYPE_E_ELEMENTNOTFOUND;
6574 /* ITypeInfo2::GetAllCustData
6576 * Gets all custom data items for the Type info.
6579 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6581 CUSTDATA *pCustData)
6583 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6584 TLBCustData *pCData;
6587 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6589 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6590 if(pCustData->prgCustData ){
6591 pCustData->cCustData=This->ctCustData;
6592 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6593 pCustData->prgCustData[i].guid=pCData->guid;
6594 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6597 ERR(" OUT OF MEMORY!\n");
6598 return E_OUTOFMEMORY;
6603 /* ITypeInfo2::GetAllFuncCustData
6605 * Gets all custom data items for the specified Function
6608 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6611 CUSTDATA *pCustData)
6613 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6614 TLBCustData *pCData;
6615 TLBFuncDesc * pFDesc;
6617 TRACE("(%p) index %d\n", This, index);
6618 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6619 pFDesc=pFDesc->next)
6622 pCustData->prgCustData =
6623 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6624 if(pCustData->prgCustData ){
6625 pCustData->cCustData=pFDesc->ctCustData;
6626 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6627 pCData = pCData->next){
6628 pCustData->prgCustData[i].guid=pCData->guid;
6629 VariantCopy(& pCustData->prgCustData[i].varValue,
6633 ERR(" OUT OF MEMORY!\n");
6634 return E_OUTOFMEMORY;
6638 return TYPE_E_ELEMENTNOTFOUND;
6641 /* ITypeInfo2::GetAllParamCustData
6643 * Gets all custom data items for the Functions
6646 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6647 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6649 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6650 TLBCustData *pCData=NULL;
6651 TLBFuncDesc * pFDesc;
6653 TRACE("(%p) index %d\n", This, indexFunc);
6654 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6655 pFDesc=pFDesc->next)
6657 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6658 pCustData->prgCustData =
6659 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6660 sizeof(CUSTDATAITEM));
6661 if(pCustData->prgCustData ){
6662 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6663 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6664 pCData; i++, pCData = pCData->next){
6665 pCustData->prgCustData[i].guid=pCData->guid;
6666 VariantCopy(& pCustData->prgCustData[i].varValue,
6670 ERR(" OUT OF MEMORY!\n");
6671 return E_OUTOFMEMORY;
6675 return TYPE_E_ELEMENTNOTFOUND;
6678 /* ITypeInfo2::GetAllVarCustData
6680 * Gets all custom data items for the specified Variable
6683 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6684 UINT index, CUSTDATA *pCustData)
6686 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6687 TLBCustData *pCData;
6688 TLBVarDesc * pVDesc;
6690 TRACE("(%p) index %d\n", This, index);
6691 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6692 pVDesc=pVDesc->next)
6695 pCustData->prgCustData =
6696 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6697 if(pCustData->prgCustData ){
6698 pCustData->cCustData=pVDesc->ctCustData;
6699 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6700 pCData = pCData->next){
6701 pCustData->prgCustData[i].guid=pCData->guid;
6702 VariantCopy(& pCustData->prgCustData[i].varValue,
6706 ERR(" OUT OF MEMORY!\n");
6707 return E_OUTOFMEMORY;
6711 return TYPE_E_ELEMENTNOTFOUND;
6714 /* ITypeInfo2::GetAllImplCustData
6716 * Gets all custom data items for the specified implementation type
6719 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6722 CUSTDATA *pCustData)
6724 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6725 TLBCustData *pCData;
6726 TLBImplType * pRDesc;
6728 TRACE("(%p) index %d\n", This, index);
6729 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6730 pRDesc=pRDesc->next)
6733 pCustData->prgCustData =
6734 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6735 if(pCustData->prgCustData ){
6736 pCustData->cCustData=pRDesc->ctCustData;
6737 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6738 pCData = pCData->next){
6739 pCustData->prgCustData[i].guid=pCData->guid;
6740 VariantCopy(& pCustData->prgCustData[i].varValue,
6744 ERR(" OUT OF MEMORY!\n");
6745 return E_OUTOFMEMORY;
6749 return TYPE_E_ELEMENTNOTFOUND;
6752 static const ITypeInfo2Vtbl tinfvt =
6755 ITypeInfo_fnQueryInterface,
6757 ITypeInfo_fnRelease,
6759 ITypeInfo_fnGetTypeAttr,
6760 ITypeInfo_fnGetTypeComp,
6761 ITypeInfo_fnGetFuncDesc,
6762 ITypeInfo_fnGetVarDesc,
6763 ITypeInfo_fnGetNames,
6764 ITypeInfo_fnGetRefTypeOfImplType,
6765 ITypeInfo_fnGetImplTypeFlags,
6766 ITypeInfo_fnGetIDsOfNames,
6768 ITypeInfo_fnGetDocumentation,
6769 ITypeInfo_fnGetDllEntry,
6770 ITypeInfo_fnGetRefTypeInfo,
6771 ITypeInfo_fnAddressOfMember,
6772 ITypeInfo_fnCreateInstance,
6773 ITypeInfo_fnGetMops,
6774 ITypeInfo_fnGetContainingTypeLib,
6775 ITypeInfo_fnReleaseTypeAttr,
6776 ITypeInfo_fnReleaseFuncDesc,
6777 ITypeInfo_fnReleaseVarDesc,
6779 ITypeInfo2_fnGetTypeKind,
6780 ITypeInfo2_fnGetTypeFlags,
6781 ITypeInfo2_fnGetFuncIndexOfMemId,
6782 ITypeInfo2_fnGetVarIndexOfMemId,
6783 ITypeInfo2_fnGetCustData,
6784 ITypeInfo2_fnGetFuncCustData,
6785 ITypeInfo2_fnGetParamCustData,
6786 ITypeInfo2_fnGetVarCustData,
6787 ITypeInfo2_fnGetImplTypeCustData,
6788 ITypeInfo2_fnGetDocumentation2,
6789 ITypeInfo2_fnGetAllCustData,
6790 ITypeInfo2_fnGetAllFuncCustData,
6791 ITypeInfo2_fnGetAllParamCustData,
6792 ITypeInfo2_fnGetAllVarCustData,
6793 ITypeInfo2_fnGetAllImplTypeCustData,
6796 /******************************************************************************
6797 * CreateDispTypeInfo [OLEAUT32.31]
6799 * Build type information for an object so it can be called through an
6800 * IDispatch interface.
6803 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6804 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6807 * This call allows an objects methods to be accessed through IDispatch, by
6808 * building an ITypeInfo object that IDispatch can use to call through.
6810 HRESULT WINAPI CreateDispTypeInfo(
6811 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6812 LCID lcid, /* [I] Locale Id */
6813 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6815 ITypeInfoImpl *pTIClass, *pTIIface;
6816 ITypeLibImpl *pTypeLibImpl;
6818 TLBFuncDesc **ppFuncDesc;
6822 pTypeLibImpl = TypeLibImpl_Constructor();
6823 if (!pTypeLibImpl) return E_FAIL;
6825 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6826 pTIIface->pTypeLib = pTypeLibImpl;
6827 pTIIface->index = 0;
6828 pTIIface->Name = NULL;
6829 pTIIface->dwHelpContext = -1;
6830 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6831 pTIIface->TypeAttr.lcid = lcid;
6832 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6833 pTIIface->TypeAttr.wMajorVerNum = 0;
6834 pTIIface->TypeAttr.wMinorVerNum = 0;
6835 pTIIface->TypeAttr.cbAlignment = 2;
6836 pTIIface->TypeAttr.cbSizeInstance = -1;
6837 pTIIface->TypeAttr.cbSizeVft = -1;
6838 pTIIface->TypeAttr.cFuncs = 0;
6839 pTIIface->TypeAttr.cImplTypes = 0;
6840 pTIIface->TypeAttr.cVars = 0;
6841 pTIIface->TypeAttr.wTypeFlags = 0;
6843 ppFuncDesc = &pTIIface->funclist;
6844 for(func = 0; func < pidata->cMembers; func++) {
6845 METHODDATA *md = pidata->pmethdata + func;
6846 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6847 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6848 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6849 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
6850 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6851 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6852 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6853 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6854 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6855 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6856 (*ppFuncDesc)->funcdesc.cScodes = 0;
6857 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6858 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6859 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6860 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6861 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6862 md->cArgs * sizeof(ELEMDESC));
6863 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6864 md->cArgs * sizeof(TLBParDesc));
6865 for(param = 0; param < md->cArgs; param++) {
6866 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6867 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6869 (*ppFuncDesc)->helpcontext = 0;
6870 (*ppFuncDesc)->HelpStringContext = 0;
6871 (*ppFuncDesc)->HelpString = NULL;
6872 (*ppFuncDesc)->Entry = NULL;
6873 (*ppFuncDesc)->ctCustData = 0;
6874 (*ppFuncDesc)->pCustData = NULL;
6875 (*ppFuncDesc)->next = NULL;
6876 ppFuncDesc = &(*ppFuncDesc)->next;
6879 dump_TypeInfo(pTIIface);
6881 pTypeLibImpl->pTypeInfo = pTIIface;
6882 pTypeLibImpl->TypeInfoCount++;
6884 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6885 pTIClass->pTypeLib = pTypeLibImpl;
6886 pTIClass->index = 1;
6887 pTIClass->Name = NULL;
6888 pTIClass->dwHelpContext = -1;
6889 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6890 pTIClass->TypeAttr.lcid = lcid;
6891 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6892 pTIClass->TypeAttr.wMajorVerNum = 0;
6893 pTIClass->TypeAttr.wMinorVerNum = 0;
6894 pTIClass->TypeAttr.cbAlignment = 2;
6895 pTIClass->TypeAttr.cbSizeInstance = -1;
6896 pTIClass->TypeAttr.cbSizeVft = -1;
6897 pTIClass->TypeAttr.cFuncs = 0;
6898 pTIClass->TypeAttr.cImplTypes = 1;
6899 pTIClass->TypeAttr.cVars = 0;
6900 pTIClass->TypeAttr.wTypeFlags = 0;
6902 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6903 pTIClass->impltypelist->hRef = 0;
6905 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
6908 ref->pImpTLInfo = TLB_REF_INTERNAL;
6909 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
6911 dump_TypeInfo(pTIClass);
6913 pTIIface->next = pTIClass;
6914 pTypeLibImpl->TypeInfoCount++;
6916 *pptinfo = (ITypeInfo*)pTIClass;
6918 ITypeInfo_AddRef(*pptinfo);
6919 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
6925 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6927 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6929 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6932 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6934 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6936 return ITypeInfo_AddRef((ITypeInfo *)This);
6939 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6941 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6943 return ITypeInfo_Release((ITypeInfo *)This);
6946 static HRESULT WINAPI ITypeComp_fnBind(
6951 ITypeInfo ** ppTInfo,
6952 DESCKIND * pDescKind,
6955 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6956 const TLBFuncDesc *pFDesc;
6957 const TLBVarDesc *pVDesc;
6958 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6960 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6962 *pDescKind = DESCKIND_NONE;
6963 pBindPtr->lpfuncdesc = NULL;
6966 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6967 if (!strcmpiW(pFDesc->Name, szName)) {
6968 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6971 /* name found, but wrong flags */
6972 hr = TYPE_E_TYPEMISMATCH;
6977 HRESULT hr = TLB_AllocAndInitFuncDesc(
6979 &pBindPtr->lpfuncdesc,
6980 This->TypeAttr.typekind == TKIND_DISPATCH);
6983 *pDescKind = DESCKIND_FUNCDESC;
6984 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6985 ITypeInfo_AddRef(*ppTInfo);
6988 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6989 if (!strcmpiW(pVDesc->Name, szName)) {
6990 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6993 *pDescKind = DESCKIND_VARDESC;
6994 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6995 ITypeInfo_AddRef(*ppTInfo);
7000 /* FIXME: search each inherited interface, not just the first */
7001 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
7002 /* recursive search */
7006 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7009 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7010 ITypeInfo_Release(pTInfo);
7014 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7015 ITypeComp_Release(pTComp);
7018 WARN("Could not search inherited interface!\n");
7020 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7024 static HRESULT WINAPI ITypeComp_fnBindType(
7028 ITypeInfo ** ppTInfo,
7029 ITypeComp ** ppTComp)
7031 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7033 /* strange behaviour (does nothing) but like the
7036 if (!ppTInfo || !ppTComp)
7045 static const ITypeCompVtbl tcompvt =
7048 ITypeComp_fnQueryInterface,
7050 ITypeComp_fnRelease,
7053 ITypeComp_fnBindType