4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
44 * -. lousy fatal error handling
49 #include "wine/port.h"
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
69 #include "wine/winbase16.h"
70 #include "wine/unicode.h"
73 #include "wine/debug.h"
75 #include "wine/list.h"
77 WINE_DEFAULT_DEBUG_CHANNEL(ole);
78 WINE_DECLARE_DEBUG_CHANNEL(typelib);
80 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
81 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
83 /****************************************************************************
86 * Takes p_iVal (which is in little endian) and returns it
87 * in the host machine's byte order.
89 #ifdef WORDS_BIGENDIAN
90 static WORD FromLEWord(WORD p_iVal)
92 return (((p_iVal & 0x00FF) << 8) |
93 ((p_iVal & 0xFF00) >> 8));
97 static DWORD FromLEDWord(DWORD p_iVal)
99 return (((p_iVal & 0x000000FF) << 24) |
100 ((p_iVal & 0x0000FF00) << 8) |
101 ((p_iVal & 0x00FF0000) >> 8) |
102 ((p_iVal & 0xFF000000) >> 24));
105 #define FromLEWord(X) (X)
106 #define FromLEDWord(X) (X)
109 #define DISPATCH_HREF_OFFSET 0x01000000
110 #define DISPATCH_HREF_MASK 0xff000000
112 /****************************************************************************
115 * Fix byte order in any structure if necessary
117 #ifdef WORDS_BIGENDIAN
118 static void FromLEWords(void *p_Val, int p_iSize)
122 p_iSize /= sizeof(WORD);
125 *Val = FromLEWord(*Val);
132 static void FromLEDWords(void *p_Val, int p_iSize)
136 p_iSize /= sizeof(DWORD);
139 *Val = FromLEDWord(*Val);
145 #define FromLEWords(X,Y) /*nothing*/
146 #define FromLEDWords(X,Y) /*nothing*/
150 * Find a typelib key which matches a requested maj.min version.
152 static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin )
154 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
161 memcpy( buffer, typelibW, sizeof(typelibW) );
162 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
164 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
167 len = sizeof(key_name);
169 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
173 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
175 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
182 break; /* exact match */
184 if (v_min > best_min) best_min = v_min;
187 len = sizeof(key_name);
198 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
199 /* buffer must be at least 60 characters long */
200 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
202 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
203 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
205 memcpy( buffer, TypelibW, sizeof(TypelibW) );
206 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
207 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
211 /* get the path of an interface key, in the form "Interface\\<guid>" */
212 /* buffer must be at least 50 characters long */
213 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
215 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
217 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
218 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
222 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
223 /* buffer must be at least 16 characters long */
224 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
226 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
227 static const WCHAR win16W[] = {'w','i','n','1','6',0};
228 static const WCHAR win32W[] = {'w','i','n','3','2',0};
230 sprintfW( buffer, LcidFormatW, lcid );
233 case SYS_WIN16: strcatW( buffer, win16W ); break;
234 case SYS_WIN32: strcatW( buffer, win32W ); break;
236 TRACE("Typelib is for unsupported syskind %i\n", syskind);
242 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
245 /****************************************************************************
246 * QueryPathOfRegTypeLib [OLEAUT32.164]
248 * Gets the path to a registered type library.
251 * guid [I] referenced guid
252 * wMaj [I] major version
253 * wMin [I] minor version
255 * path [O] path of typelib
259 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
260 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
263 HRESULT WINAPI QueryPathOfRegTypeLib(
270 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
274 WCHAR Path[MAX_PATH];
277 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
279 if (!find_typelib_key( guid, wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
280 get_typelib_key( guid, wMaj, wMin, buffer );
282 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
283 if (res == ERROR_FILE_NOT_FOUND)
285 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
286 return TYPE_E_LIBNOTREGISTERED;
288 else if (res != ERROR_SUCCESS)
290 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
291 return TYPE_E_REGISTRYACCESS;
296 LONG dwPathLen = sizeof(Path);
298 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
300 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
304 else if (myLCID == lcid)
306 /* try with sub-langid */
307 myLCID = SUBLANGID(lcid);
309 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
311 /* try with system langid */
321 *path = SysAllocString( Path );
326 TRACE_(typelib)("-- 0x%08x\n", hr);
330 /******************************************************************************
331 * CreateTypeLib [OLEAUT32.160] creates a typelib
337 HRESULT WINAPI CreateTypeLib(
338 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
340 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
344 /******************************************************************************
345 * LoadTypeLib [OLEAUT32.161]
347 * Loads a type library
350 * szFile [I] Name of file to load from.
351 * pptLib [O] Pointer that receives ITypeLib object on success.
358 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
360 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
362 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
363 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
366 /******************************************************************************
367 * LoadTypeLibEx [OLEAUT32.183]
369 * Loads and optionally registers a type library
375 HRESULT WINAPI LoadTypeLibEx(
376 LPCOLESTR szFile, /* [in] Name of file to load from */
377 REGKIND regkind, /* [in] Specify kind of registration */
378 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
380 WCHAR szPath[MAX_PATH+1];
383 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
387 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
392 case REGKIND_DEFAULT:
393 /* don't register typelibs supplied with full path. Experimentation confirms the following */
394 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
395 (szFile[0] && (szFile[1] == ':'))) break;
396 /* else fall-through */
398 case REGKIND_REGISTER:
399 if (FAILED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
401 IUnknown_Release(*pptLib);
409 TRACE(" returns %08x\n",res);
413 /******************************************************************************
414 * LoadRegTypeLib [OLEAUT32.162]
416 * Loads a registered type library.
419 * rguid [I] GUID of the registered type library.
420 * wVerMajor [I] major version.
421 * wVerMinor [I] minor version.
422 * lcid [I] locale ID.
423 * ppTLib [O] pointer that receives an ITypeLib object on success.
427 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
430 HRESULT WINAPI LoadRegTypeLib(
442 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
446 res= LoadTypeLib(bstr, ppTLib);
450 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
456 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
457 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
458 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
459 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
460 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
461 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
463 /******************************************************************************
464 * RegisterTypeLib [OLEAUT32.163]
465 * Adds information about a type library to the System Registry
467 * Docs: ITypeLib FAR * ptlib
468 * Docs: OLECHAR FAR* szFullPath
469 * Docs: OLECHAR FAR* szHelpDir
475 HRESULT WINAPI RegisterTypeLib(
476 ITypeLib * ptlib, /* [in] Pointer to the library*/
477 OLECHAR * szFullPath, /* [in] full Path of the library*/
478 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
481 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
482 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
483 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
493 if (ptlib == NULL || szFullPath == NULL)
496 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
499 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
502 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
503 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
507 /* Set the human-readable name of the typelib */
508 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
510 if (RegSetValueExW(key, NULL, 0, REG_SZ,
511 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
519 /* Make up the name of the typelib path subkey */
520 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
522 /* Create the typelib path subkey */
523 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
524 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
526 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
527 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
535 /* Create the flags subkey */
536 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
537 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
539 /* FIXME: is %u correct? */
540 static const WCHAR formatW[] = {'%','u',0};
542 sprintfW(buf, formatW, attr->wLibFlags);
543 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
544 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
552 /* create the helpdir subkey */
553 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
554 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
556 BOOL freeHelpDir = FALSE;
559 /* if we created a new key, and helpDir was null, set the helpdir
560 to the directory which contains the typelib. However,
561 if we just opened an existing key, we leave the helpdir alone */
562 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
563 szHelpDir = SysAllocString(szFullPath);
564 pIndexStr = strrchrW(szHelpDir, '\\');
571 /* if we have an szHelpDir, set it! */
572 if (szHelpDir != NULL) {
573 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
574 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
580 if (freeHelpDir) SysFreeString(szHelpDir);
592 /* register OLE Automation-compatible interfaces for this typelib */
593 types = ITypeLib_GetTypeInfoCount(ptlib);
594 for (tidx=0; tidx<types; tidx++) {
595 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
596 LPOLESTR name = NULL;
597 ITypeInfo *tinfo = NULL;
599 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
602 case TKIND_INTERFACE:
603 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
604 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
608 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
609 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
613 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
618 TYPEATTR *tattr = NULL;
619 ITypeInfo_GetTypeAttr(tinfo, &tattr);
622 TRACE_(typelib)("guid=%s, flags=%04x (",
623 debugstr_guid(&tattr->guid),
626 if (TRACE_ON(typelib)) {
627 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
647 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
649 /* register interface<->typelib coupling */
650 get_interface_key( &tattr->guid, keyName );
651 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
652 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
655 RegSetValueExW(key, NULL, 0, REG_SZ,
656 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
658 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
659 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
660 RegSetValueExW(subKey, NULL, 0, REG_SZ,
661 (const BYTE *)PSOA, sizeof PSOA);
665 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
666 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
667 RegSetValueExW(subKey, NULL, 0, REG_SZ,
668 (const BYTE *)PSOA, sizeof PSOA);
672 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
673 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
676 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
677 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
679 StringFromGUID2(&attr->guid, buffer, 40);
680 RegSetValueExW(subKey, NULL, 0, REG_SZ,
681 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
682 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
683 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
684 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
692 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
695 ITypeInfo_Release(tinfo);
702 ITypeLib_ReleaseTLibAttr(ptlib, attr);
708 /******************************************************************************
709 * UnRegisterTypeLib [OLEAUT32.186]
710 * Removes information about a type library from the System Registry
717 HRESULT WINAPI UnRegisterTypeLib(
718 REFGUID libid, /* [in] Guid of the library */
719 WORD wVerMajor, /* [in] major version */
720 WORD wVerMinor, /* [in] minor version */
721 LCID lcid, /* [in] locale id */
724 BSTR tlibPath = NULL;
727 WCHAR subKeyName[50];
730 BOOL deleteOtherStuff;
733 TYPEATTR* typeAttr = NULL;
735 ITypeInfo* typeInfo = NULL;
736 ITypeLib* typeLib = NULL;
739 TRACE("(IID: %s)\n",debugstr_guid(libid));
741 /* Create the path to the key */
742 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
744 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
746 TRACE("Unsupported syskind %i\n", syskind);
747 result = E_INVALIDARG;
751 /* get the path to the typelib on disk */
752 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
753 result = E_INVALIDARG;
757 /* Try and open the key to the type library. */
758 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
759 result = E_INVALIDARG;
763 /* Try and load the type library */
764 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
765 result = TYPE_E_INVALIDSTATE;
769 /* remove any types registered with this typelib */
770 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
771 for (i=0; i<numTypes; i++) {
772 /* get the kind of type */
773 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
777 /* skip non-interfaces, and get type info for the type */
778 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
781 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
784 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
788 /* the path to the type */
789 get_interface_key( &typeAttr->guid, subKeyName );
791 /* Delete its bits */
792 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
795 RegDeleteKeyW(subKey, ProxyStubClsidW);
796 RegDeleteKeyW(subKey, ProxyStubClsid32W);
797 RegDeleteKeyW(subKey, TypeLibW);
800 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
803 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
805 if (typeInfo) ITypeInfo_Release(typeInfo);
809 /* Now, delete the type library path subkey */
810 get_lcid_subkey( lcid, syskind, subKeyName );
811 RegDeleteKeyW(key, subKeyName);
812 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
813 RegDeleteKeyW(key, subKeyName);
815 /* check if there is anything besides the FLAGS/HELPDIR keys.
816 If there is, we don't delete them */
817 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
818 deleteOtherStuff = TRUE;
820 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
821 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
823 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
824 if (!strcmpW(subKeyName, FLAGSW)) continue;
825 if (!strcmpW(subKeyName, HELPDIRW)) continue;
826 deleteOtherStuff = FALSE;
830 /* only delete the other parts of the key if we're absolutely sure */
831 if (deleteOtherStuff) {
832 RegDeleteKeyW(key, FLAGSW);
833 RegDeleteKeyW(key, HELPDIRW);
837 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
838 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
839 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
843 SysFreeString(tlibPath);
844 if (typeLib) ITypeLib_Release(typeLib);
845 if (subKey) RegCloseKey(subKey);
846 if (key) RegCloseKey(key);
850 /*======================= ITypeLib implementation =======================*/
852 typedef struct tagTLBCustData
856 struct tagTLBCustData* next;
859 /* data structure for import typelibs */
860 typedef struct tagTLBImpLib
862 int offset; /* offset in the file (MSFT)
863 offset in nametable (SLTG)
864 just used to identify library while reading
866 GUID guid; /* libid */
867 BSTR name; /* name */
869 LCID lcid; /* lcid of imported typelib */
871 WORD wVersionMajor; /* major version number */
872 WORD wVersionMinor; /* minor version number */
874 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
875 NULL if not yet loaded */
876 struct tagTLBImpLib * next;
879 /* internal ITypeLib data */
880 typedef struct tagITypeLibImpl
882 const ITypeLib2Vtbl *lpVtbl;
883 const ITypeCompVtbl *lpVtblTypeComp;
885 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
887 /* strings can be stored in tlb as multibyte strings BUT they are *always*
888 * exported to the application as a UNICODE string.
894 unsigned long dwHelpContext;
895 int TypeInfoCount; /* nr of typeinfo's in librarry */
896 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
897 int ctCustData; /* number of items in cust data list */
898 TLBCustData * pCustData; /* linked list to cust data */
899 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
900 int ctTypeDesc; /* number of items in type desc array */
901 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
902 library. Only used while reading MSFT
904 struct list ref_list; /* list of ref types in this typelib */
905 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
908 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
909 struct tagITypeLibImpl *next, *prev;
914 static const ITypeLib2Vtbl tlbvt;
915 static const ITypeCompVtbl tlbtcvt;
917 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
919 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
922 /* ITypeLib methods */
923 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
924 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
926 /*======================= ITypeInfo implementation =======================*/
928 /* data for referenced types */
929 typedef struct tagTLBRefType
931 INT index; /* Type index for internal ref or for external ref
932 it the format is SLTG. -2 indicates to
935 GUID guid; /* guid of the referenced type */
936 /* if index == TLB_REF_USE_GUID */
938 HREFTYPE reference; /* The href of this ref */
939 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
940 TLB_REF_INTERNAL for internal refs
941 TLB_REF_NOT_FOUND for broken refs */
946 #define TLB_REF_USE_GUID -2
948 #define TLB_REF_INTERNAL (void*)-2
949 #define TLB_REF_NOT_FOUND (void*)-1
951 /* internal Parameter data */
952 typedef struct tagTLBParDesc
956 TLBCustData * pCustData; /* linked list to cust data */
959 /* internal Function data */
960 typedef struct tagTLBFuncDesc
962 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
963 BSTR Name; /* the name of this function */
964 TLBParDesc *pParamDesc; /* array with param names and custom data */
966 int HelpStringContext;
968 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
970 TLBCustData * pCustData; /* linked list to cust data; */
971 struct tagTLBFuncDesc * next;
974 /* internal Variable data */
975 typedef struct tagTLBVarDesc
977 VARDESC vardesc; /* lots of info on the variable and its attributes. */
978 BSTR Name; /* the name of this variable */
980 int HelpStringContext; /* FIXME: where? */
983 TLBCustData * pCustData;/* linked list to cust data; */
984 struct tagTLBVarDesc * next;
987 /* internal implemented interface data */
988 typedef struct tagTLBImplType
990 HREFTYPE hRef; /* hRef of interface */
991 int implflags; /* IMPLFLAG_*s */
993 TLBCustData * pCustData;/* linked list to custom data; */
994 struct tagTLBImplType *next;
997 /* internal TypeInfo data */
998 typedef struct tagITypeInfoImpl
1000 const ITypeInfo2Vtbl *lpVtbl;
1001 const ITypeCompVtbl *lpVtblTypeComp;
1003 BOOL no_free_data; /* don't free data structures */
1004 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1005 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1006 int index; /* index in this typelib; */
1007 HREFTYPE hreftype; /* hreftype for app object binding */
1008 /* type libs seem to store the doc strings in ascii
1009 * so why should we do it in unicode?
1014 unsigned long dwHelpContext;
1015 unsigned long dwHelpStringContext;
1018 TLBFuncDesc * funclist; /* linked list with function descriptions */
1021 TLBVarDesc * varlist; /* linked list with variable descriptions */
1023 /* Implemented Interfaces */
1024 TLBImplType * impltypelist;
1027 TLBCustData * pCustData; /* linked list to cust data; */
1028 struct tagITypeInfoImpl * next;
1031 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1033 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1036 static const ITypeInfo2Vtbl tinfvt;
1037 static const ITypeCompVtbl tcompvt;
1039 static ITypeInfo2 * ITypeInfo_Constructor(void);
1041 typedef struct tagTLBContext
1043 unsigned int oStart; /* start of TLB in file */
1044 unsigned int pos; /* current pos */
1045 unsigned int length; /* total length */
1046 void *mapping; /* memory mapping */
1047 MSFT_SegDir * pTblDir;
1048 ITypeLibImpl* pLibInfo;
1052 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1057 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1058 if (pTD->vt & VT_RESERVED)
1059 szVarType += strlen(strcpy(szVarType, "reserved | "));
1060 if (pTD->vt & VT_BYREF)
1061 szVarType += strlen(strcpy(szVarType, "ref to "));
1062 if (pTD->vt & VT_ARRAY)
1063 szVarType += strlen(strcpy(szVarType, "array of "));
1064 if (pTD->vt & VT_VECTOR)
1065 szVarType += strlen(strcpy(szVarType, "vector of "));
1066 switch(pTD->vt & VT_TYPEMASK) {
1067 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1068 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1069 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1070 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1071 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1072 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1073 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1074 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1075 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1076 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1077 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1078 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1079 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1080 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1081 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1082 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1083 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1084 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1085 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1086 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1087 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1088 pTD->u.hreftype); break;
1089 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1090 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1091 case VT_PTR: sprintf(szVarType, "ptr to ");
1092 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1094 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1095 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1097 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1098 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1099 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1102 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1106 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1108 USHORT flags = edesc->u.paramdesc.wParamFlags;
1109 dump_TypeDesc(&edesc->tdesc,buf);
1110 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1111 MESSAGE("\t\tu.paramdesc.wParamFlags");
1112 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1113 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1114 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1115 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1116 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1117 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1118 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1119 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1120 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1122 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1124 MESSAGE("memid is %08x\n",funcdesc->memid);
1125 for (i=0;i<funcdesc->cParams;i++) {
1126 MESSAGE("Param %d:\n",i);
1127 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1129 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1130 switch (funcdesc->funckind) {
1131 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1132 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1133 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1134 case FUNC_STATIC: MESSAGE("static");break;
1135 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1136 default: MESSAGE("unknown");break;
1138 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1139 switch (funcdesc->invkind) {
1140 case INVOKE_FUNC: MESSAGE("func");break;
1141 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1142 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1143 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1145 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1146 switch (funcdesc->callconv) {
1147 case CC_CDECL: MESSAGE("cdecl");break;
1148 case CC_PASCAL: MESSAGE("pascal");break;
1149 case CC_STDCALL: MESSAGE("stdcall");break;
1150 case CC_SYSCALL: MESSAGE("syscall");break;
1153 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1154 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1155 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1157 MESSAGE("\telemdescFunc (return value type):\n");
1158 dump_ELEMDESC(&funcdesc->elemdescFunc);
1161 static const char * const typekind_desc[] =
1174 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1177 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1178 for (i=0;i<pfd->funcdesc.cParams;i++)
1179 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1182 dump_FUNCDESC(&(pfd->funcdesc));
1184 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1185 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1187 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1191 dump_TLBFuncDescOne(pfd);
1195 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1199 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1204 static void dump_TLBImpLib(const TLBImpLib *import)
1206 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1207 debugstr_w(import->name));
1208 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1209 import->wVersionMinor, import->lcid, import->offset);
1212 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1216 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1218 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1219 if(ref->index == -1)
1220 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1222 TRACE_(typelib)("type no: %d\n", ref->index);
1224 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1226 TRACE_(typelib)("in lib\n");
1227 dump_TLBImpLib(ref->pImpTLInfo);
1232 static void dump_TLBImplType(const TLBImplType * impl)
1236 "implementing/inheriting interface hRef = %x implflags %x\n",
1237 impl->hRef, impl->implflags);
1242 static void dump_Variant(const VARIANT * pvar)
1246 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1250 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1251 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1253 TRACE(",%p", V_BYREF(pvar));
1255 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1257 TRACE(",%p", V_ARRAY(pvar));
1259 else switch (V_TYPE(pvar))
1261 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1262 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1263 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1264 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1266 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1268 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1269 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1270 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1271 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1272 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1273 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1274 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1275 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1276 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1277 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1278 V_CY(pvar).s.Lo); break;
1280 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1281 TRACE(",<invalid>");
1283 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1284 st.wHour, st.wMinute, st.wSecond);
1288 case VT_USERDEFINED:
1290 case VT_NULL: break;
1291 default: TRACE(",?"); break;
1297 static void dump_DispParms(const DISPPARAMS * pdp)
1301 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1303 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1305 TRACE("named args:\n");
1306 for (index = 0; index < pdp->cNamedArgs; index++)
1307 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1310 if (pdp->cArgs && pdp->rgvarg)
1313 for (index = 0; index < pdp->cArgs; index++)
1314 dump_Variant( &pdp->rgvarg[index] );
1318 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1320 TRACE("%p ref=%u\n", pty, pty->ref);
1321 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1322 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1323 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1324 TRACE("fct:%u var:%u impl:%u\n",
1325 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1326 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1327 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1328 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1330 dump_TLBFuncDesc(pty->funclist);
1331 dump_TLBVarDesc(pty->varlist);
1332 dump_TLBImplType(pty->impltypelist);
1335 static void dump_VARDESC(const VARDESC *v)
1337 MESSAGE("memid %d\n",v->memid);
1338 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1339 MESSAGE("oInst %d\n",v->u.oInst);
1340 dump_ELEMDESC(&(v->elemdescVar));
1341 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1342 MESSAGE("varkind %d\n",v->varkind);
1345 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1347 /* VT_LPWSTR is largest type that */
1348 /* may appear in type description*/
1349 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1350 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1351 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1352 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1353 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1354 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1358 static void TLB_abort(void)
1363 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1364 static void * TLB_Alloc(unsigned size)
1367 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1369 ERR("cannot allocate memory\n");
1374 static void TLB_Free(void * ptr)
1376 HeapFree(GetProcessHeap(), 0, ptr);
1379 /* returns the size required for a deep copy of a typedesc into a
1381 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1385 if (alloc_initial_space)
1386 size += sizeof(TYPEDESC);
1392 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1395 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1396 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1402 /* deep copy a typedesc into a flat buffer */
1403 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1408 buffer = (char *)buffer + sizeof(TYPEDESC);
1417 dest->u.lptdesc = buffer;
1418 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1421 dest->u.lpadesc = buffer;
1422 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1423 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1424 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1430 /* free custom data allocated by MSFT_CustData */
1431 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1433 TLBCustData *pCustDataNext;
1434 for (; pCustData; pCustData = pCustDataNext)
1436 VariantClear(&pCustData->data);
1438 pCustDataNext = pCustData->next;
1439 TLB_Free(pCustData);
1443 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1448 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1449 ret = SysAllocStringLen(NULL, len - 1);
1450 if (!ret) return ret;
1451 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1455 /**********************************************************************
1457 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1459 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1464 static inline void MSFT_Seek(TLBContext *pcx, long where)
1466 if (where != DO_NOT_SEEK)
1468 where += pcx->oStart;
1469 if (where > pcx->length)
1472 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1480 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1482 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1483 pcx->pos, count, pcx->oStart, pcx->length, where);
1485 MSFT_Seek(pcx, where);
1486 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1487 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1492 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1497 ret = MSFT_Read(buffer, count, pcx, where);
1498 FromLEDWords(buffer, ret);
1503 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1508 ret = MSFT_Read(buffer, count, pcx, where);
1509 FromLEWords(buffer, ret);
1514 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1516 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1517 memset(pGuid,0, sizeof(GUID));
1520 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1521 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1522 pGuid->Data2 = FromLEWord(pGuid->Data2);
1523 pGuid->Data3 = FromLEWord(pGuid->Data3);
1524 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1527 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1529 MSFT_NameIntro niName;
1533 ERR_(typelib)("bad offset %d\n", offset);
1537 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1538 pcx->pTblDir->pNametab.offset+offset);
1540 return niName.hreftype;
1543 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1546 MSFT_NameIntro niName;
1548 BSTR bstrName = NULL;
1552 ERR_(typelib)("bad offset %d\n", offset);
1555 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1556 pcx->pTblDir->pNametab.offset+offset);
1557 niName.namelen &= 0xFF; /* FIXME: correct ? */
1558 name=TLB_Alloc((niName.namelen & 0xff) +1);
1559 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1560 name[niName.namelen & 0xff]='\0';
1562 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1565 /* no invalid characters in string */
1568 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1570 /* don't check for invalid character since this has been done previously */
1571 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1575 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1579 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1586 if(offset<0) return NULL;
1587 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1588 if(length <= 0) return 0;
1589 string=TLB_Alloc(length +1);
1590 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1591 string[length]='\0';
1593 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1594 string, -1, NULL, 0);
1596 /* no invalid characters in string */
1599 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1601 /* don't check for invalid character since this has been done previously */
1602 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1606 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1610 * read a value and fill a VARIANT structure
1612 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1616 TRACE_(typelib)("\n");
1618 if(offset <0) { /* data are packed in here */
1619 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1620 V_I4(pVar) = offset & 0x3ffffff;
1623 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1624 pcx->pTblDir->pCustData.offset + offset );
1625 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1626 switch (V_VT(pVar)){
1627 case VT_EMPTY: /* FIXME: is this right? */
1628 case VT_NULL: /* FIXME: is this right? */
1629 case VT_I2 : /* this should not happen */
1640 case VT_VOID : /* FIXME: is this right? */
1648 case VT_DECIMAL : /* FIXME: is this right? */
1651 /* pointer types with known behaviour */
1654 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1657 DWORD origPos = MSFT_Tell(pcx), nullPos;
1660 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1662 nullPos = MSFT_Tell(pcx);
1663 size = nullPos - origPos;
1664 MSFT_Seek(pcx, origPos);
1666 ptr=TLB_Alloc(size);/* allocate temp buffer */
1667 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1668 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1669 /* FIXME: do we need a AtoW conversion here? */
1670 V_UNION(pVar, bstrVal[size])='\0';
1671 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1675 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1682 case VT_USERDEFINED :
1688 case VT_STREAMED_OBJECT :
1689 case VT_STORED_OBJECT :
1690 case VT_BLOB_OBJECT :
1695 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1699 if(size>0) /* (big|small) endian correct? */
1700 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1704 * create a linked list with custom data
1706 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1712 TRACE_(typelib)("\n");
1716 pNew=TLB_Alloc(sizeof(TLBCustData));
1717 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1718 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1719 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1720 /* add new custom data at head of the list */
1721 pNew->next=*ppCustData;
1723 offset = entry.next;
1728 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1732 pTd->vt=type & VT_TYPEMASK;
1734 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1736 if(pTd->vt == VT_USERDEFINED)
1737 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1739 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1742 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1744 /* resolve referenced type if any */
1747 switch (lpTypeDesc->vt)
1750 lpTypeDesc = lpTypeDesc->u.lptdesc;
1754 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1757 case VT_USERDEFINED:
1758 MSFT_DoRefType(pcx, pTI->pTypeLib,
1759 lpTypeDesc->u.hreftype);
1771 MSFT_DoFuncs(TLBContext* pcx,
1776 TLBFuncDesc** pptfd)
1779 * member information is stored in a data structure at offset
1780 * indicated by the memoffset field of the typeinfo structure
1781 * There are several distinctive parts.
1782 * The first part starts with a field that holds the total length
1783 * of this (first) part excluding this field. Then follow the records,
1784 * for each member there is one record.
1786 * The first entry is always the length of the record (including this
1788 * The rest of the record depends on the type of the member. If there is
1789 * a field indicating the member type (function, variable, interface, etc)
1790 * I have not found it yet. At this time we depend on the information
1791 * in the type info and the usual order how things are stored.
1793 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1796 * Third is an equal sized array with file offsets to the name entry
1799 * The fourth and last (?) part is an array with offsets to the records
1800 * in the first part of this file segment.
1803 int infolen, nameoffset, reclength, nrattributes, i;
1804 int recoffset = offset + sizeof(INT);
1806 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1807 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1808 TLBFuncDesc *ptfd_prev = NULL;
1810 TRACE_(typelib)("\n");
1812 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1814 for ( i = 0; i < cFuncs ; i++ )
1816 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1818 /* name, eventually add to a hash table */
1819 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1820 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1822 /* nameoffset is sometimes -1 on the second half of a propget/propput
1823 * pair of functions */
1824 if ((nameoffset == -1) && (i > 0))
1825 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1827 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1829 /* read the function information record */
1830 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1832 reclength &= 0xffff;
1834 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1836 /* do the attributes */
1837 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1840 if ( nrattributes > 0 )
1842 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1844 if ( nrattributes > 1 )
1846 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1847 pFuncRec->OptAttr[1]) ;
1849 if ( nrattributes > 2 )
1851 if ( pFuncRec->FKCCIC & 0x2000 )
1853 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1854 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1855 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1859 (*pptfd)->Entry = MSFT_ReadString(pcx,
1860 pFuncRec->OptAttr[2]);
1862 if( nrattributes > 5 )
1864 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1866 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1869 pFuncRec->OptAttr[6],
1870 &(*pptfd)->pCustData);
1876 (*pptfd)->Entry = (BSTR)-1;
1881 /* fill the FuncDesc Structure */
1882 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1883 offset + infolen + ( i + 1) * sizeof(INT));
1885 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1886 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1887 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1888 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1889 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1890 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1891 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1895 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1897 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1899 /* do the parameters/arguments */
1900 if(pFuncRec->nrargs)
1903 MSFT_ParameterInfo paraminfo;
1905 (*pptfd)->funcdesc.lprgelemdescParam =
1906 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1908 (*pptfd)->pParamDesc =
1909 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1911 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1912 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1914 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1916 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1923 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1926 if (paraminfo.oName == -1)
1927 /* this occurs for [propput] or [propget] methods, so
1928 * we should just set the name of the parameter to the
1929 * name of the method. */
1930 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1932 (*pptfd)->pParamDesc[j].Name =
1933 MSFT_ReadName( pcx, paraminfo.oName );
1934 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1936 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1939 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1940 (pFuncRec->FKCCIC & 0x1000) )
1942 INT* pInt = (INT *)((char *)pFuncRec +
1944 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1946 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1948 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1949 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1951 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1955 elemdesc->u.paramdesc.pparamdescex = NULL;
1957 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1960 pFuncRec->OptAttr[7+j],
1961 &(*pptfd)->pParamDesc[j].pCustData);
1964 /* SEEK value = jump to offset,
1965 * from there jump to the end of record,
1966 * go back by (j-1) arguments
1968 MSFT_ReadLEDWords( ¶minfo ,
1969 sizeof(MSFT_ParameterInfo), pcx,
1970 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1971 * sizeof(MSFT_ParameterInfo)));
1975 /* scode is not used: archaic win16 stuff FIXME: right? */
1976 (*pptfd)->funcdesc.cScodes = 0 ;
1977 (*pptfd)->funcdesc.lprgscode = NULL ;
1980 pptfd = & ((*pptfd)->next);
1981 recoffset += reclength;
1983 HeapFree(GetProcessHeap(), 0, recbuf);
1986 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1987 int cVars, int offset, TLBVarDesc ** pptvd)
1989 int infolen, nameoffset, reclength;
1991 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1995 TRACE_(typelib)("\n");
1997 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1998 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1999 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2000 recoffset += offset+sizeof(INT);
2001 for(i=0;i<cVars;i++){
2002 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2003 /* name, eventually add to a hash table */
2004 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2005 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2006 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2007 /* read the variable information record */
2008 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2010 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2012 if(reclength >(6*sizeof(INT)) )
2013 (*pptvd)->HelpContext=pVarRec->HelpContext;
2014 if(reclength >(7*sizeof(INT)) )
2015 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2016 if(reclength >(8*sizeof(INT)) )
2017 if(reclength >(9*sizeof(INT)) )
2018 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2019 /* fill the VarDesc Structure */
2020 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2021 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2022 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2023 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2024 MSFT_GetTdesc(pcx, pVarRec->DataType,
2025 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2026 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2027 if(pVarRec->VarKind == VAR_CONST ){
2028 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2029 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2030 pVarRec->OffsValue, pcx);
2032 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2033 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2034 pptvd=&((*pptvd)->next);
2035 recoffset += reclength;
2038 /* fill in data for a hreftype (offset). When the referenced type is contained
2039 * in the typelib, it's just an (file) offset in the type info base dir.
2040 * If comes from import, it's an offset+1 in the ImpInfo table
2042 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2047 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2049 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2051 if(ref->reference == offset) return;
2054 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2055 list_add_tail(&pTL->ref_list, &ref->entry);
2057 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2058 /* external typelib */
2059 MSFT_ImpInfo impinfo;
2060 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2062 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2064 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2065 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2066 while (pImpLib){ /* search the known offsets of all import libraries */
2067 if(pImpLib->offset==impinfo.oImpFile) break;
2068 pImpLib=pImpLib->next;
2071 ref->reference = offset;
2072 ref->pImpTLInfo = pImpLib;
2073 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2074 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2075 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2076 ref->index = TLB_REF_USE_GUID;
2078 ref->index = impinfo.oGuid;
2080 ERR("Cannot find a reference\n");
2081 ref->reference = -1;
2082 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2085 /* in this typelib */
2086 ref->index = MSFT_HREFTYPE_INDEX(offset);
2087 ref->reference = offset;
2088 ref->pImpTLInfo = TLB_REF_INTERNAL;
2092 /* process Implemented Interfaces of a com class */
2093 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2097 MSFT_RefRecord refrec;
2098 TLBImplType **ppImpl = &pTI->impltypelist;
2100 TRACE_(typelib)("\n");
2102 for(i=0;i<count;i++){
2103 if(offset<0) break; /* paranoia */
2104 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2105 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2106 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2107 (*ppImpl)->hRef = refrec.reftype;
2108 (*ppImpl)->implflags=refrec.flags;
2109 (*ppImpl)->ctCustData=
2110 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2111 offset=refrec.onext;
2112 ppImpl=&((*ppImpl)->next);
2116 * process a typeinfo record
2118 static ITypeInfoImpl * MSFT_DoTypeInfo(
2121 ITypeLibImpl * pLibInfo)
2123 MSFT_TypeInfoBase tiBase;
2124 ITypeInfoImpl *ptiRet;
2126 TRACE_(typelib)("count=%u\n", count);
2128 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2129 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2130 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2132 /* this is where we are coming from */
2133 ptiRet->pTypeLib = pLibInfo;
2134 ptiRet->index=count;
2135 /* fill in the typeattr fields */
2137 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2138 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2139 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2140 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2141 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2142 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2143 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2144 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2145 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2146 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2147 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2148 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2149 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2150 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2151 MSFT_GetTdesc(pcx, tiBase.datatype1,
2152 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2155 /* IDLDESC idldescType; *//* never saw this one != zero */
2157 /* name, eventually add to a hash table */
2158 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2159 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2160 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2162 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2163 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2164 ptiRet->dwHelpContext=tiBase.helpcontext;
2166 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2167 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2169 /* note: InfoType's Help file and HelpStringDll come from the containing
2170 * library. Further HelpString and Docstring appear to be the same thing :(
2173 if(ptiRet->TypeAttr.cFuncs >0 )
2174 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2175 ptiRet->TypeAttr.cVars,
2176 tiBase.memoffset, & ptiRet->funclist);
2178 if(ptiRet->TypeAttr.cVars >0 )
2179 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2180 ptiRet->TypeAttr.cVars,
2181 tiBase.memoffset, & ptiRet->varlist);
2182 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2183 switch(ptiRet->TypeAttr.typekind)
2186 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2189 case TKIND_DISPATCH:
2190 /* This is not -1 when the interface is a non-base dual interface or
2191 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2192 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2196 if (tiBase.datatype1 != -1)
2198 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2199 ptiRet->impltypelist->hRef = tiBase.datatype1;
2200 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2204 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2205 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2206 ptiRet->impltypelist->hRef = tiBase.datatype1;
2211 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2213 TRACE_(typelib)("%s guid: %s kind:%s\n",
2214 debugstr_w(ptiRet->Name),
2215 debugstr_guid(&ptiRet->TypeAttr.guid),
2216 typekind_desc[ptiRet->TypeAttr.typekind]);
2217 if (TRACE_ON(typelib))
2218 dump_TypeInfo(ptiRet);
2223 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2224 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2225 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2228 static ITypeLibImpl *tlb_cache_first;
2229 static CRITICAL_SECTION cache_section;
2230 static CRITICAL_SECTION_DEBUG cache_section_debug =
2232 0, 0, &cache_section,
2233 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2234 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2236 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2239 typedef struct TLB_PEFile
2241 const IUnknownVtbl *lpvtbl;
2244 HRSRC typelib_resource;
2245 HGLOBAL typelib_global;
2246 LPVOID typelib_base;
2249 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2251 if (IsEqualIID(riid, &IID_IUnknown))
2254 IUnknown_AddRef(iface);
2258 return E_NOINTERFACE;
2261 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2263 TLB_PEFile *This = (TLB_PEFile *)iface;
2264 return InterlockedIncrement(&This->refs);
2267 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2269 TLB_PEFile *This = (TLB_PEFile *)iface;
2270 ULONG refs = InterlockedDecrement(&This->refs);
2273 if (This->typelib_global)
2274 FreeResource(This->typelib_global);
2276 FreeLibrary(This->dll);
2277 HeapFree(GetProcessHeap(), 0, This);
2282 static const IUnknownVtbl TLB_PEFile_Vtable =
2284 TLB_PEFile_QueryInterface,
2289 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2293 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2295 return E_OUTOFMEMORY;
2297 This->lpvtbl = &TLB_PEFile_Vtable;
2300 This->typelib_resource = NULL;
2301 This->typelib_global = NULL;
2302 This->typelib_base = NULL;
2304 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2305 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2309 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2310 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2311 if (This->typelib_resource)
2313 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2314 if (This->typelib_global)
2316 This->typelib_base = LockResource(This->typelib_global);
2318 if (This->typelib_base)
2320 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2321 *ppBase = This->typelib_base;
2322 *ppFile = (IUnknown *)&This->lpvtbl;
2329 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2330 return TYPE_E_CANTLOADLIBRARY;
2333 typedef struct TLB_NEFile
2335 const IUnknownVtbl *lpvtbl;
2337 LPVOID typelib_base;
2340 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2342 if (IsEqualIID(riid, &IID_IUnknown))
2345 IUnknown_AddRef(iface);
2349 return E_NOINTERFACE;
2352 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2354 TLB_NEFile *This = (TLB_NEFile *)iface;
2355 return InterlockedIncrement(&This->refs);
2358 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2360 TLB_NEFile *This = (TLB_NEFile *)iface;
2361 ULONG refs = InterlockedDecrement(&This->refs);
2364 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2365 HeapFree(GetProcessHeap(), 0, This);
2370 static const IUnknownVtbl TLB_NEFile_Vtable =
2372 TLB_NEFile_QueryInterface,
2377 /***********************************************************************
2378 * read_xx_header [internal]
2380 static int read_xx_header( HFILE lzfd )
2382 IMAGE_DOS_HEADER mzh;
2385 LZSeek( lzfd, 0, SEEK_SET );
2386 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2388 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2391 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2392 if ( 2 != LZRead( lzfd, magic, 2 ) )
2395 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2397 if ( magic[0] == 'N' && magic[1] == 'E' )
2398 return IMAGE_OS2_SIGNATURE;
2399 if ( magic[0] == 'P' && magic[1] == 'E' )
2400 return IMAGE_NT_SIGNATURE;
2403 WARN("Can't handle %s files.\n", magic );
2408 /***********************************************************************
2409 * find_ne_resource [internal]
2411 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2412 DWORD *resLen, DWORD *resOff )
2414 IMAGE_OS2_HEADER nehd;
2415 NE_TYPEINFO *typeInfo;
2416 NE_NAMEINFO *nameInfo;
2422 /* Read in NE header */
2423 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2424 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2426 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2429 TRACE("No resources in NE dll\n" );
2433 /* Read in resource table */
2434 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2435 if ( !resTab ) return FALSE;
2437 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2438 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2440 HeapFree( GetProcessHeap(), 0, resTab );
2445 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2447 if (HIWORD(typeid) != 0) /* named type */
2449 BYTE len = strlen( typeid );
2450 while (typeInfo->type_id)
2452 if (!(typeInfo->type_id & 0x8000))
2454 BYTE *p = resTab + typeInfo->type_id;
2455 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2457 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2458 typeInfo->count * sizeof(NE_NAMEINFO));
2461 else /* numeric type id */
2463 WORD id = LOWORD(typeid) | 0x8000;
2464 while (typeInfo->type_id)
2466 if (typeInfo->type_id == id) goto found_type;
2467 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2468 typeInfo->count * sizeof(NE_NAMEINFO));
2471 TRACE("No typeid entry found for %p\n", typeid );
2472 HeapFree( GetProcessHeap(), 0, resTab );
2476 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2478 if (HIWORD(resid) != 0) /* named resource */
2480 BYTE len = strlen( resid );
2481 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2483 BYTE *p = resTab + nameInfo->id;
2484 if (nameInfo->id & 0x8000) continue;
2485 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2488 else /* numeric resource id */
2490 WORD id = LOWORD(resid) | 0x8000;
2491 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2492 if (nameInfo->id == id) goto found_name;
2494 TRACE("No resid entry found for %p\n", typeid );
2495 HeapFree( GetProcessHeap(), 0, resTab );
2499 /* Return resource data */
2500 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2501 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2503 HeapFree( GetProcessHeap(), 0, resTab );
2507 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2511 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2512 TLB_NEFile *This = NULL;
2514 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2515 if (!This) return E_OUTOFMEMORY;
2517 This->lpvtbl = &TLB_NEFile_Vtable;
2519 This->typelib_base = NULL;
2521 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2522 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2524 DWORD reslen, offset;
2525 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2527 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2528 if( !This->typelib_base )
2532 LZSeek( lzfd, offset, SEEK_SET );
2533 reslen = LZRead( lzfd, This->typelib_base, reslen );
2535 *ppBase = This->typelib_base;
2536 *pdwTLBLength = reslen;
2537 *ppFile = (IUnknown *)&This->lpvtbl;
2543 if( lzfd >= 0) LZClose( lzfd );
2544 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2548 typedef struct TLB_Mapping
2550 const IUnknownVtbl *lpvtbl;
2554 LPVOID typelib_base;
2557 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2559 if (IsEqualIID(riid, &IID_IUnknown))
2562 IUnknown_AddRef(iface);
2566 return E_NOINTERFACE;
2569 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2571 TLB_Mapping *This = (TLB_Mapping *)iface;
2572 return InterlockedIncrement(&This->refs);
2575 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2577 TLB_Mapping *This = (TLB_Mapping *)iface;
2578 ULONG refs = InterlockedDecrement(&This->refs);
2581 if (This->typelib_base)
2582 UnmapViewOfFile(This->typelib_base);
2584 CloseHandle(This->mapping);
2585 if (This->file != INVALID_HANDLE_VALUE)
2586 CloseHandle(This->file);
2587 HeapFree(GetProcessHeap(), 0, This);
2592 static const IUnknownVtbl TLB_Mapping_Vtable =
2594 TLB_Mapping_QueryInterface,
2599 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2603 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2605 return E_OUTOFMEMORY;
2607 This->lpvtbl = &TLB_Mapping_Vtable;
2609 This->file = INVALID_HANDLE_VALUE;
2610 This->mapping = NULL;
2611 This->typelib_base = NULL;
2613 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2614 if (INVALID_HANDLE_VALUE != This->file)
2616 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2619 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2620 if(This->typelib_base)
2622 /* retrieve file size */
2623 *pdwTLBLength = GetFileSize(This->file, NULL);
2624 *ppBase = This->typelib_base;
2625 *ppFile = (IUnknown *)&This->lpvtbl;
2631 IUnknown_Release((IUnknown *)&This->lpvtbl);
2632 return TYPE_E_CANTLOADLIBRARY;
2635 /****************************************************************************
2638 * find the type of the typelib file and map the typelib resource into
2641 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2642 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2643 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2645 ITypeLibImpl *entry;
2648 LPWSTR index_str, file = (LPWSTR)pszFileName;
2649 LPVOID pBase = NULL;
2650 DWORD dwTLBLength = 0;
2651 IUnknown *pFile = NULL;
2655 index_str = strrchrW(pszFileName, '\\');
2656 if(index_str && *++index_str != '\0')
2659 long idx = strtolW(index_str, &end_ptr, 10);
2660 if(*end_ptr == '\0')
2662 int str_len = index_str - pszFileName - 1;
2664 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2665 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2670 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2672 if(strchrW(file, '\\'))
2674 lstrcpyW(pszPath, file);
2678 int len = GetSystemDirectoryW(pszPath, cchPath);
2679 pszPath[len] = '\\';
2680 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2684 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2686 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2688 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2689 EnterCriticalSection(&cache_section);
2690 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2692 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2694 TRACE("cache hit\n");
2695 *ppTypeLib = (ITypeLib2*)entry;
2696 ITypeLib_AddRef(*ppTypeLib);
2697 LeaveCriticalSection(&cache_section);
2701 LeaveCriticalSection(&cache_section);
2703 /* now actually load and parse the typelib */
2705 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2706 if (ret == TYPE_E_CANTLOADLIBRARY)
2707 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2708 if (ret == TYPE_E_CANTLOADLIBRARY)
2709 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2712 if (dwTLBLength >= 4)
2714 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2715 if (dwSignature == MSFT_SIGNATURE)
2716 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2717 else if (dwSignature == SLTG_SIGNATURE)
2718 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2721 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2722 ret = TYPE_E_CANTLOADLIBRARY;
2726 ret = TYPE_E_CANTLOADLIBRARY;
2727 IUnknown_Release(pFile);
2731 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2733 TRACE("adding to cache\n");
2734 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2735 lstrcpyW(impl->path, pszPath);
2736 /* We should really canonicalise the path here. */
2737 impl->index = index;
2739 /* FIXME: check if it has added already in the meantime */
2740 EnterCriticalSection(&cache_section);
2741 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2743 tlb_cache_first = impl;
2744 LeaveCriticalSection(&cache_section);
2747 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2752 /*================== ITypeLib(2) Methods ===================================*/
2754 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2756 ITypeLibImpl* pTypeLibImpl;
2758 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2759 if (!pTypeLibImpl) return NULL;
2761 pTypeLibImpl->lpVtbl = &tlbvt;
2762 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2763 pTypeLibImpl->ref = 1;
2765 list_init(&pTypeLibImpl->ref_list);
2766 pTypeLibImpl->dispatch_href = -1;
2768 return pTypeLibImpl;
2771 /****************************************************************************
2772 * ITypeLib2_Constructor_MSFT
2774 * loading an MSFT typelib from an in-memory image
2776 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2780 MSFT_Header tlbHeader;
2781 MSFT_SegDir tlbSegDir;
2782 ITypeLibImpl * pTypeLibImpl;
2784 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2786 pTypeLibImpl = TypeLibImpl_Constructor();
2787 if (!pTypeLibImpl) return NULL;
2789 /* get pointer to beginning of typelib data */
2793 cx.pLibInfo = pTypeLibImpl;
2794 cx.length = dwTLBLength;
2797 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2798 TRACE_(typelib)("header:\n");
2799 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2800 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2801 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2804 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2806 /* there is a small amount of information here until the next important
2808 * the segment directory . Try to calculate the amount of data */
2809 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2811 /* now read the segment directory */
2812 TRACE("read segment directory (at %ld)\n",lPSegDir);
2813 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2814 cx.pTblDir = &tlbSegDir;
2816 /* just check two entries */
2817 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2819 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2820 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2824 /* now fill our internal data */
2825 /* TLIBATTR fields */
2826 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2828 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2829 /* Windows seems to have zero here, is this correct? */
2830 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2831 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2833 pTypeLibImpl->LibAttr.lcid = 0;
2835 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2836 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2837 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2838 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2840 /* name, eventually add to a hash table */
2841 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2844 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2845 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2847 if( tlbHeader.varflags & HELPDLLFLAG)
2850 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2851 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2854 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2857 if(tlbHeader.CustomDataOffset >= 0)
2859 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2862 /* fill in type descriptions */
2863 if(tlbSegDir.pTypdescTab.length > 0)
2865 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2867 pTypeLibImpl->ctTypeDesc = cTD;
2868 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2869 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2872 /* FIXME: add several sanity checks here */
2873 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2874 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2876 /* FIXME: check safearray */
2878 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2880 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2882 else if(td[0] == VT_CARRAY)
2884 /* array descr table here */
2885 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2887 else if(td[0] == VT_USERDEFINED)
2889 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2891 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2894 /* second time around to fill the array subscript info */
2897 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2898 if(tlbSegDir.pArrayDescriptions.offset>0)
2900 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2901 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2904 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2906 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2908 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2910 for(j = 0; j<td[2]; j++)
2912 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2913 sizeof(INT), &cx, DO_NOT_SEEK);
2914 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2915 sizeof(INT), &cx, DO_NOT_SEEK);
2920 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2921 ERR("didn't find array description data\n");
2926 /* imported type libs */
2927 if(tlbSegDir.pImpFiles.offset>0)
2929 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2930 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2933 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2937 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2938 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2939 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2941 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2942 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2943 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2944 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2947 name = TLB_Alloc(size+1);
2948 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2949 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2951 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2952 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2954 ppImpLib = &(*ppImpLib)->next;
2958 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2959 if(pTypeLibImpl->dispatch_href != -1)
2960 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2963 if(tlbHeader.nrtypeinfos >= 0 )
2965 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2966 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2969 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2971 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2973 ppTI = &((*ppTI)->next);
2974 (pTypeLibImpl->TypeInfoCount)++;
2978 TRACE("(%p)\n", pTypeLibImpl);
2979 return (ITypeLib2*) pTypeLibImpl;
2983 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2989 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2990 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2994 guid->Data4[0] = s >> 8;
2995 guid->Data4[1] = s & 0xff;
2998 for(i = 0; i < 6; i++) {
2999 memcpy(b, str + 24 + 2 * i, 2);
3000 guid->Data4[i + 2] = strtol(b, NULL, 16);
3005 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3011 bytelen = *(const WORD*)ptr;
3012 if(bytelen == 0xffff) return 2;
3013 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3014 *pBstr = SysAllocStringLen(NULL, len - 1);
3016 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3020 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3025 bytelen = *(const WORD*)ptr;
3026 if(bytelen == 0xffff) return 2;
3027 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3028 memcpy(*str, ptr + 2, bytelen);
3029 (*str)[bytelen] = '\0';
3033 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3035 char *ptr = pLibBlk;
3038 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3039 FIXME("libblk magic = %04x\n", w);
3044 if((w = *(WORD*)ptr) != 0xffff) {
3045 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3050 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3052 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3054 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3057 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3060 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3061 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3063 pTypeLibImpl->LibAttr.lcid = 0;
3066 ptr += 4; /* skip res12 */
3068 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3071 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3074 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3077 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3078 ptr += sizeof(GUID);
3080 return ptr - (char*)pLibBlk;
3083 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3088 } sltg_ref_lookup_t;
3090 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3091 HREFTYPE *typelib_ref)
3093 if(typeinfo_ref < table->num)
3095 *typelib_ref = table->refs[typeinfo_ref];
3099 ERR_(typelib)("Unable to find reference\n");
3104 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3109 if((*pType & 0xe00) == 0xe00) {
3111 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3113 pTD = pTD->u.lptdesc;
3115 switch(*pType & 0x3f) {
3118 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3120 pTD = pTD->u.lptdesc;
3123 case VT_USERDEFINED:
3124 pTD->vt = VT_USERDEFINED;
3125 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3131 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3134 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3136 pTD->vt = VT_CARRAY;
3137 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3139 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3140 pTD->u.lpadesc->cDims = pSA->cDims;
3141 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3142 pSA->cDims * sizeof(SAFEARRAYBOUND));
3144 pTD = &pTD->u.lpadesc->tdescElem;
3150 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3154 pTD->vt = VT_SAFEARRAY;
3155 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3157 pTD = pTD->u.lptdesc;
3161 pTD->vt = *pType & 0x3f;
3170 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3171 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3173 /* Handle [in/out] first */
3174 if((*pType & 0xc000) == 0xc000)
3175 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3176 else if(*pType & 0x8000)
3177 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3178 else if(*pType & 0x4000)
3179 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3181 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3184 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3187 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3189 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3193 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3198 TLBRefType *ref_type;
3199 sltg_ref_lookup_t *table;
3200 HREFTYPE typelib_ref;
3202 if(pRef->magic != SLTG_REF_MAGIC) {
3203 FIXME("Ref magic = %x\n", pRef->magic);
3206 name = ( (char*)pRef->names + pRef->number);
3208 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3209 table->num = pRef->number >> 3;
3211 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3213 /* We don't want the first href to be 0 */
3214 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3216 for(ref = 0; ref < pRef->number >> 3; ref++) {
3218 unsigned int lib_offs, type_num;
3220 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3222 name += SLTG_ReadStringA(name, &refname);
3223 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3224 FIXME_(typelib)("Can't sscanf ref\n");
3225 if(lib_offs != 0xffff) {
3226 TLBImpLib **import = &pTL->pImpLibs;
3229 if((*import)->offset == lib_offs)
3231 import = &(*import)->next;
3234 char fname[MAX_PATH+1];
3237 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3239 (*import)->offset = lib_offs;
3240 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3242 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3243 &(*import)->wVersionMajor,
3244 &(*import)->wVersionMinor,
3245 &(*import)->lcid, fname) != 4) {
3246 FIXME_(typelib)("can't sscanf ref %s\n",
3247 pNameTable + lib_offs + 40);
3249 len = strlen(fname);
3250 if(fname[len-1] != '#')
3251 FIXME("fname = %s\n", fname);
3252 fname[len-1] = '\0';
3253 (*import)->name = TLB_MultiByteToBSTR(fname);
3255 ref_type->pImpTLInfo = *import;
3257 /* Store a reference to IDispatch */
3258 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3259 pTL->dispatch_href = typelib_ref;
3261 } else { /* internal ref */
3262 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3264 ref_type->reference = typelib_ref;
3265 ref_type->index = type_num;
3267 HeapFree(GetProcessHeap(), 0, refname);
3268 list_add_tail(&pTL->ref_list, &ref_type->entry);
3270 table->refs[ref] = typelib_ref;
3273 if((BYTE)*name != SLTG_REF_MAGIC)
3274 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3275 dump_TLBRefType(pTL);
3279 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3280 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3282 SLTG_ImplInfo *info;
3283 TLBImplType **ppImplType = &pTI->impltypelist;
3284 /* I don't really get this structure, usually it's 0x16 bytes
3285 long, but iuser.tlb contains some that are 0x18 bytes long.
3286 That's ok because we can use the next ptr to jump to the next
3287 one. But how do we know the length of the last one? The WORD
3288 at offs 0x8 might be the clue. For now I'm just assuming that
3289 the last one is the regular 0x16 bytes. */
3291 info = (SLTG_ImplInfo*)pBlk;
3293 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3294 sizeof(**ppImplType));
3295 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3296 (*ppImplType)->implflags = info->impltypeflags;
3297 pTI->TypeAttr.cImplTypes++;
3298 ppImplType = &(*ppImplType)->next;
3300 if(info->next == 0xffff)
3303 FIXME_(typelib)("Interface inheriting more than one interface\n");
3304 info = (SLTG_ImplInfo*)(pBlk + info->next);
3306 info++; /* see comment at top of function */
3310 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3311 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3313 TLBVarDesc **ppVarDesc = &pTI->varlist;
3314 BSTR bstrPrevName = NULL;
3315 SLTG_Variable *pItem;
3319 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3320 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3322 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3323 sizeof(**ppVarDesc));
3324 (*ppVarDesc)->vardesc.memid = pItem->memid;
3326 if (pItem->magic != SLTG_VAR_MAGIC &&
3327 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3328 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3332 if (pItem->name == 0xfffe)
3333 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3335 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3337 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3338 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3339 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3341 if(pItem->flags & 0x02)
3342 pType = &pItem->type;
3344 pType = (WORD*)(pBlk + pItem->type);
3346 if (pItem->flags & ~0xda)
3347 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3349 SLTG_DoElem(pType, pBlk,
3350 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3352 if (TRACE_ON(typelib)) {
3354 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3355 TRACE_(typelib)("elemdescVar: %s\n", buf);
3358 if (pItem->flags & 0x40) {
3359 TRACE_(typelib)("VAR_DISPATCH\n");
3360 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3362 else if (pItem->flags & 0x10) {
3363 TRACE_(typelib)("VAR_CONST\n");
3364 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3365 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3367 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3368 if (pItem->flags & 0x08)
3369 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3371 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3377 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3379 TRACE_(typelib)("len = %u\n", len);
3380 if (len == 0xffff) {
3383 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3384 str = SysAllocStringLen(NULL, alloc_len);
3385 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3387 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3388 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3397 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3398 *(INT*)(pBlk + pItem->byte_offs);
3401 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3406 TRACE_(typelib)("VAR_PERINSTANCE\n");
3407 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3408 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3411 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3412 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3414 if (pItem->flags & 0x80)
3415 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3417 bstrPrevName = (*ppVarDesc)->Name;
3418 ppVarDesc = &((*ppVarDesc)->next);
3420 pTI->TypeAttr.cVars = cVars;
3423 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3424 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3426 SLTG_Function *pFunc;
3428 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3430 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3431 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3436 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3437 sizeof(**ppFuncDesc));
3439 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3440 case SLTG_FUNCTION_MAGIC:
3441 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3443 case SLTG_DISPATCH_FUNCTION_MAGIC:
3444 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3446 case SLTG_STATIC_FUNCTION_MAGIC:
3447 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3450 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3451 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3455 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3457 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3458 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3459 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3460 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3461 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3462 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3464 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3465 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3467 if(pFunc->retnextopt & 0x80)
3468 pType = &pFunc->rettype;
3470 pType = (WORD*)(pBlk + pFunc->rettype);
3472 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3474 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3475 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3476 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3477 (*ppFuncDesc)->pParamDesc =
3478 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3479 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3481 pArg = (WORD*)(pBlk + pFunc->arg_off);
3483 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3484 char *paramName = pNameTable + *pArg;
3486 /* If arg type follows then paramName points to the 2nd
3487 letter of the name, else the next WORD is an offset to
3488 the arg type and paramName points to the first letter.
3489 So let's take one char off paramName and see if we're
3490 pointing at an alpha-numeric char. However if *pArg is
3491 0xffff or 0xfffe then the param has no name, the former
3492 meaning that the next WORD is the type, the latter
3493 meaning that the next WORD is an offset to the type. */
3498 else if(*pArg == 0xfffe) {
3502 else if(paramName[-1] && !isalnum(paramName[-1]))
3507 if(HaveOffs) { /* the next word is an offset to type */
3508 pType = (WORD*)(pBlk + *pArg);
3509 SLTG_DoElem(pType, pBlk,
3510 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3515 pArg = SLTG_DoElem(pArg, pBlk,
3516 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3519 /* Are we an optional param ? */
3520 if((*ppFuncDesc)->funcdesc.cParams - param <=
3521 (*ppFuncDesc)->funcdesc.cParamsOpt)
3522 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3525 (*ppFuncDesc)->pParamDesc[param].Name =
3526 TLB_MultiByteToBSTR(paramName);
3528 (*ppFuncDesc)->pParamDesc[param].Name =
3529 SysAllocString((*ppFuncDesc)->Name);
3533 ppFuncDesc = &((*ppFuncDesc)->next);
3534 if(pFunc->next == 0xffff) break;
3536 pTI->TypeAttr.cFuncs = cFuncs;
3539 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3540 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3541 SLTG_TypeInfoTail *pTITail)
3544 sltg_ref_lookup_t *ref_lookup = NULL;
3546 if(pTIHeader->href_table != 0xffffffff) {
3547 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3553 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3554 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3556 HeapFree(GetProcessHeap(), 0, ref_lookup);
3560 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3561 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3562 const SLTG_TypeInfoTail *pTITail)
3565 sltg_ref_lookup_t *ref_lookup = NULL;
3567 if(pTIHeader->href_table != 0xffffffff) {
3568 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3574 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3575 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3578 if (pTITail->funcs_off != 0xffff)
3579 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3581 HeapFree(GetProcessHeap(), 0, ref_lookup);
3583 if (TRACE_ON(typelib))
3584 dump_TLBFuncDesc(pTI->funclist);
3587 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3588 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3589 const SLTG_TypeInfoTail *pTITail)
3591 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3594 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3595 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3596 const SLTG_TypeInfoTail *pTITail)
3599 sltg_ref_lookup_t *ref_lookup = NULL;
3601 if (pTITail->simple_alias) {
3602 /* if simple alias, no more processing required */
3603 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3607 if(pTIHeader->href_table != 0xffffffff) {
3608 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3612 /* otherwise it is an offset to a type */
3613 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3615 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3617 HeapFree(GetProcessHeap(), 0, ref_lookup);
3620 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3621 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3622 const SLTG_TypeInfoTail *pTITail)
3624 sltg_ref_lookup_t *ref_lookup = NULL;
3625 if (pTIHeader->href_table != 0xffffffff)
3626 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3629 if (pTITail->vars_off != 0xffff)
3630 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3632 if (pTITail->funcs_off != 0xffff)
3633 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3635 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3636 * of dispinterface functions including the IDispatch ones, so
3637 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3638 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3640 HeapFree(GetProcessHeap(), 0, ref_lookup);
3641 if (TRACE_ON(typelib))
3642 dump_TLBFuncDesc(pTI->funclist);
3645 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3646 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3647 const SLTG_TypeInfoTail *pTITail)
3649 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3652 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3653 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3654 const SLTG_TypeInfoTail *pTITail)
3656 sltg_ref_lookup_t *ref_lookup = NULL;
3657 if (pTIHeader->href_table != 0xffffffff)
3658 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3661 if (pTITail->vars_off != 0xffff)
3662 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3664 if (pTITail->funcs_off != 0xffff)
3665 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3666 HeapFree(GetProcessHeap(), 0, ref_lookup);
3667 if (TRACE_ON(typelib))
3671 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3672 managable copy of it into this */
3685 } SLTG_InternalOtherTypeInfo;
3687 /****************************************************************************
3688 * ITypeLib2_Constructor_SLTG
3690 * loading a SLTG typelib from an in-memory image
3692 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3694 ITypeLibImpl *pTypeLibImpl;
3695 SLTG_Header *pHeader;
3696 SLTG_BlkEntry *pBlkEntry;
3700 LPVOID pBlk, pFirstBlk;
3701 SLTG_LibBlk *pLibBlk;
3702 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3703 char *pAfterOTIBlks = NULL;
3704 char *pNameTable, *ptr;
3707 ITypeInfoImpl **ppTypeInfoImpl;
3709 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3712 pTypeLibImpl = TypeLibImpl_Constructor();
3713 if (!pTypeLibImpl) return NULL;
3717 TRACE_(typelib)("header:\n");
3718 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3719 pHeader->nrOfFileBlks );
3720 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3721 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3722 pHeader->SLTG_magic);
3726 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3727 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3729 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3730 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3732 /* Next we have a magic block */
3733 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3735 /* Let's see if we're still in sync */
3736 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3737 sizeof(SLTG_COMPOBJ_MAGIC))) {
3738 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3741 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3742 sizeof(SLTG_DIR_MAGIC))) {
3743 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3747 pIndex = (SLTG_Index*)(pMagic+1);
3749 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3751 pFirstBlk = (LPVOID)(pPad9 + 1);
3753 /* We'll set up a ptr to the main library block, which is the last one. */
3755 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3756 pBlkEntry[order].next != 0;
3757 order = pBlkEntry[order].next - 1, i++) {
3758 pBlk = (char*)pBlk + pBlkEntry[order].len;
3762 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3764 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3769 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3771 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3772 sizeof(*pOtherTypeInfoBlks) *
3773 pTypeLibImpl->TypeInfoCount);
3776 ptr = (char*)pLibBlk + len;
3778 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3782 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3784 w = *(WORD*)(ptr + 2);
3787 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3789 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3790 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3792 w = *(WORD*)(ptr + 4 + len);
3794 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3796 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3798 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3799 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3801 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3802 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3803 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3805 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3807 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3810 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3811 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3812 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3813 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3814 len += sizeof(SLTG_OtherTypeInfo);
3818 pAfterOTIBlks = ptr;
3820 /* Skip this WORD and get the next DWORD */
3821 len = *(DWORD*)(pAfterOTIBlks + 2);
3823 /* Now add this to pLibBLk look at what we're pointing at and
3824 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3825 dust and we should be pointing at the beginning of the name
3828 pNameTable = (char*)pLibBlk + len;
3830 switch(*(WORD*)pNameTable) {
3837 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3841 pNameTable += 0x216;
3845 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3847 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3850 /* Hopefully we now have enough ptrs set up to actually read in
3851 some TypeInfos. It's not clear which order to do them in, so
3852 I'll just follow the links along the BlkEntry chain and read
3853 them in the order in which they are in the file */
3855 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3857 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3858 pBlkEntry[order].next != 0;
3859 order = pBlkEntry[order].next - 1, i++) {
3861 SLTG_TypeInfoHeader *pTIHeader;
3862 SLTG_TypeInfoTail *pTITail;
3863 SLTG_MemberHeader *pMemHeader;
3865 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3866 pOtherTypeInfoBlks[i].index_name)) {
3867 FIXME_(typelib)("Index strings don't match\n");
3872 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3873 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3876 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3877 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3878 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3880 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3881 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3882 (*ppTypeInfoImpl)->index = i;
3883 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3884 pOtherTypeInfoBlks[i].name_offs +
3886 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3887 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3888 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3889 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3890 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3891 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3892 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3894 if((pTIHeader->typeflags1 & 7) != 2)
3895 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3896 if(pTIHeader->typeflags3 != 2)
3897 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3899 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3900 debugstr_w((*ppTypeInfoImpl)->Name),
3901 typekind_desc[pTIHeader->typekind],
3902 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3903 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3905 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3907 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3909 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3910 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3911 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3913 switch(pTIHeader->typekind) {
3915 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3916 pTIHeader, pTITail);
3920 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3921 pTIHeader, pTITail);
3924 case TKIND_INTERFACE:
3925 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3926 pTIHeader, pTITail);
3930 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3931 pTIHeader, pTITail);
3935 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3936 pTIHeader, pTITail);
3939 case TKIND_DISPATCH:
3940 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3941 pTIHeader, pTITail);
3945 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3946 pTIHeader, pTITail);
3950 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3955 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3956 but we've already set those */
3957 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3972 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3973 pBlk = (char*)pBlk + pBlkEntry[order].len;
3976 if(i != pTypeLibImpl->TypeInfoCount) {
3977 FIXME("Somehow processed %d TypeInfos\n", i);
3981 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3982 return (ITypeLib2*)pTypeLibImpl;
3985 /* ITypeLib::QueryInterface
3987 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3992 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3994 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3997 if(IsEqualIID(riid, &IID_IUnknown) ||
3998 IsEqualIID(riid,&IID_ITypeLib)||
3999 IsEqualIID(riid,&IID_ITypeLib2))
4006 ITypeLib2_AddRef(iface);
4007 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4010 TRACE("-- Interface: E_NOINTERFACE\n");
4011 return E_NOINTERFACE;
4016 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4018 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4019 ULONG ref = InterlockedIncrement(&This->ref);
4021 TRACE("(%p)->ref was %u\n",This, ref - 1);
4026 /* ITypeLib::Release
4028 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4030 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4031 ULONG ref = InterlockedDecrement(&This->ref);
4033 TRACE("(%p)->(%u)\n",This, ref);
4037 TLBImpLib *pImpLib, *pImpLibNext;
4038 TLBCustData *pCustData, *pCustDataNext;
4039 TLBRefType *ref_type;
4043 /* remove cache entry */
4046 TRACE("removing from cache list\n");
4047 EnterCriticalSection(&cache_section);
4048 if (This->next) This->next->prev = This->prev;
4049 if (This->prev) This->prev->next = This->next;
4050 else tlb_cache_first = This->next;
4051 LeaveCriticalSection(&cache_section);
4052 HeapFree(GetProcessHeap(), 0, This->path);
4054 TRACE(" destroying ITypeLib(%p)\n",This);
4056 SysFreeString(This->Name);
4059 SysFreeString(This->DocString);
4060 This->DocString = NULL;
4062 SysFreeString(This->HelpFile);
4063 This->HelpFile = NULL;
4065 SysFreeString(This->HelpStringDll);
4066 This->HelpStringDll = NULL;
4068 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4070 VariantClear(&pCustData->data);
4072 pCustDataNext = pCustData->next;
4073 TLB_Free(pCustData);
4076 for (i = 0; i < This->ctTypeDesc; i++)
4077 if (This->pTypeDesc[i].vt == VT_CARRAY)
4078 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4080 TLB_Free(This->pTypeDesc);
4082 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4084 if (pImpLib->pImpTypeLib)
4085 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4086 SysFreeString(pImpLib->name);
4088 pImpLibNext = pImpLib->next;
4092 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4094 list_remove(&ref_type->entry);
4098 if (This->pTypeInfo) /* can be NULL */
4099 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4100 HeapFree(GetProcessHeap(),0,This);
4107 /* ITypeLib::GetTypeInfoCount
4109 * Returns the number of type descriptions in the type library
4111 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4113 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4114 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4115 return This->TypeInfoCount;
4118 /* ITypeLib::GetTypeInfo
4120 * retrieves the specified type description in the library.
4122 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4125 ITypeInfo **ppTInfo)
4129 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4130 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4132 TRACE("(%p)->(index=%d)\n", This, index);
4134 if (!ppTInfo) return E_INVALIDARG;
4136 /* search element n in list */
4137 for(i=0; i < index; i++)
4139 pTypeInfo = pTypeInfo->next;
4142 TRACE("-- element not found\n");
4143 return TYPE_E_ELEMENTNOTFOUND;
4147 *ppTInfo = (ITypeInfo *) pTypeInfo;
4149 ITypeInfo_AddRef(*ppTInfo);
4150 TRACE("-- found (%p)\n",*ppTInfo);
4155 /* ITypeLibs::GetTypeInfoType
4157 * Retrieves the type of a type description.
4159 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4164 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4166 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4168 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4169 return TYPE_E_ELEMENTNOTFOUND;
4171 TRACE("(%p) index %d\n", This, index);
4173 if(!pTKind) return E_INVALIDARG;
4175 /* search element n in list */
4176 for(i=0; i < index; i++)
4180 TRACE("-- element not found\n");
4181 return TYPE_E_ELEMENTNOTFOUND;
4183 pTInfo = pTInfo->next;
4186 *pTKind = pTInfo->TypeAttr.typekind;
4187 TRACE("-- found Type (%d)\n", *pTKind);
4191 /* ITypeLib::GetTypeInfoOfGuid
4193 * Retrieves the type description that corresponds to the specified GUID.
4196 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4199 ITypeInfo **ppTInfo)
4201 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4202 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4204 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4208 WARN("-- element not found\n");
4209 return TYPE_E_ELEMENTNOTFOUND;
4212 /* search linked list for guid */
4213 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4215 pTypeInfo = pTypeInfo->next;
4219 /* end of list reached */
4220 WARN("-- element not found\n");
4221 return TYPE_E_ELEMENTNOTFOUND;
4225 TRACE("-- found (%p, %s)\n",
4227 debugstr_w(pTypeInfo->Name));
4229 *ppTInfo = (ITypeInfo*)pTypeInfo;
4230 ITypeInfo_AddRef(*ppTInfo);
4234 /* ITypeLib::GetLibAttr
4236 * Retrieves the structure that contains the library's attributes.
4239 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4241 LPTLIBATTR *ppTLibAttr)
4243 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4244 TRACE("(%p)\n",This);
4245 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4246 **ppTLibAttr = This->LibAttr;
4250 /* ITypeLib::GetTypeComp
4252 * Enables a client compiler to bind to a library's types, variables,
4253 * constants, and global functions.
4256 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4258 ITypeComp **ppTComp)
4260 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4262 TRACE("(%p)->(%p)\n",This,ppTComp);
4263 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4264 ITypeComp_AddRef(*ppTComp);
4269 /* ITypeLib::GetDocumentation
4271 * Retrieves the library's documentation string, the complete Help file name
4272 * and path, and the context identifier for the library Help topic in the Help
4275 * On a successful return all non-null BSTR pointers will have been set,
4278 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4282 BSTR *pBstrDocString,
4283 DWORD *pdwHelpContext,
4284 BSTR *pBstrHelpFile)
4286 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4288 HRESULT result = E_INVALIDARG;
4293 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4295 pBstrName, pBstrDocString,
4296 pdwHelpContext, pBstrHelpFile);
4300 /* documentation for the typelib */
4305 if(!(*pBstrName = SysAllocString(This->Name)))
4313 if (This->DocString)
4315 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4318 else if (This->Name)
4320 if(!(*pBstrDocString = SysAllocString(This->Name)))
4324 *pBstrDocString = NULL;
4328 *pdwHelpContext = This->dwHelpContext;
4334 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4338 *pBstrHelpFile = NULL;
4345 /* for a typeinfo */
4346 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4348 if(SUCCEEDED(result))
4350 result = ITypeInfo_GetDocumentation(pTInfo,
4354 pdwHelpContext, pBstrHelpFile);
4356 ITypeInfo_Release(pTInfo);
4361 if (pBstrDocString) SysFreeString (*pBstrDocString);
4363 if (pBstrName) SysFreeString (*pBstrName);
4365 return STG_E_INSUFFICIENTMEMORY;
4370 * Indicates whether a passed-in string contains the name of a type or member
4371 * described in the library.
4374 static HRESULT WINAPI ITypeLib2_fnIsName(
4380 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4381 ITypeInfoImpl *pTInfo;
4382 TLBFuncDesc *pFInfo;
4385 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4387 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4391 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4392 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4393 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4394 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4395 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4396 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4397 goto ITypeLib2_fnIsName_exit;
4399 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4400 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4405 ITypeLib2_fnIsName_exit:
4406 TRACE("(%p)slow! search for %s: %s found!\n", This,
4407 debugstr_w(szNameBuf), *pfName?"NOT":"");
4412 /* ITypeLib::FindName
4414 * Finds occurrences of a type description in a type library. This may be used
4415 * to quickly verify that a name exists in a type library.
4418 static HRESULT WINAPI ITypeLib2_fnFindName(
4422 ITypeInfo **ppTInfo,
4426 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4427 ITypeInfoImpl *pTInfo;
4428 TLBFuncDesc *pFInfo;
4431 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4433 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4434 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4435 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4436 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4437 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4438 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4439 goto ITypeLib2_fnFindName_exit;
4442 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4443 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4445 ITypeLib2_fnFindName_exit:
4446 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4447 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4450 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4451 This, *pcFound, debugstr_w(szNameBuf), j);
4458 /* ITypeLib::ReleaseTLibAttr
4460 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4463 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4465 TLIBATTR *pTLibAttr)
4467 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4468 TRACE("freeing (%p)\n",This);
4469 HeapFree(GetProcessHeap(),0,pTLibAttr);
4473 /* ITypeLib2::GetCustData
4475 * gets the custom data
4477 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4482 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4483 TLBCustData *pCData;
4485 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4487 if( IsEqualIID(guid, &pCData->guid)) break;
4490 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4494 VariantInit( pVarVal);
4495 VariantCopy( pVarVal, &pCData->data);
4498 return E_INVALIDARG; /* FIXME: correct? */
4501 /* ITypeLib2::GetLibStatistics
4503 * Returns statistics about a type library that are required for efficient
4504 * sizing of hash tables.
4507 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4509 ULONG *pcUniqueNames,
4510 ULONG *pcchUniqueNames)
4512 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4514 FIXME("(%p): stub!\n", This);
4516 if(pcUniqueNames) *pcUniqueNames=1;
4517 if(pcchUniqueNames) *pcchUniqueNames=1;
4521 /* ITypeLib2::GetDocumentation2
4523 * Retrieves the library's documentation string, the complete Help file name
4524 * and path, the localization context to use, and the context ID for the
4525 * library Help topic in the Help file.
4528 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4532 BSTR *pbstrHelpString,
4533 DWORD *pdwHelpStringContext,
4534 BSTR *pbstrHelpStringDll)
4536 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4540 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4542 /* the help string should be obtained from the helpstringdll,
4543 * using the _DLLGetDocumentation function, based on the supplied
4544 * lcid. Nice to do sometime...
4548 /* documentation for the typelib */
4550 *pbstrHelpString=SysAllocString(This->DocString);
4551 if(pdwHelpStringContext)
4552 *pdwHelpStringContext=This->dwHelpContext;
4553 if(pbstrHelpStringDll)
4554 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4560 /* for a typeinfo */
4561 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4563 if(SUCCEEDED(result))
4565 ITypeInfo2 * pTInfo2;
4566 result = ITypeInfo_QueryInterface(pTInfo,
4568 (LPVOID*) &pTInfo2);
4570 if(SUCCEEDED(result))
4572 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4576 pdwHelpStringContext,
4577 pbstrHelpStringDll);
4579 ITypeInfo2_Release(pTInfo2);
4582 ITypeInfo_Release(pTInfo);
4588 /* ITypeLib2::GetAllCustData
4590 * Gets all custom data items for the library.
4593 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4595 CUSTDATA *pCustData)
4597 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4598 TLBCustData *pCData;
4600 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4601 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4602 if(pCustData->prgCustData ){
4603 pCustData->cCustData=This->ctCustData;
4604 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4605 pCustData->prgCustData[i].guid=pCData->guid;
4606 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4609 ERR(" OUT OF MEMORY!\n");
4610 return E_OUTOFMEMORY;
4615 static const ITypeLib2Vtbl tlbvt = {
4616 ITypeLib2_fnQueryInterface,
4618 ITypeLib2_fnRelease,
4619 ITypeLib2_fnGetTypeInfoCount,
4620 ITypeLib2_fnGetTypeInfo,
4621 ITypeLib2_fnGetTypeInfoType,
4622 ITypeLib2_fnGetTypeInfoOfGuid,
4623 ITypeLib2_fnGetLibAttr,
4624 ITypeLib2_fnGetTypeComp,
4625 ITypeLib2_fnGetDocumentation,
4627 ITypeLib2_fnFindName,
4628 ITypeLib2_fnReleaseTLibAttr,
4630 ITypeLib2_fnGetCustData,
4631 ITypeLib2_fnGetLibStatistics,
4632 ITypeLib2_fnGetDocumentation2,
4633 ITypeLib2_fnGetAllCustData
4637 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4639 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4641 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4644 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4646 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4648 return ITypeLib2_AddRef((ITypeLib2 *)This);
4651 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4653 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4655 return ITypeLib2_Release((ITypeLib2 *)This);
4658 static HRESULT WINAPI ITypeLibComp_fnBind(
4663 ITypeInfo ** ppTInfo,
4664 DESCKIND * pDescKind,
4667 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4668 ITypeInfoImpl *pTypeInfo;
4670 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4672 *pDescKind = DESCKIND_NONE;
4673 pBindPtr->lptcomp = NULL;
4676 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4678 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4680 /* FIXME: check wFlags here? */
4681 /* FIXME: we should use a hash table to look this info up using lHash
4682 * instead of an O(n) search */
4683 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4684 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4686 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4688 *pDescKind = DESCKIND_TYPECOMP;
4689 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4690 ITypeComp_AddRef(pBindPtr->lptcomp);
4691 TRACE("module or enum: %s\n", debugstr_w(szName));
4696 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4697 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4699 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4702 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4703 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4705 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4710 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4711 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4713 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4715 ITypeInfo *subtypeinfo;
4717 DESCKIND subdesckind;
4719 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4720 &subtypeinfo, &subdesckind, &subbindptr);
4721 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4723 TYPEDESC tdesc_appobject =
4726 (TYPEDESC *)pTypeInfo->hreftype
4730 const VARDESC vardesc_appobject =
4733 NULL, /* lpstrSchema */
4748 VAR_STATIC /* varkind */
4751 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4753 /* cleanup things filled in by Bind call so we can put our
4754 * application object data in there instead */
4755 switch (subdesckind)
4757 case DESCKIND_FUNCDESC:
4758 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4760 case DESCKIND_VARDESC:
4761 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4766 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4768 if (pTypeInfo->hreftype == -1)
4769 FIXME("no hreftype for interface %p\n", pTypeInfo);
4771 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4775 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4776 *ppTInfo = (ITypeInfo *)pTypeInfo;
4777 ITypeInfo_AddRef(*ppTInfo);
4783 TRACE("name not found %s\n", debugstr_w(szName));
4787 static HRESULT WINAPI ITypeLibComp_fnBindType(
4791 ITypeInfo ** ppTInfo,
4792 ITypeComp ** ppTComp)
4794 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4798 static const ITypeCompVtbl tlbtcvt =
4801 ITypeLibComp_fnQueryInterface,
4802 ITypeLibComp_fnAddRef,
4803 ITypeLibComp_fnRelease,
4805 ITypeLibComp_fnBind,
4806 ITypeLibComp_fnBindType
4809 /*================== ITypeInfo(2) Methods ===================================*/
4810 static ITypeInfo2 * ITypeInfo_Constructor(void)
4812 ITypeInfoImpl * pTypeInfoImpl;
4814 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4817 pTypeInfoImpl->lpVtbl = &tinfvt;
4818 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4819 pTypeInfoImpl->ref=1;
4820 pTypeInfoImpl->hreftype = -1;
4821 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4822 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4824 TRACE("(%p)\n", pTypeInfoImpl);
4825 return (ITypeInfo2*) pTypeInfoImpl;
4828 /* ITypeInfo::QueryInterface
4830 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4835 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4837 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4840 if(IsEqualIID(riid, &IID_IUnknown) ||
4841 IsEqualIID(riid,&IID_ITypeInfo)||
4842 IsEqualIID(riid,&IID_ITypeInfo2))
4846 ITypeInfo_AddRef(iface);
4847 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4850 TRACE("-- Interface: E_NOINTERFACE\n");
4851 return E_NOINTERFACE;
4854 /* ITypeInfo::AddRef
4856 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4858 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4859 ULONG ref = InterlockedIncrement(&This->ref);
4861 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4863 TRACE("(%p)->ref is %u\n",This, ref);
4867 /* ITypeInfo::Release
4869 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4871 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4872 ULONG ref = InterlockedDecrement(&This->ref);
4874 TRACE("(%p)->(%u)\n",This, ref);
4877 /* We don't release ITypeLib when ref=0 because
4878 it means that function is called by ITypeLib2_Release */
4879 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4881 TLBFuncDesc *pFInfo, *pFInfoNext;
4882 TLBVarDesc *pVInfo, *pVInfoNext;
4883 TLBImplType *pImpl, *pImplNext;
4885 TRACE("destroying ITypeInfo(%p)\n",This);
4887 if (This->no_free_data)
4890 SysFreeString(This->Name);
4893 SysFreeString(This->DocString);
4894 This->DocString = NULL;
4896 SysFreeString(This->DllName);
4897 This->DllName = NULL;
4899 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4902 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4904 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4905 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4907 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4908 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4910 SysFreeString(pFInfo->pParamDesc[i].Name);
4912 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4913 TLB_Free(pFInfo->pParamDesc);
4914 TLB_FreeCustData(pFInfo->pCustData);
4915 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4916 SysFreeString(pFInfo->Entry);
4917 SysFreeString(pFInfo->HelpString);
4918 SysFreeString(pFInfo->Name);
4920 pFInfoNext = pFInfo->next;
4923 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4925 if (pVInfo->vardesc.varkind == VAR_CONST)
4927 VariantClear(pVInfo->vardesc.u.lpvarValue);
4928 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4930 TLB_FreeCustData(pVInfo->pCustData);
4931 SysFreeString(pVInfo->Name);
4932 pVInfoNext = pVInfo->next;
4935 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4937 TLB_FreeCustData(pImpl->pCustData);
4938 pImplNext = pImpl->next;
4941 TLB_FreeCustData(This->pCustData);
4946 ITypeInfo_Release((ITypeInfo*)This->next);
4949 HeapFree(GetProcessHeap(),0,This);
4955 /* ITypeInfo::GetTypeAttr
4957 * Retrieves a TYPEATTR structure that contains the attributes of the type
4961 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4962 LPTYPEATTR *ppTypeAttr)
4964 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4967 TRACE("(%p)\n",This);
4969 size = sizeof(**ppTypeAttr);
4970 if (This->TypeAttr.typekind == TKIND_ALIAS)
4971 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4973 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4975 return E_OUTOFMEMORY;
4977 **ppTypeAttr = This->TypeAttr;
4979 if (This->TypeAttr.typekind == TKIND_ALIAS)
4980 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4981 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4983 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4984 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4986 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4987 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4992 /* ITypeInfo::GetTypeComp
4994 * Retrieves the ITypeComp interface for the type description, which enables a
4995 * client compiler to bind to the type description's members.
4998 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4999 ITypeComp * *ppTComp)
5001 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5003 TRACE("(%p)->(%p)\n", This, ppTComp);
5005 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5006 ITypeComp_AddRef(*ppTComp);
5010 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5012 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5013 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5014 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5018 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5021 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5022 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5024 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5025 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5026 *buffer += sizeof(PARAMDESCEX);
5027 *pparamdescex_dest = *pparamdescex_src;
5028 VariantInit(&pparamdescex_dest->varDefaultValue);
5029 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5030 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5033 dest->u.paramdesc.pparamdescex = NULL;
5037 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5039 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5040 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5043 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5047 SIZE_T size = sizeof(*src);
5051 size += sizeof(*src->lprgscode) * src->cScodes;
5052 size += TLB_SizeElemDesc(&src->elemdescFunc);
5053 for (i = 0; i < src->cParams; i++)
5055 size += sizeof(ELEMDESC);
5056 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5059 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5060 if (!dest) return E_OUTOFMEMORY;
5063 if (dispinterface) /* overwrite funckind */
5064 dest->funckind = FUNC_DISPATCH;
5065 buffer = (char *)(dest + 1);
5067 dest->lprgscode = (SCODE *)buffer;
5068 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5069 buffer += sizeof(*src->lprgscode) * src->cScodes;
5071 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5074 SysFreeString((BSTR)dest);
5078 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5079 buffer += sizeof(ELEMDESC) * src->cParams;
5080 for (i = 0; i < src->cParams; i++)
5082 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5088 /* undo the above actions */
5089 for (i = i - 1; i >= 0; i--)
5090 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5091 TLB_FreeElemDesc(&dest->elemdescFunc);
5092 SysFreeString((BSTR)dest);
5096 /* special treatment for dispinterfaces: this makes functions appear
5097 * to return their [retval] value when it is really returning an
5099 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5101 if (dest->cParams &&
5102 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5104 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5105 if (elemdesc->tdesc.vt != VT_PTR)
5107 ERR("elemdesc should have started with VT_PTR instead of:\n");
5109 dump_ELEMDESC(elemdesc);
5110 return E_UNEXPECTED;
5113 /* copy last parameter to the return value. we are using a flat
5114 * buffer so there is no danger of leaking memory in
5116 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5118 /* remove the last parameter */
5122 /* otherwise this function is made to appear to have no return
5124 dest->elemdescFunc.tdesc.vt = VT_VOID;
5132 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5134 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5135 const TLBFuncDesc *pFDesc;
5138 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5143 *ppFuncDesc = &pFDesc->funcdesc;
5147 return TYPE_E_ELEMENTNOTFOUND;
5150 /* internal function to make the inherited interfaces' methods appear
5151 * part of the interface */
5152 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5153 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5155 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5157 UINT implemented_funcs = 0;
5162 *hrefoffset = DISPATCH_HREF_OFFSET;
5164 if(This->impltypelist)
5166 ITypeInfo *pSubTypeInfo;
5169 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5173 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5176 &sub_funcs, hrefoffset);
5177 implemented_funcs += sub_funcs;
5178 ITypeInfo_Release(pSubTypeInfo);
5181 *hrefoffset += DISPATCH_HREF_OFFSET;
5185 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5189 if (index < implemented_funcs)
5190 return E_INVALIDARG;
5191 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5195 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5197 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5200 switch (pTypeDesc->vt)
5202 case VT_USERDEFINED:
5203 pTypeDesc->u.hreftype += hrefoffset;
5207 pTypeDesc = pTypeDesc->u.lptdesc;
5210 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5218 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5221 for (i = 0; i < pFuncDesc->cParams; i++)
5222 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5223 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5226 /* ITypeInfo::GetFuncDesc
5228 * Retrieves the FUNCDESC structure that contains information about a
5229 * specified function.
5232 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5233 LPFUNCDESC *ppFuncDesc)
5235 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5236 const FUNCDESC *internal_funcdesc;
5238 UINT hrefoffset = 0;
5240 TRACE("(%p) index %d\n", This, index);
5242 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5243 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5244 &internal_funcdesc, NULL,
5247 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5248 &internal_funcdesc);
5251 WARN("description for function %d not found\n", index);
5255 hr = TLB_AllocAndInitFuncDesc(
5258 This->TypeAttr.typekind == TKIND_DISPATCH);
5260 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5261 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5263 TRACE("-- 0x%08x\n", hr);
5267 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5271 SIZE_T size = sizeof(*src);
5274 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5275 if (src->varkind == VAR_CONST)
5276 size += sizeof(VARIANT);
5277 size += TLB_SizeElemDesc(&src->elemdescVar);
5279 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5280 if (!dest) return E_OUTOFMEMORY;
5283 buffer = (char *)(dest + 1);
5284 if (src->lpstrSchema)
5287 dest->lpstrSchema = (LPOLESTR)buffer;
5288 len = strlenW(src->lpstrSchema);
5289 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5290 buffer += (len + 1) * sizeof(WCHAR);
5293 if (src->varkind == VAR_CONST)
5297 dest->u.lpvarValue = (VARIANT *)buffer;
5298 *dest->u.lpvarValue = *src->u.lpvarValue;
5299 buffer += sizeof(VARIANT);
5300 VariantInit(dest->u.lpvarValue);
5301 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5304 SysFreeString((BSTR)dest_ptr);
5308 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5311 if (src->varkind == VAR_CONST)
5312 VariantClear(dest->u.lpvarValue);
5313 SysFreeString((BSTR)dest);
5320 /* ITypeInfo::GetVarDesc
5322 * Retrieves a VARDESC structure that describes the specified variable.
5325 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5326 LPVARDESC *ppVarDesc)
5328 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5330 const TLBVarDesc *pVDesc;
5332 TRACE("(%p) index %d\n", This, index);
5334 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5338 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5340 return E_INVALIDARG;
5343 /* ITypeInfo_GetNames
5345 * Retrieves the variable with the specified member ID (or the name of the
5346 * property or method and its parameters) that correspond to the specified
5349 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5350 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5352 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5353 const TLBFuncDesc *pFDesc;
5354 const TLBVarDesc *pVDesc;
5356 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5357 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5360 /* function found, now return function and parameter names */
5361 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5364 *rgBstrNames=SysAllocString(pFDesc->Name);
5366 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5372 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5375 *rgBstrNames=SysAllocString(pVDesc->Name);
5380 if(This->impltypelist &&
5381 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5382 /* recursive search */
5385 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5387 if(SUCCEEDED(result))
5389 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5390 ITypeInfo_Release(pTInfo);
5393 WARN("Could not search inherited interface!\n");
5397 WARN("no names found\n");
5400 return TYPE_E_ELEMENTNOTFOUND;
5407 /* ITypeInfo::GetRefTypeOfImplType
5409 * If a type description describes a COM class, it retrieves the type
5410 * description of the implemented interface types. For an interface,
5411 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5415 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5420 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5423 const TLBImplType *pImpl = This->impltypelist;
5425 TRACE("(%p) index %d\n", This, index);
5426 if (TRACE_ON(ole)) dump_TypeInfo(This);
5430 /* only valid on dual interfaces;
5431 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5433 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5435 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5436 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5442 hr = TYPE_E_ELEMENTNOTFOUND;
5445 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5447 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5448 *pRefType = This->pTypeLib->dispatch_href;
5452 /* get element n from linked list */
5453 for(i=0; pImpl && i<index; i++)
5455 pImpl = pImpl->next;
5459 *pRefType = pImpl->hRef;
5461 hr = TYPE_E_ELEMENTNOTFOUND;
5467 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5469 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5475 /* ITypeInfo::GetImplTypeFlags
5477 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5478 * or base interface in a type description.
5480 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5481 UINT index, INT *pImplTypeFlags)
5483 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5487 TRACE("(%p) index %d\n", This, index);
5488 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5489 i++, pImpl=pImpl->next)
5491 if(i==index && pImpl){
5492 *pImplTypeFlags=pImpl->implflags;
5496 return TYPE_E_ELEMENTNOTFOUND;
5500 * Maps between member names and member IDs, and parameter names and
5503 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5504 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5506 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5507 const TLBFuncDesc *pFDesc;
5508 const TLBVarDesc *pVDesc;
5512 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5515 /* init out parameters in case of failure */
5516 for (i = 0; i < cNames; i++)
5517 pMemId[i] = MEMBERID_NIL;
5519 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5521 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5522 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5523 for(i=1; i < cNames; i++){
5524 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5525 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5527 if( j<pFDesc->funcdesc.cParams)
5530 ret=DISP_E_UNKNOWNNAME;
5532 TRACE("-- 0x%08x\n", ret);
5536 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5537 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5538 if(cNames) *pMemId=pVDesc->vardesc.memid;
5542 /* not found, see if it can be found in an inherited interface */
5543 if(This->impltypelist) {
5544 /* recursive search */
5546 ret=ITypeInfo_GetRefTypeInfo(iface,
5547 This->impltypelist->hRef, &pTInfo);
5549 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5550 ITypeInfo_Release(pTInfo);
5553 WARN("Could not search inherited interface!\n");
5555 WARN("no names found\n");
5556 return DISP_E_UNKNOWNNAME;
5559 /* ITypeInfo::Invoke
5561 * Invokes a method, or accesses a property of an object, that implements the
5562 * interface described by the type description.
5565 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5568 if (TRACE_ON(ole)) {
5570 TRACE("Calling %p(",func);
5571 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5583 res = func(args[0]);
5586 res = func(args[0],args[1]);
5589 res = func(args[0],args[1],args[2]);
5592 res = func(args[0],args[1],args[2],args[3]);
5595 res = func(args[0],args[1],args[2],args[3],args[4]);
5598 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5601 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5604 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5607 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5610 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5613 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5616 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]);
5619 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]);
5622 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]);
5625 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]);
5628 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]);
5631 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]);
5634 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]);
5637 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]);
5640 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]);
5643 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]);
5646 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]);
5649 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]);
5652 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],args[23]);
5655 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],args[23],args[24]);
5658 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],args[23],args[24],args[25]);
5661 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],args[23],args[24],args[25],args[26]);
5664 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],args[23],args[24],args[25],args[26],args[27]);
5667 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],args[23],args[24],args[25],args[26],args[27],args[28]);
5670 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],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5673 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5679 FIXME("unsupported calling convention %d\n",callconv);
5683 TRACE("returns %08x\n",res);
5687 /* The size of the argument on the stack in DWORD units (in all x86 call
5688 * convetions the arguments on the stack are DWORD-aligned)
5690 static int _dispargsize(VARTYPE vt)
5695 return 8/sizeof(DWORD);
5697 return sizeof(double)/sizeof(DWORD);
5699 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5701 return sizeof(CY)/sizeof(DWORD);
5703 return sizeof(DATE)/sizeof(DWORD);
5705 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5707 FIXME("VT_RECORD not implemented\n");
5714 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5717 ITypeInfo *tinfo2 = NULL;
5718 TYPEATTR *tattr = NULL;
5720 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5723 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5725 tdesc->u.hreftype, hr);
5728 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5731 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5732 ITypeInfo_Release(tinfo2);
5736 switch (tattr->typekind)
5743 tdesc = &tattr->tdescAlias;
5744 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5747 case TKIND_INTERFACE:
5748 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5754 case TKIND_DISPATCH:
5763 FIXME("TKIND_RECORD unhandled.\n");
5768 FIXME("TKIND_UNION unhandled.\n");
5773 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5777 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5778 ITypeInfo_Release(tinfo2);
5782 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5786 /* enforce only one level of pointer indirection */
5787 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5789 tdesc = tdesc->u.lptdesc;
5791 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5792 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5793 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5794 if ((tdesc->vt == VT_USERDEFINED) ||
5795 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5797 VARTYPE vt_userdefined = 0;
5798 const TYPEDESC *tdesc_userdefined = tdesc;
5799 if (tdesc->vt == VT_PTR)
5801 vt_userdefined = VT_BYREF;
5802 tdesc_userdefined = tdesc->u.lptdesc;
5804 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5806 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5807 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5809 *vt |= vt_userdefined;
5821 case VT_USERDEFINED:
5822 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5829 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5830 hr = DISP_E_BADVARTYPE;
5834 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5843 /***********************************************************************
5844 * DispCallFunc (OLEAUT32.@)
5846 * Invokes a function of the specified calling convention, passing the
5847 * specified arguments and returns the result.
5850 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5851 * oVft [I] The offset in the vtable. See notes.
5852 * cc [I] Calling convention of the function to call.
5853 * vtReturn [I] The return type of the function.
5854 * cActuals [I] Number of parameters.
5855 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5856 * prgpvarg [I] The arguments to pass.
5857 * pvargResult [O] The return value of the function. Can be NULL.
5861 * Failure: HRESULT code.
5864 * The HRESULT return value of this function is not affected by the return
5865 * value of the user supplied function, which is returned in pvargResult.
5867 * If pvInstance is NULL then a non-object function is to be called and oVft
5868 * is the address of the function to call.
5870 * The cc parameter can be one of the following values:
5883 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5884 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5886 int argsize, argspos;
5891 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5892 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5893 pvargResult, V_VT(pvargResult));
5897 argsize++; /* for This pointer */
5899 for (i=0;i<cActuals;i++)
5901 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5902 dump_Variant(prgpvarg[i]);
5903 argsize += _dispargsize(prgvt[i]);
5905 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5910 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5914 for (i=0;i<cActuals;i++)
5916 VARIANT *arg = prgpvarg[i];
5917 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5918 if (prgvt[i] == VT_VARIANT)
5919 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5921 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5922 argspos += _dispargsize(prgvt[i]);
5927 FARPROC *vtable = *(FARPROC**)pvInstance;
5928 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5931 /* if we aren't invoking an object then the function pointer is stored
5933 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5935 if (pvargResult && (vtReturn != VT_EMPTY))
5937 TRACE("Method returned 0x%08x\n",hres);
5938 V_VT(pvargResult) = vtReturn;
5939 V_UI4(pvargResult) = hres;
5942 HeapFree(GetProcessHeap(),0,args);
5946 #define INVBUF_ELEMENT_SIZE \
5947 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5948 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5949 ((VARIANTARG *)(buffer))
5950 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5951 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5952 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5953 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5954 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5955 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5957 static HRESULT WINAPI ITypeInfo_fnInvoke(
5962 DISPPARAMS *pDispParams,
5963 VARIANT *pVarResult,
5964 EXCEPINFO *pExcepInfo,
5967 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5969 unsigned int var_index;
5972 const TLBFuncDesc *pFuncInfo;
5974 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5975 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5980 ERR("NULL pDispParams not allowed\n");
5981 return E_INVALIDARG;
5984 dump_DispParms(pDispParams);
5986 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5988 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5989 pDispParams->cNamedArgs, pDispParams->cArgs);
5990 return E_INVALIDARG;
5993 /* we do this instead of using GetFuncDesc since it will return a fake
5994 * FUNCDESC for dispinterfaces and we want the real function description */
5995 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5996 if ((memid == pFuncInfo->funcdesc.memid) &&
5997 (wFlags & pFuncInfo->funcdesc.invkind))
6001 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6005 TRACE("invoking:\n");
6006 dump_TLBFuncDescOne(pFuncInfo);
6009 switch (func_desc->funckind) {
6010 case FUNC_PUREVIRTUAL:
6011 case FUNC_VIRTUAL: {
6012 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6014 VARIANT retval; /* pointer for storing byref retvals in */
6015 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6016 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6017 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6018 UINT cNamedArgs = pDispParams->cNamedArgs;
6019 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6023 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6025 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6027 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6028 hres = DISP_E_PARAMNOTFOUND;
6031 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6033 rgdispidNamedArgs++;
6036 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6038 ERR("functions with the vararg attribute do not support named arguments\n");
6039 hres = DISP_E_NONAMEDARGS;
6043 for (i = 0; i < func_desc->cParams; i++)
6045 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6046 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6051 TRACE("changing args\n");
6052 for (i = 0; i < func_desc->cParams; i++)
6054 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6055 VARIANTARG *src_arg;
6061 for (j = 0; j < cNamedArgs; j++)
6062 if (rgdispidNamedArgs[j] == i)
6064 src_arg = &pDispParams->rgvarg[j];
6069 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
6071 if (wParamFlags & PARAMFLAG_FRETVAL)
6073 /* under most conditions the caller is not allowed to
6074 * pass in a dispparam arg in the index of what would be
6075 * the retval parameter. however, there is an exception
6076 * where the extra parameter is used in an extra
6077 * IDispatch::Invoke below */
6078 if ((i < pDispParams->cArgs) &&
6079 ((func_desc->cParams != 1) || !pVarResult ||
6080 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6082 hres = DISP_E_BADPARAMCOUNT;
6086 /* note: this check is placed so that if the caller passes
6087 * in a VARIANTARG for the retval we just ignore it, like
6089 if (i == func_desc->cParams - 1)
6092 arg = prgpvarg[i] = &rgvarg[i];
6093 memset(arg, 0, sizeof(*arg));
6094 V_VT(arg) = rgvt[i];
6095 memset(&retval, 0, sizeof(retval));
6096 V_BYREF(arg) = &retval;
6100 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6101 hres = E_UNEXPECTED;
6107 dump_Variant(src_arg);
6109 if (rgvt[i] == VT_VARIANT)
6110 hres = VariantCopy(&rgvarg[i], src_arg);
6111 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6113 if (rgvt[i] == V_VT(src_arg))
6114 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6117 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6118 hres = VariantCopy(&missing_arg[i], src_arg);
6119 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6121 V_VT(&rgvarg[i]) = rgvt[i];
6123 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6126 SAFEARRAYBOUND bound;
6130 bound.cElements = pDispParams->cArgs-i;
6131 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6133 ERR("SafeArrayCreate failed\n");
6136 hres = SafeArrayAccessData(a, (LPVOID)&v);
6139 ERR("SafeArrayAccessData failed with %x\n", hres);
6142 for (j = 0; j < bound.cElements; j++)
6143 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6144 hres = SafeArrayUnaccessData(a);
6147 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6150 V_ARRAY(&rgvarg[i]) = a;
6151 V_VT(&rgvarg[i]) = rgvt[i];
6153 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6155 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6156 V_VT(&missing_arg[i]) = V_VT(src_arg);
6157 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6158 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6159 V_VT(&rgvarg[i]) = rgvt[i];
6161 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6163 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6164 V_VT(&rgvarg[i]) = rgvt[i];
6168 /* FIXME: this doesn't work for VT_BYREF arguments if
6169 * they are not the same type as in the paramdesc */
6170 V_VT(&rgvarg[i]) = V_VT(src_arg);
6171 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6172 V_VT(&rgvarg[i]) = rgvt[i];
6177 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6178 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6179 debugstr_VT(src_arg), debugstr_VF(src_arg));
6182 prgpvarg[i] = &rgvarg[i];
6184 else if (wParamFlags & PARAMFLAG_FOPT)
6187 arg = prgpvarg[i] = &rgvarg[i];
6188 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6190 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6196 VARIANTARG *missing_arg;
6197 /* if the function wants a pointer to a variant then
6198 * set that up, otherwise just pass the VT_ERROR in
6199 * the argument by value */
6200 if (rgvt[i] & VT_BYREF)
6202 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6203 V_VT(arg) = VT_VARIANT | VT_BYREF;
6204 V_VARIANTREF(arg) = missing_arg;
6208 V_VT(missing_arg) = VT_ERROR;
6209 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6214 hres = DISP_E_BADPARAMCOUNT;
6218 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6220 /* VT_VOID is a special case for return types, so it is not
6221 * handled in the general function */
6222 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6223 V_VT(&varresult) = VT_EMPTY;
6226 V_VT(&varresult) = 0;
6227 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6228 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6231 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6232 V_VT(&varresult), func_desc->cParams, rgvt,
6233 prgpvarg, &varresult);
6235 for (i = 0; i < func_desc->cParams; i++)
6237 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6238 if (wParamFlags & PARAMFLAG_FRETVAL)
6242 TRACE("[retval] value: ");
6243 dump_Variant(prgpvarg[i]);
6248 VariantInit(pVarResult);
6249 /* deref return value */
6250 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6253 /* free data stored in varresult. Note that
6254 * VariantClear doesn't do what we want because we are
6255 * working with byref types. */
6256 /* FIXME: clear safearrays, bstrs, records and
6257 * variants here too */
6258 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6259 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6261 if(*V_UNKNOWNREF(prgpvarg[i]))
6262 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6266 else if (i < pDispParams->cArgs)
6268 if (wParamFlags & PARAMFLAG_FOUT)
6270 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6272 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6273 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6277 ERR("failed to convert param %d to vt %d\n", i,
6278 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6282 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6283 func_desc->cParamsOpt < 0 &&
6284 i == func_desc->cParams-1)
6286 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6289 hres = SafeArrayGetUBound(a, 1, &ubound);
6292 ERR("SafeArrayGetUBound failed with %x\n", hres);
6295 hres = SafeArrayAccessData(a, (LPVOID)&v);
6298 ERR("SafeArrayAccessData failed with %x\n", hres);
6301 for (j = 0; j <= ubound; j++)
6302 VariantClear(&v[j]);
6303 hres = SafeArrayUnaccessData(a);
6306 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6310 VariantClear(&rgvarg[i]);
6312 else if (wParamFlags & PARAMFLAG_FOPT)
6314 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6315 VariantClear(&rgvarg[i]);
6319 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6321 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6322 hres = DISP_E_EXCEPTION;
6325 IErrorInfo *pErrorInfo;
6326 pExcepInfo->scode = V_ERROR(&varresult);
6327 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6329 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6330 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6331 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6332 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6334 IErrorInfo_Release(pErrorInfo);
6338 if (V_VT(&varresult) != VT_ERROR)
6340 TRACE("varresult value: ");
6341 dump_Variant(&varresult);
6345 VariantClear(pVarResult);
6346 *pVarResult = varresult;
6349 VariantClear(&varresult);
6352 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6353 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6354 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6355 (pDispParams->cArgs != 0))
6357 if (V_VT(pVarResult) == VT_DISPATCH)
6359 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6360 /* Note: not VariantClear; we still need the dispatch
6361 * pointer to be valid */
6362 VariantInit(pVarResult);
6363 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6364 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6365 pDispParams, pVarResult, pExcepInfo, pArgErr);
6366 IDispatch_Release(pDispatch);
6370 VariantClear(pVarResult);
6371 hres = DISP_E_NOTACOLLECTION;
6376 HeapFree(GetProcessHeap(), 0, buffer);
6379 case FUNC_DISPATCH: {
6382 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6383 if (SUCCEEDED(hres)) {
6384 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6385 hres = IDispatch_Invoke(
6386 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6387 pVarResult,pExcepInfo,pArgErr
6390 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6391 IDispatch_Release(disp);
6393 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6397 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6402 TRACE("-- 0x%08x\n", hres);
6405 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6408 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6409 if(FAILED(hres)) return hres;
6411 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6412 dump_VARDESC(var_desc);
6413 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6417 /* not found, look for it in inherited interfaces */
6418 ITypeInfo2_GetTypeKind(iface, &type_kind);
6419 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6420 if(This->impltypelist) {
6421 /* recursive search */
6423 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6424 if(SUCCEEDED(hres)){
6425 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6426 ITypeInfo_Release(pTInfo);
6429 WARN("Could not search inherited interface!\n");
6432 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6433 return DISP_E_MEMBERNOTFOUND;
6436 /* ITypeInfo::GetDocumentation
6438 * Retrieves the documentation string, the complete Help file name and path,
6439 * and the context ID for the Help topic for a specified type description.
6441 * (Can be tested by the Visual Basic Editor in Word for instance.)
6443 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6444 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6445 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6447 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6448 const TLBFuncDesc *pFDesc;
6449 const TLBVarDesc *pVDesc;
6450 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6451 " HelpContext(%p) HelpFile(%p)\n",
6452 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6453 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6455 *pBstrName=SysAllocString(This->Name);
6457 *pBstrDocString=SysAllocString(This->DocString);
6459 *pdwHelpContext=This->dwHelpContext;
6461 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6463 }else {/* for a member */
6464 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6465 if(pFDesc->funcdesc.memid==memid){
6467 *pBstrName = SysAllocString(pFDesc->Name);
6469 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6471 *pdwHelpContext=pFDesc->helpcontext;
6474 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6475 if(pVDesc->vardesc.memid==memid){
6477 *pBstrName = SysAllocString(pVDesc->Name);
6479 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6481 *pdwHelpContext=pVDesc->HelpContext;
6486 if(This->impltypelist &&
6487 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6488 /* recursive search */
6491 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6493 if(SUCCEEDED(result)) {
6494 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6495 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6496 ITypeInfo_Release(pTInfo);
6499 WARN("Could not search inherited interface!\n");
6502 WARN("member %d not found\n", memid);
6503 return TYPE_E_ELEMENTNOTFOUND;
6506 /* ITypeInfo::GetDllEntry
6508 * Retrieves a description or specification of an entry point for a function
6511 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6512 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6515 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6516 const TLBFuncDesc *pFDesc;
6518 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6520 if (pBstrDllName) *pBstrDllName = NULL;
6521 if (pBstrName) *pBstrName = NULL;
6522 if (pwOrdinal) *pwOrdinal = 0;
6524 if (This->TypeAttr.typekind != TKIND_MODULE)
6525 return TYPE_E_BADMODULEKIND;
6527 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6528 if(pFDesc->funcdesc.memid==memid){
6529 dump_TypeInfo(This);
6531 dump_TLBFuncDescOne(pFDesc);
6534 *pBstrDllName = SysAllocString(This->DllName);
6536 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6538 *pBstrName = SysAllocString(pFDesc->Entry);
6546 *pwOrdinal = (DWORD)pFDesc->Entry;
6549 return TYPE_E_ELEMENTNOTFOUND;
6552 /* internal function to make the inherited interfaces' methods appear
6553 * part of the interface */
6554 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6555 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6557 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6560 TRACE("%p, 0x%x\n", iface, *hRefType);
6562 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6564 ITypeInfo *pSubTypeInfo;
6566 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6570 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6572 ITypeInfo_Release(pSubTypeInfo);
6576 *hRefType -= DISPATCH_HREF_OFFSET;
6578 if (!(*hRefType & DISPATCH_HREF_MASK))
6579 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6584 /* ITypeInfo::GetRefTypeInfo
6586 * If a type description references other type descriptions, it retrieves
6587 * the referenced type descriptions.
6589 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6592 ITypeInfo **ppTInfo)
6594 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6595 HRESULT result = E_FAIL;
6597 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6599 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6600 ITypeInfo_AddRef(*ppTInfo);
6603 else if (hRefType == -1 &&
6604 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6605 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6607 /* when we meet a DUAL dispinterface, we must create the interface
6610 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6613 /* the interface version contains the same information as the dispinterface
6614 * copy the contents of the structs.
6616 *pTypeInfoImpl = *This;
6617 pTypeInfoImpl->ref = 0;
6619 /* change the type to interface */
6620 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6622 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6624 /* we use data structures from This, so we need to keep a reference
6625 * to it to stop it being destroyed and signal to the new instance to
6626 * not free its data structures when it is destroyed */
6627 pTypeInfoImpl->no_free_data = TRUE;
6628 pTypeInfoImpl->next = This;
6629 ITypeInfo_AddRef((ITypeInfo*) This);
6631 ITypeInfo_AddRef(*ppTInfo);
6635 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6636 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6637 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6639 HREFTYPE href_dispatch = hRefType;
6640 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6642 TLBRefType *ref_type;
6643 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6645 if(ref_type->reference == hRefType)
6648 if(&ref_type->entry == &This->pTypeLib->ref_list)
6650 FIXME("Can't find pRefType for ref %x\n", hRefType);
6653 if(hRefType != -1) {
6654 ITypeLib *pTLib = NULL;
6656 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6658 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6660 if(ref_type->pImpTLInfo->pImpTypeLib) {
6661 TRACE("typeinfo in imported typelib that is already loaded\n");
6662 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6663 ITypeLib2_AddRef(pTLib);
6666 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6667 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6668 ref_type->pImpTLInfo->wVersionMajor,
6669 ref_type->pImpTLInfo->wVersionMinor,
6670 ref_type->pImpTLInfo->lcid,
6673 if(FAILED(result)) {
6674 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6675 result=LoadTypeLib(libnam, &pTLib);
6676 SysFreeString(libnam);
6678 if(SUCCEEDED(result)) {
6679 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6680 ITypeLib2_AddRef(pTLib);
6684 if(SUCCEEDED(result)) {
6685 if(ref_type->index == TLB_REF_USE_GUID)
6686 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6690 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6694 ITypeLib2_Release(pTLib);
6699 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6700 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6704 /* ITypeInfo::AddressOfMember
6706 * Retrieves the addresses of static functions or variables, such as those
6709 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6710 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6712 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6718 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6720 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6724 module = LoadLibraryW(dll);
6727 ERR("couldn't load %s\n", debugstr_w(dll));
6729 SysFreeString(entry);
6730 return STG_E_FILENOTFOUND;
6732 /* FIXME: store library somewhere where we can free it */
6737 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6738 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6739 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6741 *ppv = GetProcAddress(module, entryA);
6743 ERR("function not found %s\n", debugstr_a(entryA));
6745 HeapFree(GetProcessHeap(), 0, entryA);
6749 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6751 ERR("function not found %d\n", ordinal);
6755 SysFreeString(entry);
6758 return TYPE_E_DLLFUNCTIONNOTFOUND;
6763 /* ITypeInfo::CreateInstance
6765 * Creates a new instance of a type that describes a component object class
6768 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6769 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6771 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6775 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6781 WARN("Not able to aggregate\n");
6782 return CLASS_E_NOAGGREGATION;
6785 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6786 if(FAILED(hr)) return hr;
6788 if(pTA->typekind != TKIND_COCLASS)
6790 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6796 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6799 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6800 TRACE("GetActiveObject rets %08x\n", hr);
6803 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6804 IUnknown_Release(pUnk);
6809 hr = CoCreateInstance(&pTA->guid, NULL,
6810 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6814 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6818 /* ITypeInfo::GetMops
6820 * Retrieves marshalling information.
6822 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6825 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6826 FIXME("(%p) stub!\n", This);
6830 /* ITypeInfo::GetContainingTypeLib
6832 * Retrieves the containing type library and the index of the type description
6833 * within that type library.
6835 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6836 ITypeLib * *ppTLib, UINT *pIndex)
6838 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6840 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6842 *pIndex=This->index;
6843 TRACE("returning pIndex=%d\n", *pIndex);
6847 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6848 ITypeLib2_AddRef(*ppTLib);
6849 TRACE("returning ppTLib=%p\n", *ppTLib);
6855 /* ITypeInfo::ReleaseTypeAttr
6857 * Releases a TYPEATTR previously returned by GetTypeAttr.
6860 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6861 TYPEATTR* pTypeAttr)
6863 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6864 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6865 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6868 /* ITypeInfo::ReleaseFuncDesc
6870 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6872 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6874 FUNCDESC *pFuncDesc)
6876 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6879 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6881 for (i = 0; i < pFuncDesc->cParams; i++)
6882 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6883 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6885 SysFreeString((BSTR)pFuncDesc);
6888 /* ITypeInfo::ReleaseVarDesc
6890 * Releases a VARDESC previously returned by GetVarDesc.
6892 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6895 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6896 TRACE("(%p)->(%p)\n", This, pVarDesc);
6898 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6899 if (pVarDesc->varkind == VAR_CONST)
6900 VariantClear(pVarDesc->u.lpvarValue);
6901 SysFreeString((BSTR)pVarDesc);
6904 /* ITypeInfo2::GetTypeKind
6906 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6909 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6910 TYPEKIND *pTypeKind)
6912 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6913 *pTypeKind=This->TypeAttr.typekind;
6914 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6918 /* ITypeInfo2::GetTypeFlags
6920 * Returns the type flags without any allocations. This returns a DWORD type
6921 * flag, which expands the type flags without growing the TYPEATTR (type
6925 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6927 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6928 *pTypeFlags=This->TypeAttr.wTypeFlags;
6929 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6933 /* ITypeInfo2::GetFuncIndexOfMemId
6934 * Binds to a specific member based on a known DISPID, where the member name
6935 * is not known (for example, when binding to a default member).
6938 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6939 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6941 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6942 const TLBFuncDesc *pFuncInfo;
6946 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6947 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6953 result = TYPE_E_ELEMENTNOTFOUND;
6955 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6956 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6960 /* TypeInfo2::GetVarIndexOfMemId
6962 * Binds to a specific member based on a known DISPID, where the member name
6963 * is not known (for example, when binding to a default member).
6966 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6967 MEMBERID memid, UINT *pVarIndex)
6969 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6970 TLBVarDesc *pVarInfo;
6973 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6974 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6980 result = TYPE_E_ELEMENTNOTFOUND;
6982 TRACE("(%p) memid 0x%08x -> %s\n", This,
6983 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6987 /* ITypeInfo2::GetCustData
6989 * Gets the custom data
6991 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6996 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6997 TLBCustData *pCData;
6999 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7000 if( IsEqualIID(guid, &pCData->guid)) break;
7002 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7006 VariantInit( pVarVal);
7007 VariantCopy( pVarVal, &pCData->data);
7010 return E_INVALIDARG; /* FIXME: correct? */
7013 /* ITypeInfo2::GetFuncCustData
7015 * Gets the custom data
7017 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7023 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7024 TLBCustData *pCData=NULL;
7025 TLBFuncDesc * pFDesc;
7027 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7028 pFDesc=pFDesc->next);
7031 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7032 if( IsEqualIID(guid, &pCData->guid)) break;
7034 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7037 VariantInit( pVarVal);
7038 VariantCopy( pVarVal, &pCData->data);
7041 return E_INVALIDARG; /* FIXME: correct? */
7044 /* ITypeInfo2::GetParamCustData
7046 * Gets the custom data
7048 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7055 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7056 TLBCustData *pCData=NULL;
7057 TLBFuncDesc * pFDesc;
7060 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7062 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7063 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7064 pCData = pCData->next)
7065 if( IsEqualIID(guid, &pCData->guid)) break;
7067 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7071 VariantInit( pVarVal);
7072 VariantCopy( pVarVal, &pCData->data);
7075 return E_INVALIDARG; /* FIXME: correct? */
7078 /* ITypeInfo2::GetVarCustData
7080 * Gets the custom data
7082 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7088 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7089 TLBCustData *pCData=NULL;
7090 TLBVarDesc * pVDesc;
7093 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7097 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7099 if( IsEqualIID(guid, &pCData->guid)) break;
7103 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7107 VariantInit( pVarVal);
7108 VariantCopy( pVarVal, &pCData->data);
7111 return E_INVALIDARG; /* FIXME: correct? */
7114 /* ITypeInfo2::GetImplCustData
7116 * Gets the custom data
7118 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7124 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7125 TLBCustData *pCData=NULL;
7126 TLBImplType * pRDesc;
7129 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7133 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7135 if( IsEqualIID(guid, &pCData->guid)) break;
7139 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7143 VariantInit( pVarVal);
7144 VariantCopy( pVarVal, &pCData->data);
7147 return E_INVALIDARG; /* FIXME: correct? */
7150 /* ITypeInfo2::GetDocumentation2
7152 * Retrieves the documentation string, the complete Help file name and path,
7153 * the localization context to use, and the context ID for the library Help
7154 * topic in the Help file.
7157 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7161 BSTR *pbstrHelpString,
7162 DWORD *pdwHelpStringContext,
7163 BSTR *pbstrHelpStringDll)
7165 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7166 const TLBFuncDesc *pFDesc;
7167 const TLBVarDesc *pVDesc;
7168 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7169 "HelpStringContext(%p) HelpStringDll(%p)\n",
7170 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7171 pbstrHelpStringDll );
7172 /* the help string should be obtained from the helpstringdll,
7173 * using the _DLLGetDocumentation function, based on the supplied
7174 * lcid. Nice to do sometime...
7176 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7178 *pbstrHelpString=SysAllocString(This->Name);
7179 if(pdwHelpStringContext)
7180 *pdwHelpStringContext=This->dwHelpStringContext;
7181 if(pbstrHelpStringDll)
7182 *pbstrHelpStringDll=
7183 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7185 }else {/* for a member */
7186 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7187 if(pFDesc->funcdesc.memid==memid){
7189 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7190 if(pdwHelpStringContext)
7191 *pdwHelpStringContext=pFDesc->HelpStringContext;
7192 if(pbstrHelpStringDll)
7193 *pbstrHelpStringDll=
7194 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7197 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7198 if(pVDesc->vardesc.memid==memid){
7200 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7201 if(pdwHelpStringContext)
7202 *pdwHelpStringContext=pVDesc->HelpStringContext;
7203 if(pbstrHelpStringDll)
7204 *pbstrHelpStringDll=
7205 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7209 return TYPE_E_ELEMENTNOTFOUND;
7212 /* ITypeInfo2::GetAllCustData
7214 * Gets all custom data items for the Type info.
7217 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7219 CUSTDATA *pCustData)
7221 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7222 TLBCustData *pCData;
7225 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7227 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7228 if(pCustData->prgCustData ){
7229 pCustData->cCustData=This->ctCustData;
7230 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7231 pCustData->prgCustData[i].guid=pCData->guid;
7232 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7235 ERR(" OUT OF MEMORY!\n");
7236 return E_OUTOFMEMORY;
7241 /* ITypeInfo2::GetAllFuncCustData
7243 * Gets all custom data items for the specified Function
7246 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7249 CUSTDATA *pCustData)
7251 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7252 TLBCustData *pCData;
7253 TLBFuncDesc * pFDesc;
7255 TRACE("(%p) index %d\n", This, index);
7256 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7257 pFDesc=pFDesc->next)
7260 pCustData->prgCustData =
7261 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7262 if(pCustData->prgCustData ){
7263 pCustData->cCustData=pFDesc->ctCustData;
7264 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7265 pCData = pCData->next){
7266 pCustData->prgCustData[i].guid=pCData->guid;
7267 VariantCopy(& pCustData->prgCustData[i].varValue,
7271 ERR(" OUT OF MEMORY!\n");
7272 return E_OUTOFMEMORY;
7276 return TYPE_E_ELEMENTNOTFOUND;
7279 /* ITypeInfo2::GetAllParamCustData
7281 * Gets all custom data items for the Functions
7284 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7285 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7287 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7288 TLBCustData *pCData=NULL;
7289 TLBFuncDesc * pFDesc;
7291 TRACE("(%p) index %d\n", This, indexFunc);
7292 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7293 pFDesc=pFDesc->next)
7295 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7296 pCustData->prgCustData =
7297 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7298 sizeof(CUSTDATAITEM));
7299 if(pCustData->prgCustData ){
7300 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7301 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7302 pCData; i++, pCData = pCData->next){
7303 pCustData->prgCustData[i].guid=pCData->guid;
7304 VariantCopy(& pCustData->prgCustData[i].varValue,
7308 ERR(" OUT OF MEMORY!\n");
7309 return E_OUTOFMEMORY;
7313 return TYPE_E_ELEMENTNOTFOUND;
7316 /* ITypeInfo2::GetAllVarCustData
7318 * Gets all custom data items for the specified Variable
7321 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7322 UINT index, CUSTDATA *pCustData)
7324 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7325 TLBCustData *pCData;
7326 TLBVarDesc * pVDesc;
7328 TRACE("(%p) index %d\n", This, index);
7329 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7330 pVDesc=pVDesc->next)
7333 pCustData->prgCustData =
7334 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7335 if(pCustData->prgCustData ){
7336 pCustData->cCustData=pVDesc->ctCustData;
7337 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7338 pCData = pCData->next){
7339 pCustData->prgCustData[i].guid=pCData->guid;
7340 VariantCopy(& pCustData->prgCustData[i].varValue,
7344 ERR(" OUT OF MEMORY!\n");
7345 return E_OUTOFMEMORY;
7349 return TYPE_E_ELEMENTNOTFOUND;
7352 /* ITypeInfo2::GetAllImplCustData
7354 * Gets all custom data items for the specified implementation type
7357 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7360 CUSTDATA *pCustData)
7362 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7363 TLBCustData *pCData;
7364 TLBImplType * pRDesc;
7366 TRACE("(%p) index %d\n", This, index);
7367 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7368 pRDesc=pRDesc->next)
7371 pCustData->prgCustData =
7372 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7373 if(pCustData->prgCustData ){
7374 pCustData->cCustData=pRDesc->ctCustData;
7375 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7376 pCData = pCData->next){
7377 pCustData->prgCustData[i].guid=pCData->guid;
7378 VariantCopy(& pCustData->prgCustData[i].varValue,
7382 ERR(" OUT OF MEMORY!\n");
7383 return E_OUTOFMEMORY;
7387 return TYPE_E_ELEMENTNOTFOUND;
7390 static const ITypeInfo2Vtbl tinfvt =
7393 ITypeInfo_fnQueryInterface,
7395 ITypeInfo_fnRelease,
7397 ITypeInfo_fnGetTypeAttr,
7398 ITypeInfo_fnGetTypeComp,
7399 ITypeInfo_fnGetFuncDesc,
7400 ITypeInfo_fnGetVarDesc,
7401 ITypeInfo_fnGetNames,
7402 ITypeInfo_fnGetRefTypeOfImplType,
7403 ITypeInfo_fnGetImplTypeFlags,
7404 ITypeInfo_fnGetIDsOfNames,
7406 ITypeInfo_fnGetDocumentation,
7407 ITypeInfo_fnGetDllEntry,
7408 ITypeInfo_fnGetRefTypeInfo,
7409 ITypeInfo_fnAddressOfMember,
7410 ITypeInfo_fnCreateInstance,
7411 ITypeInfo_fnGetMops,
7412 ITypeInfo_fnGetContainingTypeLib,
7413 ITypeInfo_fnReleaseTypeAttr,
7414 ITypeInfo_fnReleaseFuncDesc,
7415 ITypeInfo_fnReleaseVarDesc,
7417 ITypeInfo2_fnGetTypeKind,
7418 ITypeInfo2_fnGetTypeFlags,
7419 ITypeInfo2_fnGetFuncIndexOfMemId,
7420 ITypeInfo2_fnGetVarIndexOfMemId,
7421 ITypeInfo2_fnGetCustData,
7422 ITypeInfo2_fnGetFuncCustData,
7423 ITypeInfo2_fnGetParamCustData,
7424 ITypeInfo2_fnGetVarCustData,
7425 ITypeInfo2_fnGetImplTypeCustData,
7426 ITypeInfo2_fnGetDocumentation2,
7427 ITypeInfo2_fnGetAllCustData,
7428 ITypeInfo2_fnGetAllFuncCustData,
7429 ITypeInfo2_fnGetAllParamCustData,
7430 ITypeInfo2_fnGetAllVarCustData,
7431 ITypeInfo2_fnGetAllImplTypeCustData,
7434 /******************************************************************************
7435 * CreateDispTypeInfo [OLEAUT32.31]
7437 * Build type information for an object so it can be called through an
7438 * IDispatch interface.
7441 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7442 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7445 * This call allows an objects methods to be accessed through IDispatch, by
7446 * building an ITypeInfo object that IDispatch can use to call through.
7448 HRESULT WINAPI CreateDispTypeInfo(
7449 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7450 LCID lcid, /* [I] Locale Id */
7451 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7453 ITypeInfoImpl *pTIClass, *pTIIface;
7454 ITypeLibImpl *pTypeLibImpl;
7455 unsigned int param, func;
7456 TLBFuncDesc **ppFuncDesc;
7460 pTypeLibImpl = TypeLibImpl_Constructor();
7461 if (!pTypeLibImpl) return E_FAIL;
7463 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7464 pTIIface->pTypeLib = pTypeLibImpl;
7465 pTIIface->index = 0;
7466 pTIIface->Name = NULL;
7467 pTIIface->dwHelpContext = -1;
7468 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7469 pTIIface->TypeAttr.lcid = lcid;
7470 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7471 pTIIface->TypeAttr.wMajorVerNum = 0;
7472 pTIIface->TypeAttr.wMinorVerNum = 0;
7473 pTIIface->TypeAttr.cbAlignment = 2;
7474 pTIIface->TypeAttr.cbSizeInstance = -1;
7475 pTIIface->TypeAttr.cbSizeVft = -1;
7476 pTIIface->TypeAttr.cFuncs = 0;
7477 pTIIface->TypeAttr.cImplTypes = 0;
7478 pTIIface->TypeAttr.cVars = 0;
7479 pTIIface->TypeAttr.wTypeFlags = 0;
7481 ppFuncDesc = &pTIIface->funclist;
7482 for(func = 0; func < pidata->cMembers; func++) {
7483 METHODDATA *md = pidata->pmethdata + func;
7484 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7485 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7486 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7487 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7488 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7489 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7490 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7491 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7492 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7493 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7494 (*ppFuncDesc)->funcdesc.cScodes = 0;
7495 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7496 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7497 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7498 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7499 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7500 md->cArgs * sizeof(ELEMDESC));
7501 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7502 md->cArgs * sizeof(TLBParDesc));
7503 for(param = 0; param < md->cArgs; param++) {
7504 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7505 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7507 (*ppFuncDesc)->helpcontext = 0;
7508 (*ppFuncDesc)->HelpStringContext = 0;
7509 (*ppFuncDesc)->HelpString = NULL;
7510 (*ppFuncDesc)->Entry = NULL;
7511 (*ppFuncDesc)->ctCustData = 0;
7512 (*ppFuncDesc)->pCustData = NULL;
7513 (*ppFuncDesc)->next = NULL;
7514 pTIIface->TypeAttr.cFuncs++;
7515 ppFuncDesc = &(*ppFuncDesc)->next;
7518 dump_TypeInfo(pTIIface);
7520 pTypeLibImpl->pTypeInfo = pTIIface;
7521 pTypeLibImpl->TypeInfoCount++;
7523 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7524 pTIClass->pTypeLib = pTypeLibImpl;
7525 pTIClass->index = 1;
7526 pTIClass->Name = NULL;
7527 pTIClass->dwHelpContext = -1;
7528 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7529 pTIClass->TypeAttr.lcid = lcid;
7530 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7531 pTIClass->TypeAttr.wMajorVerNum = 0;
7532 pTIClass->TypeAttr.wMinorVerNum = 0;
7533 pTIClass->TypeAttr.cbAlignment = 2;
7534 pTIClass->TypeAttr.cbSizeInstance = -1;
7535 pTIClass->TypeAttr.cbSizeVft = -1;
7536 pTIClass->TypeAttr.cFuncs = 0;
7537 pTIClass->TypeAttr.cImplTypes = 1;
7538 pTIClass->TypeAttr.cVars = 0;
7539 pTIClass->TypeAttr.wTypeFlags = 0;
7541 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7542 pTIClass->impltypelist->hRef = 0;
7544 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7547 ref->pImpTLInfo = TLB_REF_INTERNAL;
7548 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7550 dump_TypeInfo(pTIClass);
7552 pTIIface->next = pTIClass;
7553 pTypeLibImpl->TypeInfoCount++;
7555 *pptinfo = (ITypeInfo*)pTIClass;
7557 ITypeInfo_AddRef(*pptinfo);
7558 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7564 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7566 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7568 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7571 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7573 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7575 return ITypeInfo_AddRef((ITypeInfo *)This);
7578 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7580 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7582 return ITypeInfo_Release((ITypeInfo *)This);
7585 static HRESULT WINAPI ITypeComp_fnBind(
7590 ITypeInfo ** ppTInfo,
7591 DESCKIND * pDescKind,
7594 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7595 const TLBFuncDesc *pFDesc;
7596 const TLBVarDesc *pVDesc;
7597 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7599 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7601 *pDescKind = DESCKIND_NONE;
7602 pBindPtr->lpfuncdesc = NULL;
7605 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7606 if (!strcmpiW(pFDesc->Name, szName)) {
7607 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7610 /* name found, but wrong flags */
7611 hr = TYPE_E_TYPEMISMATCH;
7616 HRESULT hr = TLB_AllocAndInitFuncDesc(
7618 &pBindPtr->lpfuncdesc,
7619 This->TypeAttr.typekind == TKIND_DISPATCH);
7622 *pDescKind = DESCKIND_FUNCDESC;
7623 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7624 ITypeInfo_AddRef(*ppTInfo);
7627 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7628 if (!strcmpiW(pVDesc->Name, szName)) {
7629 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7632 *pDescKind = DESCKIND_VARDESC;
7633 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7634 ITypeInfo_AddRef(*ppTInfo);
7639 /* FIXME: search each inherited interface, not just the first */
7640 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7641 /* recursive search */
7645 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7648 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7649 ITypeInfo_Release(pTInfo);
7653 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7654 ITypeComp_Release(pTComp);
7657 WARN("Could not search inherited interface!\n");
7659 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7663 static HRESULT WINAPI ITypeComp_fnBindType(
7667 ITypeInfo ** ppTInfo,
7668 ITypeComp ** ppTComp)
7670 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7672 /* strange behaviour (does nothing) but like the
7675 if (!ppTInfo || !ppTComp)
7684 static const ITypeCompVtbl tcompvt =
7687 ITypeComp_fnQueryInterface,
7689 ITypeComp_fnRelease,
7692 ITypeComp_fnBindType