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]);
2221 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2222 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2223 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2226 static ITypeLibImpl *tlb_cache_first;
2227 static CRITICAL_SECTION cache_section;
2228 static CRITICAL_SECTION_DEBUG cache_section_debug =
2230 0, 0, &cache_section,
2231 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2232 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2234 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2237 typedef struct TLB_PEFile
2239 const IUnknownVtbl *lpvtbl;
2242 HRSRC typelib_resource;
2243 HGLOBAL typelib_global;
2244 LPVOID typelib_base;
2247 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2249 if (IsEqualIID(riid, &IID_IUnknown))
2252 IUnknown_AddRef(iface);
2256 return E_NOINTERFACE;
2259 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2261 TLB_PEFile *This = (TLB_PEFile *)iface;
2262 return InterlockedIncrement(&This->refs);
2265 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2267 TLB_PEFile *This = (TLB_PEFile *)iface;
2268 ULONG refs = InterlockedDecrement(&This->refs);
2271 if (This->typelib_global)
2272 FreeResource(This->typelib_global);
2274 FreeLibrary(This->dll);
2275 HeapFree(GetProcessHeap(), 0, This);
2280 static const IUnknownVtbl TLB_PEFile_Vtable =
2282 TLB_PEFile_QueryInterface,
2287 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2291 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2293 return E_OUTOFMEMORY;
2295 This->lpvtbl = &TLB_PEFile_Vtable;
2298 This->typelib_resource = NULL;
2299 This->typelib_global = NULL;
2300 This->typelib_base = NULL;
2302 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2303 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2307 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2308 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2309 if (This->typelib_resource)
2311 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2312 if (This->typelib_global)
2314 This->typelib_base = LockResource(This->typelib_global);
2316 if (This->typelib_base)
2318 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2319 *ppBase = This->typelib_base;
2320 *ppFile = (IUnknown *)&This->lpvtbl;
2327 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2328 return TYPE_E_CANTLOADLIBRARY;
2331 typedef struct TLB_NEFile
2333 const IUnknownVtbl *lpvtbl;
2335 LPVOID typelib_base;
2338 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2340 if (IsEqualIID(riid, &IID_IUnknown))
2343 IUnknown_AddRef(iface);
2347 return E_NOINTERFACE;
2350 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2352 TLB_NEFile *This = (TLB_NEFile *)iface;
2353 return InterlockedIncrement(&This->refs);
2356 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2358 TLB_NEFile *This = (TLB_NEFile *)iface;
2359 ULONG refs = InterlockedDecrement(&This->refs);
2362 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2363 HeapFree(GetProcessHeap(), 0, This);
2368 static const IUnknownVtbl TLB_NEFile_Vtable =
2370 TLB_NEFile_QueryInterface,
2375 /***********************************************************************
2376 * read_xx_header [internal]
2378 static int read_xx_header( HFILE lzfd )
2380 IMAGE_DOS_HEADER mzh;
2383 LZSeek( lzfd, 0, SEEK_SET );
2384 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2386 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2389 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2390 if ( 2 != LZRead( lzfd, magic, 2 ) )
2393 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2395 if ( magic[0] == 'N' && magic[1] == 'E' )
2396 return IMAGE_OS2_SIGNATURE;
2397 if ( magic[0] == 'P' && magic[1] == 'E' )
2398 return IMAGE_NT_SIGNATURE;
2401 WARN("Can't handle %s files.\n", magic );
2406 /***********************************************************************
2407 * find_ne_resource [internal]
2409 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2410 DWORD *resLen, DWORD *resOff )
2412 IMAGE_OS2_HEADER nehd;
2413 NE_TYPEINFO *typeInfo;
2414 NE_NAMEINFO *nameInfo;
2420 /* Read in NE header */
2421 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2422 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2424 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2427 TRACE("No resources in NE dll\n" );
2431 /* Read in resource table */
2432 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2433 if ( !resTab ) return FALSE;
2435 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2436 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2438 HeapFree( GetProcessHeap(), 0, resTab );
2443 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2445 if (HIWORD(typeid) != 0) /* named type */
2447 BYTE len = strlen( typeid );
2448 while (typeInfo->type_id)
2450 if (!(typeInfo->type_id & 0x8000))
2452 BYTE *p = resTab + typeInfo->type_id;
2453 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2455 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2456 typeInfo->count * sizeof(NE_NAMEINFO));
2459 else /* numeric type id */
2461 WORD id = LOWORD(typeid) | 0x8000;
2462 while (typeInfo->type_id)
2464 if (typeInfo->type_id == id) goto found_type;
2465 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2466 typeInfo->count * sizeof(NE_NAMEINFO));
2469 TRACE("No typeid entry found for %p\n", typeid );
2470 HeapFree( GetProcessHeap(), 0, resTab );
2474 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2476 if (HIWORD(resid) != 0) /* named resource */
2478 BYTE len = strlen( resid );
2479 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2481 BYTE *p = resTab + nameInfo->id;
2482 if (nameInfo->id & 0x8000) continue;
2483 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2486 else /* numeric resource id */
2488 WORD id = LOWORD(resid) | 0x8000;
2489 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2490 if (nameInfo->id == id) goto found_name;
2492 TRACE("No resid entry found for %p\n", typeid );
2493 HeapFree( GetProcessHeap(), 0, resTab );
2497 /* Return resource data */
2498 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2499 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2501 HeapFree( GetProcessHeap(), 0, resTab );
2505 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2509 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2510 TLB_NEFile *This = NULL;
2512 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2513 if (!This) return E_OUTOFMEMORY;
2515 This->lpvtbl = &TLB_NEFile_Vtable;
2517 This->typelib_base = NULL;
2519 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2520 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2522 DWORD reslen, offset;
2523 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2525 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2526 if( !This->typelib_base )
2530 LZSeek( lzfd, offset, SEEK_SET );
2531 reslen = LZRead( lzfd, This->typelib_base, reslen );
2533 *ppBase = This->typelib_base;
2534 *pdwTLBLength = reslen;
2535 *ppFile = (IUnknown *)&This->lpvtbl;
2541 if( lzfd >= 0) LZClose( lzfd );
2542 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2546 typedef struct TLB_Mapping
2548 const IUnknownVtbl *lpvtbl;
2552 LPVOID typelib_base;
2555 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2557 if (IsEqualIID(riid, &IID_IUnknown))
2560 IUnknown_AddRef(iface);
2564 return E_NOINTERFACE;
2567 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2569 TLB_Mapping *This = (TLB_Mapping *)iface;
2570 return InterlockedIncrement(&This->refs);
2573 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2575 TLB_Mapping *This = (TLB_Mapping *)iface;
2576 ULONG refs = InterlockedDecrement(&This->refs);
2579 if (This->typelib_base)
2580 UnmapViewOfFile(This->typelib_base);
2582 CloseHandle(This->mapping);
2583 if (This->file != INVALID_HANDLE_VALUE)
2584 CloseHandle(This->file);
2585 HeapFree(GetProcessHeap(), 0, This);
2590 static const IUnknownVtbl TLB_Mapping_Vtable =
2592 TLB_Mapping_QueryInterface,
2597 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2601 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2603 return E_OUTOFMEMORY;
2605 This->lpvtbl = &TLB_Mapping_Vtable;
2607 This->file = INVALID_HANDLE_VALUE;
2608 This->mapping = NULL;
2609 This->typelib_base = NULL;
2611 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2612 if (INVALID_HANDLE_VALUE != This->file)
2614 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2617 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2618 if(This->typelib_base)
2620 /* retrieve file size */
2621 *pdwTLBLength = GetFileSize(This->file, NULL);
2622 *ppBase = This->typelib_base;
2623 *ppFile = (IUnknown *)&This->lpvtbl;
2629 IUnknown_Release((IUnknown *)&This->lpvtbl);
2630 return TYPE_E_CANTLOADLIBRARY;
2633 /****************************************************************************
2636 * find the type of the typelib file and map the typelib resource into
2639 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2640 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2641 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2643 ITypeLibImpl *entry;
2646 LPWSTR index_str, file = (LPWSTR)pszFileName;
2647 LPVOID pBase = NULL;
2648 DWORD dwTLBLength = 0;
2649 IUnknown *pFile = NULL;
2653 index_str = strrchrW(pszFileName, '\\');
2654 if(index_str && *++index_str != '\0')
2657 long idx = strtolW(index_str, &end_ptr, 10);
2658 if(*end_ptr == '\0')
2660 int str_len = index_str - pszFileName - 1;
2662 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2663 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2668 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2670 if(strchrW(file, '\\'))
2672 lstrcpyW(pszPath, file);
2676 int len = GetSystemDirectoryW(pszPath, cchPath);
2677 pszPath[len] = '\\';
2678 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2682 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2684 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2686 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2687 EnterCriticalSection(&cache_section);
2688 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2690 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2692 TRACE("cache hit\n");
2693 *ppTypeLib = (ITypeLib2*)entry;
2694 ITypeLib_AddRef(*ppTypeLib);
2695 LeaveCriticalSection(&cache_section);
2699 LeaveCriticalSection(&cache_section);
2701 /* now actually load and parse the typelib */
2703 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2704 if (ret == TYPE_E_CANTLOADLIBRARY)
2705 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2706 if (ret == TYPE_E_CANTLOADLIBRARY)
2707 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2710 if (dwTLBLength >= 4)
2712 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2713 if (dwSignature == MSFT_SIGNATURE)
2714 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2715 else if (dwSignature == SLTG_SIGNATURE)
2716 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2719 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2720 ret = TYPE_E_CANTLOADLIBRARY;
2724 ret = TYPE_E_CANTLOADLIBRARY;
2725 IUnknown_Release(pFile);
2729 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2731 TRACE("adding to cache\n");
2732 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2733 lstrcpyW(impl->path, pszPath);
2734 /* We should really canonicalise the path here. */
2735 impl->index = index;
2737 /* FIXME: check if it has added already in the meantime */
2738 EnterCriticalSection(&cache_section);
2739 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2741 tlb_cache_first = impl;
2742 LeaveCriticalSection(&cache_section);
2745 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2750 /*================== ITypeLib(2) Methods ===================================*/
2752 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2754 ITypeLibImpl* pTypeLibImpl;
2756 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2757 if (!pTypeLibImpl) return NULL;
2759 pTypeLibImpl->lpVtbl = &tlbvt;
2760 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2761 pTypeLibImpl->ref = 1;
2763 list_init(&pTypeLibImpl->ref_list);
2764 pTypeLibImpl->dispatch_href = -1;
2766 return pTypeLibImpl;
2769 /****************************************************************************
2770 * ITypeLib2_Constructor_MSFT
2772 * loading an MSFT typelib from an in-memory image
2774 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2778 MSFT_Header tlbHeader;
2779 MSFT_SegDir tlbSegDir;
2780 ITypeLibImpl * pTypeLibImpl;
2782 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2784 pTypeLibImpl = TypeLibImpl_Constructor();
2785 if (!pTypeLibImpl) return NULL;
2787 /* get pointer to beginning of typelib data */
2791 cx.pLibInfo = pTypeLibImpl;
2792 cx.length = dwTLBLength;
2795 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2796 TRACE_(typelib)("header:\n");
2797 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2798 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2799 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2802 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2804 /* there is a small amount of information here until the next important
2806 * the segment directory . Try to calculate the amount of data */
2807 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2809 /* now read the segment directory */
2810 TRACE("read segment directory (at %ld)\n",lPSegDir);
2811 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2812 cx.pTblDir = &tlbSegDir;
2814 /* just check two entries */
2815 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2817 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2818 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2822 /* now fill our internal data */
2823 /* TLIBATTR fields */
2824 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2826 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2827 /* Windows seems to have zero here, is this correct? */
2828 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2829 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2831 pTypeLibImpl->LibAttr.lcid = 0;
2833 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2834 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2835 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2836 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2838 /* name, eventually add to a hash table */
2839 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2842 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2843 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2845 if( tlbHeader.varflags & HELPDLLFLAG)
2848 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2849 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2852 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2855 if(tlbHeader.CustomDataOffset >= 0)
2857 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2860 /* fill in type descriptions */
2861 if(tlbSegDir.pTypdescTab.length > 0)
2863 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2865 pTypeLibImpl->ctTypeDesc = cTD;
2866 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2867 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2870 /* FIXME: add several sanity checks here */
2871 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2872 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2874 /* FIXME: check safearray */
2876 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2878 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2880 else if(td[0] == VT_CARRAY)
2882 /* array descr table here */
2883 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2885 else if(td[0] == VT_USERDEFINED)
2887 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2889 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2892 /* second time around to fill the array subscript info */
2895 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2896 if(tlbSegDir.pArrayDescriptions.offset>0)
2898 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2899 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2902 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2904 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2906 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2908 for(j = 0; j<td[2]; j++)
2910 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2911 sizeof(INT), &cx, DO_NOT_SEEK);
2912 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2913 sizeof(INT), &cx, DO_NOT_SEEK);
2918 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2919 ERR("didn't find array description data\n");
2924 /* imported type libs */
2925 if(tlbSegDir.pImpFiles.offset>0)
2927 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2928 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2931 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2935 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2936 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2937 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2939 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2940 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2941 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2942 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2945 name = TLB_Alloc(size+1);
2946 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2947 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2949 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2950 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2952 ppImpLib = &(*ppImpLib)->next;
2956 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2957 if(pTypeLibImpl->dispatch_href != -1)
2958 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2961 if(tlbHeader.nrtypeinfos >= 0 )
2963 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2964 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2967 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2969 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2971 ppTI = &((*ppTI)->next);
2972 (pTypeLibImpl->TypeInfoCount)++;
2976 TRACE("(%p)\n", pTypeLibImpl);
2977 return (ITypeLib2*) pTypeLibImpl;
2981 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2987 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2988 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2992 guid->Data4[0] = s >> 8;
2993 guid->Data4[1] = s & 0xff;
2996 for(i = 0; i < 6; i++) {
2997 memcpy(b, str + 24 + 2 * i, 2);
2998 guid->Data4[i + 2] = strtol(b, NULL, 16);
3003 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3009 bytelen = *(const WORD*)ptr;
3010 if(bytelen == 0xffff) return 2;
3011 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3012 *pBstr = SysAllocStringLen(NULL, len - 1);
3014 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3018 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3023 bytelen = *(const WORD*)ptr;
3024 if(bytelen == 0xffff) return 2;
3025 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3026 memcpy(*str, ptr + 2, bytelen);
3027 (*str)[bytelen] = '\0';
3031 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3033 char *ptr = pLibBlk;
3036 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3037 FIXME("libblk magic = %04x\n", w);
3042 if((w = *(WORD*)ptr) != 0xffff) {
3043 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3048 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3050 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3052 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3055 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3058 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3059 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3061 pTypeLibImpl->LibAttr.lcid = 0;
3064 ptr += 4; /* skip res12 */
3066 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3069 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3072 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3075 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3076 ptr += sizeof(GUID);
3078 return ptr - (char*)pLibBlk;
3081 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3086 } sltg_ref_lookup_t;
3088 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3089 HREFTYPE *typelib_ref)
3091 if(typeinfo_ref < table->num)
3093 *typelib_ref = table->refs[typeinfo_ref];
3097 ERR_(typelib)("Unable to find reference\n");
3102 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3107 if((*pType & 0xe00) == 0xe00) {
3109 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3111 pTD = pTD->u.lptdesc;
3113 switch(*pType & 0x3f) {
3116 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3118 pTD = pTD->u.lptdesc;
3121 case VT_USERDEFINED:
3122 pTD->vt = VT_USERDEFINED;
3123 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3129 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3132 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3134 pTD->vt = VT_CARRAY;
3135 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3137 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3138 pTD->u.lpadesc->cDims = pSA->cDims;
3139 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3140 pSA->cDims * sizeof(SAFEARRAYBOUND));
3142 pTD = &pTD->u.lpadesc->tdescElem;
3148 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3152 pTD->vt = VT_SAFEARRAY;
3153 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3155 pTD = pTD->u.lptdesc;
3159 pTD->vt = *pType & 0x3f;
3168 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3169 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3171 /* Handle [in/out] first */
3172 if((*pType & 0xc000) == 0xc000)
3173 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3174 else if(*pType & 0x8000)
3175 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3176 else if(*pType & 0x4000)
3177 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3179 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3182 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3185 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3187 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3191 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3196 TLBRefType *ref_type;
3197 sltg_ref_lookup_t *table;
3198 HREFTYPE typelib_ref;
3200 if(pRef->magic != SLTG_REF_MAGIC) {
3201 FIXME("Ref magic = %x\n", pRef->magic);
3204 name = ( (char*)pRef->names + pRef->number);
3206 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3207 table->num = pRef->number >> 3;
3209 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3211 /* We don't want the first href to be 0 */
3212 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3214 for(ref = 0; ref < pRef->number >> 3; ref++) {
3216 unsigned int lib_offs, type_num;
3218 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3220 name += SLTG_ReadStringA(name, &refname);
3221 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3222 FIXME_(typelib)("Can't sscanf ref\n");
3223 if(lib_offs != 0xffff) {
3224 TLBImpLib **import = &pTL->pImpLibs;
3227 if((*import)->offset == lib_offs)
3229 import = &(*import)->next;
3232 char fname[MAX_PATH+1];
3235 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3237 (*import)->offset = lib_offs;
3238 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3240 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3241 &(*import)->wVersionMajor,
3242 &(*import)->wVersionMinor,
3243 &(*import)->lcid, fname) != 4) {
3244 FIXME_(typelib)("can't sscanf ref %s\n",
3245 pNameTable + lib_offs + 40);
3247 len = strlen(fname);
3248 if(fname[len-1] != '#')
3249 FIXME("fname = %s\n", fname);
3250 fname[len-1] = '\0';
3251 (*import)->name = TLB_MultiByteToBSTR(fname);
3253 ref_type->pImpTLInfo = *import;
3255 /* Store a reference to IDispatch */
3256 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3257 pTL->dispatch_href = typelib_ref;
3259 } else { /* internal ref */
3260 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3262 ref_type->reference = typelib_ref;
3263 ref_type->index = type_num;
3265 HeapFree(GetProcessHeap(), 0, refname);
3266 list_add_tail(&pTL->ref_list, &ref_type->entry);
3268 table->refs[ref] = typelib_ref;
3271 if((BYTE)*name != SLTG_REF_MAGIC)
3272 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3273 dump_TLBRefType(pTL);
3277 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3278 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3280 SLTG_ImplInfo *info;
3281 TLBImplType **ppImplType = &pTI->impltypelist;
3282 /* I don't really get this structure, usually it's 0x16 bytes
3283 long, but iuser.tlb contains some that are 0x18 bytes long.
3284 That's ok because we can use the next ptr to jump to the next
3285 one. But how do we know the length of the last one? The WORD
3286 at offs 0x8 might be the clue. For now I'm just assuming that
3287 the last one is the regular 0x16 bytes. */
3289 info = (SLTG_ImplInfo*)pBlk;
3291 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3292 sizeof(**ppImplType));
3293 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3294 (*ppImplType)->implflags = info->impltypeflags;
3295 pTI->TypeAttr.cImplTypes++;
3296 ppImplType = &(*ppImplType)->next;
3298 if(info->next == 0xffff)
3301 FIXME_(typelib)("Interface inheriting more than one interface\n");
3302 info = (SLTG_ImplInfo*)(pBlk + info->next);
3304 info++; /* see comment at top of function */
3308 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3309 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3311 TLBVarDesc **ppVarDesc = &pTI->varlist;
3312 BSTR bstrPrevName = NULL;
3313 SLTG_Variable *pItem;
3317 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3318 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3320 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3321 sizeof(**ppVarDesc));
3322 (*ppVarDesc)->vardesc.memid = pItem->memid;
3324 if (pItem->magic != SLTG_VAR_MAGIC &&
3325 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3326 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3330 if (pItem->name == 0xfffe)
3331 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3333 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3335 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3336 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3337 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3339 if(pItem->flags & 0x02)
3340 pType = &pItem->type;
3342 pType = (WORD*)(pBlk + pItem->type);
3344 if (pItem->flags & ~0xda)
3345 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3347 SLTG_DoElem(pType, pBlk,
3348 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3350 if (TRACE_ON(typelib)) {
3352 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3353 TRACE_(typelib)("elemdescVar: %s\n", buf);
3356 if (pItem->flags & 0x40) {
3357 TRACE_(typelib)("VAR_DISPATCH\n");
3358 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3360 else if (pItem->flags & 0x10) {
3361 TRACE_(typelib)("VAR_CONST\n");
3362 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3363 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3365 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3366 if (pItem->flags & 0x08)
3367 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3369 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3375 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3377 TRACE_(typelib)("len = %u\n", len);
3378 if (len == 0xffff) {
3381 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3382 str = SysAllocStringLen(NULL, alloc_len);
3383 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3385 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3386 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3395 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3396 *(INT*)(pBlk + pItem->byte_offs);
3399 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3404 TRACE_(typelib)("VAR_PERINSTANCE\n");
3405 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3406 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3409 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3410 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3412 if (pItem->flags & 0x80)
3413 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3415 bstrPrevName = (*ppVarDesc)->Name;
3416 ppVarDesc = &((*ppVarDesc)->next);
3418 pTI->TypeAttr.cVars = cVars;
3421 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3422 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3424 SLTG_Function *pFunc;
3426 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3428 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3429 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3434 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3435 sizeof(**ppFuncDesc));
3437 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3438 case SLTG_FUNCTION_MAGIC:
3439 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3441 case SLTG_DISPATCH_FUNCTION_MAGIC:
3442 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3444 case SLTG_STATIC_FUNCTION_MAGIC:
3445 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3448 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3449 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3453 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3455 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3456 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3457 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3458 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3459 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3460 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3462 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3463 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3465 if(pFunc->retnextopt & 0x80)
3466 pType = &pFunc->rettype;
3468 pType = (WORD*)(pBlk + pFunc->rettype);
3470 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3472 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3473 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3474 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3475 (*ppFuncDesc)->pParamDesc =
3476 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3477 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3479 pArg = (WORD*)(pBlk + pFunc->arg_off);
3481 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3482 char *paramName = pNameTable + *pArg;
3484 /* If arg type follows then paramName points to the 2nd
3485 letter of the name, else the next WORD is an offset to
3486 the arg type and paramName points to the first letter.
3487 So let's take one char off paramName and see if we're
3488 pointing at an alpha-numeric char. However if *pArg is
3489 0xffff or 0xfffe then the param has no name, the former
3490 meaning that the next WORD is the type, the latter
3491 meaning that the next WORD is an offset to the type. */
3496 else if(*pArg == 0xfffe) {
3500 else if(paramName[-1] && !isalnum(paramName[-1]))
3505 if(HaveOffs) { /* the next word is an offset to type */
3506 pType = (WORD*)(pBlk + *pArg);
3507 SLTG_DoElem(pType, pBlk,
3508 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3513 pArg = SLTG_DoElem(pArg, pBlk,
3514 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3517 /* Are we an optional param ? */
3518 if((*ppFuncDesc)->funcdesc.cParams - param <=
3519 (*ppFuncDesc)->funcdesc.cParamsOpt)
3520 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3523 (*ppFuncDesc)->pParamDesc[param].Name =
3524 TLB_MultiByteToBSTR(paramName);
3526 (*ppFuncDesc)->pParamDesc[param].Name =
3527 SysAllocString((*ppFuncDesc)->Name);
3531 ppFuncDesc = &((*ppFuncDesc)->next);
3532 if(pFunc->next == 0xffff) break;
3534 pTI->TypeAttr.cFuncs = cFuncs;
3537 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3538 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3539 SLTG_TypeInfoTail *pTITail)
3542 sltg_ref_lookup_t *ref_lookup = NULL;
3544 if(pTIHeader->href_table != 0xffffffff) {
3545 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3551 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3552 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3554 HeapFree(GetProcessHeap(), 0, ref_lookup);
3558 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3559 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3560 const SLTG_TypeInfoTail *pTITail)
3563 sltg_ref_lookup_t *ref_lookup = NULL;
3565 if(pTIHeader->href_table != 0xffffffff) {
3566 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3572 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3573 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3576 if (pTITail->funcs_off != 0xffff)
3577 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3579 HeapFree(GetProcessHeap(), 0, ref_lookup);
3581 if (TRACE_ON(typelib))
3582 dump_TLBFuncDesc(pTI->funclist);
3585 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3586 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3587 const SLTG_TypeInfoTail *pTITail)
3589 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3592 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3593 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3594 const SLTG_TypeInfoTail *pTITail)
3597 sltg_ref_lookup_t *ref_lookup = NULL;
3599 if (pTITail->simple_alias) {
3600 /* if simple alias, no more processing required */
3601 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3605 if(pTIHeader->href_table != 0xffffffff) {
3606 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3610 /* otherwise it is an offset to a type */
3611 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3613 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3615 HeapFree(GetProcessHeap(), 0, ref_lookup);
3618 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3619 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3620 const SLTG_TypeInfoTail *pTITail)
3622 sltg_ref_lookup_t *ref_lookup = NULL;
3623 if (pTIHeader->href_table != 0xffffffff)
3624 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3627 if (pTITail->vars_off != 0xffff)
3628 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3630 if (pTITail->funcs_off != 0xffff)
3631 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3633 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3634 * of dispinterface functions including the IDispatch ones, so
3635 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3636 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3638 HeapFree(GetProcessHeap(), 0, ref_lookup);
3639 if (TRACE_ON(typelib))
3640 dump_TLBFuncDesc(pTI->funclist);
3643 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3644 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3645 const SLTG_TypeInfoTail *pTITail)
3647 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3650 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3651 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3652 const SLTG_TypeInfoTail *pTITail)
3654 sltg_ref_lookup_t *ref_lookup = NULL;
3655 if (pTIHeader->href_table != 0xffffffff)
3656 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3659 if (pTITail->vars_off != 0xffff)
3660 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3662 if (pTITail->funcs_off != 0xffff)
3663 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3664 HeapFree(GetProcessHeap(), 0, ref_lookup);
3665 if (TRACE_ON(typelib))
3669 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3670 managable copy of it into this */
3683 } SLTG_InternalOtherTypeInfo;
3685 /****************************************************************************
3686 * ITypeLib2_Constructor_SLTG
3688 * loading a SLTG typelib from an in-memory image
3690 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3692 ITypeLibImpl *pTypeLibImpl;
3693 SLTG_Header *pHeader;
3694 SLTG_BlkEntry *pBlkEntry;
3698 LPVOID pBlk, pFirstBlk;
3699 SLTG_LibBlk *pLibBlk;
3700 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3701 char *pAfterOTIBlks = NULL;
3702 char *pNameTable, *ptr;
3705 ITypeInfoImpl **ppTypeInfoImpl;
3707 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3710 pTypeLibImpl = TypeLibImpl_Constructor();
3711 if (!pTypeLibImpl) return NULL;
3715 TRACE_(typelib)("header:\n");
3716 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3717 pHeader->nrOfFileBlks );
3718 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3719 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3720 pHeader->SLTG_magic);
3724 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3725 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3727 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3728 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3730 /* Next we have a magic block */
3731 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3733 /* Let's see if we're still in sync */
3734 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3735 sizeof(SLTG_COMPOBJ_MAGIC))) {
3736 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3739 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3740 sizeof(SLTG_DIR_MAGIC))) {
3741 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3745 pIndex = (SLTG_Index*)(pMagic+1);
3747 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3749 pFirstBlk = (LPVOID)(pPad9 + 1);
3751 /* We'll set up a ptr to the main library block, which is the last one. */
3753 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3754 pBlkEntry[order].next != 0;
3755 order = pBlkEntry[order].next - 1, i++) {
3756 pBlk = (char*)pBlk + pBlkEntry[order].len;
3760 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3762 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3767 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3769 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3770 sizeof(*pOtherTypeInfoBlks) *
3771 pTypeLibImpl->TypeInfoCount);
3774 ptr = (char*)pLibBlk + len;
3776 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3780 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3782 w = *(WORD*)(ptr + 2);
3785 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3787 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3788 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3790 w = *(WORD*)(ptr + 4 + len);
3792 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3794 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3796 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3797 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3799 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3800 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3801 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3803 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3805 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3808 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3809 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3810 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3811 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3812 len += sizeof(SLTG_OtherTypeInfo);
3816 pAfterOTIBlks = ptr;
3818 /* Skip this WORD and get the next DWORD */
3819 len = *(DWORD*)(pAfterOTIBlks + 2);
3821 /* Now add this to pLibBLk look at what we're pointing at and
3822 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3823 dust and we should be pointing at the beginning of the name
3826 pNameTable = (char*)pLibBlk + len;
3828 switch(*(WORD*)pNameTable) {
3835 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3839 pNameTable += 0x216;
3843 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3845 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3848 /* Hopefully we now have enough ptrs set up to actually read in
3849 some TypeInfos. It's not clear which order to do them in, so
3850 I'll just follow the links along the BlkEntry chain and read
3851 them in the order in which they are in the file */
3853 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3855 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3856 pBlkEntry[order].next != 0;
3857 order = pBlkEntry[order].next - 1, i++) {
3859 SLTG_TypeInfoHeader *pTIHeader;
3860 SLTG_TypeInfoTail *pTITail;
3861 SLTG_MemberHeader *pMemHeader;
3863 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3864 pOtherTypeInfoBlks[i].index_name)) {
3865 FIXME_(typelib)("Index strings don't match\n");
3870 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3871 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3874 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3875 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3876 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3878 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3879 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3880 (*ppTypeInfoImpl)->index = i;
3881 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3882 pOtherTypeInfoBlks[i].name_offs +
3884 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3885 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3886 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3887 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3888 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3889 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3890 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3892 if((pTIHeader->typeflags1 & 7) != 2)
3893 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3894 if(pTIHeader->typeflags3 != 2)
3895 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3897 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3898 debugstr_w((*ppTypeInfoImpl)->Name),
3899 typekind_desc[pTIHeader->typekind],
3900 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3901 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3903 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3905 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3907 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3908 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3909 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3911 switch(pTIHeader->typekind) {
3913 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3914 pTIHeader, pTITail);
3918 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3919 pTIHeader, pTITail);
3922 case TKIND_INTERFACE:
3923 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3924 pTIHeader, pTITail);
3928 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3929 pTIHeader, pTITail);
3933 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3934 pTIHeader, pTITail);
3937 case TKIND_DISPATCH:
3938 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3939 pTIHeader, pTITail);
3943 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3944 pTIHeader, pTITail);
3948 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3953 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3954 but we've already set those */
3955 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3970 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3971 pBlk = (char*)pBlk + pBlkEntry[order].len;
3974 if(i != pTypeLibImpl->TypeInfoCount) {
3975 FIXME("Somehow processed %d TypeInfos\n", i);
3979 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3980 return (ITypeLib2*)pTypeLibImpl;
3983 /* ITypeLib::QueryInterface
3985 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3990 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3992 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3995 if(IsEqualIID(riid, &IID_IUnknown) ||
3996 IsEqualIID(riid,&IID_ITypeLib)||
3997 IsEqualIID(riid,&IID_ITypeLib2))
4004 ITypeLib2_AddRef(iface);
4005 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4008 TRACE("-- Interface: E_NOINTERFACE\n");
4009 return E_NOINTERFACE;
4014 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4016 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4017 ULONG ref = InterlockedIncrement(&This->ref);
4019 TRACE("(%p)->ref was %u\n",This, ref - 1);
4024 /* ITypeLib::Release
4026 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4028 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4029 ULONG ref = InterlockedDecrement(&This->ref);
4031 TRACE("(%p)->(%u)\n",This, ref);
4035 TLBImpLib *pImpLib, *pImpLibNext;
4036 TLBCustData *pCustData, *pCustDataNext;
4037 TLBRefType *ref_type;
4041 /* remove cache entry */
4044 TRACE("removing from cache list\n");
4045 EnterCriticalSection(&cache_section);
4046 if (This->next) This->next->prev = This->prev;
4047 if (This->prev) This->prev->next = This->next;
4048 else tlb_cache_first = This->next;
4049 LeaveCriticalSection(&cache_section);
4050 HeapFree(GetProcessHeap(), 0, This->path);
4052 TRACE(" destroying ITypeLib(%p)\n",This);
4054 SysFreeString(This->Name);
4057 SysFreeString(This->DocString);
4058 This->DocString = NULL;
4060 SysFreeString(This->HelpFile);
4061 This->HelpFile = NULL;
4063 SysFreeString(This->HelpStringDll);
4064 This->HelpStringDll = NULL;
4066 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4068 VariantClear(&pCustData->data);
4070 pCustDataNext = pCustData->next;
4071 TLB_Free(pCustData);
4074 for (i = 0; i < This->ctTypeDesc; i++)
4075 if (This->pTypeDesc[i].vt == VT_CARRAY)
4076 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4078 TLB_Free(This->pTypeDesc);
4080 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4082 if (pImpLib->pImpTypeLib)
4083 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4084 SysFreeString(pImpLib->name);
4086 pImpLibNext = pImpLib->next;
4090 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4092 list_remove(&ref_type->entry);
4096 if (This->pTypeInfo) /* can be NULL */
4097 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4098 HeapFree(GetProcessHeap(),0,This);
4105 /* ITypeLib::GetTypeInfoCount
4107 * Returns the number of type descriptions in the type library
4109 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4111 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4112 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4113 return This->TypeInfoCount;
4116 /* ITypeLib::GetTypeInfo
4118 * retrieves the specified type description in the library.
4120 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4123 ITypeInfo **ppTInfo)
4127 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4128 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4130 TRACE("(%p)->(index=%d)\n", This, index);
4132 if (!ppTInfo) return E_INVALIDARG;
4134 /* search element n in list */
4135 for(i=0; i < index; i++)
4137 pTypeInfo = pTypeInfo->next;
4140 TRACE("-- element not found\n");
4141 return TYPE_E_ELEMENTNOTFOUND;
4145 *ppTInfo = (ITypeInfo *) pTypeInfo;
4147 ITypeInfo_AddRef(*ppTInfo);
4148 TRACE("-- found (%p)\n",*ppTInfo);
4153 /* ITypeLibs::GetTypeInfoType
4155 * Retrieves the type of a type description.
4157 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4162 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4164 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4166 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4167 return TYPE_E_ELEMENTNOTFOUND;
4169 TRACE("(%p) index %d\n", This, index);
4171 if(!pTKind) return E_INVALIDARG;
4173 /* search element n in list */
4174 for(i=0; i < index; i++)
4178 TRACE("-- element not found\n");
4179 return TYPE_E_ELEMENTNOTFOUND;
4181 pTInfo = pTInfo->next;
4184 *pTKind = pTInfo->TypeAttr.typekind;
4185 TRACE("-- found Type (%d)\n", *pTKind);
4189 /* ITypeLib::GetTypeInfoOfGuid
4191 * Retrieves the type description that corresponds to the specified GUID.
4194 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4197 ITypeInfo **ppTInfo)
4199 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4200 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4202 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4206 WARN("-- element not found\n");
4207 return TYPE_E_ELEMENTNOTFOUND;
4210 /* search linked list for guid */
4211 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4213 pTypeInfo = pTypeInfo->next;
4217 /* end of list reached */
4218 WARN("-- element not found\n");
4219 return TYPE_E_ELEMENTNOTFOUND;
4223 TRACE("-- found (%p, %s)\n",
4225 debugstr_w(pTypeInfo->Name));
4227 *ppTInfo = (ITypeInfo*)pTypeInfo;
4228 ITypeInfo_AddRef(*ppTInfo);
4232 /* ITypeLib::GetLibAttr
4234 * Retrieves the structure that contains the library's attributes.
4237 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4239 LPTLIBATTR *ppTLibAttr)
4241 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4242 TRACE("(%p)\n",This);
4243 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4244 **ppTLibAttr = This->LibAttr;
4248 /* ITypeLib::GetTypeComp
4250 * Enables a client compiler to bind to a library's types, variables,
4251 * constants, and global functions.
4254 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4256 ITypeComp **ppTComp)
4258 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4260 TRACE("(%p)->(%p)\n",This,ppTComp);
4261 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4262 ITypeComp_AddRef(*ppTComp);
4267 /* ITypeLib::GetDocumentation
4269 * Retrieves the library's documentation string, the complete Help file name
4270 * and path, and the context identifier for the library Help topic in the Help
4273 * On a successful return all non-null BSTR pointers will have been set,
4276 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4280 BSTR *pBstrDocString,
4281 DWORD *pdwHelpContext,
4282 BSTR *pBstrHelpFile)
4284 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4286 HRESULT result = E_INVALIDARG;
4291 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4293 pBstrName, pBstrDocString,
4294 pdwHelpContext, pBstrHelpFile);
4298 /* documentation for the typelib */
4303 if(!(*pBstrName = SysAllocString(This->Name)))
4311 if (This->DocString)
4313 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4316 else if (This->Name)
4318 if(!(*pBstrDocString = SysAllocString(This->Name)))
4322 *pBstrDocString = NULL;
4326 *pdwHelpContext = This->dwHelpContext;
4332 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4336 *pBstrHelpFile = NULL;
4343 /* for a typeinfo */
4344 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4346 if(SUCCEEDED(result))
4348 result = ITypeInfo_GetDocumentation(pTInfo,
4352 pdwHelpContext, pBstrHelpFile);
4354 ITypeInfo_Release(pTInfo);
4359 if (pBstrDocString) SysFreeString (*pBstrDocString);
4361 if (pBstrName) SysFreeString (*pBstrName);
4363 return STG_E_INSUFFICIENTMEMORY;
4368 * Indicates whether a passed-in string contains the name of a type or member
4369 * described in the library.
4372 static HRESULT WINAPI ITypeLib2_fnIsName(
4378 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4379 ITypeInfoImpl *pTInfo;
4380 TLBFuncDesc *pFInfo;
4383 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4385 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4389 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4390 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4391 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4392 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4393 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4394 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4395 goto ITypeLib2_fnIsName_exit;
4397 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4398 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4403 ITypeLib2_fnIsName_exit:
4404 TRACE("(%p)slow! search for %s: %s found!\n", This,
4405 debugstr_w(szNameBuf), *pfName?"NOT":"");
4410 /* ITypeLib::FindName
4412 * Finds occurrences of a type description in a type library. This may be used
4413 * to quickly verify that a name exists in a type library.
4416 static HRESULT WINAPI ITypeLib2_fnFindName(
4420 ITypeInfo **ppTInfo,
4424 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4425 ITypeInfoImpl *pTInfo;
4426 TLBFuncDesc *pFInfo;
4429 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4431 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4432 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4433 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4434 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4435 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4436 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4437 goto ITypeLib2_fnFindName_exit;
4440 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4441 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4443 ITypeLib2_fnFindName_exit:
4444 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4445 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4448 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4449 This, *pcFound, debugstr_w(szNameBuf), j);
4456 /* ITypeLib::ReleaseTLibAttr
4458 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4461 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4463 TLIBATTR *pTLibAttr)
4465 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4466 TRACE("freeing (%p)\n",This);
4467 HeapFree(GetProcessHeap(),0,pTLibAttr);
4471 /* ITypeLib2::GetCustData
4473 * gets the custom data
4475 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4480 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4481 TLBCustData *pCData;
4483 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4485 if( IsEqualIID(guid, &pCData->guid)) break;
4488 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4492 VariantInit( pVarVal);
4493 VariantCopy( pVarVal, &pCData->data);
4496 return E_INVALIDARG; /* FIXME: correct? */
4499 /* ITypeLib2::GetLibStatistics
4501 * Returns statistics about a type library that are required for efficient
4502 * sizing of hash tables.
4505 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4507 ULONG *pcUniqueNames,
4508 ULONG *pcchUniqueNames)
4510 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4512 FIXME("(%p): stub!\n", This);
4514 if(pcUniqueNames) *pcUniqueNames=1;
4515 if(pcchUniqueNames) *pcchUniqueNames=1;
4519 /* ITypeLib2::GetDocumentation2
4521 * Retrieves the library's documentation string, the complete Help file name
4522 * and path, the localization context to use, and the context ID for the
4523 * library Help topic in the Help file.
4526 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4530 BSTR *pbstrHelpString,
4531 DWORD *pdwHelpStringContext,
4532 BSTR *pbstrHelpStringDll)
4534 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4538 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4540 /* the help string should be obtained from the helpstringdll,
4541 * using the _DLLGetDocumentation function, based on the supplied
4542 * lcid. Nice to do sometime...
4546 /* documentation for the typelib */
4548 *pbstrHelpString=SysAllocString(This->DocString);
4549 if(pdwHelpStringContext)
4550 *pdwHelpStringContext=This->dwHelpContext;
4551 if(pbstrHelpStringDll)
4552 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4558 /* for a typeinfo */
4559 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4561 if(SUCCEEDED(result))
4563 ITypeInfo2 * pTInfo2;
4564 result = ITypeInfo_QueryInterface(pTInfo,
4566 (LPVOID*) &pTInfo2);
4568 if(SUCCEEDED(result))
4570 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4574 pdwHelpStringContext,
4575 pbstrHelpStringDll);
4577 ITypeInfo2_Release(pTInfo2);
4580 ITypeInfo_Release(pTInfo);
4586 /* ITypeLib2::GetAllCustData
4588 * Gets all custom data items for the library.
4591 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4593 CUSTDATA *pCustData)
4595 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4596 TLBCustData *pCData;
4598 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4599 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4600 if(pCustData->prgCustData ){
4601 pCustData->cCustData=This->ctCustData;
4602 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4603 pCustData->prgCustData[i].guid=pCData->guid;
4604 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4607 ERR(" OUT OF MEMORY!\n");
4608 return E_OUTOFMEMORY;
4613 static const ITypeLib2Vtbl tlbvt = {
4614 ITypeLib2_fnQueryInterface,
4616 ITypeLib2_fnRelease,
4617 ITypeLib2_fnGetTypeInfoCount,
4618 ITypeLib2_fnGetTypeInfo,
4619 ITypeLib2_fnGetTypeInfoType,
4620 ITypeLib2_fnGetTypeInfoOfGuid,
4621 ITypeLib2_fnGetLibAttr,
4622 ITypeLib2_fnGetTypeComp,
4623 ITypeLib2_fnGetDocumentation,
4625 ITypeLib2_fnFindName,
4626 ITypeLib2_fnReleaseTLibAttr,
4628 ITypeLib2_fnGetCustData,
4629 ITypeLib2_fnGetLibStatistics,
4630 ITypeLib2_fnGetDocumentation2,
4631 ITypeLib2_fnGetAllCustData
4635 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4637 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4639 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4642 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4644 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4646 return ITypeLib2_AddRef((ITypeLib2 *)This);
4649 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4651 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4653 return ITypeLib2_Release((ITypeLib2 *)This);
4656 static HRESULT WINAPI ITypeLibComp_fnBind(
4661 ITypeInfo ** ppTInfo,
4662 DESCKIND * pDescKind,
4665 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4666 ITypeInfoImpl *pTypeInfo;
4668 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4670 *pDescKind = DESCKIND_NONE;
4671 pBindPtr->lptcomp = NULL;
4674 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4676 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4678 /* FIXME: check wFlags here? */
4679 /* FIXME: we should use a hash table to look this info up using lHash
4680 * instead of an O(n) search */
4681 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4682 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4684 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4686 *pDescKind = DESCKIND_TYPECOMP;
4687 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4688 ITypeComp_AddRef(pBindPtr->lptcomp);
4689 TRACE("module or enum: %s\n", debugstr_w(szName));
4694 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4695 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4697 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4700 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4701 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4703 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4708 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4709 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4711 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4713 ITypeInfo *subtypeinfo;
4715 DESCKIND subdesckind;
4717 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4718 &subtypeinfo, &subdesckind, &subbindptr);
4719 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4721 TYPEDESC tdesc_appobject =
4724 (TYPEDESC *)pTypeInfo->hreftype
4728 const VARDESC vardesc_appobject =
4731 NULL, /* lpstrSchema */
4746 VAR_STATIC /* varkind */
4749 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4751 /* cleanup things filled in by Bind call so we can put our
4752 * application object data in there instead */
4753 switch (subdesckind)
4755 case DESCKIND_FUNCDESC:
4756 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4758 case DESCKIND_VARDESC:
4759 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4764 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4766 if (pTypeInfo->hreftype == -1)
4767 FIXME("no hreftype for interface %p\n", pTypeInfo);
4769 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4773 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4774 *ppTInfo = (ITypeInfo *)pTypeInfo;
4775 ITypeInfo_AddRef(*ppTInfo);
4781 TRACE("name not found %s\n", debugstr_w(szName));
4785 static HRESULT WINAPI ITypeLibComp_fnBindType(
4789 ITypeInfo ** ppTInfo,
4790 ITypeComp ** ppTComp)
4792 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4796 static const ITypeCompVtbl tlbtcvt =
4799 ITypeLibComp_fnQueryInterface,
4800 ITypeLibComp_fnAddRef,
4801 ITypeLibComp_fnRelease,
4803 ITypeLibComp_fnBind,
4804 ITypeLibComp_fnBindType
4807 /*================== ITypeInfo(2) Methods ===================================*/
4808 static ITypeInfo2 * ITypeInfo_Constructor(void)
4810 ITypeInfoImpl * pTypeInfoImpl;
4812 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4815 pTypeInfoImpl->lpVtbl = &tinfvt;
4816 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4817 pTypeInfoImpl->ref=1;
4818 pTypeInfoImpl->hreftype = -1;
4819 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4820 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4822 TRACE("(%p)\n", pTypeInfoImpl);
4823 return (ITypeInfo2*) pTypeInfoImpl;
4826 /* ITypeInfo::QueryInterface
4828 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4833 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4835 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4838 if(IsEqualIID(riid, &IID_IUnknown) ||
4839 IsEqualIID(riid,&IID_ITypeInfo)||
4840 IsEqualIID(riid,&IID_ITypeInfo2))
4844 ITypeInfo_AddRef(iface);
4845 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4848 TRACE("-- Interface: E_NOINTERFACE\n");
4849 return E_NOINTERFACE;
4852 /* ITypeInfo::AddRef
4854 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4856 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4857 ULONG ref = InterlockedIncrement(&This->ref);
4859 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4861 TRACE("(%p)->ref is %u\n",This, ref);
4865 /* ITypeInfo::Release
4867 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4869 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4870 ULONG ref = InterlockedDecrement(&This->ref);
4872 TRACE("(%p)->(%u)\n",This, ref);
4875 /* We don't release ITypeLib when ref=0 because
4876 it means that function is called by ITypeLib2_Release */
4877 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4879 TLBFuncDesc *pFInfo, *pFInfoNext;
4880 TLBVarDesc *pVInfo, *pVInfoNext;
4881 TLBImplType *pImpl, *pImplNext;
4883 TRACE("destroying ITypeInfo(%p)\n",This);
4885 if (This->no_free_data)
4888 SysFreeString(This->Name);
4891 SysFreeString(This->DocString);
4892 This->DocString = NULL;
4894 SysFreeString(This->DllName);
4895 This->DllName = NULL;
4897 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4900 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4902 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4903 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4905 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4906 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4908 SysFreeString(pFInfo->pParamDesc[i].Name);
4910 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4911 TLB_Free(pFInfo->pParamDesc);
4912 TLB_FreeCustData(pFInfo->pCustData);
4913 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4914 SysFreeString(pFInfo->Entry);
4915 SysFreeString(pFInfo->HelpString);
4916 SysFreeString(pFInfo->Name);
4918 pFInfoNext = pFInfo->next;
4921 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4923 if (pVInfo->vardesc.varkind == VAR_CONST)
4925 VariantClear(pVInfo->vardesc.u.lpvarValue);
4926 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4928 TLB_FreeCustData(pVInfo->pCustData);
4929 SysFreeString(pVInfo->Name);
4930 pVInfoNext = pVInfo->next;
4933 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4935 TLB_FreeCustData(pImpl->pCustData);
4936 pImplNext = pImpl->next;
4939 TLB_FreeCustData(This->pCustData);
4944 ITypeInfo_Release((ITypeInfo*)This->next);
4947 HeapFree(GetProcessHeap(),0,This);
4953 /* ITypeInfo::GetTypeAttr
4955 * Retrieves a TYPEATTR structure that contains the attributes of the type
4959 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4960 LPTYPEATTR *ppTypeAttr)
4962 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4965 TRACE("(%p)\n",This);
4967 size = sizeof(**ppTypeAttr);
4968 if (This->TypeAttr.typekind == TKIND_ALIAS)
4969 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4971 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4973 return E_OUTOFMEMORY;
4975 **ppTypeAttr = This->TypeAttr;
4977 if (This->TypeAttr.typekind == TKIND_ALIAS)
4978 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4979 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4981 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4982 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4984 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4985 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4990 /* ITypeInfo::GetTypeComp
4992 * Retrieves the ITypeComp interface for the type description, which enables a
4993 * client compiler to bind to the type description's members.
4996 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4997 ITypeComp * *ppTComp)
4999 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5001 TRACE("(%p)->(%p)\n", This, ppTComp);
5003 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5004 ITypeComp_AddRef(*ppTComp);
5008 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5010 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5011 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5012 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5016 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5019 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5020 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5022 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5023 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5024 *buffer += sizeof(PARAMDESCEX);
5025 *pparamdescex_dest = *pparamdescex_src;
5026 VariantInit(&pparamdescex_dest->varDefaultValue);
5027 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5028 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5031 dest->u.paramdesc.pparamdescex = NULL;
5035 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5037 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5038 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5041 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5045 SIZE_T size = sizeof(*src);
5049 size += sizeof(*src->lprgscode) * src->cScodes;
5050 size += TLB_SizeElemDesc(&src->elemdescFunc);
5051 for (i = 0; i < src->cParams; i++)
5053 size += sizeof(ELEMDESC);
5054 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5057 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5058 if (!dest) return E_OUTOFMEMORY;
5061 if (dispinterface) /* overwrite funckind */
5062 dest->funckind = FUNC_DISPATCH;
5063 buffer = (char *)(dest + 1);
5065 dest->lprgscode = (SCODE *)buffer;
5066 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5067 buffer += sizeof(*src->lprgscode) * src->cScodes;
5069 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5072 SysFreeString((BSTR)dest);
5076 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5077 buffer += sizeof(ELEMDESC) * src->cParams;
5078 for (i = 0; i < src->cParams; i++)
5080 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5086 /* undo the above actions */
5087 for (i = i - 1; i >= 0; i--)
5088 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5089 TLB_FreeElemDesc(&dest->elemdescFunc);
5090 SysFreeString((BSTR)dest);
5094 /* special treatment for dispinterfaces: this makes functions appear
5095 * to return their [retval] value when it is really returning an
5097 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5099 if (dest->cParams &&
5100 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5102 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5103 if (elemdesc->tdesc.vt != VT_PTR)
5105 ERR("elemdesc should have started with VT_PTR instead of:\n");
5107 dump_ELEMDESC(elemdesc);
5108 return E_UNEXPECTED;
5111 /* copy last parameter to the return value. we are using a flat
5112 * buffer so there is no danger of leaking memory in
5114 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5116 /* remove the last parameter */
5120 /* otherwise this function is made to appear to have no return
5122 dest->elemdescFunc.tdesc.vt = VT_VOID;
5130 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5132 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5133 const TLBFuncDesc *pFDesc;
5136 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5141 *ppFuncDesc = &pFDesc->funcdesc;
5145 return TYPE_E_ELEMENTNOTFOUND;
5148 /* internal function to make the inherited interfaces' methods appear
5149 * part of the interface */
5150 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5151 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5153 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5155 UINT implemented_funcs = 0;
5160 *hrefoffset = DISPATCH_HREF_OFFSET;
5162 if(This->impltypelist)
5164 ITypeInfo *pSubTypeInfo;
5167 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5171 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5174 &sub_funcs, hrefoffset);
5175 implemented_funcs += sub_funcs;
5176 ITypeInfo_Release(pSubTypeInfo);
5179 *hrefoffset += DISPATCH_HREF_OFFSET;
5183 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5187 if (index < implemented_funcs)
5188 return E_INVALIDARG;
5189 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5193 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5195 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5198 switch (pTypeDesc->vt)
5200 case VT_USERDEFINED:
5201 pTypeDesc->u.hreftype += hrefoffset;
5205 pTypeDesc = pTypeDesc->u.lptdesc;
5208 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5216 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5219 for (i = 0; i < pFuncDesc->cParams; i++)
5220 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5221 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5224 /* ITypeInfo::GetFuncDesc
5226 * Retrieves the FUNCDESC structure that contains information about a
5227 * specified function.
5230 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5231 LPFUNCDESC *ppFuncDesc)
5233 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5234 const FUNCDESC *internal_funcdesc;
5236 UINT hrefoffset = 0;
5238 TRACE("(%p) index %d\n", This, index);
5240 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5241 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5242 &internal_funcdesc, NULL,
5245 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5246 &internal_funcdesc);
5249 WARN("description for function %d not found\n", index);
5253 hr = TLB_AllocAndInitFuncDesc(
5256 This->TypeAttr.typekind == TKIND_DISPATCH);
5258 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5259 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5261 TRACE("-- 0x%08x\n", hr);
5265 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5269 SIZE_T size = sizeof(*src);
5272 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5273 if (src->varkind == VAR_CONST)
5274 size += sizeof(VARIANT);
5275 size += TLB_SizeElemDesc(&src->elemdescVar);
5277 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5278 if (!dest) return E_OUTOFMEMORY;
5281 buffer = (char *)(dest + 1);
5282 if (src->lpstrSchema)
5285 dest->lpstrSchema = (LPOLESTR)buffer;
5286 len = strlenW(src->lpstrSchema);
5287 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5288 buffer += (len + 1) * sizeof(WCHAR);
5291 if (src->varkind == VAR_CONST)
5295 dest->u.lpvarValue = (VARIANT *)buffer;
5296 *dest->u.lpvarValue = *src->u.lpvarValue;
5297 buffer += sizeof(VARIANT);
5298 VariantInit(dest->u.lpvarValue);
5299 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5302 SysFreeString((BSTR)dest_ptr);
5306 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5309 if (src->varkind == VAR_CONST)
5310 VariantClear(dest->u.lpvarValue);
5311 SysFreeString((BSTR)dest);
5318 /* ITypeInfo::GetVarDesc
5320 * Retrieves a VARDESC structure that describes the specified variable.
5323 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5324 LPVARDESC *ppVarDesc)
5326 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5328 const TLBVarDesc *pVDesc;
5330 TRACE("(%p) index %d\n", This, index);
5332 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5336 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5338 return E_INVALIDARG;
5341 /* ITypeInfo_GetNames
5343 * Retrieves the variable with the specified member ID (or the name of the
5344 * property or method and its parameters) that correspond to the specified
5347 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5348 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5350 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5351 const TLBFuncDesc *pFDesc;
5352 const TLBVarDesc *pVDesc;
5354 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5355 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5358 /* function found, now return function and parameter names */
5359 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5362 *rgBstrNames=SysAllocString(pFDesc->Name);
5364 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5370 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5373 *rgBstrNames=SysAllocString(pVDesc->Name);
5378 if(This->impltypelist &&
5379 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5380 /* recursive search */
5383 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5385 if(SUCCEEDED(result))
5387 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5388 ITypeInfo_Release(pTInfo);
5391 WARN("Could not search inherited interface!\n");
5395 WARN("no names found\n");
5398 return TYPE_E_ELEMENTNOTFOUND;
5405 /* ITypeInfo::GetRefTypeOfImplType
5407 * If a type description describes a COM class, it retrieves the type
5408 * description of the implemented interface types. For an interface,
5409 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5413 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5418 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5421 const TLBImplType *pImpl = This->impltypelist;
5423 TRACE("(%p) index %d\n", This, index);
5424 if (TRACE_ON(ole)) dump_TypeInfo(This);
5428 /* only valid on dual interfaces;
5429 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5431 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5433 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5434 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5440 hr = TYPE_E_ELEMENTNOTFOUND;
5443 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5445 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5446 *pRefType = This->pTypeLib->dispatch_href;
5450 /* get element n from linked list */
5451 for(i=0; pImpl && i<index; i++)
5453 pImpl = pImpl->next;
5457 *pRefType = pImpl->hRef;
5459 hr = TYPE_E_ELEMENTNOTFOUND;
5465 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5467 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5473 /* ITypeInfo::GetImplTypeFlags
5475 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5476 * or base interface in a type description.
5478 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5479 UINT index, INT *pImplTypeFlags)
5481 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5485 TRACE("(%p) index %d\n", This, index);
5486 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5487 i++, pImpl=pImpl->next)
5489 if(i==index && pImpl){
5490 *pImplTypeFlags=pImpl->implflags;
5494 return TYPE_E_ELEMENTNOTFOUND;
5498 * Maps between member names and member IDs, and parameter names and
5501 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5502 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5504 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5505 const TLBFuncDesc *pFDesc;
5506 const TLBVarDesc *pVDesc;
5510 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5513 /* init out parameters in case of failure */
5514 for (i = 0; i < cNames; i++)
5515 pMemId[i] = MEMBERID_NIL;
5517 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5519 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5520 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5521 for(i=1; i < cNames; i++){
5522 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5523 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5525 if( j<pFDesc->funcdesc.cParams)
5528 ret=DISP_E_UNKNOWNNAME;
5530 TRACE("-- 0x%08x\n", ret);
5534 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5535 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5536 if(cNames) *pMemId=pVDesc->vardesc.memid;
5540 /* not found, see if it can be found in an inherited interface */
5541 if(This->impltypelist) {
5542 /* recursive search */
5544 ret=ITypeInfo_GetRefTypeInfo(iface,
5545 This->impltypelist->hRef, &pTInfo);
5547 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5548 ITypeInfo_Release(pTInfo);
5551 WARN("Could not search inherited interface!\n");
5553 WARN("no names found\n");
5554 return DISP_E_UNKNOWNNAME;
5557 /* ITypeInfo::Invoke
5559 * Invokes a method, or accesses a property of an object, that implements the
5560 * interface described by the type description.
5563 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5566 if (TRACE_ON(ole)) {
5568 TRACE("Calling %p(",func);
5569 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5581 res = func(args[0]);
5584 res = func(args[0],args[1]);
5587 res = func(args[0],args[1],args[2]);
5590 res = func(args[0],args[1],args[2],args[3]);
5593 res = func(args[0],args[1],args[2],args[3],args[4]);
5596 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5599 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5602 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5605 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5608 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5611 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5614 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]);
5617 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]);
5620 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]);
5623 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]);
5626 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]);
5629 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]);
5632 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]);
5635 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]);
5638 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]);
5641 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]);
5644 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]);
5647 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]);
5650 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]);
5653 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]);
5656 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]);
5659 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]);
5662 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]);
5665 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]);
5668 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]);
5671 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5677 FIXME("unsupported calling convention %d\n",callconv);
5681 TRACE("returns %08x\n",res);
5685 /* The size of the argument on the stack in DWORD units (in all x86 call
5686 * convetions the arguments on the stack are DWORD-aligned)
5688 static int _dispargsize(VARTYPE vt)
5693 return 8/sizeof(DWORD);
5695 return sizeof(double)/sizeof(DWORD);
5697 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5699 return sizeof(CY)/sizeof(DWORD);
5701 return sizeof(DATE)/sizeof(DWORD);
5703 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5705 FIXME("VT_RECORD not implemented\n");
5712 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5715 ITypeInfo *tinfo2 = NULL;
5716 TYPEATTR *tattr = NULL;
5718 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5721 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5723 tdesc->u.hreftype, hr);
5726 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5729 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5730 ITypeInfo_Release(tinfo2);
5734 switch (tattr->typekind)
5741 tdesc = &tattr->tdescAlias;
5742 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5745 case TKIND_INTERFACE:
5746 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5752 case TKIND_DISPATCH:
5761 FIXME("TKIND_RECORD unhandled.\n");
5766 FIXME("TKIND_UNION unhandled.\n");
5771 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5775 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5776 ITypeInfo_Release(tinfo2);
5780 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5784 /* enforce only one level of pointer indirection */
5785 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5787 tdesc = tdesc->u.lptdesc;
5789 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5790 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5791 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5792 if ((tdesc->vt == VT_USERDEFINED) ||
5793 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5795 VARTYPE vt_userdefined = 0;
5796 const TYPEDESC *tdesc_userdefined = tdesc;
5797 if (tdesc->vt == VT_PTR)
5799 vt_userdefined = VT_BYREF;
5800 tdesc_userdefined = tdesc->u.lptdesc;
5802 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5804 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5805 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5807 *vt |= vt_userdefined;
5819 case VT_USERDEFINED:
5820 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5827 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5828 hr = DISP_E_BADVARTYPE;
5832 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5841 /***********************************************************************
5842 * DispCallFunc (OLEAUT32.@)
5844 * Invokes a function of the specified calling convention, passing the
5845 * specified arguments and returns the result.
5848 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5849 * oVft [I] The offset in the vtable. See notes.
5850 * cc [I] Calling convention of the function to call.
5851 * vtReturn [I] The return type of the function.
5852 * cActuals [I] Number of parameters.
5853 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5854 * prgpvarg [I] The arguments to pass.
5855 * pvargResult [O] The return value of the function. Can be NULL.
5859 * Failure: HRESULT code.
5862 * The HRESULT return value of this function is not affected by the return
5863 * value of the user supplied function, which is returned in pvargResult.
5865 * If pvInstance is NULL then a non-object function is to be called and oVft
5866 * is the address of the function to call.
5868 * The cc parameter can be one of the following values:
5881 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5882 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5884 int argsize, argspos;
5889 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5890 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5891 pvargResult, V_VT(pvargResult));
5895 argsize++; /* for This pointer */
5897 for (i=0;i<cActuals;i++)
5899 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5900 dump_Variant(prgpvarg[i]);
5901 argsize += _dispargsize(prgvt[i]);
5903 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5908 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5912 for (i=0;i<cActuals;i++)
5914 VARIANT *arg = prgpvarg[i];
5915 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5916 if (prgvt[i] == VT_VARIANT)
5917 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5919 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5920 argspos += _dispargsize(prgvt[i]);
5925 FARPROC *vtable = *(FARPROC**)pvInstance;
5926 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5929 /* if we aren't invoking an object then the function pointer is stored
5931 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5933 if (pvargResult && (vtReturn != VT_EMPTY))
5935 TRACE("Method returned 0x%08x\n",hres);
5936 V_VT(pvargResult) = vtReturn;
5937 V_UI4(pvargResult) = hres;
5940 HeapFree(GetProcessHeap(),0,args);
5944 #define INVBUF_ELEMENT_SIZE \
5945 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5946 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5947 ((VARIANTARG *)(buffer))
5948 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5949 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5950 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5951 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5952 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5953 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5955 static HRESULT WINAPI ITypeInfo_fnInvoke(
5960 DISPPARAMS *pDispParams,
5961 VARIANT *pVarResult,
5962 EXCEPINFO *pExcepInfo,
5965 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5967 unsigned int var_index;
5970 const TLBFuncDesc *pFuncInfo;
5972 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5973 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5978 ERR("NULL pDispParams not allowed\n");
5979 return E_INVALIDARG;
5982 dump_DispParms(pDispParams);
5984 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5986 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5987 pDispParams->cNamedArgs, pDispParams->cArgs);
5988 return E_INVALIDARG;
5991 /* we do this instead of using GetFuncDesc since it will return a fake
5992 * FUNCDESC for dispinterfaces and we want the real function description */
5993 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5994 if ((memid == pFuncInfo->funcdesc.memid) &&
5995 (wFlags & pFuncInfo->funcdesc.invkind))
5999 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6003 TRACE("invoking:\n");
6004 dump_TLBFuncDescOne(pFuncInfo);
6007 switch (func_desc->funckind) {
6008 case FUNC_PUREVIRTUAL:
6009 case FUNC_VIRTUAL: {
6010 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6012 VARIANT retval; /* pointer for storing byref retvals in */
6013 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6014 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6015 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6016 UINT cNamedArgs = pDispParams->cNamedArgs;
6017 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6021 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6023 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6025 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6026 hres = DISP_E_PARAMNOTFOUND;
6029 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6031 rgdispidNamedArgs++;
6034 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6036 ERR("functions with the vararg attribute do not support named arguments\n");
6037 hres = DISP_E_NONAMEDARGS;
6041 for (i = 0; i < func_desc->cParams; i++)
6043 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6044 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6049 TRACE("changing args\n");
6050 for (i = 0; i < func_desc->cParams; i++)
6052 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6053 VARIANTARG *src_arg;
6059 for (j = 0; j < cNamedArgs; j++)
6060 if (rgdispidNamedArgs[j] == i)
6062 src_arg = &pDispParams->rgvarg[j];
6067 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
6069 if (wParamFlags & PARAMFLAG_FRETVAL)
6071 /* under most conditions the caller is not allowed to
6072 * pass in a dispparam arg in the index of what would be
6073 * the retval parameter. however, there is an exception
6074 * where the extra parameter is used in an extra
6075 * IDispatch::Invoke below */
6076 if ((i < pDispParams->cArgs) &&
6077 ((func_desc->cParams != 1) || !pVarResult ||
6078 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6080 hres = DISP_E_BADPARAMCOUNT;
6084 /* note: this check is placed so that if the caller passes
6085 * in a VARIANTARG for the retval we just ignore it, like
6087 if (i == func_desc->cParams - 1)
6090 arg = prgpvarg[i] = &rgvarg[i];
6091 memset(arg, 0, sizeof(*arg));
6092 V_VT(arg) = rgvt[i];
6093 memset(&retval, 0, sizeof(retval));
6094 V_BYREF(arg) = &retval;
6098 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6099 hres = E_UNEXPECTED;
6105 dump_Variant(src_arg);
6107 if (rgvt[i] == VT_VARIANT)
6108 hres = VariantCopy(&rgvarg[i], src_arg);
6109 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6111 if (rgvt[i] == V_VT(src_arg))
6112 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6115 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6116 hres = VariantCopy(&missing_arg[i], src_arg);
6117 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6119 V_VT(&rgvarg[i]) = rgvt[i];
6121 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6124 SAFEARRAYBOUND bound;
6128 bound.cElements = pDispParams->cArgs-i;
6129 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6131 ERR("SafeArrayCreate failed\n");
6134 hres = SafeArrayAccessData(a, (LPVOID)&v);
6137 ERR("SafeArrayAccessData failed with %x\n", hres);
6140 for (j = 0; j < bound.cElements; j++)
6141 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6142 hres = SafeArrayUnaccessData(a);
6145 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6148 V_ARRAY(&rgvarg[i]) = a;
6149 V_VT(&rgvarg[i]) = rgvt[i];
6151 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6153 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6154 V_VT(&missing_arg[i]) = V_VT(src_arg);
6155 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6156 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6157 V_VT(&rgvarg[i]) = rgvt[i];
6159 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6161 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6162 V_VT(&rgvarg[i]) = rgvt[i];
6166 /* FIXME: this doesn't work for VT_BYREF arguments if
6167 * they are not the same type as in the paramdesc */
6168 V_VT(&rgvarg[i]) = V_VT(src_arg);
6169 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6170 V_VT(&rgvarg[i]) = rgvt[i];
6175 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6176 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6177 debugstr_VT(src_arg), debugstr_VF(src_arg));
6180 prgpvarg[i] = &rgvarg[i];
6182 else if (wParamFlags & PARAMFLAG_FOPT)
6185 arg = prgpvarg[i] = &rgvarg[i];
6186 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6188 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6194 VARIANTARG *missing_arg;
6195 /* if the function wants a pointer to a variant then
6196 * set that up, otherwise just pass the VT_ERROR in
6197 * the argument by value */
6198 if (rgvt[i] & VT_BYREF)
6200 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6201 V_VT(arg) = VT_VARIANT | VT_BYREF;
6202 V_VARIANTREF(arg) = missing_arg;
6206 V_VT(missing_arg) = VT_ERROR;
6207 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6212 hres = DISP_E_BADPARAMCOUNT;
6216 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6218 /* VT_VOID is a special case for return types, so it is not
6219 * handled in the general function */
6220 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6221 V_VT(&varresult) = VT_EMPTY;
6224 V_VT(&varresult) = 0;
6225 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6226 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6229 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6230 V_VT(&varresult), func_desc->cParams, rgvt,
6231 prgpvarg, &varresult);
6233 for (i = 0; i < func_desc->cParams; i++)
6235 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6236 if (wParamFlags & PARAMFLAG_FRETVAL)
6240 TRACE("[retval] value: ");
6241 dump_Variant(prgpvarg[i]);
6246 VariantInit(pVarResult);
6247 /* deref return value */
6248 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6251 /* free data stored in varresult. Note that
6252 * VariantClear doesn't do what we want because we are
6253 * working with byref types. */
6254 /* FIXME: clear safearrays, bstrs, records and
6255 * variants here too */
6256 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6257 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6259 if(*V_UNKNOWNREF(prgpvarg[i]))
6260 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6264 else if (i < pDispParams->cArgs)
6266 if (wParamFlags & PARAMFLAG_FOUT)
6268 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6270 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6271 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6275 ERR("failed to convert param %d to vt %d\n", i,
6276 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6280 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6281 func_desc->cParamsOpt < 0 &&
6282 i == func_desc->cParams-1)
6284 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6287 hres = SafeArrayGetUBound(a, 1, &ubound);
6290 ERR("SafeArrayGetUBound failed with %x\n", hres);
6293 hres = SafeArrayAccessData(a, (LPVOID)&v);
6296 ERR("SafeArrayAccessData failed with %x\n", hres);
6299 for (j = 0; j <= ubound; j++)
6300 VariantClear(&v[j]);
6301 hres = SafeArrayUnaccessData(a);
6304 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6308 VariantClear(&rgvarg[i]);
6310 else if (wParamFlags & PARAMFLAG_FOPT)
6312 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6313 VariantClear(&rgvarg[i]);
6317 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6319 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6320 hres = DISP_E_EXCEPTION;
6323 IErrorInfo *pErrorInfo;
6324 pExcepInfo->scode = V_ERROR(&varresult);
6325 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6327 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6328 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6329 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6330 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6332 IErrorInfo_Release(pErrorInfo);
6336 if (V_VT(&varresult) != VT_ERROR)
6338 TRACE("varresult value: ");
6339 dump_Variant(&varresult);
6343 VariantClear(pVarResult);
6344 *pVarResult = varresult;
6347 VariantClear(&varresult);
6350 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6351 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6352 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6353 (pDispParams->cArgs != 0))
6355 if (V_VT(pVarResult) == VT_DISPATCH)
6357 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6358 /* Note: not VariantClear; we still need the dispatch
6359 * pointer to be valid */
6360 VariantInit(pVarResult);
6361 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6362 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6363 pDispParams, pVarResult, pExcepInfo, pArgErr);
6364 IDispatch_Release(pDispatch);
6368 VariantClear(pVarResult);
6369 hres = DISP_E_NOTACOLLECTION;
6374 HeapFree(GetProcessHeap(), 0, buffer);
6377 case FUNC_DISPATCH: {
6380 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6381 if (SUCCEEDED(hres)) {
6382 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6383 hres = IDispatch_Invoke(
6384 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6385 pVarResult,pExcepInfo,pArgErr
6388 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6389 IDispatch_Release(disp);
6391 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6395 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6400 TRACE("-- 0x%08x\n", hres);
6403 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6406 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6407 if(FAILED(hres)) return hres;
6409 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6410 dump_VARDESC(var_desc);
6411 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6415 /* not found, look for it in inherited interfaces */
6416 ITypeInfo2_GetTypeKind(iface, &type_kind);
6417 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6418 if(This->impltypelist) {
6419 /* recursive search */
6421 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6422 if(SUCCEEDED(hres)){
6423 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6424 ITypeInfo_Release(pTInfo);
6427 WARN("Could not search inherited interface!\n");
6430 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6431 return DISP_E_MEMBERNOTFOUND;
6434 /* ITypeInfo::GetDocumentation
6436 * Retrieves the documentation string, the complete Help file name and path,
6437 * and the context ID for the Help topic for a specified type description.
6439 * (Can be tested by the Visual Basic Editor in Word for instance.)
6441 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6442 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6443 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6445 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6446 const TLBFuncDesc *pFDesc;
6447 const TLBVarDesc *pVDesc;
6448 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6449 " HelpContext(%p) HelpFile(%p)\n",
6450 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6451 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6453 *pBstrName=SysAllocString(This->Name);
6455 *pBstrDocString=SysAllocString(This->DocString);
6457 *pdwHelpContext=This->dwHelpContext;
6459 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6461 }else {/* for a member */
6462 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6463 if(pFDesc->funcdesc.memid==memid){
6465 *pBstrName = SysAllocString(pFDesc->Name);
6467 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6469 *pdwHelpContext=pFDesc->helpcontext;
6472 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6473 if(pVDesc->vardesc.memid==memid){
6475 *pBstrName = SysAllocString(pVDesc->Name);
6477 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6479 *pdwHelpContext=pVDesc->HelpContext;
6484 if(This->impltypelist &&
6485 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6486 /* recursive search */
6489 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6491 if(SUCCEEDED(result)) {
6492 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6493 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6494 ITypeInfo_Release(pTInfo);
6497 WARN("Could not search inherited interface!\n");
6500 WARN("member %d not found\n", memid);
6501 return TYPE_E_ELEMENTNOTFOUND;
6504 /* ITypeInfo::GetDllEntry
6506 * Retrieves a description or specification of an entry point for a function
6509 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6510 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6513 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6514 const TLBFuncDesc *pFDesc;
6516 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6518 if (pBstrDllName) *pBstrDllName = NULL;
6519 if (pBstrName) *pBstrName = NULL;
6520 if (pwOrdinal) *pwOrdinal = 0;
6522 if (This->TypeAttr.typekind != TKIND_MODULE)
6523 return TYPE_E_BADMODULEKIND;
6525 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6526 if(pFDesc->funcdesc.memid==memid){
6527 dump_TypeInfo(This);
6529 dump_TLBFuncDescOne(pFDesc);
6532 *pBstrDllName = SysAllocString(This->DllName);
6534 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6536 *pBstrName = SysAllocString(pFDesc->Entry);
6544 *pwOrdinal = (DWORD)pFDesc->Entry;
6547 return TYPE_E_ELEMENTNOTFOUND;
6550 /* internal function to make the inherited interfaces' methods appear
6551 * part of the interface */
6552 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6553 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6555 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6558 TRACE("%p, 0x%x\n", iface, *hRefType);
6560 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6562 ITypeInfo *pSubTypeInfo;
6564 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6568 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6570 ITypeInfo_Release(pSubTypeInfo);
6574 *hRefType -= DISPATCH_HREF_OFFSET;
6576 if (!(*hRefType & DISPATCH_HREF_MASK))
6577 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6582 /* ITypeInfo::GetRefTypeInfo
6584 * If a type description references other type descriptions, it retrieves
6585 * the referenced type descriptions.
6587 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6590 ITypeInfo **ppTInfo)
6592 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6593 HRESULT result = E_FAIL;
6595 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6597 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6598 ITypeInfo_AddRef(*ppTInfo);
6601 else if (hRefType == -1 &&
6602 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6603 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6605 /* when we meet a DUAL dispinterface, we must create the interface
6608 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6611 /* the interface version contains the same information as the dispinterface
6612 * copy the contents of the structs.
6614 *pTypeInfoImpl = *This;
6615 pTypeInfoImpl->ref = 0;
6617 /* change the type to interface */
6618 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6620 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6622 /* we use data structures from This, so we need to keep a reference
6623 * to it to stop it being destroyed and signal to the new instance to
6624 * not free its data structures when it is destroyed */
6625 pTypeInfoImpl->no_free_data = TRUE;
6626 pTypeInfoImpl->next = This;
6627 ITypeInfo_AddRef((ITypeInfo*) This);
6629 ITypeInfo_AddRef(*ppTInfo);
6633 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6634 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6635 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6637 HREFTYPE href_dispatch = hRefType;
6638 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6640 TLBRefType *ref_type;
6641 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6643 if(ref_type->reference == hRefType)
6646 if(&ref_type->entry == &This->pTypeLib->ref_list)
6648 FIXME("Can't find pRefType for ref %x\n", hRefType);
6651 if(hRefType != -1) {
6652 ITypeLib *pTLib = NULL;
6654 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6656 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6658 if(ref_type->pImpTLInfo->pImpTypeLib) {
6659 TRACE("typeinfo in imported typelib that is already loaded\n");
6660 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6661 ITypeLib2_AddRef(pTLib);
6664 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6665 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6666 ref_type->pImpTLInfo->wVersionMajor,
6667 ref_type->pImpTLInfo->wVersionMinor,
6668 ref_type->pImpTLInfo->lcid,
6671 if(FAILED(result)) {
6672 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6673 result=LoadTypeLib(libnam, &pTLib);
6674 SysFreeString(libnam);
6676 if(SUCCEEDED(result)) {
6677 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6678 ITypeLib2_AddRef(pTLib);
6682 if(SUCCEEDED(result)) {
6683 if(ref_type->index == TLB_REF_USE_GUID)
6684 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6688 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6692 ITypeLib2_Release(pTLib);
6697 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6698 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6702 /* ITypeInfo::AddressOfMember
6704 * Retrieves the addresses of static functions or variables, such as those
6707 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6708 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6710 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6716 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6718 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6722 module = LoadLibraryW(dll);
6725 ERR("couldn't load %s\n", debugstr_w(dll));
6727 SysFreeString(entry);
6728 return STG_E_FILENOTFOUND;
6730 /* FIXME: store library somewhere where we can free it */
6735 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6736 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6737 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6739 *ppv = GetProcAddress(module, entryA);
6741 ERR("function not found %s\n", debugstr_a(entryA));
6743 HeapFree(GetProcessHeap(), 0, entryA);
6747 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6749 ERR("function not found %d\n", ordinal);
6753 SysFreeString(entry);
6756 return TYPE_E_DLLFUNCTIONNOTFOUND;
6761 /* ITypeInfo::CreateInstance
6763 * Creates a new instance of a type that describes a component object class
6766 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6767 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6769 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6773 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6779 WARN("Not able to aggregate\n");
6780 return CLASS_E_NOAGGREGATION;
6783 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6784 if(FAILED(hr)) return hr;
6786 if(pTA->typekind != TKIND_COCLASS)
6788 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6794 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6797 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6798 TRACE("GetActiveObject rets %08x\n", hr);
6801 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6802 IUnknown_Release(pUnk);
6807 hr = CoCreateInstance(&pTA->guid, NULL,
6808 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6812 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6816 /* ITypeInfo::GetMops
6818 * Retrieves marshalling information.
6820 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6823 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6824 FIXME("(%p) stub!\n", This);
6828 /* ITypeInfo::GetContainingTypeLib
6830 * Retrieves the containing type library and the index of the type description
6831 * within that type library.
6833 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6834 ITypeLib * *ppTLib, UINT *pIndex)
6836 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6838 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6840 *pIndex=This->index;
6841 TRACE("returning pIndex=%d\n", *pIndex);
6845 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6846 ITypeLib2_AddRef(*ppTLib);
6847 TRACE("returning ppTLib=%p\n", *ppTLib);
6853 /* ITypeInfo::ReleaseTypeAttr
6855 * Releases a TYPEATTR previously returned by GetTypeAttr.
6858 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6859 TYPEATTR* pTypeAttr)
6861 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6862 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6863 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6866 /* ITypeInfo::ReleaseFuncDesc
6868 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6870 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6872 FUNCDESC *pFuncDesc)
6874 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6877 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6879 for (i = 0; i < pFuncDesc->cParams; i++)
6880 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6881 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6883 SysFreeString((BSTR)pFuncDesc);
6886 /* ITypeInfo::ReleaseVarDesc
6888 * Releases a VARDESC previously returned by GetVarDesc.
6890 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6893 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6894 TRACE("(%p)->(%p)\n", This, pVarDesc);
6896 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6897 if (pVarDesc->varkind == VAR_CONST)
6898 VariantClear(pVarDesc->u.lpvarValue);
6899 SysFreeString((BSTR)pVarDesc);
6902 /* ITypeInfo2::GetTypeKind
6904 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6907 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6908 TYPEKIND *pTypeKind)
6910 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6911 *pTypeKind=This->TypeAttr.typekind;
6912 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6916 /* ITypeInfo2::GetTypeFlags
6918 * Returns the type flags without any allocations. This returns a DWORD type
6919 * flag, which expands the type flags without growing the TYPEATTR (type
6923 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6925 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6926 *pTypeFlags=This->TypeAttr.wTypeFlags;
6927 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6931 /* ITypeInfo2::GetFuncIndexOfMemId
6932 * Binds to a specific member based on a known DISPID, where the member name
6933 * is not known (for example, when binding to a default member).
6936 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6937 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6939 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6940 const TLBFuncDesc *pFuncInfo;
6944 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6945 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6951 result = TYPE_E_ELEMENTNOTFOUND;
6953 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6954 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6958 /* TypeInfo2::GetVarIndexOfMemId
6960 * Binds to a specific member based on a known DISPID, where the member name
6961 * is not known (for example, when binding to a default member).
6964 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6965 MEMBERID memid, UINT *pVarIndex)
6967 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6968 TLBVarDesc *pVarInfo;
6971 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6972 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6978 result = TYPE_E_ELEMENTNOTFOUND;
6980 TRACE("(%p) memid 0x%08x -> %s\n", This,
6981 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6985 /* ITypeInfo2::GetCustData
6987 * Gets the custom data
6989 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6994 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6995 TLBCustData *pCData;
6997 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6998 if( IsEqualIID(guid, &pCData->guid)) break;
7000 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7004 VariantInit( pVarVal);
7005 VariantCopy( pVarVal, &pCData->data);
7008 return E_INVALIDARG; /* FIXME: correct? */
7011 /* ITypeInfo2::GetFuncCustData
7013 * Gets the custom data
7015 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7021 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7022 TLBCustData *pCData=NULL;
7023 TLBFuncDesc * pFDesc;
7025 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7026 pFDesc=pFDesc->next);
7029 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7030 if( IsEqualIID(guid, &pCData->guid)) break;
7032 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7035 VariantInit( pVarVal);
7036 VariantCopy( pVarVal, &pCData->data);
7039 return E_INVALIDARG; /* FIXME: correct? */
7042 /* ITypeInfo2::GetParamCustData
7044 * Gets the custom data
7046 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7053 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7054 TLBCustData *pCData=NULL;
7055 TLBFuncDesc * pFDesc;
7058 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7060 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7061 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7062 pCData = pCData->next)
7063 if( IsEqualIID(guid, &pCData->guid)) break;
7065 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7069 VariantInit( pVarVal);
7070 VariantCopy( pVarVal, &pCData->data);
7073 return E_INVALIDARG; /* FIXME: correct? */
7076 /* ITypeInfo2::GetVarCustData
7078 * Gets the custom data
7080 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7086 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7087 TLBCustData *pCData=NULL;
7088 TLBVarDesc * pVDesc;
7091 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7095 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7097 if( IsEqualIID(guid, &pCData->guid)) break;
7101 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7105 VariantInit( pVarVal);
7106 VariantCopy( pVarVal, &pCData->data);
7109 return E_INVALIDARG; /* FIXME: correct? */
7112 /* ITypeInfo2::GetImplCustData
7114 * Gets the custom data
7116 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7122 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7123 TLBCustData *pCData=NULL;
7124 TLBImplType * pRDesc;
7127 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7131 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7133 if( IsEqualIID(guid, &pCData->guid)) break;
7137 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7141 VariantInit( pVarVal);
7142 VariantCopy( pVarVal, &pCData->data);
7145 return E_INVALIDARG; /* FIXME: correct? */
7148 /* ITypeInfo2::GetDocumentation2
7150 * Retrieves the documentation string, the complete Help file name and path,
7151 * the localization context to use, and the context ID for the library Help
7152 * topic in the Help file.
7155 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7159 BSTR *pbstrHelpString,
7160 DWORD *pdwHelpStringContext,
7161 BSTR *pbstrHelpStringDll)
7163 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7164 const TLBFuncDesc *pFDesc;
7165 const TLBVarDesc *pVDesc;
7166 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7167 "HelpStringContext(%p) HelpStringDll(%p)\n",
7168 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7169 pbstrHelpStringDll );
7170 /* the help string should be obtained from the helpstringdll,
7171 * using the _DLLGetDocumentation function, based on the supplied
7172 * lcid. Nice to do sometime...
7174 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7176 *pbstrHelpString=SysAllocString(This->Name);
7177 if(pdwHelpStringContext)
7178 *pdwHelpStringContext=This->dwHelpStringContext;
7179 if(pbstrHelpStringDll)
7180 *pbstrHelpStringDll=
7181 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7183 }else {/* for a member */
7184 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7185 if(pFDesc->funcdesc.memid==memid){
7187 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7188 if(pdwHelpStringContext)
7189 *pdwHelpStringContext=pFDesc->HelpStringContext;
7190 if(pbstrHelpStringDll)
7191 *pbstrHelpStringDll=
7192 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7195 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7196 if(pVDesc->vardesc.memid==memid){
7198 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7199 if(pdwHelpStringContext)
7200 *pdwHelpStringContext=pVDesc->HelpStringContext;
7201 if(pbstrHelpStringDll)
7202 *pbstrHelpStringDll=
7203 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7207 return TYPE_E_ELEMENTNOTFOUND;
7210 /* ITypeInfo2::GetAllCustData
7212 * Gets all custom data items for the Type info.
7215 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7217 CUSTDATA *pCustData)
7219 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7220 TLBCustData *pCData;
7223 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7225 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7226 if(pCustData->prgCustData ){
7227 pCustData->cCustData=This->ctCustData;
7228 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7229 pCustData->prgCustData[i].guid=pCData->guid;
7230 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7233 ERR(" OUT OF MEMORY!\n");
7234 return E_OUTOFMEMORY;
7239 /* ITypeInfo2::GetAllFuncCustData
7241 * Gets all custom data items for the specified Function
7244 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7247 CUSTDATA *pCustData)
7249 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7250 TLBCustData *pCData;
7251 TLBFuncDesc * pFDesc;
7253 TRACE("(%p) index %d\n", This, index);
7254 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7255 pFDesc=pFDesc->next)
7258 pCustData->prgCustData =
7259 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7260 if(pCustData->prgCustData ){
7261 pCustData->cCustData=pFDesc->ctCustData;
7262 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7263 pCData = pCData->next){
7264 pCustData->prgCustData[i].guid=pCData->guid;
7265 VariantCopy(& pCustData->prgCustData[i].varValue,
7269 ERR(" OUT OF MEMORY!\n");
7270 return E_OUTOFMEMORY;
7274 return TYPE_E_ELEMENTNOTFOUND;
7277 /* ITypeInfo2::GetAllParamCustData
7279 * Gets all custom data items for the Functions
7282 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7283 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7285 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7286 TLBCustData *pCData=NULL;
7287 TLBFuncDesc * pFDesc;
7289 TRACE("(%p) index %d\n", This, indexFunc);
7290 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7291 pFDesc=pFDesc->next)
7293 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7294 pCustData->prgCustData =
7295 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7296 sizeof(CUSTDATAITEM));
7297 if(pCustData->prgCustData ){
7298 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7299 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7300 pCData; i++, pCData = pCData->next){
7301 pCustData->prgCustData[i].guid=pCData->guid;
7302 VariantCopy(& pCustData->prgCustData[i].varValue,
7306 ERR(" OUT OF MEMORY!\n");
7307 return E_OUTOFMEMORY;
7311 return TYPE_E_ELEMENTNOTFOUND;
7314 /* ITypeInfo2::GetAllVarCustData
7316 * Gets all custom data items for the specified Variable
7319 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7320 UINT index, CUSTDATA *pCustData)
7322 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7323 TLBCustData *pCData;
7324 TLBVarDesc * pVDesc;
7326 TRACE("(%p) index %d\n", This, index);
7327 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7328 pVDesc=pVDesc->next)
7331 pCustData->prgCustData =
7332 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7333 if(pCustData->prgCustData ){
7334 pCustData->cCustData=pVDesc->ctCustData;
7335 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7336 pCData = pCData->next){
7337 pCustData->prgCustData[i].guid=pCData->guid;
7338 VariantCopy(& pCustData->prgCustData[i].varValue,
7342 ERR(" OUT OF MEMORY!\n");
7343 return E_OUTOFMEMORY;
7347 return TYPE_E_ELEMENTNOTFOUND;
7350 /* ITypeInfo2::GetAllImplCustData
7352 * Gets all custom data items for the specified implementation type
7355 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7358 CUSTDATA *pCustData)
7360 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7361 TLBCustData *pCData;
7362 TLBImplType * pRDesc;
7364 TRACE("(%p) index %d\n", This, index);
7365 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7366 pRDesc=pRDesc->next)
7369 pCustData->prgCustData =
7370 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7371 if(pCustData->prgCustData ){
7372 pCustData->cCustData=pRDesc->ctCustData;
7373 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7374 pCData = pCData->next){
7375 pCustData->prgCustData[i].guid=pCData->guid;
7376 VariantCopy(& pCustData->prgCustData[i].varValue,
7380 ERR(" OUT OF MEMORY!\n");
7381 return E_OUTOFMEMORY;
7385 return TYPE_E_ELEMENTNOTFOUND;
7388 static const ITypeInfo2Vtbl tinfvt =
7391 ITypeInfo_fnQueryInterface,
7393 ITypeInfo_fnRelease,
7395 ITypeInfo_fnGetTypeAttr,
7396 ITypeInfo_fnGetTypeComp,
7397 ITypeInfo_fnGetFuncDesc,
7398 ITypeInfo_fnGetVarDesc,
7399 ITypeInfo_fnGetNames,
7400 ITypeInfo_fnGetRefTypeOfImplType,
7401 ITypeInfo_fnGetImplTypeFlags,
7402 ITypeInfo_fnGetIDsOfNames,
7404 ITypeInfo_fnGetDocumentation,
7405 ITypeInfo_fnGetDllEntry,
7406 ITypeInfo_fnGetRefTypeInfo,
7407 ITypeInfo_fnAddressOfMember,
7408 ITypeInfo_fnCreateInstance,
7409 ITypeInfo_fnGetMops,
7410 ITypeInfo_fnGetContainingTypeLib,
7411 ITypeInfo_fnReleaseTypeAttr,
7412 ITypeInfo_fnReleaseFuncDesc,
7413 ITypeInfo_fnReleaseVarDesc,
7415 ITypeInfo2_fnGetTypeKind,
7416 ITypeInfo2_fnGetTypeFlags,
7417 ITypeInfo2_fnGetFuncIndexOfMemId,
7418 ITypeInfo2_fnGetVarIndexOfMemId,
7419 ITypeInfo2_fnGetCustData,
7420 ITypeInfo2_fnGetFuncCustData,
7421 ITypeInfo2_fnGetParamCustData,
7422 ITypeInfo2_fnGetVarCustData,
7423 ITypeInfo2_fnGetImplTypeCustData,
7424 ITypeInfo2_fnGetDocumentation2,
7425 ITypeInfo2_fnGetAllCustData,
7426 ITypeInfo2_fnGetAllFuncCustData,
7427 ITypeInfo2_fnGetAllParamCustData,
7428 ITypeInfo2_fnGetAllVarCustData,
7429 ITypeInfo2_fnGetAllImplTypeCustData,
7432 /******************************************************************************
7433 * CreateDispTypeInfo [OLEAUT32.31]
7435 * Build type information for an object so it can be called through an
7436 * IDispatch interface.
7439 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7440 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7443 * This call allows an objects methods to be accessed through IDispatch, by
7444 * building an ITypeInfo object that IDispatch can use to call through.
7446 HRESULT WINAPI CreateDispTypeInfo(
7447 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7448 LCID lcid, /* [I] Locale Id */
7449 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7451 ITypeInfoImpl *pTIClass, *pTIIface;
7452 ITypeLibImpl *pTypeLibImpl;
7453 unsigned int param, func;
7454 TLBFuncDesc **ppFuncDesc;
7458 pTypeLibImpl = TypeLibImpl_Constructor();
7459 if (!pTypeLibImpl) return E_FAIL;
7461 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7462 pTIIface->pTypeLib = pTypeLibImpl;
7463 pTIIface->index = 0;
7464 pTIIface->Name = NULL;
7465 pTIIface->dwHelpContext = -1;
7466 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7467 pTIIface->TypeAttr.lcid = lcid;
7468 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7469 pTIIface->TypeAttr.wMajorVerNum = 0;
7470 pTIIface->TypeAttr.wMinorVerNum = 0;
7471 pTIIface->TypeAttr.cbAlignment = 2;
7472 pTIIface->TypeAttr.cbSizeInstance = -1;
7473 pTIIface->TypeAttr.cbSizeVft = -1;
7474 pTIIface->TypeAttr.cFuncs = 0;
7475 pTIIface->TypeAttr.cImplTypes = 0;
7476 pTIIface->TypeAttr.cVars = 0;
7477 pTIIface->TypeAttr.wTypeFlags = 0;
7479 ppFuncDesc = &pTIIface->funclist;
7480 for(func = 0; func < pidata->cMembers; func++) {
7481 METHODDATA *md = pidata->pmethdata + func;
7482 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7483 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7484 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7485 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7486 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7487 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7488 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7489 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7490 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7491 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7492 (*ppFuncDesc)->funcdesc.cScodes = 0;
7493 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7494 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7495 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7496 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7497 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7498 md->cArgs * sizeof(ELEMDESC));
7499 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7500 md->cArgs * sizeof(TLBParDesc));
7501 for(param = 0; param < md->cArgs; param++) {
7502 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7503 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7505 (*ppFuncDesc)->helpcontext = 0;
7506 (*ppFuncDesc)->HelpStringContext = 0;
7507 (*ppFuncDesc)->HelpString = NULL;
7508 (*ppFuncDesc)->Entry = NULL;
7509 (*ppFuncDesc)->ctCustData = 0;
7510 (*ppFuncDesc)->pCustData = NULL;
7511 (*ppFuncDesc)->next = NULL;
7512 pTIIface->TypeAttr.cFuncs++;
7513 ppFuncDesc = &(*ppFuncDesc)->next;
7516 dump_TypeInfo(pTIIface);
7518 pTypeLibImpl->pTypeInfo = pTIIface;
7519 pTypeLibImpl->TypeInfoCount++;
7521 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7522 pTIClass->pTypeLib = pTypeLibImpl;
7523 pTIClass->index = 1;
7524 pTIClass->Name = NULL;
7525 pTIClass->dwHelpContext = -1;
7526 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7527 pTIClass->TypeAttr.lcid = lcid;
7528 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7529 pTIClass->TypeAttr.wMajorVerNum = 0;
7530 pTIClass->TypeAttr.wMinorVerNum = 0;
7531 pTIClass->TypeAttr.cbAlignment = 2;
7532 pTIClass->TypeAttr.cbSizeInstance = -1;
7533 pTIClass->TypeAttr.cbSizeVft = -1;
7534 pTIClass->TypeAttr.cFuncs = 0;
7535 pTIClass->TypeAttr.cImplTypes = 1;
7536 pTIClass->TypeAttr.cVars = 0;
7537 pTIClass->TypeAttr.wTypeFlags = 0;
7539 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7540 pTIClass->impltypelist->hRef = 0;
7542 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7545 ref->pImpTLInfo = TLB_REF_INTERNAL;
7546 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7548 dump_TypeInfo(pTIClass);
7550 pTIIface->next = pTIClass;
7551 pTypeLibImpl->TypeInfoCount++;
7553 *pptinfo = (ITypeInfo*)pTIClass;
7555 ITypeInfo_AddRef(*pptinfo);
7556 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7562 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7564 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7566 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7569 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7571 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7573 return ITypeInfo_AddRef((ITypeInfo *)This);
7576 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7578 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7580 return ITypeInfo_Release((ITypeInfo *)This);
7583 static HRESULT WINAPI ITypeComp_fnBind(
7588 ITypeInfo ** ppTInfo,
7589 DESCKIND * pDescKind,
7592 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7593 const TLBFuncDesc *pFDesc;
7594 const TLBVarDesc *pVDesc;
7595 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7597 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7599 *pDescKind = DESCKIND_NONE;
7600 pBindPtr->lpfuncdesc = NULL;
7603 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7604 if (!strcmpiW(pFDesc->Name, szName)) {
7605 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7608 /* name found, but wrong flags */
7609 hr = TYPE_E_TYPEMISMATCH;
7614 HRESULT hr = TLB_AllocAndInitFuncDesc(
7616 &pBindPtr->lpfuncdesc,
7617 This->TypeAttr.typekind == TKIND_DISPATCH);
7620 *pDescKind = DESCKIND_FUNCDESC;
7621 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7622 ITypeInfo_AddRef(*ppTInfo);
7625 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7626 if (!strcmpiW(pVDesc->Name, szName)) {
7627 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7630 *pDescKind = DESCKIND_VARDESC;
7631 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7632 ITypeInfo_AddRef(*ppTInfo);
7637 /* FIXME: search each inherited interface, not just the first */
7638 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7639 /* recursive search */
7643 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7646 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7647 ITypeInfo_Release(pTInfo);
7651 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7652 ITypeComp_Release(pTComp);
7655 WARN("Could not search inherited interface!\n");
7657 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7661 static HRESULT WINAPI ITypeComp_fnBindType(
7665 ITypeInfo ** ppTInfo,
7666 ITypeComp ** ppTComp)
7668 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7670 /* strange behaviour (does nothing) but like the
7673 if (!ppTInfo || !ppTComp)
7682 static const ITypeCompVtbl tcompvt =
7685 ITypeComp_fnQueryInterface,
7687 ITypeComp_fnRelease,
7690 ITypeComp_fnBindType