4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
44 * -. lousy fatal error handling
49 #include "wine/port.h"
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
68 #include "wine/unicode.h"
71 #include "wine/debug.h"
74 WINE_DEFAULT_DEBUG_CHANNEL(ole);
75 WINE_DECLARE_DEBUG_CHANNEL(typelib);
77 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
78 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
80 /****************************************************************************
83 * Takes p_iVal (which is in little endian) and returns it
84 * in the host machine's byte order.
86 #ifdef WORDS_BIGENDIAN
87 static WORD FromLEWord(WORD p_iVal)
89 return (((p_iVal & 0x00FF) << 8) |
90 ((p_iVal & 0xFF00) >> 8));
94 static DWORD FromLEDWord(DWORD p_iVal)
96 return (((p_iVal & 0x000000FF) << 24) |
97 ((p_iVal & 0x0000FF00) << 8) |
98 ((p_iVal & 0x00FF0000) >> 8) |
99 ((p_iVal & 0xFF000000) >> 24));
102 #define FromLEWord(X) (X)
103 #define FromLEDWord(X) (X)
107 /****************************************************************************
110 * Fix byte order in any structure if necessary
112 #ifdef WORDS_BIGENDIAN
113 static void FromLEWords(void *p_Val, int p_iSize)
117 p_iSize /= sizeof(WORD);
120 *Val = FromLEWord(*Val);
127 static void FromLEDWords(void *p_Val, int p_iSize)
131 p_iSize /= sizeof(DWORD);
134 *Val = FromLEDWord(*Val);
140 #define FromLEWords(X,Y) /*nothing*/
141 #define FromLEDWords(X,Y) /*nothing*/
145 * Find a typelib key which matches a requested maj.min version.
147 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
149 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
156 memcpy( buffer, typelibW, sizeof(typelibW) );
157 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
159 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
162 len = sizeof(key_name);
164 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
168 if (sscanf(key_name, "%u.%u", &v_maj, &v_min) == 2)
170 TRACE("found %s: %u.%u\n", debugstr_w(buffer), v_maj, v_min);
177 break; /* exact match */
179 if (v_min > best_min) best_min = v_min;
182 len = sizeof(key_name);
193 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
194 /* buffer must be at least 60 characters long */
195 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
197 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
198 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
200 memcpy( buffer, TypelibW, sizeof(TypelibW) );
201 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
202 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
206 /* get the path of an interface key, in the form "Interface\\<guid>" */
207 /* buffer must be at least 50 characters long */
208 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
210 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
212 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
213 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
217 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
218 /* buffer must be at least 16 characters long */
219 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
221 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
222 static const WCHAR win16W[] = {'w','i','n','1','6',0};
223 static const WCHAR win32W[] = {'w','i','n','3','2',0};
225 sprintfW( buffer, LcidFormatW, lcid );
228 case SYS_WIN16: strcatW( buffer, win16W ); break;
229 case SYS_WIN32: strcatW( buffer, win32W ); break;
231 TRACE("Typelib is for unsupported syskind %i\n", syskind);
237 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
240 /****************************************************************************
241 * QueryPathOfRegTypeLib [OLEAUT32.164]
243 * Gets the path to a registered type library.
246 * guid [I] referenced guid
247 * wMaj [I] major version
248 * wMin [I] minor version
250 * path [O] path of typelib
254 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
255 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
258 HRESULT WINAPI QueryPathOfRegTypeLib(
265 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
269 WCHAR Path[MAX_PATH];
272 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
274 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
275 get_typelib_key( guid, wMaj, wMin, buffer );
277 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
278 if (res == ERROR_FILE_NOT_FOUND)
280 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
281 return TYPE_E_LIBNOTREGISTERED;
283 else if (res != ERROR_SUCCESS)
285 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
286 return TYPE_E_REGISTRYACCESS;
291 LONG dwPathLen = sizeof(Path);
293 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
295 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
299 else if (myLCID == lcid)
301 /* try with sub-langid */
302 myLCID = SUBLANGID(lcid);
304 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
306 /* try with system langid */
316 *path = SysAllocString( Path );
321 TRACE_(typelib)("-- 0x%08x\n", hr);
325 /******************************************************************************
326 * CreateTypeLib [OLEAUT32.160] creates a typelib
332 HRESULT WINAPI CreateTypeLib(
333 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
335 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
339 /******************************************************************************
340 * LoadTypeLib [OLEAUT32.161]
342 * Loads a type library
345 * szFile [I] Name of file to load from.
346 * pptLib [O] Pointer that receives ITypeLib object on success.
353 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
355 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
357 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
358 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
361 /******************************************************************************
362 * LoadTypeLibEx [OLEAUT32.183]
364 * Loads and optionally registers a type library
370 HRESULT WINAPI LoadTypeLibEx(
371 LPCOLESTR szFile, /* [in] Name of file to load from */
372 REGKIND regkind, /* [in] Specify kind of registration */
373 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
375 WCHAR szPath[MAX_PATH+1];
378 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
382 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
387 case REGKIND_DEFAULT:
388 /* don't register typelibs supplied with full path. Experimentation confirms the following */
389 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
390 (szFile[0] && (szFile[1] == ':'))) break;
391 /* else fall-through */
393 case REGKIND_REGISTER:
394 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
396 IUnknown_Release(*pptLib);
404 TRACE(" returns %08x\n",res);
408 /******************************************************************************
409 * LoadRegTypeLib [OLEAUT32.162]
411 * Loads a registered type library.
414 * rguid [I] GUID of the registered type library.
415 * wVerMajor [I] major version.
416 * wVerMinor [I] minor version.
417 * lcid [I] locale ID.
418 * ppTLib [O] pointer that receives an ITypeLib object on success.
422 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
425 HRESULT WINAPI LoadRegTypeLib(
437 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
441 res= LoadTypeLib(bstr, ppTLib);
445 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
451 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
452 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
453 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
454 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
455 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
456 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
458 /******************************************************************************
459 * RegisterTypeLib [OLEAUT32.163]
460 * Adds information about a type library to the System Registry
462 * Docs: ITypeLib FAR * ptlib
463 * Docs: OLECHAR FAR* szFullPath
464 * Docs: OLECHAR FAR* szHelpDir
470 HRESULT WINAPI RegisterTypeLib(
471 ITypeLib * ptlib, /* [in] Pointer to the library*/
472 OLECHAR * szFullPath, /* [in] full Path of the library*/
473 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
476 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
477 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
478 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
488 if (ptlib == NULL || szFullPath == NULL)
491 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
494 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
497 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
498 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
502 /* Set the human-readable name of the typelib */
503 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
505 if (RegSetValueExW(key, NULL, 0, REG_SZ,
506 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
514 /* Make up the name of the typelib path subkey */
515 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
517 /* Create the typelib path subkey */
518 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
519 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
521 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
522 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
530 /* Create the flags subkey */
531 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
532 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
534 /* FIXME: is %u correct? */
535 static const WCHAR formatW[] = {'%','u',0};
537 sprintfW(buf, formatW, attr->wLibFlags);
538 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
539 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
547 /* create the helpdir subkey */
548 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
549 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
551 BOOL freeHelpDir = FALSE;
554 /* if we created a new key, and helpDir was null, set the helpdir
555 to the directory which contains the typelib. However,
556 if we just opened an existing key, we leave the helpdir alone */
557 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
558 szHelpDir = SysAllocString(szFullPath);
559 pIndexStr = strrchrW(szHelpDir, '\\');
566 /* if we have an szHelpDir, set it! */
567 if (szHelpDir != NULL) {
568 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
569 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
575 if (freeHelpDir) SysFreeString(szHelpDir);
587 /* register OLE Automation-compatible interfaces for this typelib */
588 types = ITypeLib_GetTypeInfoCount(ptlib);
589 for (tidx=0; tidx<types; tidx++) {
590 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
591 LPOLESTR name = NULL;
592 ITypeInfo *tinfo = NULL;
594 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
597 case TKIND_INTERFACE:
598 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
599 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
603 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
604 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
608 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
613 TYPEATTR *tattr = NULL;
614 ITypeInfo_GetTypeAttr(tinfo, &tattr);
617 TRACE_(typelib)("guid=%s, flags=%04x (",
618 debugstr_guid(&tattr->guid),
621 if (TRACE_ON(typelib)) {
622 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
642 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
644 /* register interface<->typelib coupling */
645 get_interface_key( &tattr->guid, keyName );
646 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
647 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
650 RegSetValueExW(key, NULL, 0, REG_SZ,
651 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
653 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
654 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
655 RegSetValueExW(subKey, NULL, 0, REG_SZ,
656 (const BYTE *)PSOA, sizeof PSOA);
660 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
661 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
662 RegSetValueExW(subKey, NULL, 0, REG_SZ,
663 (const BYTE *)PSOA, sizeof PSOA);
667 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
668 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
671 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
672 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
674 StringFromGUID2(&attr->guid, buffer, 40);
675 RegSetValueExW(subKey, NULL, 0, REG_SZ,
676 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
677 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
678 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
679 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
687 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
690 ITypeInfo_Release(tinfo);
697 ITypeLib_ReleaseTLibAttr(ptlib, attr);
703 /******************************************************************************
704 * UnRegisterTypeLib [OLEAUT32.186]
705 * Removes information about a type library from the System Registry
712 HRESULT WINAPI UnRegisterTypeLib(
713 REFGUID libid, /* [in] Guid of the library */
714 WORD wVerMajor, /* [in] major version */
715 WORD wVerMinor, /* [in] minor version */
716 LCID lcid, /* [in] locale id */
719 BSTR tlibPath = NULL;
722 WCHAR subKeyName[50];
725 BOOL deleteOtherStuff;
728 TYPEATTR* typeAttr = NULL;
730 ITypeInfo* typeInfo = NULL;
731 ITypeLib* typeLib = NULL;
734 TRACE("(IID: %s)\n",debugstr_guid(libid));
736 /* Create the path to the key */
737 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
739 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
741 TRACE("Unsupported syskind %i\n", syskind);
742 result = E_INVALIDARG;
746 /* get the path to the typelib on disk */
747 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
748 result = E_INVALIDARG;
752 /* Try and open the key to the type library. */
753 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
754 result = E_INVALIDARG;
758 /* Try and load the type library */
759 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
760 result = TYPE_E_INVALIDSTATE;
764 /* remove any types registered with this typelib */
765 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
766 for (i=0; i<numTypes; i++) {
767 /* get the kind of type */
768 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
772 /* skip non-interfaces, and get type info for the type */
773 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
776 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
779 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
783 /* the path to the type */
784 get_interface_key( &typeAttr->guid, subKeyName );
786 /* Delete its bits */
787 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
790 RegDeleteKeyW(subKey, ProxyStubClsidW);
791 RegDeleteKeyW(subKey, ProxyStubClsid32W);
792 RegDeleteKeyW(subKey, TypeLibW);
795 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
798 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
800 if (typeInfo) ITypeInfo_Release(typeInfo);
804 /* Now, delete the type library path subkey */
805 get_lcid_subkey( lcid, syskind, subKeyName );
806 RegDeleteKeyW(key, subKeyName);
807 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
808 RegDeleteKeyW(key, subKeyName);
810 /* check if there is anything besides the FLAGS/HELPDIR keys.
811 If there is, we don't delete them */
812 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
813 deleteOtherStuff = TRUE;
815 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
816 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
818 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
819 if (!strcmpW(subKeyName, FLAGSW)) continue;
820 if (!strcmpW(subKeyName, HELPDIRW)) continue;
821 deleteOtherStuff = FALSE;
825 /* only delete the other parts of the key if we're absolutely sure */
826 if (deleteOtherStuff) {
827 RegDeleteKeyW(key, FLAGSW);
828 RegDeleteKeyW(key, HELPDIRW);
832 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
833 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
834 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
838 if (tlibPath) SysFreeString(tlibPath);
839 if (typeLib) ITypeLib_Release(typeLib);
840 if (subKey) RegCloseKey(subKey);
841 if (key) RegCloseKey(key);
845 /*======================= ITypeLib implementation =======================*/
847 typedef struct tagTLBCustData
851 struct tagTLBCustData* next;
854 /* data structure for import typelibs */
855 typedef struct tagTLBImpLib
857 int offset; /* offset in the file (MSFT)
858 offset in nametable (SLTG)
859 just used to identify library while reading
861 GUID guid; /* libid */
862 BSTR name; /* name */
864 LCID lcid; /* lcid of imported typelib */
866 WORD wVersionMajor; /* major version number */
867 WORD wVersionMinor; /* minor version number */
869 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
870 NULL if not yet loaded */
871 struct tagTLBImpLib * next;
874 /* internal ITypeLib data */
875 typedef struct tagITypeLibImpl
877 const ITypeLib2Vtbl *lpVtbl;
878 const ITypeCompVtbl *lpVtblTypeComp;
880 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
882 /* strings can be stored in tlb as multibyte strings BUT they are *always*
883 * exported to the application as a UNICODE string.
889 unsigned long dwHelpContext;
890 int TypeInfoCount; /* nr of typeinfo's in librarry */
891 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
892 int ctCustData; /* number of items in cust data list */
893 TLBCustData * pCustData; /* linked list to cust data */
894 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
895 int ctTypeDesc; /* number of items in type desc array */
896 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
897 library. Only used while read MSFT
900 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
901 struct tagITypeLibImpl *next, *prev;
906 static const ITypeLib2Vtbl tlbvt;
907 static const ITypeCompVtbl tlbtcvt;
909 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
911 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
914 /* ITypeLib methods */
915 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
916 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
918 /*======================= ITypeInfo implementation =======================*/
920 /* data for referenced types */
921 typedef struct tagTLBRefType
923 INT index; /* Type index for internal ref or for external ref
924 it the format is SLTG. -2 indicates to
927 GUID guid; /* guid of the referenced type */
928 /* if index == TLB_REF_USE_GUID */
930 HREFTYPE reference; /* The href of this ref */
931 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
932 TLB_REF_INTERNAL for internal refs
933 TLB_REF_NOT_FOUND for broken refs */
935 struct tagTLBRefType * next;
938 #define TLB_REF_USE_GUID -2
940 #define TLB_REF_INTERNAL (void*)-2
941 #define TLB_REF_NOT_FOUND (void*)-1
943 /* internal Parameter data */
944 typedef struct tagTLBParDesc
948 TLBCustData * pCustData; /* linked list to cust data */
951 /* internal Function data */
952 typedef struct tagTLBFuncDesc
954 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
955 BSTR Name; /* the name of this function */
956 TLBParDesc *pParamDesc; /* array with param names and custom data */
958 int HelpStringContext;
960 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
962 TLBCustData * pCustData; /* linked list to cust data; */
963 struct tagTLBFuncDesc * next;
966 /* internal Variable data */
967 typedef struct tagTLBVarDesc
969 VARDESC vardesc; /* lots of info on the variable and its attributes. */
970 BSTR Name; /* the name of this variable */
972 int HelpStringContext; /* FIXME: where? */
975 TLBCustData * pCustData;/* linked list to cust data; */
976 struct tagTLBVarDesc * next;
979 /* internal implemented interface data */
980 typedef struct tagTLBImplType
982 HREFTYPE hRef; /* hRef of interface */
983 int implflags; /* IMPLFLAG_*s */
985 TLBCustData * pCustData;/* linked list to custom data; */
986 struct tagTLBImplType *next;
989 /* internal TypeInfo data */
990 typedef struct tagITypeInfoImpl
992 const ITypeInfo2Vtbl *lpVtbl;
993 const ITypeCompVtbl *lpVtblTypeComp;
995 BOOL no_free_data; /* don't free data structurees */
996 TYPEATTR TypeAttr ; /* _lots_ of type information. */
997 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
998 int index; /* index in this typelib; */
999 HREFTYPE hreftype; /* hreftype for app object binding */
1000 /* type libs seem to store the doc strings in ascii
1001 * so why should we do it in unicode?
1006 unsigned long dwHelpContext;
1007 unsigned long dwHelpStringContext;
1010 TLBFuncDesc * funclist; /* linked list with function descriptions */
1013 TLBVarDesc * varlist; /* linked list with variable descriptions */
1015 /* Implemented Interfaces */
1016 TLBImplType * impltypelist;
1018 TLBRefType * reflist;
1020 TLBCustData * pCustData; /* linked list to cust data; */
1021 struct tagITypeInfoImpl * next;
1024 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1026 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1029 static const ITypeInfo2Vtbl tinfvt;
1030 static const ITypeCompVtbl tcompvt;
1032 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1034 typedef struct tagTLBContext
1036 unsigned int oStart; /* start of TLB in file */
1037 unsigned int pos; /* current pos */
1038 unsigned int length; /* total length */
1039 void *mapping; /* memory mapping */
1040 MSFT_SegDir * pTblDir;
1041 ITypeLibImpl* pLibInfo;
1045 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1050 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1051 if (pTD->vt & VT_RESERVED)
1052 szVarType += strlen(strcpy(szVarType, "reserved | "));
1053 if (pTD->vt & VT_BYREF)
1054 szVarType += strlen(strcpy(szVarType, "ref to "));
1055 if (pTD->vt & VT_ARRAY)
1056 szVarType += strlen(strcpy(szVarType, "array of "));
1057 if (pTD->vt & VT_VECTOR)
1058 szVarType += strlen(strcpy(szVarType, "vector of "));
1059 switch(pTD->vt & VT_TYPEMASK) {
1060 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1061 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1062 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1063 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1064 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1065 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1066 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1067 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1068 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1069 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1070 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1071 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1072 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1073 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1074 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1075 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1076 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1077 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1078 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1079 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1080 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1081 pTD->u.hreftype); break;
1082 case VT_PTR: sprintf(szVarType, "ptr to ");
1083 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1085 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1086 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1088 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1089 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1090 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1093 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1097 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1099 USHORT flags = edesc->u.paramdesc.wParamFlags;
1100 dump_TypeDesc(&edesc->tdesc,buf);
1101 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1102 MESSAGE("\t\tu.paramdesc.wParamFlags");
1103 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1104 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1105 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1106 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1107 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1108 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1109 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1110 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1111 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1113 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1115 MESSAGE("memid is %08x\n",funcdesc->memid);
1116 for (i=0;i<funcdesc->cParams;i++) {
1117 MESSAGE("Param %d:\n",i);
1118 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1120 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1121 switch (funcdesc->funckind) {
1122 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1123 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1124 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1125 case FUNC_STATIC: MESSAGE("static");break;
1126 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1127 default: MESSAGE("unknown");break;
1129 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1130 switch (funcdesc->invkind) {
1131 case INVOKE_FUNC: MESSAGE("func");break;
1132 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1133 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1134 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1136 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1137 switch (funcdesc->callconv) {
1138 case CC_CDECL: MESSAGE("cdecl");break;
1139 case CC_PASCAL: MESSAGE("pascal");break;
1140 case CC_STDCALL: MESSAGE("stdcall");break;
1141 case CC_SYSCALL: MESSAGE("syscall");break;
1144 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1145 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1146 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1148 MESSAGE("\telemdescFunc (return value type):\n");
1149 dump_ELEMDESC(&funcdesc->elemdescFunc);
1152 static const char * const typekind_desc[] =
1165 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1168 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1169 for (i=0;i<pfd->funcdesc.cParams;i++)
1170 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1173 dump_FUNCDESC(&(pfd->funcdesc));
1175 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1176 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1178 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1182 dump_TLBFuncDescOne(pfd);
1186 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1190 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1195 static void dump_TLBImpLib(const TLBImpLib *import)
1197 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1198 debugstr_w(import->name));
1199 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1200 import->wVersionMinor, import->lcid, import->offset);
1203 static void dump_TLBRefType(const TLBRefType * prt)
1207 TRACE_(typelib)("href:0x%08x\n", prt->reference);
1208 if(prt->index == -1)
1209 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1211 TRACE_(typelib)("type no: %d\n", prt->index);
1213 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1214 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1215 TRACE_(typelib)("in lib\n");
1216 dump_TLBImpLib(prt->pImpTLInfo);
1222 static void dump_TLBImplType(const TLBImplType * impl)
1226 "implementing/inheriting interface hRef = %x implflags %x\n",
1227 impl->hRef, impl->implflags);
1232 void dump_Variant(const VARIANT * pvar)
1236 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1240 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1241 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1243 TRACE(",%p", V_BYREF(pvar));
1245 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1247 TRACE(",%p", V_ARRAY(pvar));
1249 else switch (V_TYPE(pvar))
1251 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1252 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1253 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1254 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1256 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1258 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1259 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1260 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1261 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1262 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1263 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1264 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1265 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1266 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1267 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1268 V_CY(pvar).s.Lo); break;
1270 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1271 TRACE(",<invalid>");
1273 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1274 st.wHour, st.wMinute, st.wSecond);
1278 case VT_USERDEFINED:
1280 case VT_NULL: break;
1281 default: TRACE(",?"); break;
1287 static void dump_DispParms(const DISPPARAMS * pdp)
1291 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1293 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1295 TRACE("named args:\n");
1296 for (index = 0; index < pdp->cNamedArgs; index++)
1297 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1300 if (pdp->cArgs && pdp->rgvarg)
1303 for (index = 0; index < pdp->cArgs; index++)
1304 dump_Variant( &pdp->rgvarg[index] );
1308 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1310 TRACE("%p ref=%u\n", pty, pty->ref);
1311 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1312 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1313 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1314 TRACE("fct:%u var:%u impl:%u\n",
1315 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1316 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1317 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1318 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1320 dump_TLBFuncDesc(pty->funclist);
1321 dump_TLBVarDesc(pty->varlist);
1322 dump_TLBImplType(pty->impltypelist);
1325 static void dump_VARDESC(const VARDESC *v)
1327 MESSAGE("memid %d\n",v->memid);
1328 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1329 MESSAGE("oInst %d\n",v->u.oInst);
1330 dump_ELEMDESC(&(v->elemdescVar));
1331 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1332 MESSAGE("varkind %d\n",v->varkind);
1335 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1337 /* VT_LPWSTR is largest type that */
1338 /* may appear in type description*/
1339 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1340 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1341 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1342 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1343 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1344 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1348 static void TLB_abort(void)
1352 static void * TLB_Alloc(unsigned size)
1355 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1357 ERR("cannot allocate memory\n");
1362 static void TLB_Free(void * ptr)
1364 HeapFree(GetProcessHeap(), 0, ptr);
1367 /* returns the size required for a deep copy of a typedesc into a
1369 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1373 if (alloc_initial_space)
1374 size += sizeof(TYPEDESC);
1380 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1383 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1384 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1390 /* deep copy a typedesc into a flat buffer */
1391 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1396 buffer = (char *)buffer + sizeof(TYPEDESC);
1405 dest->u.lptdesc = buffer;
1406 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1409 dest->u.lpadesc = buffer;
1410 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1411 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1412 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1418 /**********************************************************************
1420 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1422 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1427 static inline void MSFT_Seek(TLBContext *pcx, long where)
1429 if (where != DO_NOT_SEEK)
1431 where += pcx->oStart;
1432 if (where > pcx->length)
1435 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1443 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1445 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1446 pcx->pos, count, pcx->oStart, pcx->length, where);
1448 MSFT_Seek(pcx, where);
1449 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1450 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1455 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1460 ret = MSFT_Read(buffer, count, pcx, where);
1461 FromLEDWords(buffer, ret);
1466 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1471 ret = MSFT_Read(buffer, count, pcx, where);
1472 FromLEWords(buffer, ret);
1477 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1479 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1480 memset(pGuid,0, sizeof(GUID));
1483 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1484 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1485 pGuid->Data2 = FromLEWord(pGuid->Data2);
1486 pGuid->Data3 = FromLEWord(pGuid->Data3);
1487 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1490 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1492 MSFT_NameIntro niName;
1496 ERR_(typelib)("bad offset %d\n", offset);
1500 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1501 pcx->pTblDir->pNametab.offset+offset);
1503 return niName.hreftype;
1506 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1509 MSFT_NameIntro niName;
1511 BSTR bstrName = NULL;
1515 ERR_(typelib)("bad offset %d\n", offset);
1518 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1519 pcx->pTblDir->pNametab.offset+offset);
1520 niName.namelen &= 0xFF; /* FIXME: correct ? */
1521 name=TLB_Alloc((niName.namelen & 0xff) +1);
1522 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1523 name[niName.namelen & 0xff]='\0';
1525 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1528 /* no invalid characters in string */
1531 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1533 /* don't check for invalid character since this has been done previously */
1534 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1538 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1542 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1549 if(offset<0) return NULL;
1550 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1551 if(length <= 0) return 0;
1552 string=TLB_Alloc(length +1);
1553 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1554 string[length]='\0';
1556 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1557 string, -1, NULL, 0);
1559 /* no invalid characters in string */
1562 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1564 /* don't check for invalid character since this has been done previously */
1565 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1569 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1573 * read a value and fill a VARIANT structure
1575 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1579 TRACE_(typelib)("\n");
1581 if(offset <0) { /* data are packed in here */
1582 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1583 V_I4(pVar) = offset & 0x3ffffff;
1586 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1587 pcx->pTblDir->pCustData.offset + offset );
1588 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1589 switch (V_VT(pVar)){
1590 case VT_EMPTY: /* FIXME: is this right? */
1591 case VT_NULL: /* FIXME: is this right? */
1592 case VT_I2 : /* this should not happen */
1603 case VT_VOID : /* FIXME: is this right? */
1611 case VT_DECIMAL : /* FIXME: is this right? */
1614 /* pointer types with known behaviour */
1617 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1620 DWORD origPos = MSFT_Tell(pcx), nullPos;
1623 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1625 nullPos = MSFT_Tell(pcx);
1626 size = nullPos - origPos;
1627 MSFT_Seek(pcx, origPos);
1629 ptr=TLB_Alloc(size);/* allocate temp buffer */
1630 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1631 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1632 /* FIXME: do we need a AtoW conversion here? */
1633 V_UNION(pVar, bstrVal[size])=L'\0';
1634 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1638 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1645 case VT_USERDEFINED :
1651 case VT_STREAMED_OBJECT :
1652 case VT_STORED_OBJECT :
1653 case VT_BLOB_OBJECT :
1658 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1662 if(size>0) /* (big|small) endian correct? */
1663 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1667 * create a linked list with custom data
1669 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1675 TRACE_(typelib)("\n");
1679 pNew=TLB_Alloc(sizeof(TLBCustData));
1680 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1681 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1682 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1683 /* add new custom data at head of the list */
1684 pNew->next=*ppCustData;
1686 offset = entry.next;
1691 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1695 pTd->vt=type & VT_TYPEMASK;
1697 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1699 if(pTd->vt == VT_USERDEFINED)
1700 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1702 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1705 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1707 /* resolve referenced type if any */
1710 switch (lpTypeDesc->vt)
1713 lpTypeDesc = lpTypeDesc->u.lptdesc;
1717 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1720 case VT_USERDEFINED:
1721 MSFT_DoRefType(pcx, pTI,
1722 lpTypeDesc->u.hreftype);
1734 MSFT_DoFuncs(TLBContext* pcx,
1739 TLBFuncDesc** pptfd)
1742 * member information is stored in a data structure at offset
1743 * indicated by the memoffset field of the typeinfo structure
1744 * There are several distinctive parts.
1745 * The first part starts with a field that holds the total length
1746 * of this (first) part excluding this field. Then follow the records,
1747 * for each member there is one record.
1749 * The first entry is always the length of the record (including this
1751 * The rest of the record depends on the type of the member. If there is
1752 * a field indicating the member type (function, variable, interface, etc)
1753 * I have not found it yet. At this time we depend on the information
1754 * in the type info and the usual order how things are stored.
1756 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1759 * Third is an equal sized array with file offsets to the name entry
1762 * The fourth and last (?) part is an array with offsets to the records
1763 * in the first part of this file segment.
1766 int infolen, nameoffset, reclength, nrattributes, i;
1767 int recoffset = offset + sizeof(INT);
1769 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1770 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1771 TLBFuncDesc *ptfd_prev = NULL;
1773 TRACE_(typelib)("\n");
1775 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1777 for ( i = 0; i < cFuncs ; i++ )
1779 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1781 /* name, eventually add to a hash table */
1782 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1783 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1785 /* nameoffset is sometimes -1 on the second half of a propget/propput
1786 * pair of functions */
1787 if ((nameoffset == -1) && (i > 0))
1788 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1790 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1792 /* read the function information record */
1793 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1795 reclength &= 0xffff;
1797 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1799 /* do the attributes */
1800 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1803 if ( nrattributes > 0 )
1805 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1807 if ( nrattributes > 1 )
1809 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1810 pFuncRec->OptAttr[1]) ;
1812 if ( nrattributes > 2 )
1814 if ( pFuncRec->FKCCIC & 0x2000 )
1816 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1817 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1818 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1822 (*pptfd)->Entry = MSFT_ReadString(pcx,
1823 pFuncRec->OptAttr[2]);
1825 if( nrattributes > 5 )
1827 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1829 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1832 pFuncRec->OptAttr[6],
1833 &(*pptfd)->pCustData);
1839 (*pptfd)->Entry = (BSTR)-1;
1844 /* fill the FuncDesc Structure */
1845 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1846 offset + infolen + ( i + 1) * sizeof(INT));
1848 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1849 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1850 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1851 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1852 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1853 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1854 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1858 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1860 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1862 /* do the parameters/arguments */
1863 if(pFuncRec->nrargs)
1866 MSFT_ParameterInfo paraminfo;
1868 (*pptfd)->funcdesc.lprgelemdescParam =
1869 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1871 (*pptfd)->pParamDesc =
1872 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1874 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1875 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1877 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1879 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1886 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1889 if (paraminfo.oName == -1)
1890 /* this occurs for [propput] or [propget] methods, so
1891 * we should just set the name of the parameter to the
1892 * name of the method. */
1893 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1895 (*pptfd)->pParamDesc[j].Name =
1896 MSFT_ReadName( pcx, paraminfo.oName );
1897 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1899 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1902 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1903 (pFuncRec->FKCCIC & 0x1000) )
1905 INT* pInt = (INT *)((char *)pFuncRec +
1907 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1909 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1911 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1912 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1914 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1918 elemdesc->u.paramdesc.pparamdescex = NULL;
1920 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1923 pFuncRec->OptAttr[7+j],
1924 &(*pptfd)->pParamDesc[j].pCustData);
1927 /* SEEK value = jump to offset,
1928 * from there jump to the end of record,
1929 * go back by (j-1) arguments
1931 MSFT_ReadLEDWords( ¶minfo ,
1932 sizeof(MSFT_ParameterInfo), pcx,
1933 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1934 * sizeof(MSFT_ParameterInfo)));
1938 /* scode is not used: archaic win16 stuff FIXME: right? */
1939 (*pptfd)->funcdesc.cScodes = 0 ;
1940 (*pptfd)->funcdesc.lprgscode = NULL ;
1943 pptfd = & ((*pptfd)->next);
1944 recoffset += reclength;
1946 HeapFree(GetProcessHeap(), 0, recbuf);
1949 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1950 int cVars, int offset, TLBVarDesc ** pptvd)
1952 int infolen, nameoffset, reclength;
1954 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1958 TRACE_(typelib)("\n");
1960 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1961 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1962 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1963 recoffset += offset+sizeof(INT);
1964 for(i=0;i<cVars;i++){
1965 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1966 /* name, eventually add to a hash table */
1967 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1968 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1969 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1970 /* read the variable information record */
1971 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1973 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1975 if(reclength >(6*sizeof(INT)) )
1976 (*pptvd)->HelpContext=pVarRec->HelpContext;
1977 if(reclength >(7*sizeof(INT)) )
1978 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1979 if(reclength >(8*sizeof(INT)) )
1980 if(reclength >(9*sizeof(INT)) )
1981 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1982 /* fill the VarDesc Structure */
1983 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1984 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1985 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1986 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1987 MSFT_GetTdesc(pcx, pVarRec->DataType,
1988 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1989 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1990 if(pVarRec->VarKind == VAR_CONST ){
1991 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1992 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1993 pVarRec->OffsValue, pcx);
1995 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1996 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1997 pptvd=&((*pptvd)->next);
1998 recoffset += reclength;
2001 /* fill in data for a hreftype (offset). When the referenced type is contained
2002 * in the typelib, it's just an (file) offset in the type info base dir.
2003 * If comes from import, it's an offset+1 in the ImpInfo table
2005 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
2009 TLBRefType **ppRefType = &pTI->reflist;
2011 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2014 if((*ppRefType)->reference == offset)
2016 ppRefType = &(*ppRefType)->next;
2019 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2020 sizeof(**ppRefType));
2022 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2023 /* external typelib */
2024 MSFT_ImpInfo impinfo;
2025 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2027 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2029 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2030 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2031 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2032 if(pImpLib->offset==impinfo.oImpFile) break;
2033 pImpLib=pImpLib->next;
2036 (*ppRefType)->reference=offset;
2037 (*ppRefType)->pImpTLInfo = pImpLib;
2038 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2039 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2040 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
2041 (*ppRefType)->index = TLB_REF_USE_GUID;
2043 (*ppRefType)->index = impinfo.oGuid;
2045 ERR("Cannot find a reference\n");
2046 (*ppRefType)->reference=-1;
2047 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2050 /* in this typelib */
2051 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2052 (*ppRefType)->reference=offset;
2053 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2057 /* process Implemented Interfaces of a com class */
2058 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2062 MSFT_RefRecord refrec;
2063 TLBImplType **ppImpl = &pTI->impltypelist;
2065 TRACE_(typelib)("\n");
2067 for(i=0;i<count;i++){
2068 if(offset<0) break; /* paranoia */
2069 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2070 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2071 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2072 (*ppImpl)->hRef = refrec.reftype;
2073 (*ppImpl)->implflags=refrec.flags;
2074 (*ppImpl)->ctCustData=
2075 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2076 offset=refrec.onext;
2077 ppImpl=&((*ppImpl)->next);
2081 * process a typeinfo record
2083 static ITypeInfoImpl * MSFT_DoTypeInfo(
2087 ITypeLibImpl * pLibInfo)
2089 MSFT_TypeInfoBase tiBase;
2090 ITypeInfoImpl *ptiRet;
2092 TRACE_(typelib)("count=%u\n", count);
2094 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2095 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2096 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2098 /* this is where we are coming from */
2099 ptiRet->pTypeLib = pLibInfo;
2100 ptiRet->index=count;
2101 /* fill in the typeattr fields */
2103 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2104 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2105 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2106 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2107 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2108 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2109 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2110 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2111 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2112 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2113 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2114 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2115 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2116 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2117 MSFT_GetTdesc(pcx, tiBase.datatype1,
2118 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2121 /* IDLDESC idldescType; *//* never saw this one != zero */
2123 /* name, eventually add to a hash table */
2124 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2125 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2126 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2128 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2129 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2130 ptiRet->dwHelpContext=tiBase.helpcontext;
2132 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2133 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2135 /* note: InfoType's Help file and HelpStringDll come from the containing
2136 * library. Further HelpString and Docstring appear to be the same thing :(
2139 if(ptiRet->TypeAttr.cFuncs >0 )
2140 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2141 ptiRet->TypeAttr.cVars,
2142 tiBase.memoffset, & ptiRet->funclist);
2144 if(ptiRet->TypeAttr.cVars >0 )
2145 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2146 ptiRet->TypeAttr.cVars,
2147 tiBase.memoffset, & ptiRet->varlist);
2148 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2149 switch(ptiRet->TypeAttr.typekind)
2152 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2155 case TKIND_DISPATCH:
2156 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2158 if (tiBase.datatype1 != -1)
2160 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2161 ptiRet->impltypelist->hRef = tiBase.datatype1;
2165 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2166 ptiRet->impltypelist->hRef = dispatch_href;
2170 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2171 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2172 ptiRet->impltypelist->hRef = tiBase.datatype1;
2177 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2179 TRACE_(typelib)("%s guid: %s kind:%s\n",
2180 debugstr_w(ptiRet->Name),
2181 debugstr_guid(&ptiRet->TypeAttr.guid),
2182 typekind_desc[ptiRet->TypeAttr.typekind]);
2187 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2188 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2189 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2192 static ITypeLibImpl *tlb_cache_first;
2193 static CRITICAL_SECTION cache_section;
2194 static CRITICAL_SECTION_DEBUG cache_section_debug =
2196 0, 0, &cache_section,
2197 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2198 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2200 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2203 /****************************************************************************
2206 * find the type of the typelib file and map the typelib resource into
2209 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2210 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2211 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2213 ITypeLibImpl *entry;
2214 int ret = TYPE_E_CANTLOADLIBRARY;
2220 lstrcpynW(pszPath, pszFileName, cchPath);
2222 /* first try loading as a dll and access the typelib as a resource */
2223 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2224 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2227 /* it may have been specified with resource index appended to the
2228 * path, so remove it and try again */
2229 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2230 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2232 index = atoiW(pIndexStr);
2233 pszPath[pIndexStr - pszFileName - 1] = '\0';
2235 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2236 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2240 /* get the path to the specified typelib file */
2243 /* otherwise, try loading as a regular file */
2244 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2245 return TYPE_E_CANTLOADLIBRARY;
2248 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2250 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2251 EnterCriticalSection(&cache_section);
2252 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2254 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2256 TRACE("cache hit\n");
2257 *ppTypeLib = (ITypeLib2*)entry;
2258 ITypeLib_AddRef(*ppTypeLib);
2259 LeaveCriticalSection(&cache_section);
2260 FreeLibrary(hinstDLL);
2264 LeaveCriticalSection(&cache_section);
2266 /* now actually load and parse the typelib */
2269 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2270 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2273 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2276 LPVOID pBase = LockResource(hGlobal);
2277 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2281 /* try to load as incore resource */
2282 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2283 if (dwSignature == MSFT_SIGNATURE)
2284 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2285 else if (dwSignature == SLTG_SIGNATURE)
2286 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2288 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2290 FreeResource( hGlobal );
2293 FreeLibrary(hinstDLL);
2297 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2298 if (INVALID_HANDLE_VALUE != hFile)
2300 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2303 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2306 /* retrieve file size */
2307 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2308 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2310 if (dwSignature == MSFT_SIGNATURE)
2311 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2312 else if (dwSignature == SLTG_SIGNATURE)
2313 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2315 UnmapViewOfFile(pBase);
2317 CloseHandle(hMapping);
2324 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2326 TRACE("adding to cache\n");
2327 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2328 lstrcpyW(impl->path, pszPath);
2329 /* We should really canonicalise the path here. */
2330 impl->index = index;
2332 /* FIXME: check if it has added already in the meantime */
2333 EnterCriticalSection(&cache_section);
2334 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2336 tlb_cache_first = impl;
2337 LeaveCriticalSection(&cache_section);
2340 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2345 /*================== ITypeLib(2) Methods ===================================*/
2347 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2349 ITypeLibImpl* pTypeLibImpl;
2351 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2352 if (!pTypeLibImpl) return NULL;
2354 pTypeLibImpl->lpVtbl = &tlbvt;
2355 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2356 pTypeLibImpl->ref = 1;
2358 return pTypeLibImpl;
2361 /****************************************************************************
2362 * ITypeLib2_Constructor_MSFT
2364 * loading an MSFT typelib from an in-memory image
2366 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2370 MSFT_Header tlbHeader;
2371 MSFT_SegDir tlbSegDir;
2372 ITypeLibImpl * pTypeLibImpl;
2374 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2376 pTypeLibImpl = TypeLibImpl_Constructor();
2377 if (!pTypeLibImpl) return NULL;
2379 /* get pointer to beginning of typelib data */
2383 cx.pLibInfo = pTypeLibImpl;
2384 cx.length = dwTLBLength;
2387 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2388 TRACE_(typelib)("header:\n");
2389 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2390 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2391 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2394 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2396 /* there is a small amount of information here until the next important
2398 * the segment directory . Try to calculate the amount of data */
2399 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2401 /* now read the segment directory */
2402 TRACE("read segment directory (at %ld)\n",lPSegDir);
2403 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2404 cx.pTblDir = &tlbSegDir;
2406 /* just check two entries */
2407 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2409 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2410 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2414 /* now fill our internal data */
2415 /* TLIBATTR fields */
2416 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2418 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2419 /* Windows seems to have zero here, is this correct? */
2420 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2421 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2423 pTypeLibImpl->LibAttr.lcid = 0;
2425 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2426 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2427 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2428 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2430 /* name, eventually add to a hash table */
2431 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2434 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2435 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2437 if( tlbHeader.varflags & HELPDLLFLAG)
2440 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2441 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2444 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2447 if(tlbHeader.CustomDataOffset >= 0)
2449 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2452 /* fill in typedescriptions */
2453 if(tlbSegDir.pTypdescTab.length > 0)
2455 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2457 pTypeLibImpl->ctTypeDesc = cTD;
2458 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2459 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2462 /* FIXME: add several sanity checks here */
2463 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2464 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2466 /* FIXME: check safearray */
2468 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2470 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2472 else if(td[0] == VT_CARRAY)
2474 /* array descr table here */
2475 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2477 else if(td[0] == VT_USERDEFINED)
2479 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2481 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2484 /* second time around to fill the array subscript info */
2487 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2488 if(tlbSegDir.pArrayDescriptions.offset>0)
2490 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2491 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2494 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2496 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2498 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2500 for(j = 0; j<td[2]; j++)
2502 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2503 sizeof(INT), &cx, DO_NOT_SEEK);
2504 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2505 sizeof(INT), &cx, DO_NOT_SEEK);
2510 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2511 ERR("didn't find array description data\n");
2516 /* imported type libs */
2517 if(tlbSegDir.pImpFiles.offset>0)
2519 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2520 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2523 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2528 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2529 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2530 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2532 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2533 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2534 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2535 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2538 name = TLB_Alloc(size+1);
2539 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2540 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2541 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2542 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2545 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2546 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2548 ppImpLib = &(*ppImpLib)->next;
2553 if(tlbHeader.nrtypeinfos >= 0 )
2555 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2556 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2559 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2561 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2563 ppTI = &((*ppTI)->next);
2564 (pTypeLibImpl->TypeInfoCount)++;
2568 TRACE("(%p)\n", pTypeLibImpl);
2569 return (ITypeLib2*) pTypeLibImpl;
2573 static BSTR TLB_MultiByteToBSTR(char *ptr)
2579 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2580 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2581 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2582 ret = SysAllocString(nameW);
2583 HeapFree(GetProcessHeap(), 0, nameW);
2587 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2593 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2594 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2598 guid->Data4[0] = s >> 8;
2599 guid->Data4[1] = s & 0xff;
2602 for(i = 0; i < 6; i++) {
2603 memcpy(b, str + 24 + 2 * i, 2);
2604 guid->Data4[i + 2] = strtol(b, NULL, 16);
2609 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2616 bytelen = *(WORD*)ptr;
2617 if(bytelen == 0xffff) return 2;
2618 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2619 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2620 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2621 *pBstr = SysAllocStringLen(nameW, len);
2622 HeapFree(GetProcessHeap(), 0, nameW);
2626 static WORD SLTG_ReadStringA(char *ptr, char **str)
2631 bytelen = *(WORD*)ptr;
2632 if(bytelen == 0xffff) return 2;
2633 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2634 memcpy(*str, ptr + 2, bytelen);
2635 (*str)[bytelen] = '\0';
2639 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2641 char *ptr = pLibBlk;
2644 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2645 FIXME("libblk magic = %04x\n", w);
2650 if((w = *(WORD*)ptr) != 0xffff) {
2651 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2656 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2658 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2660 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2663 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2666 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2667 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2669 pTypeLibImpl->LibAttr.lcid = 0;
2672 ptr += 4; /* skip res12 */
2674 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2677 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2680 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2683 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2684 ptr += sizeof(GUID);
2686 return ptr - (char*)pLibBlk;
2689 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2694 if((*pType & 0xe00) == 0xe00) {
2696 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2698 pTD = pTD->u.lptdesc;
2700 switch(*pType & 0x3f) {
2703 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2705 pTD = pTD->u.lptdesc;
2708 case VT_USERDEFINED:
2709 pTD->vt = VT_USERDEFINED;
2710 pTD->u.hreftype = *(++pType) / 4;
2716 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2719 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2721 pTD->vt = VT_CARRAY;
2722 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2724 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2725 pTD->u.lpadesc->cDims = pSA->cDims;
2726 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2727 pSA->cDims * sizeof(SAFEARRAYBOUND));
2729 pTD = &pTD->u.lpadesc->tdescElem;
2735 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2739 pTD->vt = VT_SAFEARRAY;
2740 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2742 pTD = pTD->u.lptdesc;
2746 pTD->vt = *pType & 0x3f;
2755 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2757 /* Handle [in/out] first */
2758 if((*pType & 0xc000) == 0xc000)
2759 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2760 else if(*pType & 0x8000)
2761 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2762 else if(*pType & 0x4000)
2763 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2765 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2768 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2771 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2773 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2777 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2782 TLBRefType **ppRefType;
2784 if(pRef->magic != SLTG_REF_MAGIC) {
2785 FIXME("Ref magic = %x\n", pRef->magic);
2788 name = ( (char*)(&pRef->names) + pRef->number);
2790 ppRefType = &pTI->reflist;
2791 for(ref = 0; ref < pRef->number >> 3; ref++) {
2793 unsigned int lib_offs, type_num;
2795 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2796 sizeof(**ppRefType));
2798 name += SLTG_ReadStringA(name, &refname);
2799 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2800 FIXME("Can't sscanf ref\n");
2801 if(lib_offs != 0xffff) {
2802 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2805 if((*import)->offset == lib_offs)
2807 import = &(*import)->next;
2810 char fname[MAX_PATH+1];
2813 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2815 (*import)->offset = lib_offs;
2816 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2818 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2819 &(*import)->wVersionMajor,
2820 &(*import)->wVersionMinor,
2821 &(*import)->lcid, fname) != 4) {
2822 FIXME("can't sscanf ref %s\n",
2823 pNameTable + lib_offs + 40);
2825 len = strlen(fname);
2826 if(fname[len-1] != '#')
2827 FIXME("fname = %s\n", fname);
2828 fname[len-1] = '\0';
2829 (*import)->name = TLB_MultiByteToBSTR(fname);
2831 (*ppRefType)->pImpTLInfo = *import;
2832 } else { /* internal ref */
2833 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2835 (*ppRefType)->reference = ref;
2836 (*ppRefType)->index = type_num;
2838 HeapFree(GetProcessHeap(), 0, refname);
2839 ppRefType = &(*ppRefType)->next;
2841 if((BYTE)*name != SLTG_REF_MAGIC)
2842 FIXME("End of ref block magic = %x\n", *name);
2843 dump_TLBRefType(pTI->reflist);
2846 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2849 SLTG_ImplInfo *info;
2850 TLBImplType **ppImplType = &pTI->impltypelist;
2851 /* I don't really get this structure, usually it's 0x16 bytes
2852 long, but iuser.tlb contains some that are 0x18 bytes long.
2853 That's ok because we can use the next ptr to jump to the next
2854 one. But how do we know the length of the last one? The WORD
2855 at offs 0x8 might be the clue. For now I'm just assuming that
2856 the last one is the regular 0x16 bytes. */
2858 info = (SLTG_ImplInfo*)pBlk;
2860 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2861 sizeof(**ppImplType));
2862 (*ppImplType)->hRef = info->ref;
2863 (*ppImplType)->implflags = info->impltypeflags;
2864 pTI->TypeAttr.cImplTypes++;
2865 ppImplType = &(*ppImplType)->next;
2867 if(info->next == 0xffff)
2870 FIXME("Interface inheriting more than one interface\n");
2871 info = (SLTG_ImplInfo*)(pBlk + info->next);
2873 info++; /* see comment at top of function */
2877 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2879 TLBVarDesc **ppVarDesc = &pTI->varlist;
2880 BSTR bstrPrevName = NULL;
2881 SLTG_Variable *pItem;
2886 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2887 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2889 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2890 sizeof(**ppVarDesc));
2891 (*ppVarDesc)->vardesc.memid = pItem->memid;
2893 if (pItem->magic != SLTG_VAR_MAGIC &&
2894 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2895 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2899 if (pItem->name == 0xfffe)
2900 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2902 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2904 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2905 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2907 if (pItem->flags & 0x40) {
2908 TRACE_(typelib)("VAR_DISPATCH\n");
2909 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2911 else if (pItem->flags & 0x10) {
2912 TRACE_(typelib)("VAR_CONST\n");
2913 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2914 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2916 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2917 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2918 *(INT*)(pBlk + pItem->byte_offs);
2921 TRACE_(typelib)("VAR_PERINSTANCE\n");
2922 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2923 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2926 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2927 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2929 if (pItem->flags & 0x80)
2930 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2932 if(pItem->flags & 0x02)
2933 pType = &pItem->type;
2935 pType = (WORD*)(pBlk + pItem->type);
2937 if (pItem->flags & ~0xd2)
2938 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2940 SLTG_DoElem(pType, pBlk,
2941 &(*ppVarDesc)->vardesc.elemdescVar);
2943 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2945 bstrPrevName = (*ppVarDesc)->Name;
2946 ppVarDesc = &((*ppVarDesc)->next);
2948 pTI->TypeAttr.cVars = cVars;
2951 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2953 SLTG_Function *pFunc;
2955 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2957 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2958 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2963 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2964 sizeof(**ppFuncDesc));
2966 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2967 case SLTG_FUNCTION_MAGIC:
2968 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2970 case SLTG_DISPATCH_FUNCTION_MAGIC:
2971 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2973 case SLTG_STATIC_FUNCTION_MAGIC:
2974 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2977 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2978 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2982 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2984 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2985 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2986 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2987 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2988 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2989 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2991 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2992 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2994 if(pFunc->retnextopt & 0x80)
2995 pType = &pFunc->rettype;
2997 pType = (WORD*)(pBlk + pFunc->rettype);
2999 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
3001 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3002 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3003 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3004 (*ppFuncDesc)->pParamDesc =
3005 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3006 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3008 pArg = (WORD*)(pBlk + pFunc->arg_off);
3010 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3011 char *paramName = pNameTable + *pArg;
3013 /* If arg type follows then paramName points to the 2nd
3014 letter of the name, else the next WORD is an offset to
3015 the arg type and paramName points to the first letter.
3016 So let's take one char off paramName and see if we're
3017 pointing at an alpha-numeric char. However if *pArg is
3018 0xffff or 0xfffe then the param has no name, the former
3019 meaning that the next WORD is the type, the latter
3020 meaning the the next WORD is an offset to the type. */
3025 else if(*pArg == 0xfffe) {
3029 else if(paramName[-1] && !isalnum(paramName[-1]))
3034 if(HaveOffs) { /* the next word is an offset to type */
3035 pType = (WORD*)(pBlk + *pArg);
3036 SLTG_DoElem(pType, pBlk,
3037 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3042 pArg = SLTG_DoElem(pArg, pBlk,
3043 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3046 /* Are we an optional param ? */
3047 if((*ppFuncDesc)->funcdesc.cParams - param <=
3048 (*ppFuncDesc)->funcdesc.cParamsOpt)
3049 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3052 (*ppFuncDesc)->pParamDesc[param].Name =
3053 TLB_MultiByteToBSTR(paramName);
3057 ppFuncDesc = &((*ppFuncDesc)->next);
3058 if(pFunc->next == 0xffff) break;
3060 pTI->TypeAttr.cFuncs = cFuncs;
3063 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3064 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3065 SLTG_TypeInfoTail *pTITail)
3067 char *pFirstItem, *pNextItem;
3069 if(pTIHeader->href_table != 0xffffffff) {
3070 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3074 pFirstItem = pNextItem = pBlk;
3076 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3077 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3082 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3083 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3084 SLTG_TypeInfoTail *pTITail)
3086 char *pFirstItem, *pNextItem;
3088 if(pTIHeader->href_table != 0xffffffff) {
3089 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3093 pFirstItem = pNextItem = pBlk;
3095 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3096 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3099 if (pTITail->funcs_off != 0xffff)
3100 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3102 if (TRACE_ON(typelib))
3103 dump_TLBFuncDesc(pTI->funclist);
3106 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3107 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3108 SLTG_TypeInfoTail *pTITail)
3110 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3113 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3114 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3115 SLTG_TypeInfoTail *pTITail)
3119 if (pTITail->simple_alias) {
3120 /* if simple alias, no more processing required */
3121 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3125 if(pTIHeader->href_table != 0xffffffff) {
3126 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3130 /* otherwise it is an offset to a type */
3131 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3133 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3136 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3137 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3138 SLTG_TypeInfoTail *pTITail)
3140 if (pTIHeader->href_table != 0xffffffff)
3141 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3144 if (pTITail->vars_off != 0xffff)
3145 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3147 if (pTITail->funcs_off != 0xffff)
3148 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3150 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3151 * of dispinterface functons including the IDispatch ones, so
3152 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3153 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3155 if (TRACE_ON(typelib))
3156 dump_TLBFuncDesc(pTI->funclist);
3159 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3160 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3161 SLTG_TypeInfoTail *pTITail)
3163 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3166 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3167 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3168 SLTG_TypeInfoTail *pTITail)
3170 if (pTIHeader->href_table != 0xffffffff)
3171 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3174 if (pTITail->vars_off != 0xffff)
3175 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3177 if (pTITail->funcs_off != 0xffff)
3178 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3181 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3182 managable copy of it into this */
3195 } SLTG_InternalOtherTypeInfo;
3197 /****************************************************************************
3198 * ITypeLib2_Constructor_SLTG
3200 * loading a SLTG typelib from an in-memory image
3202 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3204 ITypeLibImpl *pTypeLibImpl;
3205 SLTG_Header *pHeader;
3206 SLTG_BlkEntry *pBlkEntry;
3210 LPVOID pBlk, pFirstBlk;
3211 SLTG_LibBlk *pLibBlk;
3212 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3213 char *pAfterOTIBlks = NULL;
3214 char *pNameTable, *ptr;
3217 ITypeInfoImpl **ppTypeInfoImpl;
3219 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3222 pTypeLibImpl = TypeLibImpl_Constructor();
3223 if (!pTypeLibImpl) return NULL;
3227 TRACE_(typelib)("header:\n");
3228 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3229 pHeader->nrOfFileBlks );
3230 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3231 FIXME("Header type magic 0x%08x not supported.\n",
3232 pHeader->SLTG_magic);
3236 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3237 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3239 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3240 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3242 /* Next we have a magic block */
3243 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3245 /* Let's see if we're still in sync */
3246 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3247 sizeof(SLTG_COMPOBJ_MAGIC))) {
3248 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3251 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3252 sizeof(SLTG_DIR_MAGIC))) {
3253 FIXME("dir magic = %s\n", pMagic->dir_magic);
3257 pIndex = (SLTG_Index*)(pMagic+1);
3259 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3261 pFirstBlk = (LPVOID)(pPad9 + 1);
3263 /* We'll set up a ptr to the main library block, which is the last one. */
3265 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3266 pBlkEntry[order].next != 0;
3267 order = pBlkEntry[order].next - 1, i++) {
3268 pBlk = (char*)pBlk + pBlkEntry[order].len;
3272 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3274 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3279 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3281 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3282 sizeof(*pOtherTypeInfoBlks) *
3283 pTypeLibImpl->TypeInfoCount);
3286 ptr = (char*)pLibBlk + len;
3288 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3292 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3294 w = *(WORD*)(ptr + 2);
3297 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3299 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3300 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3302 w = *(WORD*)(ptr + 4 + len);
3304 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3306 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3308 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3309 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3311 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3312 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3313 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3315 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3317 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3320 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3321 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3322 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3323 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3324 len += sizeof(SLTG_OtherTypeInfo);
3328 pAfterOTIBlks = ptr;
3330 /* Skip this WORD and get the next DWORD */
3331 len = *(DWORD*)(pAfterOTIBlks + 2);
3333 /* Now add this to pLibBLk look at what we're pointing at and
3334 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3335 dust and we should be pointing at the beginning of the name
3338 pNameTable = (char*)pLibBlk + len;
3340 switch(*(WORD*)pNameTable) {
3347 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3351 pNameTable += 0x216;
3355 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3357 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3360 /* Hopefully we now have enough ptrs set up to actually read in
3361 some TypeInfos. It's not clear which order to do them in, so
3362 I'll just follow the links along the BlkEntry chain and read
3363 them in the order in which they are in the file */
3365 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3367 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3368 pBlkEntry[order].next != 0;
3369 order = pBlkEntry[order].next - 1, i++) {
3371 SLTG_TypeInfoHeader *pTIHeader;
3372 SLTG_TypeInfoTail *pTITail;
3373 SLTG_MemberHeader *pMemHeader;
3375 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3376 pOtherTypeInfoBlks[i].index_name)) {
3377 FIXME("Index strings don't match\n");
3382 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3383 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3386 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3387 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3389 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3390 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3391 (*ppTypeInfoImpl)->index = i;
3392 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3393 pOtherTypeInfoBlks[i].name_offs +
3395 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3396 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3398 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3399 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3400 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3401 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3402 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3404 if((pTIHeader->typeflags1 & 7) != 2)
3405 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3406 if(pTIHeader->typeflags3 != 2)
3407 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3409 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3410 debugstr_w((*ppTypeInfoImpl)->Name),
3411 typekind_desc[pTIHeader->typekind],
3412 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3413 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3415 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3417 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3419 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3420 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3421 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3423 switch(pTIHeader->typekind) {
3425 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3426 pTIHeader, pTITail);
3430 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3431 pTIHeader, pTITail);
3434 case TKIND_INTERFACE:
3435 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3436 pTIHeader, pTITail);
3440 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3441 pTIHeader, pTITail);
3445 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3446 pTIHeader, pTITail);
3449 case TKIND_DISPATCH:
3450 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3451 pTIHeader, pTITail);
3455 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3456 pTIHeader, pTITail);
3460 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3465 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3466 but we've already set those */
3467 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3482 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3483 pBlk = (char*)pBlk + pBlkEntry[order].len;
3486 if(i != pTypeLibImpl->TypeInfoCount) {
3487 FIXME("Somehow processed %d TypeInfos\n", i);
3491 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3492 return (ITypeLib2*)pTypeLibImpl;
3495 /* ITypeLib::QueryInterface
3497 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3502 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3504 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3507 if(IsEqualIID(riid, &IID_IUnknown) ||
3508 IsEqualIID(riid,&IID_ITypeLib)||
3509 IsEqualIID(riid,&IID_ITypeLib2))
3516 ITypeLib2_AddRef(iface);
3517 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3520 TRACE("-- Interface: E_NOINTERFACE\n");
3521 return E_NOINTERFACE;
3526 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3528 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3529 ULONG ref = InterlockedIncrement(&This->ref);
3531 TRACE("(%p)->ref was %u\n",This, ref - 1);
3536 /* ITypeLib::Release
3538 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3540 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3541 ULONG ref = InterlockedDecrement(&This->ref);
3543 TRACE("(%p)->(%u)\n",This, ref);
3547 TLBImpLib *pImpLib, *pImpLibNext;
3548 TLBCustData *pCustData, *pCustDataNext;
3551 /* remove cache entry */
3554 TRACE("removing from cache list\n");
3555 EnterCriticalSection(&cache_section);
3556 if (This->next) This->next->prev = This->prev;
3557 if (This->prev) This->prev->next = This->next;
3558 else tlb_cache_first = This->next;
3559 LeaveCriticalSection(&cache_section);
3560 HeapFree(GetProcessHeap(), 0, This->path);
3562 TRACE(" destroying ITypeLib(%p)\n",This);
3566 SysFreeString(This->Name);
3570 if (This->DocString)
3572 SysFreeString(This->DocString);
3573 This->DocString = NULL;
3578 SysFreeString(This->HelpFile);
3579 This->HelpFile = NULL;
3582 if (This->HelpStringDll)
3584 SysFreeString(This->HelpStringDll);
3585 This->HelpStringDll = NULL;
3588 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3590 VariantClear(&pCustData->data);
3592 pCustDataNext = pCustData->next;
3593 TLB_Free(pCustData);
3596 for (i = 0; i < This->ctTypeDesc; i++)
3597 if (This->pTypeDesc[i].vt == VT_CARRAY)
3598 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3600 TLB_Free(This->pTypeDesc);
3602 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3604 if (pImpLib->pImpTypeLib)
3605 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3606 TLB_Free(pImpLib->name);
3608 pImpLibNext = pImpLib->next;
3612 if (This->pTypeInfo) /* can be NULL */
3613 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3614 HeapFree(GetProcessHeap(),0,This);
3621 /* ITypeLib::GetTypeInfoCount
3623 * Returns the number of type descriptions in the type library
3625 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3627 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3628 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3629 return This->TypeInfoCount;
3632 /* ITypeLib::GetTypeInfo
3634 * retrieves the specified type description in the library.
3636 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3639 ITypeInfo **ppTInfo)
3643 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3644 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3646 TRACE("(%p)->(index=%d)\n", This, index);
3648 if (!ppTInfo) return E_INVALIDARG;
3650 /* search element n in list */
3651 for(i=0; i < index; i++)
3653 pTypeInfo = pTypeInfo->next;
3656 TRACE("-- element not found\n");
3657 return TYPE_E_ELEMENTNOTFOUND;
3661 *ppTInfo = (ITypeInfo *) pTypeInfo;
3663 ITypeInfo_AddRef(*ppTInfo);
3664 TRACE("-- found (%p)\n",*ppTInfo);
3669 /* ITypeLibs::GetTypeInfoType
3671 * Retrieves the type of a type description.
3673 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3678 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3680 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3682 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3683 return TYPE_E_ELEMENTNOTFOUND;
3685 TRACE("(%p) index %d\n", This, index);
3687 if(!pTKind) return E_INVALIDARG;
3689 /* search element n in list */
3690 for(i=0; i < index; i++)
3694 TRACE("-- element not found\n");
3695 return TYPE_E_ELEMENTNOTFOUND;
3697 pTInfo = pTInfo->next;
3700 *pTKind = pTInfo->TypeAttr.typekind;
3701 TRACE("-- found Type (%d)\n", *pTKind);
3705 /* ITypeLib::GetTypeInfoOfGuid
3707 * Retrieves the type description that corresponds to the specified GUID.
3710 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3713 ITypeInfo **ppTInfo)
3715 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3716 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3718 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3722 WARN("-- element not found\n");
3723 return TYPE_E_ELEMENTNOTFOUND;
3726 /* search linked list for guid */
3727 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3729 pTypeInfo = pTypeInfo->next;
3733 /* end of list reached */
3734 WARN("-- element not found\n");
3735 return TYPE_E_ELEMENTNOTFOUND;
3739 TRACE("-- found (%p, %s)\n",
3741 debugstr_w(pTypeInfo->Name));
3743 *ppTInfo = (ITypeInfo*)pTypeInfo;
3744 ITypeInfo_AddRef(*ppTInfo);
3748 /* ITypeLib::GetLibAttr
3750 * Retrieves the structure that contains the library's attributes.
3753 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3755 LPTLIBATTR *ppTLibAttr)
3757 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3758 TRACE("(%p)\n",This);
3759 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3760 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3764 /* ITypeLib::GetTypeComp
3766 * Enables a client compiler to bind to a library's types, variables,
3767 * constants, and global functions.
3770 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3772 ITypeComp **ppTComp)
3774 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3776 TRACE("(%p)->(%p)\n",This,ppTComp);
3777 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3778 ITypeComp_AddRef(*ppTComp);
3783 /* ITypeLib::GetDocumentation
3785 * Retrieves the library's documentation string, the complete Help file name
3786 * and path, and the context identifier for the library Help topic in the Help
3789 * On a successful return all non-null BSTR pointers will have been set,
3792 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3796 BSTR *pBstrDocString,
3797 DWORD *pdwHelpContext,
3798 BSTR *pBstrHelpFile)
3800 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3802 HRESULT result = E_INVALIDARG;
3807 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3809 pBstrName, pBstrDocString,
3810 pdwHelpContext, pBstrHelpFile);
3814 /* documentation for the typelib */
3819 if(!(*pBstrName = SysAllocString(This->Name)))
3827 if (This->DocString)
3829 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3832 else if (This->Name)
3834 if(!(*pBstrDocString = SysAllocString(This->Name)))
3838 *pBstrDocString = NULL;
3842 *pdwHelpContext = This->dwHelpContext;
3848 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3852 *pBstrHelpFile = NULL;
3859 /* for a typeinfo */
3860 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3862 if(SUCCEEDED(result))
3864 result = ITypeInfo_GetDocumentation(pTInfo,
3868 pdwHelpContext, pBstrHelpFile);
3870 ITypeInfo_Release(pTInfo);
3875 if (pBstrDocString) SysFreeString (*pBstrDocString);
3877 if (pBstrName) SysFreeString (*pBstrName);
3879 return STG_E_INSUFFICIENTMEMORY;
3884 * Indicates whether a passed-in string contains the name of a type or member
3885 * described in the library.
3888 static HRESULT WINAPI ITypeLib2_fnIsName(
3894 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3895 ITypeInfoImpl *pTInfo;
3896 TLBFuncDesc *pFInfo;
3899 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3901 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3905 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3906 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3907 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3908 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3909 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3910 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3911 goto ITypeLib2_fnIsName_exit;
3913 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3914 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3919 ITypeLib2_fnIsName_exit:
3920 TRACE("(%p)slow! search for %s: %s found!\n", This,
3921 debugstr_w(szNameBuf), *pfName?"NOT":"");
3926 /* ITypeLib::FindName
3928 * Finds occurrences of a type description in a type library. This may be used
3929 * to quickly verify that a name exists in a type library.
3932 static HRESULT WINAPI ITypeLib2_fnFindName(
3936 ITypeInfo **ppTInfo,
3940 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3941 ITypeInfoImpl *pTInfo;
3942 TLBFuncDesc *pFInfo;
3945 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3947 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3948 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3949 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3950 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3951 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3952 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3953 goto ITypeLib2_fnFindName_exit;
3956 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3957 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3959 ITypeLib2_fnFindName_exit:
3960 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3961 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3964 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3965 This, *pcFound, debugstr_w(szNameBuf), j);
3972 /* ITypeLib::ReleaseTLibAttr
3974 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3977 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3979 TLIBATTR *pTLibAttr)
3981 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3982 TRACE("freeing (%p)\n",This);
3983 HeapFree(GetProcessHeap(),0,pTLibAttr);
3987 /* ITypeLib2::GetCustData
3989 * gets the custom data
3991 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3996 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3997 TLBCustData *pCData;
3999 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4001 if( IsEqualIID(guid, &pCData->guid)) break;
4004 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4008 VariantInit( pVarVal);
4009 VariantCopy( pVarVal, &pCData->data);
4012 return E_INVALIDARG; /* FIXME: correct? */
4015 /* ITypeLib2::GetLibStatistics
4017 * Returns statistics about a type library that are required for efficient
4018 * sizing of hash tables.
4021 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4023 ULONG *pcUniqueNames,
4024 ULONG *pcchUniqueNames)
4026 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4028 FIXME("(%p): stub!\n", This);
4030 if(pcUniqueNames) *pcUniqueNames=1;
4031 if(pcchUniqueNames) *pcchUniqueNames=1;
4035 /* ITypeLib2::GetDocumentation2
4037 * Retrieves the library's documentation string, the complete Help file name
4038 * and path, the localization context to use, and the context ID for the
4039 * library Help topic in the Help file.
4042 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4046 BSTR *pbstrHelpString,
4047 DWORD *pdwHelpStringContext,
4048 BSTR *pbstrHelpStringDll)
4050 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4054 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4056 /* the help string should be obtained from the helpstringdll,
4057 * using the _DLLGetDocumentation function, based on the supplied
4058 * lcid. Nice to do sometime...
4062 /* documentation for the typelib */
4064 *pbstrHelpString=SysAllocString(This->DocString);
4065 if(pdwHelpStringContext)
4066 *pdwHelpStringContext=This->dwHelpContext;
4067 if(pbstrHelpStringDll)
4068 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4074 /* for a typeinfo */
4075 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4077 if(SUCCEEDED(result))
4079 ITypeInfo2 * pTInfo2;
4080 result = ITypeInfo_QueryInterface(pTInfo,
4082 (LPVOID*) &pTInfo2);
4084 if(SUCCEEDED(result))
4086 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4090 pdwHelpStringContext,
4091 pbstrHelpStringDll);
4093 ITypeInfo2_Release(pTInfo2);
4096 ITypeInfo_Release(pTInfo);
4102 /* ITypeLib2::GetAllCustData
4104 * Gets all custom data items for the library.
4107 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4109 CUSTDATA *pCustData)
4111 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4112 TLBCustData *pCData;
4114 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4115 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4116 if(pCustData->prgCustData ){
4117 pCustData->cCustData=This->ctCustData;
4118 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4119 pCustData->prgCustData[i].guid=pCData->guid;
4120 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4123 ERR(" OUT OF MEMORY!\n");
4124 return E_OUTOFMEMORY;
4129 static const ITypeLib2Vtbl tlbvt = {
4130 ITypeLib2_fnQueryInterface,
4132 ITypeLib2_fnRelease,
4133 ITypeLib2_fnGetTypeInfoCount,
4134 ITypeLib2_fnGetTypeInfo,
4135 ITypeLib2_fnGetTypeInfoType,
4136 ITypeLib2_fnGetTypeInfoOfGuid,
4137 ITypeLib2_fnGetLibAttr,
4138 ITypeLib2_fnGetTypeComp,
4139 ITypeLib2_fnGetDocumentation,
4141 ITypeLib2_fnFindName,
4142 ITypeLib2_fnReleaseTLibAttr,
4144 ITypeLib2_fnGetCustData,
4145 ITypeLib2_fnGetLibStatistics,
4146 ITypeLib2_fnGetDocumentation2,
4147 ITypeLib2_fnGetAllCustData
4151 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4153 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4155 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4158 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4160 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4162 return ITypeLib2_AddRef((ITypeLib2 *)This);
4165 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4167 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4169 return ITypeLib2_Release((ITypeLib2 *)This);
4172 static HRESULT WINAPI ITypeLibComp_fnBind(
4177 ITypeInfo ** ppTInfo,
4178 DESCKIND * pDescKind,
4181 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4182 ITypeInfoImpl *pTypeInfo;
4184 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4186 *pDescKind = DESCKIND_NONE;
4187 pBindPtr->lptcomp = NULL;
4190 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4192 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4194 /* FIXME: check wFlags here? */
4195 /* FIXME: we should use a hash table to look this info up using lHash
4196 * instead of an O(n) search */
4197 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4198 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4200 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4202 *pDescKind = DESCKIND_TYPECOMP;
4203 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4204 ITypeComp_AddRef(pBindPtr->lptcomp);
4205 TRACE("module or enum: %s\n", debugstr_w(szName));
4210 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4211 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4213 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4216 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4217 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4219 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4224 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4225 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4227 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4229 ITypeInfo *subtypeinfo;
4231 DESCKIND subdesckind;
4233 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4234 &subtypeinfo, &subdesckind, &subbindptr);
4235 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4237 TYPEDESC tdesc_appobject =
4240 (TYPEDESC *)pTypeInfo->hreftype
4244 const VARDESC vardesc_appobject =
4247 NULL, /* lpstrSchema */
4262 VAR_STATIC /* varkind */
4265 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4267 /* cleanup things filled in by Bind call so we can put our
4268 * application object data in there instead */
4269 switch (subdesckind)
4271 case DESCKIND_FUNCDESC:
4272 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4274 case DESCKIND_VARDESC:
4275 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4280 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4282 if (pTypeInfo->hreftype == -1)
4283 FIXME("no hreftype for interface %p\n", pTypeInfo);
4285 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4289 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4290 *ppTInfo = (ITypeInfo *)pTypeInfo;
4291 ITypeInfo_AddRef(*ppTInfo);
4297 TRACE("name not found %s\n", debugstr_w(szName));
4301 static HRESULT WINAPI ITypeLibComp_fnBindType(
4305 ITypeInfo ** ppTInfo,
4306 ITypeComp ** ppTComp)
4308 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4312 static const ITypeCompVtbl tlbtcvt =
4315 ITypeLibComp_fnQueryInterface,
4316 ITypeLibComp_fnAddRef,
4317 ITypeLibComp_fnRelease,
4319 ITypeLibComp_fnBind,
4320 ITypeLibComp_fnBindType
4323 /*================== ITypeInfo(2) Methods ===================================*/
4324 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4326 ITypeInfoImpl * pTypeInfoImpl;
4328 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4331 pTypeInfoImpl->lpVtbl = &tinfvt;
4332 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4333 pTypeInfoImpl->ref=1;
4334 pTypeInfoImpl->hreftype = -1;
4335 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4336 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4338 TRACE("(%p)\n", pTypeInfoImpl);
4339 return (ITypeInfo2*) pTypeInfoImpl;
4342 /* ITypeInfo::QueryInterface
4344 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4349 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4351 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4354 if(IsEqualIID(riid, &IID_IUnknown) ||
4355 IsEqualIID(riid,&IID_ITypeInfo)||
4356 IsEqualIID(riid,&IID_ITypeInfo2))
4360 ITypeInfo_AddRef(iface);
4361 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4364 TRACE("-- Interface: E_NOINTERFACE\n");
4365 return E_NOINTERFACE;
4368 /* ITypeInfo::AddRef
4370 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4372 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4373 ULONG ref = InterlockedIncrement(&This->ref);
4375 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4377 TRACE("(%p)->ref is %u\n",This, ref);
4381 /* ITypeInfo::Release
4383 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4385 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4386 ULONG ref = InterlockedDecrement(&This->ref);
4388 TRACE("(%p)->(%u)\n",This, ref);
4391 /* We don't release ITypeLib when ref=0 because
4392 it means that function is called by ITypeLib2_Release */
4393 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4395 TLBFuncDesc *pFInfo, *pFInfoNext;
4396 TLBVarDesc *pVInfo, *pVInfoNext;
4397 TLBImplType *pImpl, *pImplNext;
4398 TLBRefType *pRefType,*pRefTypeNext;
4399 TLBCustData *pCustData, *pCustDataNext;
4401 TRACE("destroying ITypeInfo(%p)\n",This);
4403 if (This->no_free_data)
4408 SysFreeString(This->Name);
4412 if (This->DocString)
4414 SysFreeString(This->DocString);
4415 This->DocString = 0;
4420 SysFreeString(This->DllName);
4424 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4427 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4429 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4430 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4432 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4433 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4435 SysFreeString(pFInfo->pParamDesc[i].Name);
4437 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4438 TLB_Free(pFInfo->pParamDesc);
4439 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4441 VariantClear(&pCustData->data);
4443 pCustDataNext = pCustData->next;
4444 TLB_Free(pCustData);
4446 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4447 SysFreeString(pFInfo->Entry);
4448 SysFreeString(pFInfo->HelpString);
4449 SysFreeString(pFInfo->Name);
4451 pFInfoNext = pFInfo->next;
4454 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4456 if (pVInfo->vardesc.varkind == VAR_CONST)
4458 VariantClear(pVInfo->vardesc.u.lpvarValue);
4459 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4461 SysFreeString(pVInfo->Name);
4462 pVInfoNext = pVInfo->next;
4465 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4467 for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4469 VariantClear(&pCustData->data);
4471 pCustDataNext = pCustData->next;
4472 TLB_Free(pCustData);
4474 pImplNext = pImpl->next;
4477 for(pRefType = This->reflist; pRefType; pRefType = pRefTypeNext)
4479 pRefTypeNext = pRefType->next;
4482 TLB_Free(This->pCustData);
4487 ITypeInfo_Release((ITypeInfo*)This->next);
4490 HeapFree(GetProcessHeap(),0,This);
4496 /* ITypeInfo::GetTypeAttr
4498 * Retrieves a TYPEATTR structure that contains the attributes of the type
4502 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4503 LPTYPEATTR *ppTypeAttr)
4505 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4508 TRACE("(%p)\n",This);
4510 size = sizeof(**ppTypeAttr);
4511 if (This->TypeAttr.typekind == TKIND_ALIAS)
4512 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4514 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4516 return E_OUTOFMEMORY;
4518 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4520 if (This->TypeAttr.typekind == TKIND_ALIAS)
4521 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4522 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4524 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4525 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4527 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4528 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4533 /* ITypeInfo::GetTypeComp
4535 * Retrieves the ITypeComp interface for the type description, which enables a
4536 * client compiler to bind to the type description's members.
4539 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4540 ITypeComp * *ppTComp)
4542 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4544 TRACE("(%p)->(%p)\n", This, ppTComp);
4546 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4547 ITypeComp_AddRef(*ppTComp);
4551 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4553 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4554 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4555 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4559 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4561 memcpy(dest, src, sizeof(ELEMDESC));
4562 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4563 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4565 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4566 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4567 *buffer += sizeof(PARAMDESCEX);
4568 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4569 VariantInit(&pparamdescex_dest->varDefaultValue);
4570 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4571 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4574 dest->u.paramdesc.pparamdescex = NULL;
4578 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4580 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4581 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4584 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4588 SIZE_T size = sizeof(*src);
4592 size += sizeof(*src->lprgscode) * src->cScodes;
4593 size += TLB_SizeElemDesc(&src->elemdescFunc);
4594 for (i = 0; i < src->cParams; i++)
4596 size += sizeof(ELEMDESC);
4597 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4600 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4601 if (!dest) return E_OUTOFMEMORY;
4603 memcpy(dest, src, sizeof(FUNCDESC));
4604 buffer = (char *)(dest + 1);
4606 dest->lprgscode = (SCODE *)buffer;
4607 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4608 buffer += sizeof(*src->lprgscode) * src->cScodes;
4610 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4613 SysFreeString((BSTR)dest);
4617 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4618 buffer += sizeof(ELEMDESC) * src->cParams;
4619 for (i = 0; i < src->cParams; i++)
4621 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4627 /* undo the above actions */
4628 for (i = i - 1; i >= 0; i--)
4629 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4630 TLB_FreeElemDesc(&dest->elemdescFunc);
4631 SysFreeString((BSTR)dest);
4635 /* special treatment for dispinterfaces: this makes functions appear
4636 * to return their [retval] value when it is really returning an
4638 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4640 if (dest->cParams &&
4641 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4643 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4644 if (elemdesc->tdesc.vt != VT_PTR)
4646 ERR("elemdesc should have started with VT_PTR instead of:\n");
4648 dump_ELEMDESC(elemdesc);
4649 return E_UNEXPECTED;
4652 /* copy last parameter to the return value. we are using a flat
4653 * buffer so there is no danger of leaking memory in
4655 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4657 /* remove the last parameter */
4661 /* otherwise this function is made to appear to have no return
4663 dest->elemdescFunc.tdesc.vt = VT_VOID;
4671 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4673 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4674 const TLBFuncDesc *pFDesc;
4677 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4682 *ppFuncDesc = &pFDesc->funcdesc;
4686 return E_INVALIDARG;
4689 /* internal function to make the inherited interfaces' methods appear
4690 * part of the interface */
4691 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4692 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs)
4694 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4697 UINT implemented_funcs = 0;
4702 for (i = 0; i < This->TypeAttr.cImplTypes; i++)
4705 ITypeInfo *pSubTypeInfo;
4708 hr = ITypeInfo_GetRefTypeOfImplType(iface, i, &href);
4711 hr = ITypeInfo_GetRefTypeInfo(iface, href, &pSubTypeInfo);
4715 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4719 implemented_funcs += sub_funcs;
4720 ITypeInfo_Release(pSubTypeInfo);
4726 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4728 if (index < implemented_funcs)
4729 return E_INVALIDARG;
4730 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4734 /* ITypeInfo::GetFuncDesc
4736 * Retrieves the FUNCDESC structure that contains information about a
4737 * specified function.
4740 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4741 LPFUNCDESC *ppFuncDesc)
4743 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4744 const FUNCDESC *internal_funcdesc;
4747 TRACE("(%p) index %d\n", This, index);
4749 if ((This->TypeAttr.typekind == TKIND_DISPATCH) &&
4750 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4751 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4752 &internal_funcdesc, NULL);
4754 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4755 &internal_funcdesc);
4758 WARN("description for function %d not found\n", index);
4762 return TLB_AllocAndInitFuncDesc(
4765 This->TypeAttr.typekind == TKIND_DISPATCH);
4768 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4772 SIZE_T size = sizeof(*src);
4775 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4776 if (src->varkind == VAR_CONST)
4777 size += sizeof(VARIANT);
4778 size += TLB_SizeElemDesc(&src->elemdescVar);
4780 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4781 if (!dest) return E_OUTOFMEMORY;
4784 buffer = (char *)(dest + 1);
4785 if (src->lpstrSchema)
4788 dest->lpstrSchema = (LPOLESTR)buffer;
4789 len = strlenW(src->lpstrSchema);
4790 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4791 buffer += (len + 1) * sizeof(WCHAR);
4794 if (src->varkind == VAR_CONST)
4798 dest->u.lpvarValue = (VARIANT *)buffer;
4799 *dest->u.lpvarValue = *src->u.lpvarValue;
4800 buffer += sizeof(VARIANT);
4801 VariantInit(dest->u.lpvarValue);
4802 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4805 SysFreeString((BSTR)dest_ptr);
4809 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4812 if (src->varkind == VAR_CONST)
4813 VariantClear(dest->u.lpvarValue);
4814 SysFreeString((BSTR)dest);
4821 /* ITypeInfo::GetVarDesc
4823 * Retrieves a VARDESC structure that describes the specified variable.
4826 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4827 LPVARDESC *ppVarDesc)
4829 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4831 const TLBVarDesc *pVDesc;
4833 TRACE("(%p) index %d\n", This, index);
4835 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4839 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4841 return E_INVALIDARG;
4844 /* ITypeInfo_GetNames
4846 * Retrieves the variable with the specified member ID (or the name of the
4847 * property or method and its parameters) that correspond to the specified
4850 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4851 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4853 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4854 const TLBFuncDesc *pFDesc;
4855 const TLBVarDesc *pVDesc;
4857 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4858 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4861 /* function found, now return function and parameter names */
4862 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4865 *rgBstrNames=SysAllocString(pFDesc->Name);
4867 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4873 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4876 *rgBstrNames=SysAllocString(pVDesc->Name);
4881 if(This->TypeAttr.cImplTypes &&
4882 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4883 /* recursive search */
4886 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4888 if(SUCCEEDED(result))
4890 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4891 ITypeInfo_Release(pTInfo);
4894 WARN("Could not search inherited interface!\n");
4898 WARN("no names found\n");
4901 return TYPE_E_ELEMENTNOTFOUND;
4908 /* ITypeInfo::GetRefTypeOfImplType
4910 * If a type description describes a COM class, it retrieves the type
4911 * description of the implemented interface types. For an interface,
4912 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4916 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4921 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4924 const TLBImplType *pImpl = This->impltypelist;
4926 TRACE("(%p) index %d\n", This, index);
4927 if (TRACE_ON(ole)) dump_TypeInfo(This);
4931 /* only valid on dual interfaces;
4932 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4934 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4936 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4937 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4943 hr = TYPE_E_ELEMENTNOTFOUND;
4948 /* get element n from linked list */
4949 for(i=0; pImpl && i<index; i++)
4951 pImpl = pImpl->next;
4955 *pRefType = pImpl->hRef;
4957 hr = TYPE_E_ELEMENTNOTFOUND;
4963 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
4965 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
4971 /* ITypeInfo::GetImplTypeFlags
4973 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4974 * or base interface in a type description.
4976 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4977 UINT index, INT *pImplTypeFlags)
4979 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4983 TRACE("(%p) index %d\n", This, index);
4984 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4985 i++, pImpl=pImpl->next)
4987 if(i==index && pImpl){
4988 *pImplTypeFlags=pImpl->implflags;
4992 return TYPE_E_ELEMENTNOTFOUND;
4996 * Maps between member names and member IDs, and parameter names and
4999 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5000 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5002 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5003 const TLBFuncDesc *pFDesc;
5004 const TLBVarDesc *pVDesc;
5008 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5011 /* init out parameters in case of failure */
5012 for (i = 0; i < cNames; i++)
5013 pMemId[i] = MEMBERID_NIL;
5015 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5017 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5018 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5019 for(i=1; i < cNames; i++){
5020 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5021 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5023 if( j<pFDesc->funcdesc.cParams)
5026 ret=DISP_E_UNKNOWNNAME;
5028 TRACE("-- 0x%08x\n", ret);
5032 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5033 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5034 if(cNames) *pMemId=pVDesc->vardesc.memid;
5038 /* not found, see if it can be found in an inherited interface */
5039 if(This->TypeAttr.cImplTypes) {
5040 /* recursive search */
5042 ret=ITypeInfo_GetRefTypeInfo(iface,
5043 This->impltypelist->hRef, &pTInfo);
5045 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5046 ITypeInfo_Release(pTInfo);
5049 WARN("Could not search inherited interface!\n");
5051 WARN("no names found\n");
5052 return DISP_E_UNKNOWNNAME;
5055 /* ITypeInfo::Invoke
5057 * Invokes a method, or accesses a property of an object, that implements the
5058 * interface described by the type description.
5061 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5064 if (TRACE_ON(ole)) {
5066 TRACE("Calling %p(",func);
5067 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5079 res = func(args[0]);
5082 res = func(args[0],args[1]);
5085 res = func(args[0],args[1],args[2]);
5088 res = func(args[0],args[1],args[2],args[3]);
5091 res = func(args[0],args[1],args[2],args[3],args[4]);
5094 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5097 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5100 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5103 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5106 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5109 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5112 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]);
5115 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]);
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],args[11],args[12],args[13]);
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],args[12],args[13],args[14]);
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],args[13],args[14],args[15]);
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],args[14],args[15],args[16]);
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],args[15],args[16],args[17]);
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],args[16],args[17],args[18]);
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],args[17],args[18],args[19]);
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],args[18],args[19],args[20]);
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],args[19],args[20],args[21]);
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],args[20],args[21],args[22]);
5148 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5154 FIXME("unsupported calling convention %d\n",callconv);
5158 TRACE("returns %08x\n",res);
5162 extern int _argsize(DWORD vt);
5164 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5167 ITypeInfo *tinfo2 = NULL;
5168 TYPEATTR *tattr = NULL;
5170 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5173 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5175 tdesc->u.hreftype, hr);
5178 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5181 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5182 ITypeInfo_Release(tinfo2);
5186 switch (tattr->typekind)
5193 tdesc = &tattr->tdescAlias;
5194 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5197 case TKIND_INTERFACE:
5198 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5204 case TKIND_DISPATCH:
5213 FIXME("TKIND_RECORD unhandled.\n");
5218 FIXME("TKIND_UNION unhandled.\n");
5223 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5227 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5228 ITypeInfo_Release(tinfo2);
5232 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5236 /* enforce only one level of pointer indirection */
5237 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5239 tdesc = tdesc->u.lptdesc;
5241 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5242 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5243 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5244 if ((tdesc->vt == VT_USERDEFINED) ||
5245 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5247 VARTYPE vt_userdefined = 0;
5248 const TYPEDESC *tdesc_userdefined = tdesc;
5249 if (tdesc->vt == VT_PTR)
5251 vt_userdefined = VT_BYREF;
5252 tdesc_userdefined = tdesc->u.lptdesc;
5254 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5256 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5257 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5259 *vt |= vt_userdefined;
5271 case VT_USERDEFINED:
5272 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5279 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5280 hr = DISP_E_BADVARTYPE;
5284 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5293 /***********************************************************************
5294 * DispCallFunc (OLEAUT32.@)
5296 * Invokes a function of the specifed calling convention, passing the
5297 * specified arguments and returns the result.
5300 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5301 * oVft [I] The offset in the vtable. See notes.
5302 * cc [I] Calling convention of the function to call.
5303 * vtReturn [I] The return type of the function.
5304 * cActuals [I] Number of parameters.
5305 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5306 * prgpvarg [I] The arguments to pass.
5307 * pvargResult [O] The return value of the function. Can be NULL.
5311 * Failure: HRESULT code.
5314 * The HRESULT return value of this function is not affected by the return
5315 * value of the user supplied function, which is returned in pvargResult.
5317 * If pvInstance is NULL then a non-object function is to be called and oVft
5318 * is the address of the function to call.
5320 * The cc parameter can be one of the following values:
5333 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5334 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5336 int i, argsize, argspos;
5340 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5341 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5342 pvargResult, V_VT(pvargResult));
5346 argsize++; /* for This pointer */
5348 for (i=0;i<cActuals;i++)
5350 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5351 dump_Variant(prgpvarg[i]);
5352 argsize += _argsize(prgvt[i]);
5354 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5359 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5363 for (i=0;i<cActuals;i++)
5365 VARIANT *arg = prgpvarg[i];
5366 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5367 if (prgvt[i] == VT_VARIANT)
5368 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5370 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5371 argspos += _argsize(prgvt[i]);
5376 FARPROC *vtable = *(FARPROC**)pvInstance;
5377 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5380 /* if we aren't invoking an object then the function pointer is stored
5382 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5384 if (pvargResult && (vtReturn != VT_EMPTY))
5386 TRACE("Method returned 0x%08x\n",hres);
5387 V_VT(pvargResult) = vtReturn;
5388 V_UI4(pvargResult) = hres;
5391 HeapFree(GetProcessHeap(),0,args);
5395 #define INVBUF_ELEMENT_SIZE \
5396 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5397 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5398 ((VARIANTARG *)(buffer))
5399 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5400 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5401 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5402 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5403 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5404 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5406 static HRESULT WINAPI ITypeInfo_fnInvoke(
5411 DISPPARAMS *pDispParams,
5412 VARIANT *pVarResult,
5413 EXCEPINFO *pExcepInfo,
5416 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5418 unsigned int var_index;
5421 const TLBFuncDesc *pFuncInfo;
5423 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5424 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5429 ERR("NULL pDispParams not allowed\n");
5430 return E_INVALIDARG;
5433 dump_DispParms(pDispParams);
5435 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5437 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5438 pDispParams->cNamedArgs, pDispParams->cArgs);
5439 return E_INVALIDARG;
5442 /* we do this instead of using GetFuncDesc since it will return a fake
5443 * FUNCDESC for dispinterfaces and we want the real function description */
5444 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5445 if ((memid == pFuncInfo->funcdesc.memid) &&
5446 (wFlags & pFuncInfo->funcdesc.invkind))
5450 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5454 TRACE("invoking:\n");
5455 dump_TLBFuncDescOne(pFuncInfo);
5458 switch (func_desc->funckind) {
5459 case FUNC_PUREVIRTUAL:
5460 case FUNC_VIRTUAL: {
5461 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5463 VARIANT retval; /* pointer for storing byref retvals in */
5464 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5465 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5466 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5469 for (i = 0; i < func_desc->cParams; i++)
5471 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5472 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5477 TRACE("changing args\n");
5478 for (i = 0; i < func_desc->cParams; i++)
5480 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5482 if (wParamFlags & PARAMFLAG_FRETVAL)
5484 /* note: this check is placed so that if the caller passes
5485 * in a VARIANTARG for the retval we just ignore it, like
5487 if (i == func_desc->cParams - 1)
5490 arg = prgpvarg[i] = &rgvarg[i];
5491 memset(arg, 0, sizeof(*arg));
5492 V_VT(arg) = rgvt[i];
5493 memset(&retval, 0, sizeof(retval));
5494 V_BYREF(arg) = &retval;
5498 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5499 hres = E_UNEXPECTED;
5503 else if (i < pDispParams->cArgs)
5505 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5506 dump_Variant(src_arg);
5508 if (rgvt[i] == VT_VARIANT)
5509 hres = VariantCopy(&rgvarg[i], src_arg);
5510 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5512 if (rgvt[i] == V_VT(src_arg))
5513 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5516 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5517 hres = VariantCopy(&missing_arg[i], src_arg);
5518 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5520 V_VT(&rgvarg[i]) = rgvt[i];
5522 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5524 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5525 V_VT(&missing_arg[i]) = V_VT(src_arg);
5526 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5527 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5528 V_VT(&rgvarg[i]) = rgvt[i];
5530 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5532 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5533 V_VT(&rgvarg[i]) = rgvt[i];
5537 /* FIXME: this doesn't work for VT_BYREF arguments if
5538 * they are not the same type as in the paramdesc */
5539 V_VT(&rgvarg[i]) = V_VT(src_arg);
5540 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5541 V_VT(&rgvarg[i]) = rgvt[i];
5546 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5547 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5548 debugstr_VT(src_arg), debugstr_VF(src_arg));
5551 prgpvarg[i] = &rgvarg[i];
5553 else if (wParamFlags & PARAMFLAG_FOPT)
5556 arg = prgpvarg[i] = &rgvarg[i];
5557 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5559 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5565 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5566 V_VT(arg) = VT_VARIANT | VT_BYREF;
5567 V_VARIANTREF(arg) = &missing_arg[i];
5568 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5569 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5574 hres = DISP_E_BADPARAMCOUNT;
5578 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5579 if (func_desc->cParamsOpt < 0)
5581 FIXME("Does not support safearray optional parameters\n");
5582 hres = DISP_E_BADPARAMCOUNT;
5583 goto func_fail; /* FIXME: we don't free changed types here */
5586 /* VT_VOID is a special case for return types, so it is not
5587 * handled in the general function */
5588 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5589 V_VT(&varresult) = VT_EMPTY;
5592 V_VT(&varresult) = 0;
5593 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5594 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5597 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5598 V_VT(&varresult), func_desc->cParams, rgvt,
5599 prgpvarg, &varresult);
5601 for (i = 0; i < func_desc->cParams; i++)
5603 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5604 if (wParamFlags & PARAMFLAG_FRETVAL)
5608 TRACE("[retval] value: ");
5609 dump_Variant(prgpvarg[i]);
5614 VariantInit(pVarResult);
5615 /* deref return value */
5616 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5619 /* free data stored in varresult. Note that
5620 * VariantClear doesn't do what we want because we are
5621 * working with byref types. */
5622 /* FIXME: clear safearrays, bstrs, records and
5623 * variants here too */
5624 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5625 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5627 if(*V_UNKNOWNREF(prgpvarg[i]))
5628 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5632 else if (i < pDispParams->cArgs)
5634 if (wParamFlags & PARAMFLAG_FOUT)
5636 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5638 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5639 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5643 ERR("failed to convert param %d to vt %d\n", i,
5644 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5648 VariantClear(&rgvarg[i]);
5650 else if (wParamFlags & PARAMFLAG_FOPT)
5652 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5653 VariantClear(&rgvarg[i]);
5657 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5659 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5660 hres = DISP_E_EXCEPTION;
5661 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5665 HeapFree(GetProcessHeap(), 0, buffer);
5668 case FUNC_DISPATCH: {
5671 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5672 if (SUCCEEDED(hres)) {
5673 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5674 hres = IDispatch_Invoke(
5675 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5676 pVarResult,pExcepInfo,pArgErr
5679 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5680 IDispatch_Release(disp);
5682 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5686 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5691 TRACE("-- 0x%08x\n", hres);
5694 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5697 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5698 if(FAILED(hres)) return hres;
5700 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5701 dump_VARDESC(var_desc);
5702 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5706 /* not found, look for it in inherited interfaces */
5707 ITypeInfo2_GetTypeKind(iface, &type_kind);
5708 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5710 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5711 /* recursive search */
5713 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5714 if(SUCCEEDED(hres)){
5715 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5716 ITypeInfo_Release(pTInfo);
5719 WARN("Could not search inherited interface!\n");
5722 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
5723 return DISP_E_MEMBERNOTFOUND;
5726 /* ITypeInfo::GetDocumentation
5728 * Retrieves the documentation string, the complete Help file name and path,
5729 * and the context ID for the Help topic for a specified type description.
5731 * (Can be tested by the Visual Basic Editor in Word for instance.)
5733 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5734 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5735 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5737 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5738 const TLBFuncDesc *pFDesc;
5739 const TLBVarDesc *pVDesc;
5740 TRACE("(%p) memid %d Name(%p) DocString(%p)"
5741 " HelpContext(%p) HelpFile(%p)\n",
5742 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5743 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5745 *pBstrName=SysAllocString(This->Name);
5747 *pBstrDocString=SysAllocString(This->DocString);
5749 *pdwHelpContext=This->dwHelpContext;
5751 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5753 }else {/* for a member */
5754 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5755 if(pFDesc->funcdesc.memid==memid){
5757 *pBstrName = SysAllocString(pFDesc->Name);
5759 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5761 *pdwHelpContext=pFDesc->helpcontext;
5764 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5765 if(pVDesc->vardesc.memid==memid){
5767 *pBstrName = SysAllocString(pVDesc->Name);
5769 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5771 *pdwHelpContext=pVDesc->HelpContext;
5776 if(This->TypeAttr.cImplTypes &&
5777 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5778 /* recursive search */
5781 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5783 if(SUCCEEDED(result)) {
5784 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
5785 pBstrDocString, pdwHelpContext, pBstrHelpFile);
5786 ITypeInfo_Release(pTInfo);
5789 WARN("Could not search inherited interface!\n");
5792 WARN("member %d not found\n", memid);
5793 return TYPE_E_ELEMENTNOTFOUND;
5796 /* ITypeInfo::GetDllEntry
5798 * Retrieves a description or specification of an entry point for a function
5801 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5802 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5805 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5806 const TLBFuncDesc *pFDesc;
5808 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5810 if (pBstrDllName) *pBstrDllName = NULL;
5811 if (pBstrName) *pBstrName = NULL;
5812 if (pwOrdinal) *pwOrdinal = 0;
5814 if (This->TypeAttr.typekind != TKIND_MODULE)
5815 return TYPE_E_BADMODULEKIND;
5817 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5818 if(pFDesc->funcdesc.memid==memid){
5819 dump_TypeInfo(This);
5821 dump_TLBFuncDescOne(pFDesc);
5824 *pBstrDllName = SysAllocString(This->DllName);
5826 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5828 *pBstrName = SysAllocString(pFDesc->Entry);
5836 *pwOrdinal = (DWORD)pFDesc->Entry;
5839 return TYPE_E_ELEMENTNOTFOUND;
5842 /* ITypeInfo::GetRefTypeInfo
5844 * If a type description references other type descriptions, it retrieves
5845 * the referenced type descriptions.
5847 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5850 ITypeInfo **ppTInfo)
5852 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5853 HRESULT result = E_FAIL;
5855 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5857 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5858 ITypeInfo_AddRef(*ppTInfo);
5861 else if (hRefType == -1 &&
5862 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5863 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5865 /* when we meet a DUAL dispinterface, we must create the interface
5868 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5871 /* the interface version contains the same information as the dispinterface
5872 * copy the contents of the structs.
5874 *pTypeInfoImpl = *This;
5875 pTypeInfoImpl->ref = 0;
5877 /* change the type to interface */
5878 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5880 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5882 /* we use data structures from This, so we need to keep a reference
5883 * to it to stop it being destroyed and signal to the new instance to
5884 * not free its data structures when it is destroyed */
5885 pTypeInfoImpl->no_free_data = TRUE;
5886 pTypeInfoImpl->next = This;
5887 ITypeInfo_AddRef((ITypeInfo*) This);
5889 ITypeInfo_AddRef(*ppTInfo);
5894 TLBRefType *pRefType;
5895 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5896 if(pRefType->reference == hRefType)
5900 FIXME("Can't find pRefType for ref %x\n", hRefType);
5901 if(pRefType && hRefType != -1) {
5902 ITypeLib *pTLib = NULL;
5904 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5906 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5908 if(pRefType->pImpTLInfo->pImpTypeLib) {
5909 TRACE("typeinfo in imported typelib that is already loaded\n");
5910 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5911 ITypeLib2_AddRef((ITypeLib*) pTLib);
5914 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5915 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5916 pRefType->pImpTLInfo->wVersionMajor,
5917 pRefType->pImpTLInfo->wVersionMinor,
5918 pRefType->pImpTLInfo->lcid,
5921 if(!SUCCEEDED(result)) {
5922 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5923 result=LoadTypeLib(libnam, &pTLib);
5924 SysFreeString(libnam);
5926 if(SUCCEEDED(result)) {
5927 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5928 ITypeLib2_AddRef(pTLib);
5932 if(SUCCEEDED(result)) {
5933 if(pRefType->index == TLB_REF_USE_GUID)
5934 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5938 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5942 ITypeLib2_Release(pTLib);
5946 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
5947 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5951 /* ITypeInfo::AddressOfMember
5953 * Retrieves the addresses of static functions or variables, such as those
5956 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5957 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5959 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5965 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
5967 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5971 module = LoadLibraryW(dll);
5974 ERR("couldn't load %s\n", debugstr_w(dll));
5976 if (entry) SysFreeString(entry);
5977 return STG_E_FILENOTFOUND;
5979 /* FIXME: store library somewhere where we can free it */
5984 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5985 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5986 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5988 *ppv = GetProcAddress(module, entryA);
5990 ERR("function not found %s\n", debugstr_a(entryA));
5992 HeapFree(GetProcessHeap(), 0, entryA);
5996 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5998 ERR("function not found %d\n", ordinal);
6002 if (entry) SysFreeString(entry);
6005 return TYPE_E_DLLFUNCTIONNOTFOUND;
6010 /* ITypeInfo::CreateInstance
6012 * Creates a new instance of a type that describes a component object class
6015 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6016 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6018 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6022 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6028 WARN("Not able to aggregate\n");
6029 return CLASS_E_NOAGGREGATION;
6032 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6033 if(FAILED(hr)) return hr;
6035 if(pTA->typekind != TKIND_COCLASS)
6037 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6043 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6046 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6047 TRACE("GetActiveObject rets %08x\n", hr);
6050 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6051 IUnknown_Release(pUnk);
6056 hr = CoCreateInstance(&pTA->guid, NULL,
6057 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6061 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6065 /* ITypeInfo::GetMops
6067 * Retrieves marshalling information.
6069 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6072 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6073 FIXME("(%p) stub!\n", This);
6077 /* ITypeInfo::GetContainingTypeLib
6079 * Retrieves the containing type library and the index of the type description
6080 * within that type library.
6082 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6083 ITypeLib * *ppTLib, UINT *pIndex)
6085 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6087 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6089 *pIndex=This->index;
6090 TRACE("returning pIndex=%d\n", *pIndex);
6094 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6095 ITypeLib2_AddRef(*ppTLib);
6096 TRACE("returning ppTLib=%p\n", *ppTLib);
6102 /* ITypeInfo::ReleaseTypeAttr
6104 * Releases a TYPEATTR previously returned by GetTypeAttr.
6107 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6108 TYPEATTR* pTypeAttr)
6110 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6111 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6112 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6115 /* ITypeInfo::ReleaseFuncDesc
6117 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6119 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6121 FUNCDESC *pFuncDesc)
6123 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6126 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6128 for (i = 0; i < pFuncDesc->cParams; i++)
6129 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6130 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6132 SysFreeString((BSTR)pFuncDesc);
6135 /* ITypeInfo::ReleaseVarDesc
6137 * Releases a VARDESC previously returned by GetVarDesc.
6139 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6142 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6143 TRACE("(%p)->(%p)\n", This, pVarDesc);
6145 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6146 if (pVarDesc->varkind == VAR_CONST)
6147 VariantClear(pVarDesc->u.lpvarValue);
6148 SysFreeString((BSTR)pVarDesc);
6151 /* ITypeInfo2::GetTypeKind
6153 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6156 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6157 TYPEKIND *pTypeKind)
6159 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6160 *pTypeKind=This->TypeAttr.typekind;
6161 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6165 /* ITypeInfo2::GetTypeFlags
6167 * Returns the type flags without any allocations. This returns a DWORD type
6168 * flag, which expands the type flags without growing the TYPEATTR (type
6172 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6174 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6175 *pTypeFlags=This->TypeAttr.wTypeFlags;
6176 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6180 /* ITypeInfo2::GetFuncIndexOfMemId
6181 * Binds to a specific member based on a known DISPID, where the member name
6182 * is not known (for example, when binding to a default member).
6185 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6186 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6188 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6189 const TLBFuncDesc *pFuncInfo;
6193 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6194 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6200 result = TYPE_E_ELEMENTNOTFOUND;
6202 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6203 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6207 /* TypeInfo2::GetVarIndexOfMemId
6209 * Binds to a specific member based on a known DISPID, where the member name
6210 * is not known (for example, when binding to a default member).
6213 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6214 MEMBERID memid, UINT *pVarIndex)
6216 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6217 TLBVarDesc *pVarInfo;
6220 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6221 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6227 result = TYPE_E_ELEMENTNOTFOUND;
6229 TRACE("(%p) memid 0x%08x -> %s\n", This,
6230 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6234 /* ITypeInfo2::GetCustData
6236 * Gets the custom data
6238 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6243 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6244 TLBCustData *pCData;
6246 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6247 if( IsEqualIID(guid, &pCData->guid)) break;
6249 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6253 VariantInit( pVarVal);
6254 VariantCopy( pVarVal, &pCData->data);
6257 return E_INVALIDARG; /* FIXME: correct? */
6260 /* ITypeInfo2::GetFuncCustData
6262 * Gets the custom data
6264 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6270 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6271 TLBCustData *pCData=NULL;
6272 TLBFuncDesc * pFDesc;
6274 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6275 pFDesc=pFDesc->next);
6278 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6279 if( IsEqualIID(guid, &pCData->guid)) break;
6281 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6284 VariantInit( pVarVal);
6285 VariantCopy( pVarVal, &pCData->data);
6288 return E_INVALIDARG; /* FIXME: correct? */
6291 /* ITypeInfo2::GetParamCustData
6293 * Gets the custom data
6295 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6302 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6303 TLBCustData *pCData=NULL;
6304 TLBFuncDesc * pFDesc;
6307 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6309 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6310 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6311 pCData = pCData->next)
6312 if( IsEqualIID(guid, &pCData->guid)) break;
6314 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6318 VariantInit( pVarVal);
6319 VariantCopy( pVarVal, &pCData->data);
6322 return E_INVALIDARG; /* FIXME: correct? */
6325 /* ITypeInfo2::GetVarCustData
6327 * Gets the custom data
6329 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6335 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6336 TLBCustData *pCData=NULL;
6337 TLBVarDesc * pVDesc;
6340 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6344 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6346 if( IsEqualIID(guid, &pCData->guid)) break;
6350 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6354 VariantInit( pVarVal);
6355 VariantCopy( pVarVal, &pCData->data);
6358 return E_INVALIDARG; /* FIXME: correct? */
6361 /* ITypeInfo2::GetImplCustData
6363 * Gets the custom data
6365 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6371 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6372 TLBCustData *pCData=NULL;
6373 TLBImplType * pRDesc;
6376 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6380 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6382 if( IsEqualIID(guid, &pCData->guid)) break;
6386 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6390 VariantInit( pVarVal);
6391 VariantCopy( pVarVal, &pCData->data);
6394 return E_INVALIDARG; /* FIXME: correct? */
6397 /* ITypeInfo2::GetDocumentation2
6399 * Retrieves the documentation string, the complete Help file name and path,
6400 * the localization context to use, and the context ID for the library Help
6401 * topic in the Help file.
6404 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6408 BSTR *pbstrHelpString,
6409 DWORD *pdwHelpStringContext,
6410 BSTR *pbstrHelpStringDll)
6412 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6413 const TLBFuncDesc *pFDesc;
6414 const TLBVarDesc *pVDesc;
6415 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6416 "HelpStringContext(%p) HelpStringDll(%p)\n",
6417 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6418 pbstrHelpStringDll );
6419 /* the help string should be obtained from the helpstringdll,
6420 * using the _DLLGetDocumentation function, based on the supplied
6421 * lcid. Nice to do sometime...
6423 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6425 *pbstrHelpString=SysAllocString(This->Name);
6426 if(pdwHelpStringContext)
6427 *pdwHelpStringContext=This->dwHelpStringContext;
6428 if(pbstrHelpStringDll)
6429 *pbstrHelpStringDll=
6430 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6432 }else {/* for a member */
6433 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6434 if(pFDesc->funcdesc.memid==memid){
6436 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6437 if(pdwHelpStringContext)
6438 *pdwHelpStringContext=pFDesc->HelpStringContext;
6439 if(pbstrHelpStringDll)
6440 *pbstrHelpStringDll=
6441 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6444 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6445 if(pVDesc->vardesc.memid==memid){
6447 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6448 if(pdwHelpStringContext)
6449 *pdwHelpStringContext=pVDesc->HelpStringContext;
6450 if(pbstrHelpStringDll)
6451 *pbstrHelpStringDll=
6452 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6456 return TYPE_E_ELEMENTNOTFOUND;
6459 /* ITypeInfo2::GetAllCustData
6461 * Gets all custom data items for the Type info.
6464 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6466 CUSTDATA *pCustData)
6468 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6469 TLBCustData *pCData;
6472 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6474 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6475 if(pCustData->prgCustData ){
6476 pCustData->cCustData=This->ctCustData;
6477 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6478 pCustData->prgCustData[i].guid=pCData->guid;
6479 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6482 ERR(" OUT OF MEMORY!\n");
6483 return E_OUTOFMEMORY;
6488 /* ITypeInfo2::GetAllFuncCustData
6490 * Gets all custom data items for the specified Function
6493 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6496 CUSTDATA *pCustData)
6498 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6499 TLBCustData *pCData;
6500 TLBFuncDesc * pFDesc;
6502 TRACE("(%p) index %d\n", This, index);
6503 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6504 pFDesc=pFDesc->next)
6507 pCustData->prgCustData =
6508 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6509 if(pCustData->prgCustData ){
6510 pCustData->cCustData=pFDesc->ctCustData;
6511 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6512 pCData = pCData->next){
6513 pCustData->prgCustData[i].guid=pCData->guid;
6514 VariantCopy(& pCustData->prgCustData[i].varValue,
6518 ERR(" OUT OF MEMORY!\n");
6519 return E_OUTOFMEMORY;
6523 return TYPE_E_ELEMENTNOTFOUND;
6526 /* ITypeInfo2::GetAllParamCustData
6528 * Gets all custom data items for the Functions
6531 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6532 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6534 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6535 TLBCustData *pCData=NULL;
6536 TLBFuncDesc * pFDesc;
6538 TRACE("(%p) index %d\n", This, indexFunc);
6539 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6540 pFDesc=pFDesc->next)
6542 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6543 pCustData->prgCustData =
6544 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6545 sizeof(CUSTDATAITEM));
6546 if(pCustData->prgCustData ){
6547 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6548 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6549 pCData; i++, pCData = pCData->next){
6550 pCustData->prgCustData[i].guid=pCData->guid;
6551 VariantCopy(& pCustData->prgCustData[i].varValue,
6555 ERR(" OUT OF MEMORY!\n");
6556 return E_OUTOFMEMORY;
6560 return TYPE_E_ELEMENTNOTFOUND;
6563 /* ITypeInfo2::GetAllVarCustData
6565 * Gets all custom data items for the specified Variable
6568 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6569 UINT index, CUSTDATA *pCustData)
6571 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6572 TLBCustData *pCData;
6573 TLBVarDesc * pVDesc;
6575 TRACE("(%p) index %d\n", This, index);
6576 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6577 pVDesc=pVDesc->next)
6580 pCustData->prgCustData =
6581 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6582 if(pCustData->prgCustData ){
6583 pCustData->cCustData=pVDesc->ctCustData;
6584 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6585 pCData = pCData->next){
6586 pCustData->prgCustData[i].guid=pCData->guid;
6587 VariantCopy(& pCustData->prgCustData[i].varValue,
6591 ERR(" OUT OF MEMORY!\n");
6592 return E_OUTOFMEMORY;
6596 return TYPE_E_ELEMENTNOTFOUND;
6599 /* ITypeInfo2::GetAllImplCustData
6601 * Gets all custom data items for the specified implementation type
6604 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6607 CUSTDATA *pCustData)
6609 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6610 TLBCustData *pCData;
6611 TLBImplType * pRDesc;
6613 TRACE("(%p) index %d\n", This, index);
6614 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6615 pRDesc=pRDesc->next)
6618 pCustData->prgCustData =
6619 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6620 if(pCustData->prgCustData ){
6621 pCustData->cCustData=pRDesc->ctCustData;
6622 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6623 pCData = pCData->next){
6624 pCustData->prgCustData[i].guid=pCData->guid;
6625 VariantCopy(& pCustData->prgCustData[i].varValue,
6629 ERR(" OUT OF MEMORY!\n");
6630 return E_OUTOFMEMORY;
6634 return TYPE_E_ELEMENTNOTFOUND;
6637 static const ITypeInfo2Vtbl tinfvt =
6640 ITypeInfo_fnQueryInterface,
6642 ITypeInfo_fnRelease,
6644 ITypeInfo_fnGetTypeAttr,
6645 ITypeInfo_fnGetTypeComp,
6646 ITypeInfo_fnGetFuncDesc,
6647 ITypeInfo_fnGetVarDesc,
6648 ITypeInfo_fnGetNames,
6649 ITypeInfo_fnGetRefTypeOfImplType,
6650 ITypeInfo_fnGetImplTypeFlags,
6651 ITypeInfo_fnGetIDsOfNames,
6653 ITypeInfo_fnGetDocumentation,
6654 ITypeInfo_fnGetDllEntry,
6655 ITypeInfo_fnGetRefTypeInfo,
6656 ITypeInfo_fnAddressOfMember,
6657 ITypeInfo_fnCreateInstance,
6658 ITypeInfo_fnGetMops,
6659 ITypeInfo_fnGetContainingTypeLib,
6660 ITypeInfo_fnReleaseTypeAttr,
6661 ITypeInfo_fnReleaseFuncDesc,
6662 ITypeInfo_fnReleaseVarDesc,
6664 ITypeInfo2_fnGetTypeKind,
6665 ITypeInfo2_fnGetTypeFlags,
6666 ITypeInfo2_fnGetFuncIndexOfMemId,
6667 ITypeInfo2_fnGetVarIndexOfMemId,
6668 ITypeInfo2_fnGetCustData,
6669 ITypeInfo2_fnGetFuncCustData,
6670 ITypeInfo2_fnGetParamCustData,
6671 ITypeInfo2_fnGetVarCustData,
6672 ITypeInfo2_fnGetImplTypeCustData,
6673 ITypeInfo2_fnGetDocumentation2,
6674 ITypeInfo2_fnGetAllCustData,
6675 ITypeInfo2_fnGetAllFuncCustData,
6676 ITypeInfo2_fnGetAllParamCustData,
6677 ITypeInfo2_fnGetAllVarCustData,
6678 ITypeInfo2_fnGetAllImplTypeCustData,
6681 /******************************************************************************
6682 * CreateDispTypeInfo [OLEAUT32.31]
6684 * Build type information for an object so it can be called through an
6685 * IDispatch interface.
6688 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6689 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6692 * This call allows an objects methods to be accessed through IDispatch, by
6693 * building an ITypeInfo object that IDispatch can use to call through.
6695 HRESULT WINAPI CreateDispTypeInfo(
6696 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6697 LCID lcid, /* [I] Locale Id */
6698 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6700 ITypeInfoImpl *pTIClass, *pTIIface;
6701 ITypeLibImpl *pTypeLibImpl;
6703 TLBFuncDesc **ppFuncDesc;
6706 pTypeLibImpl = TypeLibImpl_Constructor();
6707 if (!pTypeLibImpl) return E_FAIL;
6709 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6710 pTIIface->pTypeLib = pTypeLibImpl;
6711 pTIIface->index = 0;
6712 pTIIface->Name = NULL;
6713 pTIIface->dwHelpContext = -1;
6714 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6715 pTIIface->TypeAttr.lcid = lcid;
6716 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6717 pTIIface->TypeAttr.wMajorVerNum = 0;
6718 pTIIface->TypeAttr.wMinorVerNum = 0;
6719 pTIIface->TypeAttr.cbAlignment = 2;
6720 pTIIface->TypeAttr.cbSizeInstance = -1;
6721 pTIIface->TypeAttr.cbSizeVft = -1;
6722 pTIIface->TypeAttr.cFuncs = 0;
6723 pTIIface->TypeAttr.cImplTypes = 0;
6724 pTIIface->TypeAttr.cVars = 0;
6725 pTIIface->TypeAttr.wTypeFlags = 0;
6727 ppFuncDesc = &pTIIface->funclist;
6728 for(func = 0; func < pidata->cMembers; func++) {
6729 METHODDATA *md = pidata->pmethdata + func;
6730 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6731 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6732 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6733 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
6734 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6735 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6736 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6737 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6738 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6739 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6740 (*ppFuncDesc)->funcdesc.cScodes = 0;
6741 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6742 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6743 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6744 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6745 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6746 md->cArgs * sizeof(ELEMDESC));
6747 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6748 md->cArgs * sizeof(TLBParDesc));
6749 for(param = 0; param < md->cArgs; param++) {
6750 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6751 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6753 (*ppFuncDesc)->helpcontext = 0;
6754 (*ppFuncDesc)->HelpStringContext = 0;
6755 (*ppFuncDesc)->HelpString = NULL;
6756 (*ppFuncDesc)->Entry = NULL;
6757 (*ppFuncDesc)->ctCustData = 0;
6758 (*ppFuncDesc)->pCustData = NULL;
6759 (*ppFuncDesc)->next = NULL;
6760 ppFuncDesc = &(*ppFuncDesc)->next;
6763 dump_TypeInfo(pTIIface);
6765 pTypeLibImpl->pTypeInfo = pTIIface;
6766 pTypeLibImpl->TypeInfoCount++;
6768 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6769 pTIClass->pTypeLib = pTypeLibImpl;
6770 pTIClass->index = 1;
6771 pTIClass->Name = NULL;
6772 pTIClass->dwHelpContext = -1;
6773 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6774 pTIClass->TypeAttr.lcid = lcid;
6775 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6776 pTIClass->TypeAttr.wMajorVerNum = 0;
6777 pTIClass->TypeAttr.wMinorVerNum = 0;
6778 pTIClass->TypeAttr.cbAlignment = 2;
6779 pTIClass->TypeAttr.cbSizeInstance = -1;
6780 pTIClass->TypeAttr.cbSizeVft = -1;
6781 pTIClass->TypeAttr.cFuncs = 0;
6782 pTIClass->TypeAttr.cImplTypes = 1;
6783 pTIClass->TypeAttr.cVars = 0;
6784 pTIClass->TypeAttr.wTypeFlags = 0;
6786 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6787 pTIClass->impltypelist->hRef = 1;
6789 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6790 pTIClass->reflist->index = 0;
6791 pTIClass->reflist->reference = 1;
6792 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6794 dump_TypeInfo(pTIClass);
6796 pTIIface->next = pTIClass;
6797 pTypeLibImpl->TypeInfoCount++;
6799 *pptinfo = (ITypeInfo*)pTIClass;
6801 ITypeInfo_AddRef(*pptinfo);
6802 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
6808 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6810 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6812 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6815 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6817 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6819 return ITypeInfo_AddRef((ITypeInfo *)This);
6822 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6824 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6826 return ITypeInfo_Release((ITypeInfo *)This);
6829 static HRESULT WINAPI ITypeComp_fnBind(
6834 ITypeInfo ** ppTInfo,
6835 DESCKIND * pDescKind,
6838 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6839 const TLBFuncDesc *pFDesc;
6840 const TLBVarDesc *pVDesc;
6841 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6843 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6845 *pDescKind = DESCKIND_NONE;
6846 pBindPtr->lpfuncdesc = NULL;
6849 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6850 if (!strcmpiW(pFDesc->Name, szName)) {
6851 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6854 /* name found, but wrong flags */
6855 hr = TYPE_E_TYPEMISMATCH;
6860 HRESULT hr = TLB_AllocAndInitFuncDesc(
6862 &pBindPtr->lpfuncdesc,
6863 This->TypeAttr.typekind == TKIND_DISPATCH);
6866 *pDescKind = DESCKIND_FUNCDESC;
6867 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6868 ITypeInfo_AddRef(*ppTInfo);
6871 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6872 if (!strcmpiW(pVDesc->Name, szName)) {
6873 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6876 *pDescKind = DESCKIND_VARDESC;
6877 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6878 ITypeInfo_AddRef(*ppTInfo);
6883 /* FIXME: search each inherited interface, not just the first */
6884 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6885 /* recursive search */
6889 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6892 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6893 ITypeInfo_Release(pTInfo);
6897 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6898 ITypeComp_Release(pTComp);
6901 WARN("Could not search inherited interface!\n");
6903 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6907 static HRESULT WINAPI ITypeComp_fnBindType(
6911 ITypeInfo ** ppTInfo,
6912 ITypeComp ** ppTComp)
6914 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6916 /* strange behaviour (does nothing) but like the
6919 if (!ppTInfo || !ppTComp)
6928 static const ITypeCompVtbl tcompvt =
6931 ITypeComp_fnQueryInterface,
6933 ITypeComp_fnRelease,
6936 ITypeComp_fnBindType