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 libary. 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 * 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", 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 (*pptfd)->Entry = SysAllocString((WCHAR*)pFuncRec->OptAttr[2]);
1820 (*pptfd)->Entry = MSFT_ReadString(pcx,
1821 pFuncRec->OptAttr[2]);
1823 if( nrattributes > 5 )
1825 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1827 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1830 pFuncRec->OptAttr[6],
1831 &(*pptfd)->pCustData);
1838 /* fill the FuncDesc Structure */
1839 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1840 offset + infolen + ( i + 1) * sizeof(INT));
1842 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1843 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1844 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1845 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1846 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1847 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1848 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1852 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1854 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1856 /* do the parameters/arguments */
1857 if(pFuncRec->nrargs)
1860 MSFT_ParameterInfo paraminfo;
1862 (*pptfd)->funcdesc.lprgelemdescParam =
1863 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1865 (*pptfd)->pParamDesc =
1866 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1868 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1869 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1871 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1873 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1880 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1883 if (paraminfo.oName == -1)
1884 /* this occurs for [propput] or [propget] methods, so
1885 * we should just set the name of the parameter to the
1886 * name of the method. */
1887 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1889 (*pptfd)->pParamDesc[j].Name =
1890 MSFT_ReadName( pcx, paraminfo.oName );
1891 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1893 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1896 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1897 (pFuncRec->FKCCIC & 0x1000) )
1899 INT* pInt = (INT *)((char *)pFuncRec +
1901 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1903 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1905 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1906 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1908 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1912 elemdesc->u.paramdesc.pparamdescex = NULL;
1914 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1917 pFuncRec->OptAttr[7+j],
1918 &(*pptfd)->pParamDesc[j].pCustData);
1921 /* SEEK value = jump to offset,
1922 * from there jump to the end of record,
1923 * go back by (j-1) arguments
1925 MSFT_ReadLEDWords( ¶minfo ,
1926 sizeof(MSFT_ParameterInfo), pcx,
1927 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1928 * sizeof(MSFT_ParameterInfo)));
1932 /* scode is not used: archaic win16 stuff FIXME: right? */
1933 (*pptfd)->funcdesc.cScodes = 0 ;
1934 (*pptfd)->funcdesc.lprgscode = NULL ;
1937 pptfd = & ((*pptfd)->next);
1938 recoffset += reclength;
1940 HeapFree(GetProcessHeap(), 0, recbuf);
1943 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1944 int cVars, int offset, TLBVarDesc ** pptvd)
1946 int infolen, nameoffset, reclength;
1948 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1952 TRACE_(typelib)("\n");
1954 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1955 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1956 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1957 recoffset += offset+sizeof(INT);
1958 for(i=0;i<cVars;i++){
1959 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1960 /* name, eventually add to a hash table */
1961 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1962 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1963 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1964 /* read the variable information record */
1965 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1967 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1969 if(reclength >(6*sizeof(INT)) )
1970 (*pptvd)->HelpContext=pVarRec->HelpContext;
1971 if(reclength >(7*sizeof(INT)) )
1972 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1973 if(reclength >(8*sizeof(INT)) )
1974 if(reclength >(9*sizeof(INT)) )
1975 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1976 /* fill the VarDesc Structure */
1977 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1978 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1979 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1980 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1981 MSFT_GetTdesc(pcx, pVarRec->DataType,
1982 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1983 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1984 if(pVarRec->VarKind == VAR_CONST ){
1985 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1986 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1987 pVarRec->OffsValue, pcx);
1989 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1990 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1991 pptvd=&((*pptvd)->next);
1992 recoffset += reclength;
1995 /* fill in data for a hreftype (offset). When the referenced type is contained
1996 * in the typelib, it's just an (file) offset in the type info base dir.
1997 * If comes from import, it's an offset+1 in the ImpInfo table
1999 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
2003 TLBRefType **ppRefType = &pTI->reflist;
2005 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2008 if((*ppRefType)->reference == offset)
2010 ppRefType = &(*ppRefType)->next;
2013 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2014 sizeof(**ppRefType));
2016 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2017 /* external typelib */
2018 MSFT_ImpInfo impinfo;
2019 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2021 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2023 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2024 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2025 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2026 if(pImpLib->offset==impinfo.oImpFile) break;
2027 pImpLib=pImpLib->next;
2030 (*ppRefType)->reference=offset;
2031 (*ppRefType)->pImpTLInfo = pImpLib;
2032 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2033 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
2034 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
2035 (*ppRefType)->index = TLB_REF_USE_GUID;
2037 (*ppRefType)->index = impinfo.oGuid;
2039 ERR("Cannot find a reference\n");
2040 (*ppRefType)->reference=-1;
2041 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2044 /* in this typelib */
2045 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2046 (*ppRefType)->reference=offset;
2047 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2051 /* process Implemented Interfaces of a com class */
2052 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2056 MSFT_RefRecord refrec;
2057 TLBImplType **ppImpl = &pTI->impltypelist;
2059 TRACE_(typelib)("\n");
2061 for(i=0;i<count;i++){
2062 if(offset<0) break; /* paranoia */
2063 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2064 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2065 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2066 (*ppImpl)->hRef = refrec.reftype;
2067 (*ppImpl)->implflags=refrec.flags;
2068 (*ppImpl)->ctCustData=
2069 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2070 offset=refrec.onext;
2071 ppImpl=&((*ppImpl)->next);
2075 * process a typeinfo record
2077 static ITypeInfoImpl * MSFT_DoTypeInfo(
2081 ITypeLibImpl * pLibInfo)
2083 MSFT_TypeInfoBase tiBase;
2084 ITypeInfoImpl *ptiRet;
2086 TRACE_(typelib)("count=%u\n", count);
2088 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2089 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2090 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2092 /* this is where we are coming from */
2093 ptiRet->pTypeLib = pLibInfo;
2094 ptiRet->index=count;
2095 /* fill in the typeattr fields */
2097 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2098 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2099 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2100 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2101 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2102 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2103 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2104 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2105 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2106 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2107 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2108 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2109 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2110 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2111 MSFT_GetTdesc(pcx, tiBase.datatype1,
2112 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2115 /* IDLDESC idldescType; *//* never saw this one != zero */
2117 /* name, eventually add to a hash table */
2118 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2119 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2120 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2122 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2123 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2124 ptiRet->dwHelpContext=tiBase.helpcontext;
2126 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2127 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2129 /* note: InfoType's Help file and HelpStringDll come from the containing
2130 * library. Further HelpString and Docstring appear to be the same thing :(
2133 if(ptiRet->TypeAttr.cFuncs >0 )
2134 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2135 ptiRet->TypeAttr.cVars,
2136 tiBase.memoffset, & ptiRet->funclist);
2138 if(ptiRet->TypeAttr.cVars >0 )
2139 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2140 ptiRet->TypeAttr.cVars,
2141 tiBase.memoffset, & ptiRet->varlist);
2142 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2143 switch(ptiRet->TypeAttr.typekind)
2146 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2149 case TKIND_DISPATCH:
2150 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2152 if (tiBase.datatype1 != -1)
2154 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2155 ptiRet->impltypelist->hRef = tiBase.datatype1;
2159 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2160 ptiRet->impltypelist->hRef = dispatch_href;
2164 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2165 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2166 ptiRet->impltypelist->hRef = tiBase.datatype1;
2171 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2173 TRACE_(typelib)("%s guid: %s kind:%s\n",
2174 debugstr_w(ptiRet->Name),
2175 debugstr_guid(&ptiRet->TypeAttr.guid),
2176 typekind_desc[ptiRet->TypeAttr.typekind]);
2181 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2182 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2183 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2186 static ITypeLibImpl *tlb_cache_first;
2187 static CRITICAL_SECTION cache_section;
2188 static CRITICAL_SECTION_DEBUG cache_section_debug =
2190 0, 0, &cache_section,
2191 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2192 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2194 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2197 /****************************************************************************
2200 * find the type of the typelib file and map the typelib resource into
2203 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2204 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2205 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2207 ITypeLibImpl *entry;
2208 int ret = TYPE_E_CANTLOADLIBRARY;
2214 lstrcpynW(pszPath, pszFileName, cchPath);
2216 /* first try loading as a dll and access the typelib as a resource */
2217 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2218 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2221 /* it may have been specified with resource index appended to the
2222 * path, so remove it and try again */
2223 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2224 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2226 index = atoiW(pIndexStr);
2227 pszPath[pIndexStr - pszFileName - 1] = '\0';
2229 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2230 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2234 /* get the path to the specified typelib file */
2237 /* otherwise, try loading as a regular file */
2238 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2239 return TYPE_E_CANTLOADLIBRARY;
2242 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2244 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2245 EnterCriticalSection(&cache_section);
2246 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2248 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2250 TRACE("cache hit\n");
2251 *ppTypeLib = (ITypeLib2*)entry;
2252 ITypeLib_AddRef(*ppTypeLib);
2253 LeaveCriticalSection(&cache_section);
2254 FreeLibrary(hinstDLL);
2258 LeaveCriticalSection(&cache_section);
2260 /* now actually load and parse the typelib */
2263 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2264 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2267 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2270 LPVOID pBase = LockResource(hGlobal);
2271 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2275 /* try to load as incore resource */
2276 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2277 if (dwSignature == MSFT_SIGNATURE)
2278 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2279 else if (dwSignature == SLTG_SIGNATURE)
2280 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2282 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2284 FreeResource( hGlobal );
2287 FreeLibrary(hinstDLL);
2291 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2292 if (INVALID_HANDLE_VALUE != hFile)
2294 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2297 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2300 /* retrieve file size */
2301 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2302 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2304 if (dwSignature == MSFT_SIGNATURE)
2305 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2306 else if (dwSignature == SLTG_SIGNATURE)
2307 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2309 UnmapViewOfFile(pBase);
2311 CloseHandle(hMapping);
2318 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2320 TRACE("adding to cache\n");
2321 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2322 lstrcpyW(impl->path, pszPath);
2323 /* We should really canonicalise the path here. */
2324 impl->index = index;
2326 /* FIXME: check if it has added already in the meantime */
2327 EnterCriticalSection(&cache_section);
2328 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2330 tlb_cache_first = impl;
2331 LeaveCriticalSection(&cache_section);
2334 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2339 /*================== ITypeLib(2) Methods ===================================*/
2341 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2343 ITypeLibImpl* pTypeLibImpl;
2345 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2346 if (!pTypeLibImpl) return NULL;
2348 pTypeLibImpl->lpVtbl = &tlbvt;
2349 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2350 pTypeLibImpl->ref = 1;
2352 return pTypeLibImpl;
2355 /****************************************************************************
2356 * ITypeLib2_Constructor_MSFT
2358 * loading an MSFT typelib from an in-memory image
2360 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2364 MSFT_Header tlbHeader;
2365 MSFT_SegDir tlbSegDir;
2366 ITypeLibImpl * pTypeLibImpl;
2368 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2370 pTypeLibImpl = TypeLibImpl_Constructor();
2371 if (!pTypeLibImpl) return NULL;
2373 /* get pointer to beginning of typelib data */
2377 cx.pLibInfo = pTypeLibImpl;
2378 cx.length = dwTLBLength;
2381 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2382 TRACE_(typelib)("header:\n");
2383 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2384 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2385 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2388 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2390 /* there is a small amount of information here until the next important
2392 * the segment directory . Try to calculate the amount of data */
2393 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2395 /* now read the segment directory */
2396 TRACE("read segment directory (at %ld)\n",lPSegDir);
2397 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2398 cx.pTblDir = &tlbSegDir;
2400 /* just check two entries */
2401 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2403 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2404 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2408 /* now fill our internal data */
2409 /* TLIBATTR fields */
2410 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2412 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2413 /* Windows seems to have zero here, is this correct? */
2414 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2415 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2417 pTypeLibImpl->LibAttr.lcid = 0;
2419 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2420 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2421 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2422 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2424 /* name, eventually add to a hash table */
2425 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2428 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2429 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2431 if( tlbHeader.varflags & HELPDLLFLAG)
2434 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2435 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2438 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2441 if(tlbHeader.CustomDataOffset >= 0)
2443 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2446 /* fill in typedescriptions */
2447 if(tlbSegDir.pTypdescTab.length > 0)
2449 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2451 pTypeLibImpl->ctTypeDesc = cTD;
2452 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2453 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2456 /* FIXME: add several sanity checks here */
2457 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2458 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2460 /* FIXME: check safearray */
2462 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2464 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2466 else if(td[0] == VT_CARRAY)
2468 /* array descr table here */
2469 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2471 else if(td[0] == VT_USERDEFINED)
2473 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2475 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2478 /* second time around to fill the array subscript info */
2481 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2482 if(tlbSegDir.pArrayDescriptions.offset>0)
2484 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2485 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2488 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2490 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2492 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2494 for(j = 0; j<td[2]; j++)
2496 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2497 sizeof(INT), &cx, DO_NOT_SEEK);
2498 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2499 sizeof(INT), &cx, DO_NOT_SEEK);
2504 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2505 ERR("didn't find array description data\n");
2510 /* imported type libs */
2511 if(tlbSegDir.pImpFiles.offset>0)
2513 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2514 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2517 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2522 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2523 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2524 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2526 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2527 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2528 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2529 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2532 name = TLB_Alloc(size+1);
2533 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2534 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2535 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2536 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2539 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2540 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2542 ppImpLib = &(*ppImpLib)->next;
2547 if(tlbHeader.nrtypeinfos >= 0 )
2549 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2550 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2553 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2555 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2557 ppTI = &((*ppTI)->next);
2558 (pTypeLibImpl->TypeInfoCount)++;
2562 TRACE("(%p)\n", pTypeLibImpl);
2563 return (ITypeLib2*) pTypeLibImpl;
2567 static BSTR TLB_MultiByteToBSTR(char *ptr)
2573 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2574 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2575 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2576 ret = SysAllocString(nameW);
2577 HeapFree(GetProcessHeap(), 0, nameW);
2581 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2587 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2588 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2592 guid->Data4[0] = s >> 8;
2593 guid->Data4[1] = s & 0xff;
2596 for(i = 0; i < 6; i++) {
2597 memcpy(b, str + 24 + 2 * i, 2);
2598 guid->Data4[i + 2] = strtol(b, NULL, 16);
2603 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2610 bytelen = *(WORD*)ptr;
2611 if(bytelen == 0xffff) return 2;
2612 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2613 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2614 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2615 *pBstr = SysAllocStringLen(nameW, len);
2616 HeapFree(GetProcessHeap(), 0, nameW);
2620 static WORD SLTG_ReadStringA(char *ptr, char **str)
2625 bytelen = *(WORD*)ptr;
2626 if(bytelen == 0xffff) return 2;
2627 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2628 memcpy(*str, ptr + 2, bytelen);
2629 (*str)[bytelen] = '\0';
2633 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2635 char *ptr = pLibBlk;
2638 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2639 FIXME("libblk magic = %04x\n", w);
2644 if((w = *(WORD*)ptr) != 0xffff) {
2645 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2650 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2652 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2654 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2657 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2660 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2661 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2663 pTypeLibImpl->LibAttr.lcid = 0;
2666 ptr += 4; /* skip res12 */
2668 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2671 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2674 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2677 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2678 ptr += sizeof(GUID);
2680 return ptr - (char*)pLibBlk;
2683 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2688 if((*pType & 0xe00) == 0xe00) {
2690 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2692 pTD = pTD->u.lptdesc;
2694 switch(*pType & 0x3f) {
2697 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2699 pTD = pTD->u.lptdesc;
2702 case VT_USERDEFINED:
2703 pTD->vt = VT_USERDEFINED;
2704 pTD->u.hreftype = *(++pType) / 4;
2710 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2713 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2715 pTD->vt = VT_CARRAY;
2716 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2718 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2719 pTD->u.lpadesc->cDims = pSA->cDims;
2720 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2721 pSA->cDims * sizeof(SAFEARRAYBOUND));
2723 pTD = &pTD->u.lpadesc->tdescElem;
2729 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2733 pTD->vt = VT_SAFEARRAY;
2734 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2736 pTD = pTD->u.lptdesc;
2740 pTD->vt = *pType & 0x3f;
2749 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2751 /* Handle [in/out] first */
2752 if((*pType & 0xc000) == 0xc000)
2753 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2754 else if(*pType & 0x8000)
2755 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2756 else if(*pType & 0x4000)
2757 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2759 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2762 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2765 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2767 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2771 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2776 TLBRefType **ppRefType;
2778 if(pRef->magic != SLTG_REF_MAGIC) {
2779 FIXME("Ref magic = %x\n", pRef->magic);
2782 name = ( (char*)(&pRef->names) + pRef->number);
2784 ppRefType = &pTI->reflist;
2785 for(ref = 0; ref < pRef->number >> 3; ref++) {
2787 unsigned int lib_offs, type_num;
2789 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2790 sizeof(**ppRefType));
2792 name += SLTG_ReadStringA(name, &refname);
2793 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2794 FIXME("Can't sscanf ref\n");
2795 if(lib_offs != 0xffff) {
2796 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2799 if((*import)->offset == lib_offs)
2801 import = &(*import)->next;
2804 char fname[MAX_PATH+1];
2807 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2809 (*import)->offset = lib_offs;
2810 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2812 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
2813 &(*import)->wVersionMajor,
2814 &(*import)->wVersionMinor,
2815 &(*import)->lcid, fname) != 4) {
2816 FIXME("can't sscanf ref %s\n",
2817 pNameTable + lib_offs + 40);
2819 len = strlen(fname);
2820 if(fname[len-1] != '#')
2821 FIXME("fname = %s\n", fname);
2822 fname[len-1] = '\0';
2823 (*import)->name = TLB_MultiByteToBSTR(fname);
2825 (*ppRefType)->pImpTLInfo = *import;
2826 } else { /* internal ref */
2827 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2829 (*ppRefType)->reference = ref;
2830 (*ppRefType)->index = type_num;
2832 HeapFree(GetProcessHeap(), 0, refname);
2833 ppRefType = &(*ppRefType)->next;
2835 if((BYTE)*name != SLTG_REF_MAGIC)
2836 FIXME("End of ref block magic = %x\n", *name);
2837 dump_TLBRefType(pTI->reflist);
2840 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2843 SLTG_ImplInfo *info;
2844 TLBImplType **ppImplType = &pTI->impltypelist;
2845 /* I don't really get this structure, usually it's 0x16 bytes
2846 long, but iuser.tlb contains some that are 0x18 bytes long.
2847 That's ok because we can use the next ptr to jump to the next
2848 one. But how do we know the length of the last one? The WORD
2849 at offs 0x8 might be the clue. For now I'm just assuming that
2850 the last one is the regular 0x16 bytes. */
2852 info = (SLTG_ImplInfo*)pBlk;
2854 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2855 sizeof(**ppImplType));
2856 (*ppImplType)->hRef = info->ref;
2857 (*ppImplType)->implflags = info->impltypeflags;
2858 pTI->TypeAttr.cImplTypes++;
2859 ppImplType = &(*ppImplType)->next;
2861 if(info->next == 0xffff)
2864 FIXME("Interface inheriting more than one interface\n");
2865 info = (SLTG_ImplInfo*)(pBlk + info->next);
2867 info++; /* see comment at top of function */
2871 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2873 TLBVarDesc **ppVarDesc = &pTI->varlist;
2874 BSTR bstrPrevName = NULL;
2875 SLTG_Variable *pItem;
2880 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2881 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2883 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2884 sizeof(**ppVarDesc));
2885 (*ppVarDesc)->vardesc.memid = pItem->memid;
2887 if (pItem->magic != SLTG_VAR_MAGIC &&
2888 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2889 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2893 if (pItem->name == 0xfffe)
2894 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2896 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2898 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2899 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
2901 if (pItem->flags & 0x40) {
2902 TRACE_(typelib)("VAR_DISPATCH\n");
2903 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2905 else if (pItem->flags & 0x10) {
2906 TRACE_(typelib)("VAR_CONST\n");
2907 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2908 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2910 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2911 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2912 *(INT*)(pBlk + pItem->byte_offs);
2915 TRACE_(typelib)("VAR_PERINSTANCE\n");
2916 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2917 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2920 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2921 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2923 if (pItem->flags & 0x80)
2924 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2926 if(pItem->flags & 0x02)
2927 pType = &pItem->type;
2929 pType = (WORD*)(pBlk + pItem->type);
2931 if (pItem->flags & ~0xd2)
2932 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2934 SLTG_DoElem(pType, pBlk,
2935 &(*ppVarDesc)->vardesc.elemdescVar);
2937 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2939 bstrPrevName = (*ppVarDesc)->Name;
2940 ppVarDesc = &((*ppVarDesc)->next);
2942 pTI->TypeAttr.cVars = cVars;
2945 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2947 SLTG_Function *pFunc;
2949 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2951 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2952 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2957 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2958 sizeof(**ppFuncDesc));
2960 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2961 case SLTG_FUNCTION_MAGIC:
2962 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2964 case SLTG_DISPATCH_FUNCTION_MAGIC:
2965 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2967 case SLTG_STATIC_FUNCTION_MAGIC:
2968 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2971 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2972 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2976 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2978 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2979 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2980 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2981 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2982 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2983 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2985 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2986 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2988 if(pFunc->retnextopt & 0x80)
2989 pType = &pFunc->rettype;
2991 pType = (WORD*)(pBlk + pFunc->rettype);
2993 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2995 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2996 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2997 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2998 (*ppFuncDesc)->pParamDesc =
2999 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3000 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3002 pArg = (WORD*)(pBlk + pFunc->arg_off);
3004 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3005 char *paramName = pNameTable + *pArg;
3007 /* If arg type follows then paramName points to the 2nd
3008 letter of the name, else the next WORD is an offset to
3009 the arg type and paramName points to the first letter.
3010 So let's take one char off paramName and see if we're
3011 pointing at an alpha-numeric char. However if *pArg is
3012 0xffff or 0xfffe then the param has no name, the former
3013 meaning that the next WORD is the type, the latter
3014 meaning the the next WORD is an offset to the type. */
3019 else if(*pArg == 0xfffe) {
3023 else if(paramName[-1] && !isalnum(paramName[-1]))
3028 if(HaveOffs) { /* the next word is an offset to type */
3029 pType = (WORD*)(pBlk + *pArg);
3030 SLTG_DoElem(pType, pBlk,
3031 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3036 pArg = SLTG_DoElem(pArg, pBlk,
3037 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
3040 /* Are we an optional param ? */
3041 if((*ppFuncDesc)->funcdesc.cParams - param <=
3042 (*ppFuncDesc)->funcdesc.cParamsOpt)
3043 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3046 (*ppFuncDesc)->pParamDesc[param].Name =
3047 TLB_MultiByteToBSTR(paramName);
3051 ppFuncDesc = &((*ppFuncDesc)->next);
3052 if(pFunc->next == 0xffff) break;
3054 pTI->TypeAttr.cFuncs = cFuncs;
3057 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3058 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3059 SLTG_TypeInfoTail *pTITail)
3061 char *pFirstItem, *pNextItem;
3063 if(pTIHeader->href_table != 0xffffffff) {
3064 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3068 pFirstItem = pNextItem = pBlk;
3070 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3071 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3076 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3077 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3078 SLTG_TypeInfoTail *pTITail)
3080 char *pFirstItem, *pNextItem;
3082 if(pTIHeader->href_table != 0xffffffff) {
3083 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3087 pFirstItem = pNextItem = pBlk;
3089 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3090 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3093 if (pTITail->funcs_off != 0xffff)
3094 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3096 if (TRACE_ON(typelib))
3097 dump_TLBFuncDesc(pTI->funclist);
3100 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3101 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3102 SLTG_TypeInfoTail *pTITail)
3104 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3107 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3108 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3109 SLTG_TypeInfoTail *pTITail)
3113 if (pTITail->simple_alias) {
3114 /* if simple alias, no more processing required */
3115 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3119 if(pTIHeader->href_table != 0xffffffff) {
3120 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3124 /* otherwise it is an offset to a type */
3125 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3127 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3130 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3131 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3132 SLTG_TypeInfoTail *pTITail)
3134 if (pTIHeader->href_table != 0xffffffff)
3135 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3138 if (pTITail->vars_off != 0xffff)
3139 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3141 if (pTITail->funcs_off != 0xffff)
3142 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3144 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3145 * of dispinterface functons including the IDispatch ones, so
3146 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3147 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3149 if (TRACE_ON(typelib))
3150 dump_TLBFuncDesc(pTI->funclist);
3153 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3154 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3155 SLTG_TypeInfoTail *pTITail)
3157 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3160 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3161 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3162 SLTG_TypeInfoTail *pTITail)
3164 if (pTIHeader->href_table != 0xffffffff)
3165 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3168 if (pTITail->vars_off != 0xffff)
3169 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3171 if (pTITail->funcs_off != 0xffff)
3172 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3175 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3176 managable copy of it into this */
3189 } SLTG_InternalOtherTypeInfo;
3191 /****************************************************************************
3192 * ITypeLib2_Constructor_SLTG
3194 * loading a SLTG typelib from an in-memory image
3196 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3198 ITypeLibImpl *pTypeLibImpl;
3199 SLTG_Header *pHeader;
3200 SLTG_BlkEntry *pBlkEntry;
3204 LPVOID pBlk, pFirstBlk;
3205 SLTG_LibBlk *pLibBlk;
3206 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3207 char *pAfterOTIBlks = NULL;
3208 char *pNameTable, *ptr;
3211 ITypeInfoImpl **ppTypeInfoImpl;
3213 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3216 pTypeLibImpl = TypeLibImpl_Constructor();
3217 if (!pTypeLibImpl) return NULL;
3221 TRACE_(typelib)("header:\n");
3222 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3223 pHeader->nrOfFileBlks );
3224 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3225 FIXME("Header type magic 0x%08x not supported.\n",
3226 pHeader->SLTG_magic);
3230 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3231 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3233 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3234 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3236 /* Next we have a magic block */
3237 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3239 /* Let's see if we're still in sync */
3240 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3241 sizeof(SLTG_COMPOBJ_MAGIC))) {
3242 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3245 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3246 sizeof(SLTG_DIR_MAGIC))) {
3247 FIXME("dir magic = %s\n", pMagic->dir_magic);
3251 pIndex = (SLTG_Index*)(pMagic+1);
3253 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3255 pFirstBlk = (LPVOID)(pPad9 + 1);
3257 /* We'll set up a ptr to the main library block, which is the last one. */
3259 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3260 pBlkEntry[order].next != 0;
3261 order = pBlkEntry[order].next - 1, i++) {
3262 pBlk = (char*)pBlk + pBlkEntry[order].len;
3266 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3268 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3273 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3275 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3276 sizeof(*pOtherTypeInfoBlks) *
3277 pTypeLibImpl->TypeInfoCount);
3280 ptr = (char*)pLibBlk + len;
3282 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3286 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3288 w = *(WORD*)(ptr + 2);
3291 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3293 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3294 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3296 w = *(WORD*)(ptr + 4 + len);
3298 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3300 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3302 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3303 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3305 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3306 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3307 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3309 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3311 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3314 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3315 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3316 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3317 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3318 len += sizeof(SLTG_OtherTypeInfo);
3322 pAfterOTIBlks = ptr;
3324 /* Skip this WORD and get the next DWORD */
3325 len = *(DWORD*)(pAfterOTIBlks + 2);
3327 /* Now add this to pLibBLk look at what we're pointing at and
3328 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3329 dust and we should be pointing at the beginning of the name
3332 pNameTable = (char*)pLibBlk + len;
3334 switch(*(WORD*)pNameTable) {
3341 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3345 pNameTable += 0x216;
3349 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3351 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3354 /* Hopefully we now have enough ptrs set up to actually read in
3355 some TypeInfos. It's not clear which order to do them in, so
3356 I'll just follow the links along the BlkEntry chain and read
3357 them in the order in which they are in the file */
3359 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3361 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3362 pBlkEntry[order].next != 0;
3363 order = pBlkEntry[order].next - 1, i++) {
3365 SLTG_TypeInfoHeader *pTIHeader;
3366 SLTG_TypeInfoTail *pTITail;
3367 SLTG_MemberHeader *pMemHeader;
3369 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3370 pOtherTypeInfoBlks[i].index_name)) {
3371 FIXME("Index strings don't match\n");
3376 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3377 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3380 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3381 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3383 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3384 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3385 (*ppTypeInfoImpl)->index = i;
3386 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3387 pOtherTypeInfoBlks[i].name_offs +
3389 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3390 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3392 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3393 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3394 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3395 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3396 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3398 if((pTIHeader->typeflags1 & 7) != 2)
3399 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3400 if(pTIHeader->typeflags3 != 2)
3401 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3403 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3404 debugstr_w((*ppTypeInfoImpl)->Name),
3405 typekind_desc[pTIHeader->typekind],
3406 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3407 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3409 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3411 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3413 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3414 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3415 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3417 switch(pTIHeader->typekind) {
3419 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3420 pTIHeader, pTITail);
3424 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3425 pTIHeader, pTITail);
3428 case TKIND_INTERFACE:
3429 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3430 pTIHeader, pTITail);
3434 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3435 pTIHeader, pTITail);
3439 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3440 pTIHeader, pTITail);
3443 case TKIND_DISPATCH:
3444 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3445 pTIHeader, pTITail);
3449 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3450 pTIHeader, pTITail);
3454 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3459 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3460 but we've already set those */
3461 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3476 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3477 pBlk = (char*)pBlk + pBlkEntry[order].len;
3480 if(i != pTypeLibImpl->TypeInfoCount) {
3481 FIXME("Somehow processed %d TypeInfos\n", i);
3485 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3486 return (ITypeLib2*)pTypeLibImpl;
3489 /* ITypeLib::QueryInterface
3491 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3496 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3498 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3501 if(IsEqualIID(riid, &IID_IUnknown) ||
3502 IsEqualIID(riid,&IID_ITypeLib)||
3503 IsEqualIID(riid,&IID_ITypeLib2))
3510 ITypeLib2_AddRef(iface);
3511 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3514 TRACE("-- Interface: E_NOINTERFACE\n");
3515 return E_NOINTERFACE;
3520 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3522 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3523 ULONG ref = InterlockedIncrement(&This->ref);
3525 TRACE("(%p)->ref was %u\n",This, ref - 1);
3530 /* ITypeLib::Release
3532 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3534 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3535 ULONG ref = InterlockedDecrement(&This->ref);
3537 TRACE("(%p)->(%u)\n",This, ref);
3541 TLBImpLib *pImpLib, *pImpLibNext;
3542 TLBCustData *pCustData, *pCustDataNext;
3545 /* remove cache entry */
3548 TRACE("removing from cache list\n");
3549 EnterCriticalSection(&cache_section);
3550 if (This->next) This->next->prev = This->prev;
3551 if (This->prev) This->prev->next = This->next;
3552 else tlb_cache_first = This->next;
3553 LeaveCriticalSection(&cache_section);
3554 HeapFree(GetProcessHeap(), 0, This->path);
3556 TRACE(" destroying ITypeLib(%p)\n",This);
3560 SysFreeString(This->Name);
3564 if (This->DocString)
3566 SysFreeString(This->DocString);
3567 This->DocString = NULL;
3572 SysFreeString(This->HelpFile);
3573 This->HelpFile = NULL;
3576 if (This->HelpStringDll)
3578 SysFreeString(This->HelpStringDll);
3579 This->HelpStringDll = NULL;
3582 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3584 VariantClear(&pCustData->data);
3586 pCustDataNext = pCustData->next;
3587 TLB_Free(pCustData);
3590 for (i = 0; i < This->ctTypeDesc; i++)
3591 if (This->pTypeDesc[i].vt == VT_CARRAY)
3592 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3594 TLB_Free(This->pTypeDesc);
3596 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3598 if (pImpLib->pImpTypeLib)
3599 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3600 TLB_Free(pImpLib->name);
3602 pImpLibNext = pImpLib->next;
3606 if (This->pTypeInfo) /* can be NULL */
3607 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3608 HeapFree(GetProcessHeap(),0,This);
3615 /* ITypeLib::GetTypeInfoCount
3617 * Returns the number of type descriptions in the type library
3619 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3621 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3622 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3623 return This->TypeInfoCount;
3626 /* ITypeLib::GetTypeInfo
3628 * retrieves the specified type description in the library.
3630 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3633 ITypeInfo **ppTInfo)
3637 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3638 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3640 TRACE("(%p)->(index=%d)\n", This, index);
3642 if (!ppTInfo) return E_INVALIDARG;
3644 /* search element n in list */
3645 for(i=0; i < index; i++)
3647 pTypeInfo = pTypeInfo->next;
3650 TRACE("-- element not found\n");
3651 return TYPE_E_ELEMENTNOTFOUND;
3655 *ppTInfo = (ITypeInfo *) pTypeInfo;
3657 ITypeInfo_AddRef(*ppTInfo);
3658 TRACE("-- found (%p)\n",*ppTInfo);
3663 /* ITypeLibs::GetTypeInfoType
3665 * Retrieves the type of a type description.
3667 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3672 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3674 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3676 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3677 return TYPE_E_ELEMENTNOTFOUND;
3679 TRACE("(%p) index %d\n", This, index);
3681 if(!pTKind) return E_INVALIDARG;
3683 /* search element n in list */
3684 for(i=0; i < index; i++)
3688 TRACE("-- element not found\n");
3689 return TYPE_E_ELEMENTNOTFOUND;
3691 pTInfo = pTInfo->next;
3694 *pTKind = pTInfo->TypeAttr.typekind;
3695 TRACE("-- found Type (%d)\n", *pTKind);
3699 /* ITypeLib::GetTypeInfoOfGuid
3701 * Retrieves the type description that corresponds to the specified GUID.
3704 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3707 ITypeInfo **ppTInfo)
3709 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3710 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3712 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3716 WARN("-- element not found\n");
3717 return TYPE_E_ELEMENTNOTFOUND;
3720 /* search linked list for guid */
3721 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3723 pTypeInfo = pTypeInfo->next;
3727 /* end of list reached */
3728 WARN("-- element not found\n");
3729 return TYPE_E_ELEMENTNOTFOUND;
3733 TRACE("-- found (%p, %s)\n",
3735 debugstr_w(pTypeInfo->Name));
3737 *ppTInfo = (ITypeInfo*)pTypeInfo;
3738 ITypeInfo_AddRef(*ppTInfo);
3742 /* ITypeLib::GetLibAttr
3744 * Retrieves the structure that contains the library's attributes.
3747 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3749 LPTLIBATTR *ppTLibAttr)
3751 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3752 TRACE("(%p)\n",This);
3753 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3754 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3758 /* ITypeLib::GetTypeComp
3760 * Enables a client compiler to bind to a library's types, variables,
3761 * constants, and global functions.
3764 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3766 ITypeComp **ppTComp)
3768 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3770 TRACE("(%p)->(%p)\n",This,ppTComp);
3771 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3772 ITypeComp_AddRef(*ppTComp);
3777 /* ITypeLib::GetDocumentation
3779 * Retrieves the library's documentation string, the complete Help file name
3780 * and path, and the context identifier for the library Help topic in the Help
3783 * On a successful return all non-null BSTR pointers will have been set,
3786 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3790 BSTR *pBstrDocString,
3791 DWORD *pdwHelpContext,
3792 BSTR *pBstrHelpFile)
3794 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3796 HRESULT result = E_INVALIDARG;
3801 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3803 pBstrName, pBstrDocString,
3804 pdwHelpContext, pBstrHelpFile);
3808 /* documentation for the typelib */
3813 if(!(*pBstrName = SysAllocString(This->Name)))
3821 if (This->DocString)
3823 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3826 else if (This->Name)
3828 if(!(*pBstrDocString = SysAllocString(This->Name)))
3832 *pBstrDocString = NULL;
3836 *pdwHelpContext = This->dwHelpContext;
3842 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3846 *pBstrHelpFile = NULL;
3853 /* for a typeinfo */
3854 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3856 if(SUCCEEDED(result))
3858 result = ITypeInfo_GetDocumentation(pTInfo,
3862 pdwHelpContext, pBstrHelpFile);
3864 ITypeInfo_Release(pTInfo);
3869 if (pBstrDocString) SysFreeString (*pBstrDocString);
3871 if (pBstrName) SysFreeString (*pBstrName);
3873 return STG_E_INSUFFICIENTMEMORY;
3878 * Indicates whether a passed-in string contains the name of a type or member
3879 * described in the library.
3882 static HRESULT WINAPI ITypeLib2_fnIsName(
3888 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3889 ITypeInfoImpl *pTInfo;
3890 TLBFuncDesc *pFInfo;
3893 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3895 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3899 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3900 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3901 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3902 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3903 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3904 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3905 goto ITypeLib2_fnIsName_exit;
3907 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3908 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3913 ITypeLib2_fnIsName_exit:
3914 TRACE("(%p)slow! search for %s: %s found!\n", This,
3915 debugstr_w(szNameBuf), *pfName?"NOT":"");
3920 /* ITypeLib::FindName
3922 * Finds occurrences of a type description in a type library. This may be used
3923 * to quickly verify that a name exists in a type library.
3926 static HRESULT WINAPI ITypeLib2_fnFindName(
3930 ITypeInfo **ppTInfo,
3934 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3935 ITypeInfoImpl *pTInfo;
3936 TLBFuncDesc *pFInfo;
3939 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3941 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3942 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3943 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3944 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3945 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3946 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3947 goto ITypeLib2_fnFindName_exit;
3950 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3951 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3953 ITypeLib2_fnFindName_exit:
3954 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3955 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3958 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3959 This, *pcFound, debugstr_w(szNameBuf), j);
3966 /* ITypeLib::ReleaseTLibAttr
3968 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3971 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3973 TLIBATTR *pTLibAttr)
3975 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3976 TRACE("freeing (%p)\n",This);
3977 HeapFree(GetProcessHeap(),0,pTLibAttr);
3981 /* ITypeLib2::GetCustData
3983 * gets the custom data
3985 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3990 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3991 TLBCustData *pCData;
3993 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3995 if( IsEqualIID(guid, &pCData->guid)) break;
3998 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4002 VariantInit( pVarVal);
4003 VariantCopy( pVarVal, &pCData->data);
4006 return E_INVALIDARG; /* FIXME: correct? */
4009 /* ITypeLib2::GetLibStatistics
4011 * Returns statistics about a type library that are required for efficient
4012 * sizing of hash tables.
4015 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4017 ULONG *pcUniqueNames,
4018 ULONG *pcchUniqueNames)
4020 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4022 FIXME("(%p): stub!\n", This);
4024 if(pcUniqueNames) *pcUniqueNames=1;
4025 if(pcchUniqueNames) *pcchUniqueNames=1;
4029 /* ITypeLib2::GetDocumentation2
4031 * Retrieves the library's documentation string, the complete Help file name
4032 * and path, the localization context to use, and the context ID for the
4033 * library Help topic in the Help file.
4036 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4040 BSTR *pbstrHelpString,
4041 DWORD *pdwHelpStringContext,
4042 BSTR *pbstrHelpStringDll)
4044 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4048 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4050 /* the help string should be obtained from the helpstringdll,
4051 * using the _DLLGetDocumentation function, based on the supplied
4052 * lcid. Nice to do sometime...
4056 /* documentation for the typelib */
4058 *pbstrHelpString=SysAllocString(This->DocString);
4059 if(pdwHelpStringContext)
4060 *pdwHelpStringContext=This->dwHelpContext;
4061 if(pbstrHelpStringDll)
4062 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4068 /* for a typeinfo */
4069 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4071 if(SUCCEEDED(result))
4073 ITypeInfo2 * pTInfo2;
4074 result = ITypeInfo_QueryInterface(pTInfo,
4076 (LPVOID*) &pTInfo2);
4078 if(SUCCEEDED(result))
4080 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4084 pdwHelpStringContext,
4085 pbstrHelpStringDll);
4087 ITypeInfo2_Release(pTInfo2);
4090 ITypeInfo_Release(pTInfo);
4096 /* ITypeLib2::GetAllCustData
4098 * Gets all custom data items for the library.
4101 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4103 CUSTDATA *pCustData)
4105 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4106 TLBCustData *pCData;
4108 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4109 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4110 if(pCustData->prgCustData ){
4111 pCustData->cCustData=This->ctCustData;
4112 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4113 pCustData->prgCustData[i].guid=pCData->guid;
4114 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4117 ERR(" OUT OF MEMORY!\n");
4118 return E_OUTOFMEMORY;
4123 static const ITypeLib2Vtbl tlbvt = {
4124 ITypeLib2_fnQueryInterface,
4126 ITypeLib2_fnRelease,
4127 ITypeLib2_fnGetTypeInfoCount,
4128 ITypeLib2_fnGetTypeInfo,
4129 ITypeLib2_fnGetTypeInfoType,
4130 ITypeLib2_fnGetTypeInfoOfGuid,
4131 ITypeLib2_fnGetLibAttr,
4132 ITypeLib2_fnGetTypeComp,
4133 ITypeLib2_fnGetDocumentation,
4135 ITypeLib2_fnFindName,
4136 ITypeLib2_fnReleaseTLibAttr,
4138 ITypeLib2_fnGetCustData,
4139 ITypeLib2_fnGetLibStatistics,
4140 ITypeLib2_fnGetDocumentation2,
4141 ITypeLib2_fnGetAllCustData
4145 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4147 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4149 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4152 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4154 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4156 return ITypeLib2_AddRef((ITypeLib2 *)This);
4159 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4161 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4163 return ITypeLib2_Release((ITypeLib2 *)This);
4166 static HRESULT WINAPI ITypeLibComp_fnBind(
4171 ITypeInfo ** ppTInfo,
4172 DESCKIND * pDescKind,
4175 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4176 ITypeInfoImpl *pTypeInfo;
4178 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4180 *pDescKind = DESCKIND_NONE;
4181 pBindPtr->lptcomp = NULL;
4184 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4186 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4188 /* FIXME: check wFlags here? */
4189 /* FIXME: we should use a hash table to look this info up using lHash
4190 * instead of an O(n) search */
4191 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4192 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4194 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4196 *pDescKind = DESCKIND_TYPECOMP;
4197 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4198 ITypeComp_AddRef(pBindPtr->lptcomp);
4199 TRACE("module or enum: %s\n", debugstr_w(szName));
4204 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4205 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4207 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4210 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4211 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4213 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4218 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4219 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4221 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4223 ITypeInfo *subtypeinfo;
4225 DESCKIND subdesckind;
4227 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4228 &subtypeinfo, &subdesckind, &subbindptr);
4229 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4231 TYPEDESC tdesc_appobject =
4234 (TYPEDESC *)pTypeInfo->hreftype
4238 const VARDESC vardesc_appobject =
4241 NULL, /* lpstrSchema */
4256 VAR_STATIC /* varkind */
4259 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4261 /* cleanup things filled in by Bind call so we can put our
4262 * application object data in there instead */
4263 switch (subdesckind)
4265 case DESCKIND_FUNCDESC:
4266 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4268 case DESCKIND_VARDESC:
4269 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4274 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4276 if (pTypeInfo->hreftype == -1)
4277 FIXME("no hreftype for interface %p\n", pTypeInfo);
4279 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4283 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4284 *ppTInfo = (ITypeInfo *)pTypeInfo;
4285 ITypeInfo_AddRef(*ppTInfo);
4291 TRACE("name not found %s\n", debugstr_w(szName));
4295 static HRESULT WINAPI ITypeLibComp_fnBindType(
4299 ITypeInfo ** ppTInfo,
4300 ITypeComp ** ppTComp)
4302 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4306 static const ITypeCompVtbl tlbtcvt =
4309 ITypeLibComp_fnQueryInterface,
4310 ITypeLibComp_fnAddRef,
4311 ITypeLibComp_fnRelease,
4313 ITypeLibComp_fnBind,
4314 ITypeLibComp_fnBindType
4317 /*================== ITypeInfo(2) Methods ===================================*/
4318 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4320 ITypeInfoImpl * pTypeInfoImpl;
4322 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4325 pTypeInfoImpl->lpVtbl = &tinfvt;
4326 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4327 pTypeInfoImpl->ref=1;
4328 pTypeInfoImpl->hreftype = -1;
4329 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4330 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4332 TRACE("(%p)\n", pTypeInfoImpl);
4333 return (ITypeInfo2*) pTypeInfoImpl;
4336 /* ITypeInfo::QueryInterface
4338 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4343 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4345 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4348 if(IsEqualIID(riid, &IID_IUnknown) ||
4349 IsEqualIID(riid,&IID_ITypeInfo)||
4350 IsEqualIID(riid,&IID_ITypeInfo2))
4354 ITypeInfo_AddRef(iface);
4355 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4358 TRACE("-- Interface: E_NOINTERFACE\n");
4359 return E_NOINTERFACE;
4362 /* ITypeInfo::AddRef
4364 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4366 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4367 ULONG ref = InterlockedIncrement(&This->ref);
4369 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4371 TRACE("(%p)->ref is %u\n",This, ref);
4375 /* ITypeInfo::Release
4377 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4379 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4380 ULONG ref = InterlockedDecrement(&This->ref);
4382 TRACE("(%p)->(%u)\n",This, ref);
4385 /* We don't release ITypeLib when ref=0 because
4386 it means that function is called by ITypeLib2_Release */
4387 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4389 TLBFuncDesc *pFInfo, *pFInfoNext;
4390 TLBVarDesc *pVInfo, *pVInfoNext;
4391 TLBImplType *pImpl, *pImplNext;
4392 TLBRefType *pRefType,*pRefTypeNext;
4393 TLBCustData *pCustData, *pCustDataNext;
4395 TRACE("destroying ITypeInfo(%p)\n",This);
4397 if (This->no_free_data)
4402 SysFreeString(This->Name);
4406 if (This->DocString)
4408 SysFreeString(This->DocString);
4409 This->DocString = 0;
4414 SysFreeString(This->DllName);
4418 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4421 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4423 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4424 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4426 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4427 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4429 SysFreeString(pFInfo->pParamDesc[i].Name);
4431 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4432 TLB_Free(pFInfo->pParamDesc);
4433 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4435 VariantClear(&pCustData->data);
4437 pCustDataNext = pCustData->next;
4438 TLB_Free(pCustData);
4440 SysFreeString(pFInfo->Entry);
4441 SysFreeString(pFInfo->HelpString);
4442 SysFreeString(pFInfo->Name);
4444 pFInfoNext = pFInfo->next;
4447 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4449 if (pVInfo->vardesc.varkind == VAR_CONST)
4451 VariantClear(pVInfo->vardesc.u.lpvarValue);
4452 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4454 SysFreeString(pVInfo->Name);
4455 pVInfoNext = pVInfo->next;
4458 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4460 for (pCustData = pImpl->pCustData; pCustData; pCustData = pCustDataNext)
4462 VariantClear(&pCustData->data);
4464 pCustDataNext = pCustData->next;
4465 TLB_Free(pCustData);
4467 pImplNext = pImpl->next;
4470 for(pRefType = This->reflist; pRefType; pRefType = pRefTypeNext)
4472 pRefTypeNext = pRefType->next;
4475 TLB_Free(This->pCustData);
4480 ITypeInfo_Release((ITypeInfo*)This->next);
4483 HeapFree(GetProcessHeap(),0,This);
4489 /* ITypeInfo::GetTypeAttr
4491 * Retrieves a TYPEATTR structure that contains the attributes of the type
4495 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4496 LPTYPEATTR *ppTypeAttr)
4498 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4501 TRACE("(%p)\n",This);
4503 size = sizeof(**ppTypeAttr);
4504 if (This->TypeAttr.typekind == TKIND_ALIAS)
4505 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4507 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4509 return E_OUTOFMEMORY;
4511 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4513 if (This->TypeAttr.typekind == TKIND_ALIAS)
4514 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4515 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4517 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4518 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4520 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4521 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4526 /* ITypeInfo::GetTypeComp
4528 * Retrieves the ITypeComp interface for the type description, which enables a
4529 * client compiler to bind to the type description's members.
4532 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4533 ITypeComp * *ppTComp)
4535 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4537 TRACE("(%p)->(%p)\n", This, ppTComp);
4539 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4540 ITypeComp_AddRef(*ppTComp);
4544 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4546 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4547 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4548 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4552 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4554 memcpy(dest, src, sizeof(ELEMDESC));
4555 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4556 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4558 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4559 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4560 *buffer += sizeof(PARAMDESCEX);
4561 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4562 VariantInit(&pparamdescex_dest->varDefaultValue);
4563 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4564 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4567 dest->u.paramdesc.pparamdescex = NULL;
4571 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4573 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4574 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4577 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4581 SIZE_T size = sizeof(*src);
4585 size += sizeof(*src->lprgscode) * src->cScodes;
4586 size += TLB_SizeElemDesc(&src->elemdescFunc);
4587 for (i = 0; i < src->cParams; i++)
4589 size += sizeof(ELEMDESC);
4590 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4593 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4594 if (!dest) return E_OUTOFMEMORY;
4596 memcpy(dest, src, sizeof(FUNCDESC));
4597 buffer = (char *)(dest + 1);
4599 dest->lprgscode = (SCODE *)buffer;
4600 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4601 buffer += sizeof(*src->lprgscode) * src->cScodes;
4603 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4606 SysFreeString((BSTR)dest);
4610 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4611 buffer += sizeof(ELEMDESC) * src->cParams;
4612 for (i = 0; i < src->cParams; i++)
4614 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4620 /* undo the above actions */
4621 for (i = i - 1; i >= 0; i--)
4622 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4623 TLB_FreeElemDesc(&dest->elemdescFunc);
4624 SysFreeString((BSTR)dest);
4628 /* special treatment for dispinterfaces: this makes functions appear
4629 * to return their [retval] value when it is really returning an
4631 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4633 if (dest->cParams &&
4634 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4636 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4637 if (elemdesc->tdesc.vt != VT_PTR)
4639 ERR("elemdesc should have started with VT_PTR instead of:\n");
4641 dump_ELEMDESC(elemdesc);
4642 return E_UNEXPECTED;
4645 /* copy last parameter to the return value. we are using a flat
4646 * buffer so there is no danger of leaking memory in
4648 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4650 /* remove the last parameter */
4654 /* otherwise this function is made to appear to have no return
4656 dest->elemdescFunc.tdesc.vt = VT_VOID;
4664 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4666 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4667 const TLBFuncDesc *pFDesc;
4670 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4675 *ppFuncDesc = &pFDesc->funcdesc;
4679 return E_INVALIDARG;
4682 /* internal function to make the inherited interfaces' methods appear
4683 * part of the interface */
4684 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4685 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs)
4687 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4690 UINT implemented_funcs = 0;
4695 for (i = 0; i < This->TypeAttr.cImplTypes; i++)
4698 ITypeInfo *pSubTypeInfo;
4701 hr = ITypeInfo_GetRefTypeOfImplType(iface, i, &href);
4704 hr = ITypeInfo_GetRefTypeInfo(iface, href, &pSubTypeInfo);
4708 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4712 implemented_funcs += sub_funcs;
4713 ITypeInfo_Release(pSubTypeInfo);
4719 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4721 if (index < implemented_funcs)
4722 return E_INVALIDARG;
4723 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4727 /* ITypeInfo::GetFuncDesc
4729 * Retrieves the FUNCDESC structure that contains information about a
4730 * specified function.
4733 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4734 LPFUNCDESC *ppFuncDesc)
4736 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4737 const FUNCDESC *internal_funcdesc;
4740 TRACE("(%p) index %d\n", This, index);
4742 if ((This->TypeAttr.typekind == TKIND_DISPATCH) &&
4743 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4744 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4745 &internal_funcdesc, NULL);
4747 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4748 &internal_funcdesc);
4751 WARN("description for function %d not found\n", index);
4755 return TLB_AllocAndInitFuncDesc(
4758 This->TypeAttr.typekind == TKIND_DISPATCH);
4761 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4765 SIZE_T size = sizeof(*src);
4768 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4769 if (src->varkind == VAR_CONST)
4770 size += sizeof(VARIANT);
4771 size += TLB_SizeElemDesc(&src->elemdescVar);
4773 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4774 if (!dest) return E_OUTOFMEMORY;
4777 buffer = (char *)(dest + 1);
4778 if (src->lpstrSchema)
4781 dest->lpstrSchema = (LPOLESTR)buffer;
4782 len = strlenW(src->lpstrSchema);
4783 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4784 buffer += (len + 1) * sizeof(WCHAR);
4787 if (src->varkind == VAR_CONST)
4791 dest->u.lpvarValue = (VARIANT *)buffer;
4792 *dest->u.lpvarValue = *src->u.lpvarValue;
4793 buffer += sizeof(VARIANT);
4794 VariantInit(dest->u.lpvarValue);
4795 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4798 SysFreeString((BSTR)dest_ptr);
4802 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4805 if (src->varkind == VAR_CONST)
4806 VariantClear(dest->u.lpvarValue);
4807 SysFreeString((BSTR)dest);
4814 /* ITypeInfo::GetVarDesc
4816 * Retrieves a VARDESC structure that describes the specified variable.
4819 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4820 LPVARDESC *ppVarDesc)
4822 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4824 const TLBVarDesc *pVDesc;
4826 TRACE("(%p) index %d\n", This, index);
4828 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4832 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4834 return E_INVALIDARG;
4837 /* ITypeInfo_GetNames
4839 * Retrieves the variable with the specified member ID (or the name of the
4840 * property or method and its parameters) that correspond to the specified
4843 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4844 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4846 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4847 const TLBFuncDesc *pFDesc;
4848 const TLBVarDesc *pVDesc;
4850 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
4851 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4854 /* function found, now return function and parameter names */
4855 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4858 *rgBstrNames=SysAllocString(pFDesc->Name);
4860 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4866 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4869 *rgBstrNames=SysAllocString(pVDesc->Name);
4874 if(This->TypeAttr.cImplTypes &&
4875 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4876 /* recursive search */
4879 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4881 if(SUCCEEDED(result))
4883 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4884 ITypeInfo_Release(pTInfo);
4887 WARN("Could not search inherited interface!\n");
4891 WARN("no names found\n");
4894 return TYPE_E_ELEMENTNOTFOUND;
4901 /* ITypeInfo::GetRefTypeOfImplType
4903 * If a type description describes a COM class, it retrieves the type
4904 * description of the implemented interface types. For an interface,
4905 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4909 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4914 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4917 const TLBImplType *pImpl = This->impltypelist;
4919 TRACE("(%p) index %d\n", This, index);
4920 if (TRACE_ON(ole)) dump_TypeInfo(This);
4924 /* only valid on dual interfaces;
4925 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4927 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4929 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4930 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4936 hr = TYPE_E_ELEMENTNOTFOUND;
4941 /* get element n from linked list */
4942 for(i=0; pImpl && i<index; i++)
4944 pImpl = pImpl->next;
4948 *pRefType = pImpl->hRef;
4950 hr = TYPE_E_ELEMENTNOTFOUND;
4956 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
4958 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
4964 /* ITypeInfo::GetImplTypeFlags
4966 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4967 * or base interface in a type description.
4969 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4970 UINT index, INT *pImplTypeFlags)
4972 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4976 TRACE("(%p) index %d\n", This, index);
4977 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4978 i++, pImpl=pImpl->next)
4980 if(i==index && pImpl){
4981 *pImplTypeFlags=pImpl->implflags;
4985 return TYPE_E_ELEMENTNOTFOUND;
4989 * Maps between member names and member IDs, and parameter names and
4992 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4993 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4995 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4996 const TLBFuncDesc *pFDesc;
4997 const TLBVarDesc *pVDesc;
5001 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5004 /* init out parameters in case of failure */
5005 for (i = 0; i < cNames; i++)
5006 pMemId[i] = MEMBERID_NIL;
5008 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5010 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5011 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5012 for(i=1; i < cNames; i++){
5013 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5014 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5016 if( j<pFDesc->funcdesc.cParams)
5019 ret=DISP_E_UNKNOWNNAME;
5021 TRACE("-- 0x%08x\n", ret);
5025 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5026 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5027 if(cNames) *pMemId=pVDesc->vardesc.memid;
5031 /* not found, see if it can be found in an inherited interface */
5032 if(This->TypeAttr.cImplTypes) {
5033 /* recursive search */
5035 ret=ITypeInfo_GetRefTypeInfo(iface,
5036 This->impltypelist->hRef, &pTInfo);
5038 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5039 ITypeInfo_Release(pTInfo);
5042 WARN("Could not search inherited interface!\n");
5044 WARN("no names found\n");
5045 return DISP_E_UNKNOWNNAME;
5048 /* ITypeInfo::Invoke
5050 * Invokes a method, or accesses a property of an object, that implements the
5051 * interface described by the type description.
5054 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5057 if (TRACE_ON(ole)) {
5059 TRACE("Calling %p(",func);
5060 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5072 res = func(args[0]);
5075 res = func(args[0],args[1]);
5078 res = func(args[0],args[1],args[2]);
5081 res = func(args[0],args[1],args[2],args[3]);
5084 res = func(args[0],args[1],args[2],args[3],args[4]);
5087 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5090 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5093 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5096 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5099 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5102 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5105 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]);
5108 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]);
5111 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]);
5114 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]);
5117 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]);
5120 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]);
5123 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]);
5126 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]);
5129 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]);
5132 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]);
5135 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]);
5138 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]);
5141 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5147 FIXME("unsupported calling convention %d\n",callconv);
5151 TRACE("returns %08x\n",res);
5155 extern int _argsize(DWORD vt);
5157 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5160 ITypeInfo *tinfo2 = NULL;
5161 TYPEATTR *tattr = NULL;
5163 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5166 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5168 tdesc->u.hreftype, hr);
5171 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5174 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5175 ITypeInfo_Release(tinfo2);
5179 switch (tattr->typekind)
5186 tdesc = &tattr->tdescAlias;
5187 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5190 case TKIND_INTERFACE:
5191 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5197 case TKIND_DISPATCH:
5206 FIXME("TKIND_RECORD unhandled.\n");
5211 FIXME("TKIND_UNION unhandled.\n");
5216 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5220 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5221 ITypeInfo_Release(tinfo2);
5225 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5229 /* enforce only one level of pointer indirection */
5230 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5232 tdesc = tdesc->u.lptdesc;
5234 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5235 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5236 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5237 if ((tdesc->vt == VT_USERDEFINED) ||
5238 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5240 VARTYPE vt_userdefined = 0;
5241 const TYPEDESC *tdesc_userdefined = tdesc;
5242 if (tdesc->vt == VT_PTR)
5244 vt_userdefined = VT_BYREF;
5245 tdesc_userdefined = tdesc->u.lptdesc;
5247 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5249 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5250 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5252 *vt |= vt_userdefined;
5264 case VT_USERDEFINED:
5265 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5272 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5273 hr = DISP_E_BADVARTYPE;
5277 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5286 /***********************************************************************
5287 * DispCallFunc (OLEAUT32.@)
5289 * Invokes a function of the specifed calling convention, passing the
5290 * specified arguments and returns the result.
5293 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5294 * oVft [I] The offset in the vtable. See notes.
5295 * cc [I] Calling convention of the function to call.
5296 * vtReturn [I] The return type of the function.
5297 * cActuals [I] Number of parameters.
5298 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5299 * prgpvarg [I] The arguments to pass.
5300 * pvargResult [O] The return value of the function. Can be NULL.
5304 * Failure: HRESULT code.
5307 * The HRESULT return value of this function is not affected by the return
5308 * value of the user supplied function, which is returned in pvargResult.
5310 * If pvInstance is NULL then a non-object function is to be called and oVft
5311 * is the address of the function to call.
5313 * The cc parameter can be one of the following values:
5326 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5327 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5329 int i, argsize, argspos;
5333 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5334 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5335 pvargResult, V_VT(pvargResult));
5339 argsize++; /* for This pointer */
5341 for (i=0;i<cActuals;i++)
5343 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5344 dump_Variant(prgpvarg[i]);
5345 argsize += _argsize(prgvt[i]);
5347 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5352 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5356 for (i=0;i<cActuals;i++)
5358 VARIANT *arg = prgpvarg[i];
5359 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5360 if (prgvt[i] == VT_VARIANT)
5361 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5363 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5364 argspos += _argsize(prgvt[i]);
5369 FARPROC *vtable = *(FARPROC**)pvInstance;
5370 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5373 /* if we aren't invoking an object then the function pointer is stored
5375 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5377 if (pvargResult && (vtReturn != VT_EMPTY))
5379 TRACE("Method returned 0x%08x\n",hres);
5380 V_VT(pvargResult) = vtReturn;
5381 V_UI4(pvargResult) = hres;
5384 HeapFree(GetProcessHeap(),0,args);
5388 #define INVBUF_ELEMENT_SIZE \
5389 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5390 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5391 ((VARIANTARG *)(buffer))
5392 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5393 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5394 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5395 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5396 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5397 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5399 static HRESULT WINAPI ITypeInfo_fnInvoke(
5404 DISPPARAMS *pDispParams,
5405 VARIANT *pVarResult,
5406 EXCEPINFO *pExcepInfo,
5409 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5411 unsigned int var_index;
5414 const TLBFuncDesc *pFuncInfo;
5416 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5417 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5422 ERR("NULL pDispParams not allowed\n");
5423 return E_INVALIDARG;
5426 dump_DispParms(pDispParams);
5428 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5430 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5431 pDispParams->cNamedArgs, pDispParams->cArgs);
5432 return E_INVALIDARG;
5435 /* we do this instead of using GetFuncDesc since it will return a fake
5436 * FUNCDESC for dispinterfaces and we want the real function description */
5437 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5438 if ((memid == pFuncInfo->funcdesc.memid) &&
5439 (wFlags & pFuncInfo->funcdesc.invkind))
5443 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5447 TRACE("invoking:\n");
5448 dump_TLBFuncDescOne(pFuncInfo);
5451 switch (func_desc->funckind) {
5452 case FUNC_PUREVIRTUAL:
5453 case FUNC_VIRTUAL: {
5454 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5456 VARIANT retval; /* pointer for storing byref retvals in */
5457 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5458 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5459 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5462 for (i = 0; i < func_desc->cParams; i++)
5464 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5465 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5470 TRACE("changing args\n");
5471 for (i = 0; i < func_desc->cParams; i++)
5473 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5475 if (wParamFlags & PARAMFLAG_FRETVAL)
5477 /* note: this check is placed so that if the caller passes
5478 * in a VARIANTARG for the retval we just ignore it, like
5480 if (i == func_desc->cParams - 1)
5483 arg = prgpvarg[i] = &rgvarg[i];
5484 memset(arg, 0, sizeof(*arg));
5485 V_VT(arg) = rgvt[i];
5486 memset(&retval, 0, sizeof(retval));
5487 V_BYREF(arg) = &retval;
5491 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5492 hres = E_UNEXPECTED;
5496 else if (i < pDispParams->cArgs)
5498 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5499 dump_Variant(src_arg);
5501 if (rgvt[i] == VT_VARIANT)
5502 hres = VariantCopy(&rgvarg[i], src_arg);
5503 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5505 if (rgvt[i] == V_VT(src_arg))
5506 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5509 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5510 hres = VariantCopy(&missing_arg[i], src_arg);
5511 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5513 V_VT(&rgvarg[i]) = rgvt[i];
5515 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5517 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5518 V_VT(&missing_arg[i]) = V_VT(src_arg);
5519 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5520 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5521 V_VT(&rgvarg[i]) = rgvt[i];
5523 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5525 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5526 V_VT(&rgvarg[i]) = rgvt[i];
5530 /* FIXME: this doesn't work for VT_BYREF arguments if
5531 * they are not the same type as in the paramdesc */
5532 V_VT(&rgvarg[i]) = V_VT(src_arg);
5533 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5534 V_VT(&rgvarg[i]) = rgvt[i];
5539 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5540 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5541 debugstr_VT(src_arg), debugstr_VF(src_arg));
5544 prgpvarg[i] = &rgvarg[i];
5546 else if (wParamFlags & PARAMFLAG_FOPT)
5549 arg = prgpvarg[i] = &rgvarg[i];
5550 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5552 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5558 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5559 V_VT(arg) = VT_VARIANT | VT_BYREF;
5560 V_VARIANTREF(arg) = &missing_arg[i];
5561 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5562 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5567 hres = DISP_E_BADPARAMCOUNT;
5571 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5572 if (func_desc->cParamsOpt < 0)
5574 FIXME("Does not support safearray optional parameters\n");
5575 hres = DISP_E_BADPARAMCOUNT;
5576 goto func_fail; /* FIXME: we don't free changed types here */
5579 /* VT_VOID is a special case for return types, so it is not
5580 * handled in the general function */
5581 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5582 V_VT(&varresult) = VT_EMPTY;
5585 V_VT(&varresult) = 0;
5586 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5587 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5590 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5591 V_VT(&varresult), func_desc->cParams, rgvt,
5592 prgpvarg, &varresult);
5594 for (i = 0; i < func_desc->cParams; i++)
5596 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5597 if (wParamFlags & PARAMFLAG_FRETVAL)
5601 TRACE("[retval] value: ");
5602 dump_Variant(prgpvarg[i]);
5607 VariantInit(pVarResult);
5608 /* deref return value */
5609 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5612 /* free data stored in varresult. Note that
5613 * VariantClear doesn't do what we want because we are
5614 * working with byref types. */
5615 /* FIXME: clear safearrays, bstrs, records and
5616 * variants here too */
5617 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5618 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5620 if(*V_UNKNOWNREF(prgpvarg[i]))
5621 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5625 else if (i < pDispParams->cArgs)
5627 if (wParamFlags & PARAMFLAG_FOUT)
5629 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5631 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5632 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5636 ERR("failed to convert param %d to vt %d\n", i,
5637 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5641 VariantClear(&rgvarg[i]);
5643 else if (wParamFlags & PARAMFLAG_FOPT)
5645 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5646 VariantClear(&rgvarg[i]);
5650 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5652 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
5653 hres = DISP_E_EXCEPTION;
5654 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5658 HeapFree(GetProcessHeap(), 0, buffer);
5661 case FUNC_DISPATCH: {
5664 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5665 if (SUCCEEDED(hres)) {
5666 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5667 hres = IDispatch_Invoke(
5668 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5669 pVarResult,pExcepInfo,pArgErr
5672 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
5673 IDispatch_Release(disp);
5675 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5679 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5684 TRACE("-- 0x%08x\n", hres);
5687 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5690 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5691 if(FAILED(hres)) return hres;
5693 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5694 dump_VARDESC(var_desc);
5695 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5699 /* not found, look for it in inherited interfaces */
5700 ITypeInfo2_GetTypeKind(iface, &type_kind);
5701 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5703 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5704 /* recursive search */
5706 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5707 if(SUCCEEDED(hres)){
5708 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5709 ITypeInfo_Release(pTInfo);
5712 WARN("Could not search inherited interface!\n");
5715 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
5716 return DISP_E_MEMBERNOTFOUND;
5719 /* ITypeInfo::GetDocumentation
5721 * Retrieves the documentation string, the complete Help file name and path,
5722 * and the context ID for the Help topic for a specified type description.
5724 * (Can be tested by the Visual Basic Editor in Word for instance.)
5726 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5727 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5728 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5730 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5731 const TLBFuncDesc *pFDesc;
5732 const TLBVarDesc *pVDesc;
5733 TRACE("(%p) memid %d Name(%p) DocString(%p)"
5734 " HelpContext(%p) HelpFile(%p)\n",
5735 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5736 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5738 *pBstrName=SysAllocString(This->Name);
5740 *pBstrDocString=SysAllocString(This->DocString);
5742 *pdwHelpContext=This->dwHelpContext;
5744 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5746 }else {/* for a member */
5747 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5748 if(pFDesc->funcdesc.memid==memid){
5750 *pBstrName = SysAllocString(pFDesc->Name);
5752 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5754 *pdwHelpContext=pFDesc->helpcontext;
5757 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5758 if(pVDesc->vardesc.memid==memid){
5760 *pBstrName = SysAllocString(pVDesc->Name);
5762 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5764 *pdwHelpContext=pVDesc->HelpContext;
5769 if(This->TypeAttr.cImplTypes &&
5770 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5771 /* recursive search */
5774 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5776 if(SUCCEEDED(result)) {
5777 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
5778 pBstrDocString, pdwHelpContext, pBstrHelpFile);
5779 ITypeInfo_Release(pTInfo);
5782 WARN("Could not search inherited interface!\n");
5785 WARN("member %d not found\n", memid);
5786 return TYPE_E_ELEMENTNOTFOUND;
5789 /* ITypeInfo::GetDllEntry
5791 * Retrieves a description or specification of an entry point for a function
5794 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5795 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5798 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5799 const TLBFuncDesc *pFDesc;
5801 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5803 if (pBstrDllName) *pBstrDllName = NULL;
5804 if (pBstrName) *pBstrName = NULL;
5805 if (pwOrdinal) *pwOrdinal = 0;
5807 if (This->TypeAttr.typekind != TKIND_MODULE)
5808 return TYPE_E_BADMODULEKIND;
5810 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5811 if(pFDesc->funcdesc.memid==memid){
5812 dump_TypeInfo(This);
5814 dump_TLBFuncDescOne(pFDesc);
5817 *pBstrDllName = SysAllocString(This->DllName);
5819 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5821 *pBstrName = SysAllocString(pFDesc->Entry);
5829 *pwOrdinal = (DWORD)pFDesc->Entry;
5832 return TYPE_E_ELEMENTNOTFOUND;
5835 /* ITypeInfo::GetRefTypeInfo
5837 * If a type description references other type descriptions, it retrieves
5838 * the referenced type descriptions.
5840 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5843 ITypeInfo **ppTInfo)
5845 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5846 HRESULT result = E_FAIL;
5848 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5850 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5851 ITypeInfo_AddRef(*ppTInfo);
5854 else if (hRefType == -1 &&
5855 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5856 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5858 /* when we meet a DUAL dispinterface, we must create the interface
5861 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5864 /* the interface version contains the same information as the dispinterface
5865 * copy the contents of the structs.
5867 *pTypeInfoImpl = *This;
5868 pTypeInfoImpl->ref = 0;
5870 /* change the type to interface */
5871 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5873 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5875 /* we use data structures from This, so we need to keep a reference
5876 * to it to stop it being destroyed and signal to the new instance to
5877 * not free its data structures when it is destroyed */
5878 pTypeInfoImpl->no_free_data = TRUE;
5879 pTypeInfoImpl->next = This;
5880 ITypeInfo_AddRef((ITypeInfo*) This);
5882 ITypeInfo_AddRef(*ppTInfo);
5887 TLBRefType *pRefType;
5888 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5889 if(pRefType->reference == hRefType)
5893 FIXME("Can't find pRefType for ref %x\n", hRefType);
5894 if(pRefType && hRefType != -1) {
5895 ITypeLib *pTLib = NULL;
5897 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5899 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5901 if(pRefType->pImpTLInfo->pImpTypeLib) {
5902 TRACE("typeinfo in imported typelib that is already loaded\n");
5903 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5904 ITypeLib2_AddRef((ITypeLib*) pTLib);
5907 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5908 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5909 pRefType->pImpTLInfo->wVersionMajor,
5910 pRefType->pImpTLInfo->wVersionMinor,
5911 pRefType->pImpTLInfo->lcid,
5914 if(!SUCCEEDED(result)) {
5915 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5916 result=LoadTypeLib(libnam, &pTLib);
5917 SysFreeString(libnam);
5919 if(SUCCEEDED(result)) {
5920 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5921 ITypeLib2_AddRef(pTLib);
5925 if(SUCCEEDED(result)) {
5926 if(pRefType->index == TLB_REF_USE_GUID)
5927 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5931 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5935 ITypeLib2_Release(pTLib);
5939 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
5940 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5944 /* ITypeInfo::AddressOfMember
5946 * Retrieves the addresses of static functions or variables, such as those
5949 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5950 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5952 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5958 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
5960 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5964 module = LoadLibraryW(dll);
5967 ERR("couldn't load %s\n", debugstr_w(dll));
5969 if (entry) SysFreeString(entry);
5970 return STG_E_FILENOTFOUND;
5972 /* FIXME: store library somewhere where we can free it */
5977 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5978 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5979 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5981 *ppv = GetProcAddress(module, entryA);
5983 ERR("function not found %s\n", debugstr_a(entryA));
5985 HeapFree(GetProcessHeap(), 0, entryA);
5989 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5991 ERR("function not found %d\n", ordinal);
5995 if (entry) SysFreeString(entry);
5998 return TYPE_E_DLLFUNCTIONNOTFOUND;
6003 /* ITypeInfo::CreateInstance
6005 * Creates a new instance of a type that describes a component object class
6008 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6009 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6011 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6015 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6021 WARN("Not able to aggregate\n");
6022 return CLASS_E_NOAGGREGATION;
6025 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6026 if(FAILED(hr)) return hr;
6028 if(pTA->typekind != TKIND_COCLASS)
6030 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6036 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6039 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6040 TRACE("GetActiveObject rets %08x\n", hr);
6043 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6044 IUnknown_Release(pUnk);
6049 hr = CoCreateInstance(&pTA->guid, NULL,
6050 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6054 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6058 /* ITypeInfo::GetMops
6060 * Retrieves marshalling information.
6062 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6065 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6066 FIXME("(%p) stub!\n", This);
6070 /* ITypeInfo::GetContainingTypeLib
6072 * Retrieves the containing type library and the index of the type description
6073 * within that type library.
6075 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6076 ITypeLib * *ppTLib, UINT *pIndex)
6078 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6080 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6082 *pIndex=This->index;
6083 TRACE("returning pIndex=%d\n", *pIndex);
6087 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6088 ITypeLib2_AddRef(*ppTLib);
6089 TRACE("returning ppTLib=%p\n", *ppTLib);
6095 /* ITypeInfo::ReleaseTypeAttr
6097 * Releases a TYPEATTR previously returned by GetTypeAttr.
6100 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6101 TYPEATTR* pTypeAttr)
6103 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6104 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6105 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6108 /* ITypeInfo::ReleaseFuncDesc
6110 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6112 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6114 FUNCDESC *pFuncDesc)
6116 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6119 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6121 for (i = 0; i < pFuncDesc->cParams; i++)
6122 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6123 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6125 SysFreeString((BSTR)pFuncDesc);
6128 /* ITypeInfo::ReleaseVarDesc
6130 * Releases a VARDESC previously returned by GetVarDesc.
6132 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6135 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6136 TRACE("(%p)->(%p)\n", This, pVarDesc);
6138 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6139 if (pVarDesc->varkind == VAR_CONST)
6140 VariantClear(pVarDesc->u.lpvarValue);
6141 SysFreeString((BSTR)pVarDesc);
6144 /* ITypeInfo2::GetTypeKind
6146 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6149 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6150 TYPEKIND *pTypeKind)
6152 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6153 *pTypeKind=This->TypeAttr.typekind;
6154 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6158 /* ITypeInfo2::GetTypeFlags
6160 * Returns the type flags without any allocations. This returns a DWORD type
6161 * flag, which expands the type flags without growing the TYPEATTR (type
6165 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6167 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6168 *pTypeFlags=This->TypeAttr.wTypeFlags;
6169 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6173 /* ITypeInfo2::GetFuncIndexOfMemId
6174 * Binds to a specific member based on a known DISPID, where the member name
6175 * is not known (for example, when binding to a default member).
6178 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6179 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6181 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6182 const TLBFuncDesc *pFuncInfo;
6186 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6187 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6193 result = TYPE_E_ELEMENTNOTFOUND;
6195 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6196 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6200 /* TypeInfo2::GetVarIndexOfMemId
6202 * Binds to a specific member based on a known DISPID, where the member name
6203 * is not known (for example, when binding to a default member).
6206 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6207 MEMBERID memid, UINT *pVarIndex)
6209 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6210 TLBVarDesc *pVarInfo;
6213 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6214 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6220 result = TYPE_E_ELEMENTNOTFOUND;
6222 TRACE("(%p) memid 0x%08x -> %s\n", This,
6223 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6227 /* ITypeInfo2::GetCustData
6229 * Gets the custom data
6231 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6236 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6237 TLBCustData *pCData;
6239 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6240 if( IsEqualIID(guid, &pCData->guid)) break;
6242 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6246 VariantInit( pVarVal);
6247 VariantCopy( pVarVal, &pCData->data);
6250 return E_INVALIDARG; /* FIXME: correct? */
6253 /* ITypeInfo2::GetFuncCustData
6255 * Gets the custom data
6257 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6263 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6264 TLBCustData *pCData=NULL;
6265 TLBFuncDesc * pFDesc;
6267 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6268 pFDesc=pFDesc->next);
6271 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6272 if( IsEqualIID(guid, &pCData->guid)) break;
6274 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6277 VariantInit( pVarVal);
6278 VariantCopy( pVarVal, &pCData->data);
6281 return E_INVALIDARG; /* FIXME: correct? */
6284 /* ITypeInfo2::GetParamCustData
6286 * Gets the custom data
6288 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6295 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6296 TLBCustData *pCData=NULL;
6297 TLBFuncDesc * pFDesc;
6300 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6302 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6303 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6304 pCData = pCData->next)
6305 if( IsEqualIID(guid, &pCData->guid)) break;
6307 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6311 VariantInit( pVarVal);
6312 VariantCopy( pVarVal, &pCData->data);
6315 return E_INVALIDARG; /* FIXME: correct? */
6318 /* ITypeInfo2::GetVarCustData
6320 * Gets the custom data
6322 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6328 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6329 TLBCustData *pCData=NULL;
6330 TLBVarDesc * pVDesc;
6333 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6337 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6339 if( IsEqualIID(guid, &pCData->guid)) break;
6343 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6347 VariantInit( pVarVal);
6348 VariantCopy( pVarVal, &pCData->data);
6351 return E_INVALIDARG; /* FIXME: correct? */
6354 /* ITypeInfo2::GetImplCustData
6356 * Gets the custom data
6358 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6364 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6365 TLBCustData *pCData=NULL;
6366 TLBImplType * pRDesc;
6369 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6373 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6375 if( IsEqualIID(guid, &pCData->guid)) break;
6379 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6383 VariantInit( pVarVal);
6384 VariantCopy( pVarVal, &pCData->data);
6387 return E_INVALIDARG; /* FIXME: correct? */
6390 /* ITypeInfo2::GetDocumentation2
6392 * Retrieves the documentation string, the complete Help file name and path,
6393 * the localization context to use, and the context ID for the library Help
6394 * topic in the Help file.
6397 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6401 BSTR *pbstrHelpString,
6402 DWORD *pdwHelpStringContext,
6403 BSTR *pbstrHelpStringDll)
6405 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6406 const TLBFuncDesc *pFDesc;
6407 const TLBVarDesc *pVDesc;
6408 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6409 "HelpStringContext(%p) HelpStringDll(%p)\n",
6410 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6411 pbstrHelpStringDll );
6412 /* the help string should be obtained from the helpstringdll,
6413 * using the _DLLGetDocumentation function, based on the supplied
6414 * lcid. Nice to do sometime...
6416 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6418 *pbstrHelpString=SysAllocString(This->Name);
6419 if(pdwHelpStringContext)
6420 *pdwHelpStringContext=This->dwHelpStringContext;
6421 if(pbstrHelpStringDll)
6422 *pbstrHelpStringDll=
6423 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6425 }else {/* for a member */
6426 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6427 if(pFDesc->funcdesc.memid==memid){
6429 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6430 if(pdwHelpStringContext)
6431 *pdwHelpStringContext=pFDesc->HelpStringContext;
6432 if(pbstrHelpStringDll)
6433 *pbstrHelpStringDll=
6434 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6437 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6438 if(pVDesc->vardesc.memid==memid){
6440 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6441 if(pdwHelpStringContext)
6442 *pdwHelpStringContext=pVDesc->HelpStringContext;
6443 if(pbstrHelpStringDll)
6444 *pbstrHelpStringDll=
6445 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6449 return TYPE_E_ELEMENTNOTFOUND;
6452 /* ITypeInfo2::GetAllCustData
6454 * Gets all custom data items for the Type info.
6457 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6459 CUSTDATA *pCustData)
6461 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6462 TLBCustData *pCData;
6465 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6467 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6468 if(pCustData->prgCustData ){
6469 pCustData->cCustData=This->ctCustData;
6470 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6471 pCustData->prgCustData[i].guid=pCData->guid;
6472 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6475 ERR(" OUT OF MEMORY!\n");
6476 return E_OUTOFMEMORY;
6481 /* ITypeInfo2::GetAllFuncCustData
6483 * Gets all custom data items for the specified Function
6486 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6489 CUSTDATA *pCustData)
6491 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6492 TLBCustData *pCData;
6493 TLBFuncDesc * pFDesc;
6495 TRACE("(%p) index %d\n", This, index);
6496 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6497 pFDesc=pFDesc->next)
6500 pCustData->prgCustData =
6501 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6502 if(pCustData->prgCustData ){
6503 pCustData->cCustData=pFDesc->ctCustData;
6504 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6505 pCData = pCData->next){
6506 pCustData->prgCustData[i].guid=pCData->guid;
6507 VariantCopy(& pCustData->prgCustData[i].varValue,
6511 ERR(" OUT OF MEMORY!\n");
6512 return E_OUTOFMEMORY;
6516 return TYPE_E_ELEMENTNOTFOUND;
6519 /* ITypeInfo2::GetAllParamCustData
6521 * Gets all custom data items for the Functions
6524 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6525 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6527 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6528 TLBCustData *pCData=NULL;
6529 TLBFuncDesc * pFDesc;
6531 TRACE("(%p) index %d\n", This, indexFunc);
6532 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6533 pFDesc=pFDesc->next)
6535 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6536 pCustData->prgCustData =
6537 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6538 sizeof(CUSTDATAITEM));
6539 if(pCustData->prgCustData ){
6540 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6541 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6542 pCData; i++, pCData = pCData->next){
6543 pCustData->prgCustData[i].guid=pCData->guid;
6544 VariantCopy(& pCustData->prgCustData[i].varValue,
6548 ERR(" OUT OF MEMORY!\n");
6549 return E_OUTOFMEMORY;
6553 return TYPE_E_ELEMENTNOTFOUND;
6556 /* ITypeInfo2::GetAllVarCustData
6558 * Gets all custom data items for the specified Variable
6561 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6562 UINT index, CUSTDATA *pCustData)
6564 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6565 TLBCustData *pCData;
6566 TLBVarDesc * pVDesc;
6568 TRACE("(%p) index %d\n", This, index);
6569 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6570 pVDesc=pVDesc->next)
6573 pCustData->prgCustData =
6574 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6575 if(pCustData->prgCustData ){
6576 pCustData->cCustData=pVDesc->ctCustData;
6577 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6578 pCData = pCData->next){
6579 pCustData->prgCustData[i].guid=pCData->guid;
6580 VariantCopy(& pCustData->prgCustData[i].varValue,
6584 ERR(" OUT OF MEMORY!\n");
6585 return E_OUTOFMEMORY;
6589 return TYPE_E_ELEMENTNOTFOUND;
6592 /* ITypeInfo2::GetAllImplCustData
6594 * Gets all custom data items for the specified implementation type
6597 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6600 CUSTDATA *pCustData)
6602 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6603 TLBCustData *pCData;
6604 TLBImplType * pRDesc;
6606 TRACE("(%p) index %d\n", This, index);
6607 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6608 pRDesc=pRDesc->next)
6611 pCustData->prgCustData =
6612 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6613 if(pCustData->prgCustData ){
6614 pCustData->cCustData=pRDesc->ctCustData;
6615 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6616 pCData = pCData->next){
6617 pCustData->prgCustData[i].guid=pCData->guid;
6618 VariantCopy(& pCustData->prgCustData[i].varValue,
6622 ERR(" OUT OF MEMORY!\n");
6623 return E_OUTOFMEMORY;
6627 return TYPE_E_ELEMENTNOTFOUND;
6630 static const ITypeInfo2Vtbl tinfvt =
6633 ITypeInfo_fnQueryInterface,
6635 ITypeInfo_fnRelease,
6637 ITypeInfo_fnGetTypeAttr,
6638 ITypeInfo_fnGetTypeComp,
6639 ITypeInfo_fnGetFuncDesc,
6640 ITypeInfo_fnGetVarDesc,
6641 ITypeInfo_fnGetNames,
6642 ITypeInfo_fnGetRefTypeOfImplType,
6643 ITypeInfo_fnGetImplTypeFlags,
6644 ITypeInfo_fnGetIDsOfNames,
6646 ITypeInfo_fnGetDocumentation,
6647 ITypeInfo_fnGetDllEntry,
6648 ITypeInfo_fnGetRefTypeInfo,
6649 ITypeInfo_fnAddressOfMember,
6650 ITypeInfo_fnCreateInstance,
6651 ITypeInfo_fnGetMops,
6652 ITypeInfo_fnGetContainingTypeLib,
6653 ITypeInfo_fnReleaseTypeAttr,
6654 ITypeInfo_fnReleaseFuncDesc,
6655 ITypeInfo_fnReleaseVarDesc,
6657 ITypeInfo2_fnGetTypeKind,
6658 ITypeInfo2_fnGetTypeFlags,
6659 ITypeInfo2_fnGetFuncIndexOfMemId,
6660 ITypeInfo2_fnGetVarIndexOfMemId,
6661 ITypeInfo2_fnGetCustData,
6662 ITypeInfo2_fnGetFuncCustData,
6663 ITypeInfo2_fnGetParamCustData,
6664 ITypeInfo2_fnGetVarCustData,
6665 ITypeInfo2_fnGetImplTypeCustData,
6666 ITypeInfo2_fnGetDocumentation2,
6667 ITypeInfo2_fnGetAllCustData,
6668 ITypeInfo2_fnGetAllFuncCustData,
6669 ITypeInfo2_fnGetAllParamCustData,
6670 ITypeInfo2_fnGetAllVarCustData,
6671 ITypeInfo2_fnGetAllImplTypeCustData,
6674 /******************************************************************************
6675 * CreateDispTypeInfo [OLEAUT32.31]
6677 * Build type information for an object so it can be called through an
6678 * IDispatch interface.
6681 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6682 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6685 * This call allows an objects methods to be accessed through IDispatch, by
6686 * building an ITypeInfo object that IDispatch can use to call through.
6688 HRESULT WINAPI CreateDispTypeInfo(
6689 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6690 LCID lcid, /* [I] Locale Id */
6691 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6693 ITypeInfoImpl *pTIClass, *pTIIface;
6694 ITypeLibImpl *pTypeLibImpl;
6696 TLBFuncDesc **ppFuncDesc;
6699 pTypeLibImpl = TypeLibImpl_Constructor();
6700 if (!pTypeLibImpl) return E_FAIL;
6702 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6703 pTIIface->pTypeLib = pTypeLibImpl;
6704 pTIIface->index = 0;
6705 pTIIface->Name = NULL;
6706 pTIIface->dwHelpContext = -1;
6707 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6708 pTIIface->TypeAttr.lcid = lcid;
6709 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6710 pTIIface->TypeAttr.wMajorVerNum = 0;
6711 pTIIface->TypeAttr.wMinorVerNum = 0;
6712 pTIIface->TypeAttr.cbAlignment = 2;
6713 pTIIface->TypeAttr.cbSizeInstance = -1;
6714 pTIIface->TypeAttr.cbSizeVft = -1;
6715 pTIIface->TypeAttr.cFuncs = 0;
6716 pTIIface->TypeAttr.cImplTypes = 0;
6717 pTIIface->TypeAttr.cVars = 0;
6718 pTIIface->TypeAttr.wTypeFlags = 0;
6720 ppFuncDesc = &pTIIface->funclist;
6721 for(func = 0; func < pidata->cMembers; func++) {
6722 METHODDATA *md = pidata->pmethdata + func;
6723 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6724 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6725 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6726 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
6727 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6728 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6729 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6730 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6731 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6732 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6733 (*ppFuncDesc)->funcdesc.cScodes = 0;
6734 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6735 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6736 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6737 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6738 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6739 md->cArgs * sizeof(ELEMDESC));
6740 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6741 md->cArgs * sizeof(TLBParDesc));
6742 for(param = 0; param < md->cArgs; param++) {
6743 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6744 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6746 (*ppFuncDesc)->helpcontext = 0;
6747 (*ppFuncDesc)->HelpStringContext = 0;
6748 (*ppFuncDesc)->HelpString = NULL;
6749 (*ppFuncDesc)->Entry = NULL;
6750 (*ppFuncDesc)->ctCustData = 0;
6751 (*ppFuncDesc)->pCustData = NULL;
6752 (*ppFuncDesc)->next = NULL;
6753 ppFuncDesc = &(*ppFuncDesc)->next;
6756 dump_TypeInfo(pTIIface);
6758 pTypeLibImpl->pTypeInfo = pTIIface;
6759 pTypeLibImpl->TypeInfoCount++;
6761 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6762 pTIClass->pTypeLib = pTypeLibImpl;
6763 pTIClass->index = 1;
6764 pTIClass->Name = NULL;
6765 pTIClass->dwHelpContext = -1;
6766 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6767 pTIClass->TypeAttr.lcid = lcid;
6768 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6769 pTIClass->TypeAttr.wMajorVerNum = 0;
6770 pTIClass->TypeAttr.wMinorVerNum = 0;
6771 pTIClass->TypeAttr.cbAlignment = 2;
6772 pTIClass->TypeAttr.cbSizeInstance = -1;
6773 pTIClass->TypeAttr.cbSizeVft = -1;
6774 pTIClass->TypeAttr.cFuncs = 0;
6775 pTIClass->TypeAttr.cImplTypes = 1;
6776 pTIClass->TypeAttr.cVars = 0;
6777 pTIClass->TypeAttr.wTypeFlags = 0;
6779 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6780 pTIClass->impltypelist->hRef = 1;
6782 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6783 pTIClass->reflist->index = 0;
6784 pTIClass->reflist->reference = 1;
6785 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6787 dump_TypeInfo(pTIClass);
6789 pTIIface->next = pTIClass;
6790 pTypeLibImpl->TypeInfoCount++;
6792 *pptinfo = (ITypeInfo*)pTIClass;
6794 ITypeInfo_AddRef(*pptinfo);
6795 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
6801 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6803 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6805 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6808 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6810 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6812 return ITypeInfo_AddRef((ITypeInfo *)This);
6815 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6817 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6819 return ITypeInfo_Release((ITypeInfo *)This);
6822 static HRESULT WINAPI ITypeComp_fnBind(
6827 ITypeInfo ** ppTInfo,
6828 DESCKIND * pDescKind,
6831 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6832 const TLBFuncDesc *pFDesc;
6833 const TLBVarDesc *pVDesc;
6834 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6836 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6838 *pDescKind = DESCKIND_NONE;
6839 pBindPtr->lpfuncdesc = NULL;
6842 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6843 if (!strcmpiW(pFDesc->Name, szName)) {
6844 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6847 /* name found, but wrong flags */
6848 hr = TYPE_E_TYPEMISMATCH;
6853 HRESULT hr = TLB_AllocAndInitFuncDesc(
6855 &pBindPtr->lpfuncdesc,
6856 This->TypeAttr.typekind == TKIND_DISPATCH);
6859 *pDescKind = DESCKIND_FUNCDESC;
6860 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6861 ITypeInfo_AddRef(*ppTInfo);
6864 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6865 if (!strcmpiW(pVDesc->Name, szName)) {
6866 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6869 *pDescKind = DESCKIND_VARDESC;
6870 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6871 ITypeInfo_AddRef(*ppTInfo);
6876 /* FIXME: search each inherited interface, not just the first */
6877 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6878 /* recursive search */
6882 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6885 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6886 ITypeInfo_Release(pTInfo);
6890 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6891 ITypeComp_Release(pTComp);
6894 WARN("Could not search inherited interface!\n");
6896 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6900 static HRESULT WINAPI ITypeComp_fnBindType(
6904 ITypeInfo ** ppTInfo,
6905 ITypeComp ** ppTComp)
6907 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6909 /* strange behaviour (does nothing) but like the
6912 if (!ppTInfo || !ppTComp)
6921 static const ITypeCompVtbl tcompvt =
6924 ITypeComp_fnQueryInterface,
6926 ITypeComp_fnRelease,
6929 ITypeComp_fnBindType