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, 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 * sizeof(void *))/4;
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 * sizeof(void *))/4; /* FIXME: this is only the non inherited part */
2150 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2151 MSFT_GetTdesc(pcx, tiBase.datatype1,
2152 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2155 /* IDLDESC idldescType; *//* never saw this one != zero */
2157 /* name, eventually add to a hash table */
2158 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2159 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2160 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2162 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2163 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2164 ptiRet->dwHelpContext=tiBase.helpcontext;
2166 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2167 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2169 /* note: InfoType's Help file and HelpStringDll come from the containing
2170 * library. Further HelpString and Docstring appear to be the same thing :(
2173 if(ptiRet->TypeAttr.cFuncs >0 )
2174 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2175 ptiRet->TypeAttr.cVars,
2176 tiBase.memoffset, & ptiRet->funclist);
2178 if(ptiRet->TypeAttr.cVars >0 )
2179 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2180 ptiRet->TypeAttr.cVars,
2181 tiBase.memoffset, & ptiRet->varlist);
2182 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2183 switch(ptiRet->TypeAttr.typekind)
2186 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2189 case TKIND_DISPATCH:
2190 /* This is not -1 when the interface is a non-base dual interface or
2191 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2192 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2196 if (tiBase.datatype1 != -1)
2198 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2199 ptiRet->impltypelist->hRef = tiBase.datatype1;
2200 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2204 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2205 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2206 ptiRet->impltypelist->hRef = tiBase.datatype1;
2211 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2213 TRACE_(typelib)("%s guid: %s kind:%s\n",
2214 debugstr_w(ptiRet->Name),
2215 debugstr_guid(&ptiRet->TypeAttr.guid),
2216 typekind_desc[ptiRet->TypeAttr.typekind]);
2217 if (TRACE_ON(typelib))
2218 dump_TypeInfo(ptiRet);
2223 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2224 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2225 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2228 static ITypeLibImpl *tlb_cache_first;
2229 static CRITICAL_SECTION cache_section;
2230 static CRITICAL_SECTION_DEBUG cache_section_debug =
2232 0, 0, &cache_section,
2233 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2234 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2236 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2239 typedef struct TLB_PEFile
2241 const IUnknownVtbl *lpvtbl;
2244 HRSRC typelib_resource;
2245 HGLOBAL typelib_global;
2246 LPVOID typelib_base;
2249 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2251 if (IsEqualIID(riid, &IID_IUnknown))
2254 IUnknown_AddRef(iface);
2258 return E_NOINTERFACE;
2261 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2263 TLB_PEFile *This = (TLB_PEFile *)iface;
2264 return InterlockedIncrement(&This->refs);
2267 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2269 TLB_PEFile *This = (TLB_PEFile *)iface;
2270 ULONG refs = InterlockedDecrement(&This->refs);
2273 if (This->typelib_global)
2274 FreeResource(This->typelib_global);
2276 FreeLibrary(This->dll);
2277 HeapFree(GetProcessHeap(), 0, This);
2282 static const IUnknownVtbl TLB_PEFile_Vtable =
2284 TLB_PEFile_QueryInterface,
2289 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2293 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2295 return E_OUTOFMEMORY;
2297 This->lpvtbl = &TLB_PEFile_Vtable;
2300 This->typelib_resource = NULL;
2301 This->typelib_global = NULL;
2302 This->typelib_base = NULL;
2304 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2305 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2309 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2310 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2311 if (This->typelib_resource)
2313 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2314 if (This->typelib_global)
2316 This->typelib_base = LockResource(This->typelib_global);
2318 if (This->typelib_base)
2320 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2321 *ppBase = This->typelib_base;
2322 *ppFile = (IUnknown *)&This->lpvtbl;
2329 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2330 return TYPE_E_CANTLOADLIBRARY;
2333 typedef struct TLB_NEFile
2335 const IUnknownVtbl *lpvtbl;
2337 LPVOID typelib_base;
2340 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2342 if (IsEqualIID(riid, &IID_IUnknown))
2345 IUnknown_AddRef(iface);
2349 return E_NOINTERFACE;
2352 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2354 TLB_NEFile *This = (TLB_NEFile *)iface;
2355 return InterlockedIncrement(&This->refs);
2358 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2360 TLB_NEFile *This = (TLB_NEFile *)iface;
2361 ULONG refs = InterlockedDecrement(&This->refs);
2364 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2365 HeapFree(GetProcessHeap(), 0, This);
2370 static const IUnknownVtbl TLB_NEFile_Vtable =
2372 TLB_NEFile_QueryInterface,
2377 /***********************************************************************
2378 * read_xx_header [internal]
2380 static int read_xx_header( HFILE lzfd )
2382 IMAGE_DOS_HEADER mzh;
2385 LZSeek( lzfd, 0, SEEK_SET );
2386 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2388 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2391 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2392 if ( 2 != LZRead( lzfd, magic, 2 ) )
2395 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2397 if ( magic[0] == 'N' && magic[1] == 'E' )
2398 return IMAGE_OS2_SIGNATURE;
2399 if ( magic[0] == 'P' && magic[1] == 'E' )
2400 return IMAGE_NT_SIGNATURE;
2403 WARN("Can't handle %s files.\n", magic );
2408 /***********************************************************************
2409 * find_ne_resource [internal]
2411 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2412 DWORD *resLen, DWORD *resOff )
2414 IMAGE_OS2_HEADER nehd;
2415 NE_TYPEINFO *typeInfo;
2416 NE_NAMEINFO *nameInfo;
2422 /* Read in NE header */
2423 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2424 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2426 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2429 TRACE("No resources in NE dll\n" );
2433 /* Read in resource table */
2434 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2435 if ( !resTab ) return FALSE;
2437 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2438 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2440 HeapFree( GetProcessHeap(), 0, resTab );
2445 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2447 if (HIWORD(typeid) != 0) /* named type */
2449 BYTE len = strlen( typeid );
2450 while (typeInfo->type_id)
2452 if (!(typeInfo->type_id & 0x8000))
2454 BYTE *p = resTab + typeInfo->type_id;
2455 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2457 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2458 typeInfo->count * sizeof(NE_NAMEINFO));
2461 else /* numeric type id */
2463 WORD id = LOWORD(typeid) | 0x8000;
2464 while (typeInfo->type_id)
2466 if (typeInfo->type_id == id) goto found_type;
2467 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2468 typeInfo->count * sizeof(NE_NAMEINFO));
2471 TRACE("No typeid entry found for %p\n", typeid );
2472 HeapFree( GetProcessHeap(), 0, resTab );
2476 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2478 if (HIWORD(resid) != 0) /* named resource */
2480 BYTE len = strlen( resid );
2481 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2483 BYTE *p = resTab + nameInfo->id;
2484 if (nameInfo->id & 0x8000) continue;
2485 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2488 else /* numeric resource id */
2490 WORD id = LOWORD(resid) | 0x8000;
2491 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2492 if (nameInfo->id == id) goto found_name;
2494 TRACE("No resid entry found for %p\n", typeid );
2495 HeapFree( GetProcessHeap(), 0, resTab );
2499 /* Return resource data */
2500 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2501 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2503 HeapFree( GetProcessHeap(), 0, resTab );
2507 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2511 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2512 TLB_NEFile *This = NULL;
2514 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2515 if (!This) return E_OUTOFMEMORY;
2517 This->lpvtbl = &TLB_NEFile_Vtable;
2519 This->typelib_base = NULL;
2521 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2522 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2524 DWORD reslen, offset;
2525 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2527 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2528 if( !This->typelib_base )
2532 LZSeek( lzfd, offset, SEEK_SET );
2533 reslen = LZRead( lzfd, This->typelib_base, reslen );
2535 *ppBase = This->typelib_base;
2536 *pdwTLBLength = reslen;
2537 *ppFile = (IUnknown *)&This->lpvtbl;
2543 if( lzfd >= 0) LZClose( lzfd );
2544 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2548 typedef struct TLB_Mapping
2550 const IUnknownVtbl *lpvtbl;
2554 LPVOID typelib_base;
2557 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2559 if (IsEqualIID(riid, &IID_IUnknown))
2562 IUnknown_AddRef(iface);
2566 return E_NOINTERFACE;
2569 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2571 TLB_Mapping *This = (TLB_Mapping *)iface;
2572 return InterlockedIncrement(&This->refs);
2575 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2577 TLB_Mapping *This = (TLB_Mapping *)iface;
2578 ULONG refs = InterlockedDecrement(&This->refs);
2581 if (This->typelib_base)
2582 UnmapViewOfFile(This->typelib_base);
2584 CloseHandle(This->mapping);
2585 if (This->file != INVALID_HANDLE_VALUE)
2586 CloseHandle(This->file);
2587 HeapFree(GetProcessHeap(), 0, This);
2592 static const IUnknownVtbl TLB_Mapping_Vtable =
2594 TLB_Mapping_QueryInterface,
2599 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2603 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2605 return E_OUTOFMEMORY;
2607 This->lpvtbl = &TLB_Mapping_Vtable;
2609 This->file = INVALID_HANDLE_VALUE;
2610 This->mapping = NULL;
2611 This->typelib_base = NULL;
2613 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2614 if (INVALID_HANDLE_VALUE != This->file)
2616 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2619 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2620 if(This->typelib_base)
2622 /* retrieve file size */
2623 *pdwTLBLength = GetFileSize(This->file, NULL);
2624 *ppBase = This->typelib_base;
2625 *ppFile = (IUnknown *)&This->lpvtbl;
2631 IUnknown_Release((IUnknown *)&This->lpvtbl);
2632 return TYPE_E_CANTLOADLIBRARY;
2635 /****************************************************************************
2638 * find the type of the typelib file and map the typelib resource into
2641 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2642 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2643 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2645 ITypeLibImpl *entry;
2648 LPWSTR index_str, file = (LPWSTR)pszFileName;
2649 LPVOID pBase = NULL;
2650 DWORD dwTLBLength = 0;
2651 IUnknown *pFile = NULL;
2655 index_str = strrchrW(pszFileName, '\\');
2656 if(index_str && *++index_str != '\0')
2659 long idx = strtolW(index_str, &end_ptr, 10);
2660 if(*end_ptr == '\0')
2662 int str_len = index_str - pszFileName - 1;
2664 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2665 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2670 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2672 if(strchrW(file, '\\'))
2674 lstrcpyW(pszPath, file);
2678 int len = GetSystemDirectoryW(pszPath, cchPath);
2679 pszPath[len] = '\\';
2680 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2684 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2686 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2688 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2689 EnterCriticalSection(&cache_section);
2690 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2692 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2694 TRACE("cache hit\n");
2695 *ppTypeLib = (ITypeLib2*)entry;
2696 ITypeLib_AddRef(*ppTypeLib);
2697 LeaveCriticalSection(&cache_section);
2701 LeaveCriticalSection(&cache_section);
2703 /* now actually load and parse the typelib */
2705 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2706 if (ret == TYPE_E_CANTLOADLIBRARY)
2707 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2708 if (ret == TYPE_E_CANTLOADLIBRARY)
2709 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2712 if (dwTLBLength >= 4)
2714 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2715 if (dwSignature == MSFT_SIGNATURE)
2716 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2717 else if (dwSignature == SLTG_SIGNATURE)
2718 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2721 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2722 ret = TYPE_E_CANTLOADLIBRARY;
2726 ret = TYPE_E_CANTLOADLIBRARY;
2727 IUnknown_Release(pFile);
2731 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2733 TRACE("adding to cache\n");
2734 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2735 lstrcpyW(impl->path, pszPath);
2736 /* We should really canonicalise the path here. */
2737 impl->index = index;
2739 /* FIXME: check if it has added already in the meantime */
2740 EnterCriticalSection(&cache_section);
2741 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2743 tlb_cache_first = impl;
2744 LeaveCriticalSection(&cache_section);
2747 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2752 /*================== ITypeLib(2) Methods ===================================*/
2754 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2756 ITypeLibImpl* pTypeLibImpl;
2758 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2759 if (!pTypeLibImpl) return NULL;
2761 pTypeLibImpl->lpVtbl = &tlbvt;
2762 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2763 pTypeLibImpl->ref = 1;
2765 list_init(&pTypeLibImpl->ref_list);
2766 pTypeLibImpl->dispatch_href = -1;
2768 return pTypeLibImpl;
2771 /****************************************************************************
2772 * ITypeLib2_Constructor_MSFT
2774 * loading an MSFT typelib from an in-memory image
2776 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2780 MSFT_Header tlbHeader;
2781 MSFT_SegDir tlbSegDir;
2782 ITypeLibImpl * pTypeLibImpl;
2784 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2786 pTypeLibImpl = TypeLibImpl_Constructor();
2787 if (!pTypeLibImpl) return NULL;
2789 /* get pointer to beginning of typelib data */
2793 cx.pLibInfo = pTypeLibImpl;
2794 cx.length = dwTLBLength;
2797 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2798 TRACE_(typelib)("header:\n");
2799 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2800 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2801 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2804 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2806 /* there is a small amount of information here until the next important
2808 * the segment directory . Try to calculate the amount of data */
2809 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2811 /* now read the segment directory */
2812 TRACE("read segment directory (at %ld)\n",lPSegDir);
2813 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2814 cx.pTblDir = &tlbSegDir;
2816 /* just check two entries */
2817 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2819 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2820 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2824 /* now fill our internal data */
2825 /* TLIBATTR fields */
2826 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2828 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2829 /* Windows seems to have zero here, is this correct? */
2830 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2831 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2833 pTypeLibImpl->LibAttr.lcid = 0;
2835 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2836 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2837 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2838 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2840 /* name, eventually add to a hash table */
2841 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2844 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2845 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2847 if( tlbHeader.varflags & HELPDLLFLAG)
2850 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2851 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2854 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2857 if(tlbHeader.CustomDataOffset >= 0)
2859 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2862 /* fill in type descriptions */
2863 if(tlbSegDir.pTypdescTab.length > 0)
2865 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2867 pTypeLibImpl->ctTypeDesc = cTD;
2868 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2869 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2872 /* FIXME: add several sanity checks here */
2873 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2874 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2876 /* FIXME: check safearray */
2878 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2880 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2882 else if(td[0] == VT_CARRAY)
2884 /* array descr table here */
2885 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2887 else if(td[0] == VT_USERDEFINED)
2889 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2891 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2894 /* second time around to fill the array subscript info */
2897 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2898 if(tlbSegDir.pArrayDescriptions.offset>0)
2900 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2901 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2904 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2906 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2908 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2910 for(j = 0; j<td[2]; j++)
2912 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2913 sizeof(INT), &cx, DO_NOT_SEEK);
2914 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2915 sizeof(INT), &cx, DO_NOT_SEEK);
2920 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2921 ERR("didn't find array description data\n");
2926 /* imported type libs */
2927 if(tlbSegDir.pImpFiles.offset>0)
2929 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2930 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2933 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2937 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2938 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2939 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2941 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2942 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2943 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2944 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2947 name = TLB_Alloc(size+1);
2948 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2949 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2951 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2952 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2954 ppImpLib = &(*ppImpLib)->next;
2958 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2959 if(pTypeLibImpl->dispatch_href != -1)
2960 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2963 if(tlbHeader.nrtypeinfos >= 0 )
2965 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2966 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2969 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2971 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2973 ppTI = &((*ppTI)->next);
2974 (pTypeLibImpl->TypeInfoCount)++;
2978 TRACE("(%p)\n", pTypeLibImpl);
2979 return (ITypeLib2*) pTypeLibImpl;
2983 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2989 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2990 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2994 guid->Data4[0] = s >> 8;
2995 guid->Data4[1] = s & 0xff;
2998 for(i = 0; i < 6; i++) {
2999 memcpy(b, str + 24 + 2 * i, 2);
3000 guid->Data4[i + 2] = strtol(b, NULL, 16);
3005 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3011 bytelen = *(const WORD*)ptr;
3012 if(bytelen == 0xffff) return 2;
3013 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3014 *pBstr = SysAllocStringLen(NULL, len - 1);
3016 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3020 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3025 bytelen = *(const WORD*)ptr;
3026 if(bytelen == 0xffff) return 2;
3027 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3028 memcpy(*str, ptr + 2, bytelen);
3029 (*str)[bytelen] = '\0';
3033 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3035 char *ptr = pLibBlk;
3038 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3039 FIXME("libblk magic = %04x\n", w);
3044 if((w = *(WORD*)ptr) != 0xffff) {
3045 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3050 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3052 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3054 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3057 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3060 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3061 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3063 pTypeLibImpl->LibAttr.lcid = 0;
3066 ptr += 4; /* skip res12 */
3068 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3071 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3074 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3077 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3078 ptr += sizeof(GUID);
3080 return ptr - (char*)pLibBlk;
3083 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3088 } sltg_ref_lookup_t;
3090 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3091 HREFTYPE *typelib_ref)
3093 if(typeinfo_ref < table->num)
3095 *typelib_ref = table->refs[typeinfo_ref];
3099 ERR_(typelib)("Unable to find reference\n");
3104 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3109 if((*pType & 0xe00) == 0xe00) {
3111 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3113 pTD = pTD->u.lptdesc;
3115 switch(*pType & 0x3f) {
3118 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3120 pTD = pTD->u.lptdesc;
3123 case VT_USERDEFINED:
3124 pTD->vt = VT_USERDEFINED;
3125 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3131 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3134 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3136 pTD->vt = VT_CARRAY;
3137 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3139 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3140 pTD->u.lpadesc->cDims = pSA->cDims;
3141 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3142 pSA->cDims * sizeof(SAFEARRAYBOUND));
3144 pTD = &pTD->u.lpadesc->tdescElem;
3150 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3154 pTD->vt = VT_SAFEARRAY;
3155 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3157 pTD = pTD->u.lptdesc;
3161 pTD->vt = *pType & 0x3f;
3170 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3171 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3173 /* Handle [in/out] first */
3174 if((*pType & 0xc000) == 0xc000)
3175 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3176 else if(*pType & 0x8000)
3177 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3178 else if(*pType & 0x4000)
3179 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3181 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3184 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3187 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3189 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3193 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3198 TLBRefType *ref_type;
3199 sltg_ref_lookup_t *table;
3200 HREFTYPE typelib_ref;
3202 if(pRef->magic != SLTG_REF_MAGIC) {
3203 FIXME("Ref magic = %x\n", pRef->magic);
3206 name = ( (char*)pRef->names + pRef->number);
3208 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3209 table->num = pRef->number >> 3;
3211 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3213 /* We don't want the first href to be 0 */
3214 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3216 for(ref = 0; ref < pRef->number >> 3; ref++) {
3218 unsigned int lib_offs, type_num;
3220 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3222 name += SLTG_ReadStringA(name, &refname);
3223 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3224 FIXME_(typelib)("Can't sscanf ref\n");
3225 if(lib_offs != 0xffff) {
3226 TLBImpLib **import = &pTL->pImpLibs;
3229 if((*import)->offset == lib_offs)
3231 import = &(*import)->next;
3234 char fname[MAX_PATH+1];
3237 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3239 (*import)->offset = lib_offs;
3240 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3242 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3243 &(*import)->wVersionMajor,
3244 &(*import)->wVersionMinor,
3245 &(*import)->lcid, fname) != 4) {
3246 FIXME_(typelib)("can't sscanf ref %s\n",
3247 pNameTable + lib_offs + 40);
3249 len = strlen(fname);
3250 if(fname[len-1] != '#')
3251 FIXME("fname = %s\n", fname);
3252 fname[len-1] = '\0';
3253 (*import)->name = TLB_MultiByteToBSTR(fname);
3255 ref_type->pImpTLInfo = *import;
3257 /* Store a reference to IDispatch */
3258 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3259 pTL->dispatch_href = typelib_ref;
3261 } else { /* internal ref */
3262 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3264 ref_type->reference = typelib_ref;
3265 ref_type->index = type_num;
3267 HeapFree(GetProcessHeap(), 0, refname);
3268 list_add_tail(&pTL->ref_list, &ref_type->entry);
3270 table->refs[ref] = typelib_ref;
3273 if((BYTE)*name != SLTG_REF_MAGIC)
3274 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3275 dump_TLBRefType(pTL);
3279 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3280 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3282 SLTG_ImplInfo *info;
3283 TLBImplType **ppImplType = &pTI->impltypelist;
3284 /* I don't really get this structure, usually it's 0x16 bytes
3285 long, but iuser.tlb contains some that are 0x18 bytes long.
3286 That's ok because we can use the next ptr to jump to the next
3287 one. But how do we know the length of the last one? The WORD
3288 at offs 0x8 might be the clue. For now I'm just assuming that
3289 the last one is the regular 0x16 bytes. */
3291 info = (SLTG_ImplInfo*)pBlk;
3293 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3294 sizeof(**ppImplType));
3295 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3296 (*ppImplType)->implflags = info->impltypeflags;
3297 pTI->TypeAttr.cImplTypes++;
3298 ppImplType = &(*ppImplType)->next;
3300 if(info->next == 0xffff)
3303 FIXME_(typelib)("Interface inheriting more than one interface\n");
3304 info = (SLTG_ImplInfo*)(pBlk + info->next);
3306 info++; /* see comment at top of function */
3310 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3311 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3313 TLBVarDesc **ppVarDesc = &pTI->varlist;
3314 BSTR bstrPrevName = NULL;
3315 SLTG_Variable *pItem;
3319 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3320 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3322 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3323 sizeof(**ppVarDesc));
3324 (*ppVarDesc)->vardesc.memid = pItem->memid;
3326 if (pItem->magic != SLTG_VAR_MAGIC &&
3327 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3328 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3332 if (pItem->name == 0xfffe)
3333 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3335 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3337 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3338 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3339 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3341 if(pItem->flags & 0x02)
3342 pType = &pItem->type;
3344 pType = (WORD*)(pBlk + pItem->type);
3346 if (pItem->flags & ~0xda)
3347 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3349 SLTG_DoElem(pType, pBlk,
3350 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3352 if (TRACE_ON(typelib)) {
3354 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3355 TRACE_(typelib)("elemdescVar: %s\n", buf);
3358 if (pItem->flags & 0x40) {
3359 TRACE_(typelib)("VAR_DISPATCH\n");
3360 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3362 else if (pItem->flags & 0x10) {
3363 TRACE_(typelib)("VAR_CONST\n");
3364 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3365 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3367 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3368 if (pItem->flags & 0x08)
3369 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3371 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3377 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3379 TRACE_(typelib)("len = %u\n", len);
3380 if (len == 0xffff) {
3383 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3384 str = SysAllocStringLen(NULL, alloc_len);
3385 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3387 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3388 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3397 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3398 *(INT*)(pBlk + pItem->byte_offs);
3401 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3406 TRACE_(typelib)("VAR_PERINSTANCE\n");
3407 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3408 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3411 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3412 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3414 if (pItem->flags & 0x80)
3415 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3417 bstrPrevName = (*ppVarDesc)->Name;
3418 ppVarDesc = &((*ppVarDesc)->next);
3420 pTI->TypeAttr.cVars = cVars;
3423 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3424 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3426 SLTG_Function *pFunc;
3428 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3430 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3431 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3436 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3437 sizeof(**ppFuncDesc));
3439 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3440 case SLTG_FUNCTION_MAGIC:
3441 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3443 case SLTG_DISPATCH_FUNCTION_MAGIC:
3444 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3446 case SLTG_STATIC_FUNCTION_MAGIC:
3447 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3450 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3451 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3455 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3457 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3458 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3459 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3460 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3461 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3462 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3464 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3465 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3467 if(pFunc->retnextopt & 0x80)
3468 pType = &pFunc->rettype;
3470 pType = (WORD*)(pBlk + pFunc->rettype);
3472 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3474 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3475 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3476 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3477 (*ppFuncDesc)->pParamDesc =
3478 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3479 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3481 pArg = (WORD*)(pBlk + pFunc->arg_off);
3483 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3484 char *paramName = pNameTable + *pArg;
3486 /* If arg type follows then paramName points to the 2nd
3487 letter of the name, else the next WORD is an offset to
3488 the arg type and paramName points to the first letter.
3489 So let's take one char off paramName and see if we're
3490 pointing at an alpha-numeric char. However if *pArg is
3491 0xffff or 0xfffe then the param has no name, the former
3492 meaning that the next WORD is the type, the latter
3493 meaning that the next WORD is an offset to the type. */
3498 else if(*pArg == 0xfffe) {
3502 else if(paramName[-1] && !isalnum(paramName[-1]))
3507 if(HaveOffs) { /* the next word is an offset to type */
3508 pType = (WORD*)(pBlk + *pArg);
3509 SLTG_DoElem(pType, pBlk,
3510 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3515 pArg = SLTG_DoElem(pArg, pBlk,
3516 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3519 /* Are we an optional param ? */
3520 if((*ppFuncDesc)->funcdesc.cParams - param <=
3521 (*ppFuncDesc)->funcdesc.cParamsOpt)
3522 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3525 (*ppFuncDesc)->pParamDesc[param].Name =
3526 TLB_MultiByteToBSTR(paramName);
3528 (*ppFuncDesc)->pParamDesc[param].Name =
3529 SysAllocString((*ppFuncDesc)->Name);
3533 ppFuncDesc = &((*ppFuncDesc)->next);
3534 if(pFunc->next == 0xffff) break;
3536 pTI->TypeAttr.cFuncs = cFuncs;
3539 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3540 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3541 SLTG_TypeInfoTail *pTITail)
3544 sltg_ref_lookup_t *ref_lookup = NULL;
3546 if(pTIHeader->href_table != 0xffffffff) {
3547 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3553 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3554 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3556 HeapFree(GetProcessHeap(), 0, ref_lookup);
3560 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3561 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3562 const SLTG_TypeInfoTail *pTITail)
3565 sltg_ref_lookup_t *ref_lookup = NULL;
3567 if(pTIHeader->href_table != 0xffffffff) {
3568 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3574 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3575 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3578 if (pTITail->funcs_off != 0xffff)
3579 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3581 HeapFree(GetProcessHeap(), 0, ref_lookup);
3583 if (TRACE_ON(typelib))
3584 dump_TLBFuncDesc(pTI->funclist);
3587 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3588 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3589 const SLTG_TypeInfoTail *pTITail)
3591 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3594 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3595 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3596 const SLTG_TypeInfoTail *pTITail)
3599 sltg_ref_lookup_t *ref_lookup = NULL;
3601 if (pTITail->simple_alias) {
3602 /* if simple alias, no more processing required */
3603 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3607 if(pTIHeader->href_table != 0xffffffff) {
3608 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3612 /* otherwise it is an offset to a type */
3613 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3615 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3617 HeapFree(GetProcessHeap(), 0, ref_lookup);
3620 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3621 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3622 const SLTG_TypeInfoTail *pTITail)
3624 sltg_ref_lookup_t *ref_lookup = NULL;
3625 if (pTIHeader->href_table != 0xffffffff)
3626 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3629 if (pTITail->vars_off != 0xffff)
3630 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3632 if (pTITail->funcs_off != 0xffff)
3633 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3635 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3636 * of dispinterface functions including the IDispatch ones, so
3637 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3638 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3640 HeapFree(GetProcessHeap(), 0, ref_lookup);
3641 if (TRACE_ON(typelib))
3642 dump_TLBFuncDesc(pTI->funclist);
3645 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3646 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3647 const SLTG_TypeInfoTail *pTITail)
3649 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3652 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3653 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3654 const SLTG_TypeInfoTail *pTITail)
3656 sltg_ref_lookup_t *ref_lookup = NULL;
3657 if (pTIHeader->href_table != 0xffffffff)
3658 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3661 if (pTITail->vars_off != 0xffff)
3662 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3664 if (pTITail->funcs_off != 0xffff)
3665 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3666 HeapFree(GetProcessHeap(), 0, ref_lookup);
3667 if (TRACE_ON(typelib))
3671 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3672 managable copy of it into this */
3685 } SLTG_InternalOtherTypeInfo;
3687 /****************************************************************************
3688 * ITypeLib2_Constructor_SLTG
3690 * loading a SLTG typelib from an in-memory image
3692 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3694 ITypeLibImpl *pTypeLibImpl;
3695 SLTG_Header *pHeader;
3696 SLTG_BlkEntry *pBlkEntry;
3700 LPVOID pBlk, pFirstBlk;
3701 SLTG_LibBlk *pLibBlk;
3702 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3703 char *pAfterOTIBlks = NULL;
3704 char *pNameTable, *ptr;
3707 ITypeInfoImpl **ppTypeInfoImpl;
3709 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3712 pTypeLibImpl = TypeLibImpl_Constructor();
3713 if (!pTypeLibImpl) return NULL;
3717 TRACE_(typelib)("header:\n");
3718 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3719 pHeader->nrOfFileBlks );
3720 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3721 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3722 pHeader->SLTG_magic);
3726 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3727 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3729 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3730 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3732 /* Next we have a magic block */
3733 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3735 /* Let's see if we're still in sync */
3736 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3737 sizeof(SLTG_COMPOBJ_MAGIC))) {
3738 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3741 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3742 sizeof(SLTG_DIR_MAGIC))) {
3743 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3747 pIndex = (SLTG_Index*)(pMagic+1);
3749 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3751 pFirstBlk = pPad9 + 1;
3753 /* We'll set up a ptr to the main library block, which is the last one. */
3755 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3756 pBlkEntry[order].next != 0;
3757 order = pBlkEntry[order].next - 1, i++) {
3758 pBlk = (char*)pBlk + pBlkEntry[order].len;
3762 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3764 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3769 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3771 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3772 sizeof(*pOtherTypeInfoBlks) *
3773 pTypeLibImpl->TypeInfoCount);
3776 ptr = (char*)pLibBlk + len;
3778 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3782 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3784 w = *(WORD*)(ptr + 2);
3787 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3789 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3790 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3792 w = *(WORD*)(ptr + 4 + len);
3794 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3796 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3798 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3799 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3801 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3802 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3803 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3805 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3807 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3810 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3811 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3812 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3813 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3814 len += sizeof(SLTG_OtherTypeInfo);
3818 pAfterOTIBlks = ptr;
3820 /* Skip this WORD and get the next DWORD */
3821 len = *(DWORD*)(pAfterOTIBlks + 2);
3823 /* Now add this to pLibBLk look at what we're pointing at and
3824 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3825 dust and we should be pointing at the beginning of the name
3828 pNameTable = (char*)pLibBlk + len;
3830 switch(*(WORD*)pNameTable) {
3837 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3841 pNameTable += 0x216;
3845 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3847 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3850 /* Hopefully we now have enough ptrs set up to actually read in
3851 some TypeInfos. It's not clear which order to do them in, so
3852 I'll just follow the links along the BlkEntry chain and read
3853 them in the order in which they are in the file */
3855 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3857 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3858 pBlkEntry[order].next != 0;
3859 order = pBlkEntry[order].next - 1, i++) {
3861 SLTG_TypeInfoHeader *pTIHeader;
3862 SLTG_TypeInfoTail *pTITail;
3863 SLTG_MemberHeader *pMemHeader;
3865 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3866 pOtherTypeInfoBlks[i].index_name)) {
3867 FIXME_(typelib)("Index strings don't match\n");
3872 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3873 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3876 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3877 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3878 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3880 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3881 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3882 (*ppTypeInfoImpl)->index = i;
3883 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3884 pOtherTypeInfoBlks[i].name_offs +
3886 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3887 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3888 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3889 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3890 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3891 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3892 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3894 if((pTIHeader->typeflags1 & 7) != 2)
3895 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3896 if(pTIHeader->typeflags3 != 2)
3897 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3899 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3900 debugstr_w((*ppTypeInfoImpl)->Name),
3901 typekind_desc[pTIHeader->typekind],
3902 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3903 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3905 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3907 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3909 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3910 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3911 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = (pTITail->cbSizeVft * sizeof(void *))/4;
3913 switch(pTIHeader->typekind) {
3915 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3916 pTIHeader, pTITail);
3920 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3921 pTIHeader, pTITail);
3924 case TKIND_INTERFACE:
3925 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3926 pTIHeader, pTITail);
3930 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3931 pTIHeader, pTITail);
3935 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3936 pTIHeader, pTITail);
3939 case TKIND_DISPATCH:
3940 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3941 pTIHeader, pTITail);
3945 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3946 pTIHeader, pTITail);
3950 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3955 /* could get cFuncs, cVars and cImplTypes from here
3956 but we've already set those */
3957 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3972 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3973 pBlk = (char*)pBlk + pBlkEntry[order].len;
3976 if(i != pTypeLibImpl->TypeInfoCount) {
3977 FIXME("Somehow processed %d TypeInfos\n", i);
3981 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3982 return (ITypeLib2*)pTypeLibImpl;
3985 /* ITypeLib::QueryInterface
3987 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3992 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3994 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3997 if(IsEqualIID(riid, &IID_IUnknown) ||
3998 IsEqualIID(riid,&IID_ITypeLib)||
3999 IsEqualIID(riid,&IID_ITypeLib2))
4006 ITypeLib2_AddRef(iface);
4007 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4010 TRACE("-- Interface: E_NOINTERFACE\n");
4011 return E_NOINTERFACE;
4016 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4018 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4019 ULONG ref = InterlockedIncrement(&This->ref);
4021 TRACE("(%p)->ref was %u\n",This, ref - 1);
4026 /* ITypeLib::Release
4028 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4030 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4031 ULONG ref = InterlockedDecrement(&This->ref);
4033 TRACE("(%p)->(%u)\n",This, ref);
4037 TLBImpLib *pImpLib, *pImpLibNext;
4038 TLBCustData *pCustData, *pCustDataNext;
4039 TLBRefType *ref_type;
4043 /* remove cache entry */
4046 TRACE("removing from cache list\n");
4047 EnterCriticalSection(&cache_section);
4048 if (This->next) This->next->prev = This->prev;
4049 if (This->prev) This->prev->next = This->next;
4050 else tlb_cache_first = This->next;
4051 LeaveCriticalSection(&cache_section);
4052 HeapFree(GetProcessHeap(), 0, This->path);
4054 TRACE(" destroying ITypeLib(%p)\n",This);
4056 SysFreeString(This->Name);
4059 SysFreeString(This->DocString);
4060 This->DocString = NULL;
4062 SysFreeString(This->HelpFile);
4063 This->HelpFile = NULL;
4065 SysFreeString(This->HelpStringDll);
4066 This->HelpStringDll = NULL;
4068 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4070 VariantClear(&pCustData->data);
4072 pCustDataNext = pCustData->next;
4073 TLB_Free(pCustData);
4076 for (i = 0; i < This->ctTypeDesc; i++)
4077 if (This->pTypeDesc[i].vt == VT_CARRAY)
4078 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4080 TLB_Free(This->pTypeDesc);
4082 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4084 if (pImpLib->pImpTypeLib)
4085 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4086 SysFreeString(pImpLib->name);
4088 pImpLibNext = pImpLib->next;
4092 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4094 list_remove(&ref_type->entry);
4098 if (This->pTypeInfo) /* can be NULL */
4099 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4100 HeapFree(GetProcessHeap(),0,This);
4107 /* ITypeLib::GetTypeInfoCount
4109 * Returns the number of type descriptions in the type library
4111 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4113 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4114 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4115 return This->TypeInfoCount;
4118 /* ITypeLib::GetTypeInfo
4120 * retrieves the specified type description in the library.
4122 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4125 ITypeInfo **ppTInfo)
4129 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4130 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4132 TRACE("(%p)->(index=%d)\n", This, index);
4134 if (!ppTInfo) return E_INVALIDARG;
4136 /* search element n in list */
4137 for(i=0; i < index; i++)
4139 pTypeInfo = pTypeInfo->next;
4142 TRACE("-- element not found\n");
4143 return TYPE_E_ELEMENTNOTFOUND;
4147 *ppTInfo = (ITypeInfo *) pTypeInfo;
4149 ITypeInfo_AddRef(*ppTInfo);
4150 TRACE("-- found (%p)\n",*ppTInfo);
4155 /* ITypeLibs::GetTypeInfoType
4157 * Retrieves the type of a type description.
4159 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4164 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4166 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4168 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4169 return TYPE_E_ELEMENTNOTFOUND;
4171 TRACE("(%p) index %d\n", This, index);
4173 if(!pTKind) return E_INVALIDARG;
4175 /* search element n in list */
4176 for(i=0; i < index; i++)
4180 TRACE("-- element not found\n");
4181 return TYPE_E_ELEMENTNOTFOUND;
4183 pTInfo = pTInfo->next;
4186 *pTKind = pTInfo->TypeAttr.typekind;
4187 TRACE("-- found Type (%d)\n", *pTKind);
4191 /* ITypeLib::GetTypeInfoOfGuid
4193 * Retrieves the type description that corresponds to the specified GUID.
4196 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4199 ITypeInfo **ppTInfo)
4201 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4202 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4204 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4208 WARN("-- element not found\n");
4209 return TYPE_E_ELEMENTNOTFOUND;
4212 /* search linked list for guid */
4213 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4215 pTypeInfo = pTypeInfo->next;
4219 /* end of list reached */
4220 WARN("-- element not found\n");
4221 return TYPE_E_ELEMENTNOTFOUND;
4225 TRACE("-- found (%p, %s)\n",
4227 debugstr_w(pTypeInfo->Name));
4229 *ppTInfo = (ITypeInfo*)pTypeInfo;
4230 ITypeInfo_AddRef(*ppTInfo);
4234 /* ITypeLib::GetLibAttr
4236 * Retrieves the structure that contains the library's attributes.
4239 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4241 LPTLIBATTR *ppTLibAttr)
4243 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4244 TRACE("(%p)\n",This);
4245 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4246 **ppTLibAttr = This->LibAttr;
4250 /* ITypeLib::GetTypeComp
4252 * Enables a client compiler to bind to a library's types, variables,
4253 * constants, and global functions.
4256 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4258 ITypeComp **ppTComp)
4260 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4262 TRACE("(%p)->(%p)\n",This,ppTComp);
4263 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4264 ITypeComp_AddRef(*ppTComp);
4269 /* ITypeLib::GetDocumentation
4271 * Retrieves the library's documentation string, the complete Help file name
4272 * and path, and the context identifier for the library Help topic in the Help
4275 * On a successful return all non-null BSTR pointers will have been set,
4278 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4282 BSTR *pBstrDocString,
4283 DWORD *pdwHelpContext,
4284 BSTR *pBstrHelpFile)
4286 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4288 HRESULT result = E_INVALIDARG;
4293 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4295 pBstrName, pBstrDocString,
4296 pdwHelpContext, pBstrHelpFile);
4300 /* documentation for the typelib */
4305 if(!(*pBstrName = SysAllocString(This->Name)))
4313 if (This->DocString)
4315 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4318 else if (This->Name)
4320 if(!(*pBstrDocString = SysAllocString(This->Name)))
4324 *pBstrDocString = NULL;
4328 *pdwHelpContext = This->dwHelpContext;
4334 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4338 *pBstrHelpFile = NULL;
4345 /* for a typeinfo */
4346 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4348 if(SUCCEEDED(result))
4350 result = ITypeInfo_GetDocumentation(pTInfo,
4354 pdwHelpContext, pBstrHelpFile);
4356 ITypeInfo_Release(pTInfo);
4361 if (pBstrDocString) SysFreeString (*pBstrDocString);
4363 if (pBstrName) SysFreeString (*pBstrName);
4365 return STG_E_INSUFFICIENTMEMORY;
4370 * Indicates whether a passed-in string contains the name of a type or member
4371 * described in the library.
4374 static HRESULT WINAPI ITypeLib2_fnIsName(
4380 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4381 ITypeInfoImpl *pTInfo;
4382 TLBFuncDesc *pFInfo;
4385 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4387 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4391 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4392 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4393 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4394 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4395 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4396 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4397 goto ITypeLib2_fnIsName_exit;
4399 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4400 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4405 ITypeLib2_fnIsName_exit:
4406 TRACE("(%p)slow! search for %s: %s found!\n", This,
4407 debugstr_w(szNameBuf), *pfName?"NOT":"");
4412 /* ITypeLib::FindName
4414 * Finds occurrences of a type description in a type library. This may be used
4415 * to quickly verify that a name exists in a type library.
4418 static HRESULT WINAPI ITypeLib2_fnFindName(
4422 ITypeInfo **ppTInfo,
4426 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4427 ITypeInfoImpl *pTInfo;
4428 TLBFuncDesc *pFInfo;
4431 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4433 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4434 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4435 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4436 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4437 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4438 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4439 goto ITypeLib2_fnFindName_exit;
4442 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4443 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4445 ITypeLib2_fnFindName_exit:
4446 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4447 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4450 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4451 This, *pcFound, debugstr_w(szNameBuf), j);
4458 /* ITypeLib::ReleaseTLibAttr
4460 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4463 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4465 TLIBATTR *pTLibAttr)
4467 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4468 TRACE("freeing (%p)\n",This);
4469 HeapFree(GetProcessHeap(),0,pTLibAttr);
4473 /* ITypeLib2::GetCustData
4475 * gets the custom data
4477 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4482 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4483 TLBCustData *pCData;
4485 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4487 if( IsEqualIID(guid, &pCData->guid)) break;
4490 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4494 VariantInit( pVarVal);
4495 VariantCopy( pVarVal, &pCData->data);
4498 return E_INVALIDARG; /* FIXME: correct? */
4501 /* ITypeLib2::GetLibStatistics
4503 * Returns statistics about a type library that are required for efficient
4504 * sizing of hash tables.
4507 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4509 ULONG *pcUniqueNames,
4510 ULONG *pcchUniqueNames)
4512 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4514 FIXME("(%p): stub!\n", This);
4516 if(pcUniqueNames) *pcUniqueNames=1;
4517 if(pcchUniqueNames) *pcchUniqueNames=1;
4521 /* ITypeLib2::GetDocumentation2
4523 * Retrieves the library's documentation string, the complete Help file name
4524 * and path, the localization context to use, and the context ID for the
4525 * library Help topic in the Help file.
4528 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4532 BSTR *pbstrHelpString,
4533 DWORD *pdwHelpStringContext,
4534 BSTR *pbstrHelpStringDll)
4536 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4540 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4542 /* the help string should be obtained from the helpstringdll,
4543 * using the _DLLGetDocumentation function, based on the supplied
4544 * lcid. Nice to do sometime...
4548 /* documentation for the typelib */
4550 *pbstrHelpString=SysAllocString(This->DocString);
4551 if(pdwHelpStringContext)
4552 *pdwHelpStringContext=This->dwHelpContext;
4553 if(pbstrHelpStringDll)
4554 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4560 /* for a typeinfo */
4561 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4563 if(SUCCEEDED(result))
4565 ITypeInfo2 * pTInfo2;
4566 result = ITypeInfo_QueryInterface(pTInfo,
4568 (LPVOID*) &pTInfo2);
4570 if(SUCCEEDED(result))
4572 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4576 pdwHelpStringContext,
4577 pbstrHelpStringDll);
4579 ITypeInfo2_Release(pTInfo2);
4582 ITypeInfo_Release(pTInfo);
4588 /* ITypeLib2::GetAllCustData
4590 * Gets all custom data items for the library.
4593 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4595 CUSTDATA *pCustData)
4597 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4598 TLBCustData *pCData;
4600 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4601 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4602 if(pCustData->prgCustData ){
4603 pCustData->cCustData=This->ctCustData;
4604 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4605 pCustData->prgCustData[i].guid=pCData->guid;
4606 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4609 ERR(" OUT OF MEMORY!\n");
4610 return E_OUTOFMEMORY;
4615 static const ITypeLib2Vtbl tlbvt = {
4616 ITypeLib2_fnQueryInterface,
4618 ITypeLib2_fnRelease,
4619 ITypeLib2_fnGetTypeInfoCount,
4620 ITypeLib2_fnGetTypeInfo,
4621 ITypeLib2_fnGetTypeInfoType,
4622 ITypeLib2_fnGetTypeInfoOfGuid,
4623 ITypeLib2_fnGetLibAttr,
4624 ITypeLib2_fnGetTypeComp,
4625 ITypeLib2_fnGetDocumentation,
4627 ITypeLib2_fnFindName,
4628 ITypeLib2_fnReleaseTLibAttr,
4630 ITypeLib2_fnGetCustData,
4631 ITypeLib2_fnGetLibStatistics,
4632 ITypeLib2_fnGetDocumentation2,
4633 ITypeLib2_fnGetAllCustData
4637 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4639 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4641 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4644 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4646 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4648 return ITypeLib2_AddRef((ITypeLib2 *)This);
4651 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4653 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4655 return ITypeLib2_Release((ITypeLib2 *)This);
4658 static HRESULT WINAPI ITypeLibComp_fnBind(
4663 ITypeInfo ** ppTInfo,
4664 DESCKIND * pDescKind,
4667 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4668 ITypeInfoImpl *pTypeInfo;
4670 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4672 *pDescKind = DESCKIND_NONE;
4673 pBindPtr->lptcomp = NULL;
4676 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4678 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4680 /* FIXME: check wFlags here? */
4681 /* FIXME: we should use a hash table to look this info up using lHash
4682 * instead of an O(n) search */
4683 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4684 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4686 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4688 *pDescKind = DESCKIND_TYPECOMP;
4689 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4690 ITypeComp_AddRef(pBindPtr->lptcomp);
4691 TRACE("module or enum: %s\n", debugstr_w(szName));
4696 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4697 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4699 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4702 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4703 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4705 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4710 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4711 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4713 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4715 ITypeInfo *subtypeinfo;
4717 DESCKIND subdesckind;
4719 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4720 &subtypeinfo, &subdesckind, &subbindptr);
4721 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4723 TYPEDESC tdesc_appobject =
4726 (TYPEDESC *)pTypeInfo->hreftype
4730 const VARDESC vardesc_appobject =
4733 NULL, /* lpstrSchema */
4748 VAR_STATIC /* varkind */
4751 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4753 /* cleanup things filled in by Bind call so we can put our
4754 * application object data in there instead */
4755 switch (subdesckind)
4757 case DESCKIND_FUNCDESC:
4758 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4760 case DESCKIND_VARDESC:
4761 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4766 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4768 if (pTypeInfo->hreftype == -1)
4769 FIXME("no hreftype for interface %p\n", pTypeInfo);
4771 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4775 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4776 *ppTInfo = (ITypeInfo *)pTypeInfo;
4777 ITypeInfo_AddRef(*ppTInfo);
4783 TRACE("name not found %s\n", debugstr_w(szName));
4787 static HRESULT WINAPI ITypeLibComp_fnBindType(
4791 ITypeInfo ** ppTInfo,
4792 ITypeComp ** ppTComp)
4794 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4798 static const ITypeCompVtbl tlbtcvt =
4801 ITypeLibComp_fnQueryInterface,
4802 ITypeLibComp_fnAddRef,
4803 ITypeLibComp_fnRelease,
4805 ITypeLibComp_fnBind,
4806 ITypeLibComp_fnBindType
4809 /*================== ITypeInfo(2) Methods ===================================*/
4810 static ITypeInfo2 * ITypeInfo_Constructor(void)
4812 ITypeInfoImpl * pTypeInfoImpl;
4814 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4817 pTypeInfoImpl->lpVtbl = &tinfvt;
4818 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4819 pTypeInfoImpl->ref=1;
4820 pTypeInfoImpl->hreftype = -1;
4821 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4822 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4824 TRACE("(%p)\n", pTypeInfoImpl);
4825 return (ITypeInfo2*) pTypeInfoImpl;
4828 /* ITypeInfo::QueryInterface
4830 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4835 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4837 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4840 if(IsEqualIID(riid, &IID_IUnknown) ||
4841 IsEqualIID(riid,&IID_ITypeInfo)||
4842 IsEqualIID(riid,&IID_ITypeInfo2))
4846 ITypeInfo_AddRef(iface);
4847 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4850 TRACE("-- Interface: E_NOINTERFACE\n");
4851 return E_NOINTERFACE;
4854 /* ITypeInfo::AddRef
4856 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4858 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4859 ULONG ref = InterlockedIncrement(&This->ref);
4861 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4863 TRACE("(%p)->ref is %u\n",This, ref);
4867 /* ITypeInfo::Release
4869 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4871 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4872 ULONG ref = InterlockedDecrement(&This->ref);
4874 TRACE("(%p)->(%u)\n",This, ref);
4877 /* We don't release ITypeLib when ref=0 because
4878 it means that function is called by ITypeLib2_Release */
4879 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4881 TLBFuncDesc *pFInfo, *pFInfoNext;
4882 TLBVarDesc *pVInfo, *pVInfoNext;
4883 TLBImplType *pImpl, *pImplNext;
4885 TRACE("destroying ITypeInfo(%p)\n",This);
4887 if (This->no_free_data)
4890 SysFreeString(This->Name);
4893 SysFreeString(This->DocString);
4894 This->DocString = NULL;
4896 SysFreeString(This->DllName);
4897 This->DllName = NULL;
4899 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4902 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4904 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4905 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4907 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4908 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4910 SysFreeString(pFInfo->pParamDesc[i].Name);
4912 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4913 TLB_Free(pFInfo->pParamDesc);
4914 TLB_FreeCustData(pFInfo->pCustData);
4915 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4916 SysFreeString(pFInfo->Entry);
4917 SysFreeString(pFInfo->HelpString);
4918 SysFreeString(pFInfo->Name);
4920 pFInfoNext = pFInfo->next;
4923 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4925 if (pVInfo->vardesc.varkind == VAR_CONST)
4927 VariantClear(pVInfo->vardesc.u.lpvarValue);
4928 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4930 TLB_FreeCustData(pVInfo->pCustData);
4931 SysFreeString(pVInfo->Name);
4932 pVInfoNext = pVInfo->next;
4935 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4937 TLB_FreeCustData(pImpl->pCustData);
4938 pImplNext = pImpl->next;
4941 TLB_FreeCustData(This->pCustData);
4946 ITypeInfo_Release((ITypeInfo*)This->next);
4949 HeapFree(GetProcessHeap(),0,This);
4955 /* ITypeInfo::GetTypeAttr
4957 * Retrieves a TYPEATTR structure that contains the attributes of the type
4961 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4962 LPTYPEATTR *ppTypeAttr)
4964 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4967 TRACE("(%p)\n",This);
4969 size = sizeof(**ppTypeAttr);
4970 if (This->TypeAttr.typekind == TKIND_ALIAS)
4971 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4973 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4975 return E_OUTOFMEMORY;
4977 **ppTypeAttr = This->TypeAttr;
4979 if (This->TypeAttr.typekind == TKIND_ALIAS)
4980 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4981 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
4983 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4984 /* This should include all the inherited funcs */
4985 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
4986 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
4987 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4992 /* ITypeInfo::GetTypeComp
4994 * Retrieves the ITypeComp interface for the type description, which enables a
4995 * client compiler to bind to the type description's members.
4998 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4999 ITypeComp * *ppTComp)
5001 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5003 TRACE("(%p)->(%p)\n", This, ppTComp);
5005 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5006 ITypeComp_AddRef(*ppTComp);
5010 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5012 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5013 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5014 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5018 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5021 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5022 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5024 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5025 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5026 *buffer += sizeof(PARAMDESCEX);
5027 *pparamdescex_dest = *pparamdescex_src;
5028 VariantInit(&pparamdescex_dest->varDefaultValue);
5029 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5030 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5033 dest->u.paramdesc.pparamdescex = NULL;
5037 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5039 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5040 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5043 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5047 SIZE_T size = sizeof(*src);
5051 size += sizeof(*src->lprgscode) * src->cScodes;
5052 size += TLB_SizeElemDesc(&src->elemdescFunc);
5053 for (i = 0; i < src->cParams; i++)
5055 size += sizeof(ELEMDESC);
5056 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5059 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5060 if (!dest) return E_OUTOFMEMORY;
5063 if (dispinterface) /* overwrite funckind */
5064 dest->funckind = FUNC_DISPATCH;
5065 buffer = (char *)(dest + 1);
5067 dest->lprgscode = (SCODE *)buffer;
5068 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5069 buffer += sizeof(*src->lprgscode) * src->cScodes;
5071 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5074 SysFreeString((BSTR)dest);
5078 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5079 buffer += sizeof(ELEMDESC) * src->cParams;
5080 for (i = 0; i < src->cParams; i++)
5082 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5088 /* undo the above actions */
5089 for (i = i - 1; i >= 0; i--)
5090 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5091 TLB_FreeElemDesc(&dest->elemdescFunc);
5092 SysFreeString((BSTR)dest);
5096 /* special treatment for dispinterfaces: this makes functions appear
5097 * to return their [retval] value when it is really returning an
5099 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5101 if (dest->cParams &&
5102 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5104 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5105 if (elemdesc->tdesc.vt != VT_PTR)
5107 ERR("elemdesc should have started with VT_PTR instead of:\n");
5109 dump_ELEMDESC(elemdesc);
5110 return E_UNEXPECTED;
5113 /* copy last parameter to the return value. we are using a flat
5114 * buffer so there is no danger of leaking memory in
5116 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5118 /* remove the last parameter */
5122 /* otherwise this function is made to appear to have no return
5124 dest->elemdescFunc.tdesc.vt = VT_VOID;
5132 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5134 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5135 const TLBFuncDesc *pFDesc;
5138 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5143 *ppFuncDesc = &pFDesc->funcdesc;
5147 return TYPE_E_ELEMENTNOTFOUND;
5150 /* internal function to make the inherited interfaces' methods appear
5151 * part of the interface */
5152 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5153 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5155 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5157 UINT implemented_funcs = 0;
5162 *hrefoffset = DISPATCH_HREF_OFFSET;
5164 if(This->impltypelist)
5166 ITypeInfo *pSubTypeInfo;
5169 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5173 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5176 &sub_funcs, hrefoffset);
5177 implemented_funcs += sub_funcs;
5178 ITypeInfo_Release(pSubTypeInfo);
5181 *hrefoffset += DISPATCH_HREF_OFFSET;
5185 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5189 if (index < implemented_funcs)
5190 return E_INVALIDARG;
5191 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5195 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5197 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5200 switch (pTypeDesc->vt)
5202 case VT_USERDEFINED:
5203 pTypeDesc->u.hreftype += hrefoffset;
5207 pTypeDesc = pTypeDesc->u.lptdesc;
5210 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5218 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5221 for (i = 0; i < pFuncDesc->cParams; i++)
5222 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5223 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5226 /* ITypeInfo::GetFuncDesc
5228 * Retrieves the FUNCDESC structure that contains information about a
5229 * specified function.
5232 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5233 LPFUNCDESC *ppFuncDesc)
5235 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5236 const FUNCDESC *internal_funcdesc;
5238 UINT hrefoffset = 0;
5240 TRACE("(%p) index %d\n", This, index);
5242 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5243 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5244 &internal_funcdesc, NULL,
5247 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5248 &internal_funcdesc);
5251 WARN("description for function %d not found\n", index);
5255 hr = TLB_AllocAndInitFuncDesc(
5258 This->TypeAttr.typekind == TKIND_DISPATCH);
5260 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5261 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5263 TRACE("-- 0x%08x\n", hr);
5267 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5271 SIZE_T size = sizeof(*src);
5274 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5275 if (src->varkind == VAR_CONST)
5276 size += sizeof(VARIANT);
5277 size += TLB_SizeElemDesc(&src->elemdescVar);
5279 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5280 if (!dest) return E_OUTOFMEMORY;
5283 buffer = (char *)(dest + 1);
5284 if (src->lpstrSchema)
5287 dest->lpstrSchema = (LPOLESTR)buffer;
5288 len = strlenW(src->lpstrSchema);
5289 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5290 buffer += (len + 1) * sizeof(WCHAR);
5293 if (src->varkind == VAR_CONST)
5297 dest->u.lpvarValue = (VARIANT *)buffer;
5298 *dest->u.lpvarValue = *src->u.lpvarValue;
5299 buffer += sizeof(VARIANT);
5300 VariantInit(dest->u.lpvarValue);
5301 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5304 SysFreeString((BSTR)dest_ptr);
5308 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5311 if (src->varkind == VAR_CONST)
5312 VariantClear(dest->u.lpvarValue);
5313 SysFreeString((BSTR)dest);
5320 /* ITypeInfo::GetVarDesc
5322 * Retrieves a VARDESC structure that describes the specified variable.
5325 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5326 LPVARDESC *ppVarDesc)
5328 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5330 const TLBVarDesc *pVDesc;
5332 TRACE("(%p) index %d\n", This, index);
5334 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5338 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5340 return E_INVALIDARG;
5343 /* ITypeInfo_GetNames
5345 * Retrieves the variable with the specified member ID (or the name of the
5346 * property or method and its parameters) that correspond to the specified
5349 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5350 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5352 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5353 const TLBFuncDesc *pFDesc;
5354 const TLBVarDesc *pVDesc;
5356 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5357 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5360 /* function found, now return function and parameter names */
5361 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5364 *rgBstrNames=SysAllocString(pFDesc->Name);
5366 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5372 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5375 *rgBstrNames=SysAllocString(pVDesc->Name);
5380 if(This->impltypelist &&
5381 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5382 /* recursive search */
5385 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5387 if(SUCCEEDED(result))
5389 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5390 ITypeInfo_Release(pTInfo);
5393 WARN("Could not search inherited interface!\n");
5397 WARN("no names found\n");
5400 return TYPE_E_ELEMENTNOTFOUND;
5407 /* ITypeInfo::GetRefTypeOfImplType
5409 * If a type description describes a COM class, it retrieves the type
5410 * description of the implemented interface types. For an interface,
5411 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5415 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5420 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5423 const TLBImplType *pImpl = This->impltypelist;
5425 TRACE("(%p) index %d\n", This, index);
5426 if (TRACE_ON(ole)) dump_TypeInfo(This);
5430 /* only valid on dual interfaces;
5431 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5433 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5435 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5436 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5442 hr = TYPE_E_ELEMENTNOTFOUND;
5445 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5447 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5448 *pRefType = This->pTypeLib->dispatch_href;
5452 /* get element n from linked list */
5453 for(i=0; pImpl && i<index; i++)
5455 pImpl = pImpl->next;
5459 *pRefType = pImpl->hRef;
5461 hr = TYPE_E_ELEMENTNOTFOUND;
5467 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5469 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5475 /* ITypeInfo::GetImplTypeFlags
5477 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5478 * or base interface in a type description.
5480 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5481 UINT index, INT *pImplTypeFlags)
5483 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5487 TRACE("(%p) index %d\n", This, index);
5488 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5489 i++, pImpl=pImpl->next)
5491 if(i==index && pImpl){
5492 *pImplTypeFlags=pImpl->implflags;
5496 return TYPE_E_ELEMENTNOTFOUND;
5500 * Maps between member names and member IDs, and parameter names and
5503 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5504 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5506 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5507 const TLBFuncDesc *pFDesc;
5508 const TLBVarDesc *pVDesc;
5512 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5515 /* init out parameters in case of failure */
5516 for (i = 0; i < cNames; i++)
5517 pMemId[i] = MEMBERID_NIL;
5519 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5521 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5522 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5523 for(i=1; i < cNames; i++){
5524 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5525 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5527 if( j<pFDesc->funcdesc.cParams)
5530 ret=DISP_E_UNKNOWNNAME;
5532 TRACE("-- 0x%08x\n", ret);
5536 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5537 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5538 if(cNames) *pMemId=pVDesc->vardesc.memid;
5542 /* not found, see if it can be found in an inherited interface */
5543 if(This->impltypelist) {
5544 /* recursive search */
5546 ret=ITypeInfo_GetRefTypeInfo(iface,
5547 This->impltypelist->hRef, &pTInfo);
5549 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5550 ITypeInfo_Release(pTInfo);
5553 WARN("Could not search inherited interface!\n");
5555 WARN("no names found\n");
5556 return DISP_E_UNKNOWNNAME;
5559 /* ITypeInfo::Invoke
5561 * Invokes a method, or accesses a property of an object, that implements the
5562 * interface described by the type description.
5565 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5568 if (TRACE_ON(ole)) {
5570 TRACE("Calling %p(",func);
5571 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5583 res = func(args[0]);
5586 res = func(args[0],args[1]);
5589 res = func(args[0],args[1],args[2]);
5592 res = func(args[0],args[1],args[2],args[3]);
5595 res = func(args[0],args[1],args[2],args[3],args[4]);
5598 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5601 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5604 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5607 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5610 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5613 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5616 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
5619 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
5622 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
5625 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5628 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5631 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5634 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5637 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5640 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5643 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5646 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5649 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5652 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23]);
5655 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24]);
5658 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25]);
5661 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26]);
5664 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27]);
5667 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28]);
5670 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5673 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5679 FIXME("unsupported calling convention %d\n",callconv);
5683 TRACE("returns %08x\n",res);
5687 /* The size of the argument on the stack in DWORD units (in all x86 call
5688 * convetions the arguments on the stack are DWORD-aligned)
5690 static int _dispargsize(VARTYPE vt)
5695 return 8/sizeof(DWORD);
5697 return sizeof(double)/sizeof(DWORD);
5699 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5701 return sizeof(CY)/sizeof(DWORD);
5703 return sizeof(DATE)/sizeof(DWORD);
5705 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5707 FIXME("VT_RECORD not implemented\n");
5714 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5717 ITypeInfo *tinfo2 = NULL;
5718 TYPEATTR *tattr = NULL;
5720 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5723 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5725 tdesc->u.hreftype, hr);
5728 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5731 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5732 ITypeInfo_Release(tinfo2);
5736 switch (tattr->typekind)
5743 tdesc = &tattr->tdescAlias;
5744 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5747 case TKIND_INTERFACE:
5748 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5754 case TKIND_DISPATCH:
5763 FIXME("TKIND_RECORD unhandled.\n");
5768 FIXME("TKIND_UNION unhandled.\n");
5773 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5777 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5778 ITypeInfo_Release(tinfo2);
5782 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5786 /* enforce only one level of pointer indirection */
5787 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5789 tdesc = tdesc->u.lptdesc;
5791 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5792 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5793 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5794 if ((tdesc->vt == VT_USERDEFINED) ||
5795 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5797 VARTYPE vt_userdefined = 0;
5798 const TYPEDESC *tdesc_userdefined = tdesc;
5799 if (tdesc->vt == VT_PTR)
5801 vt_userdefined = VT_BYREF;
5802 tdesc_userdefined = tdesc->u.lptdesc;
5804 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5806 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5807 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5809 *vt |= vt_userdefined;
5821 case VT_USERDEFINED:
5822 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5829 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5830 hr = DISP_E_BADVARTYPE;
5834 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5843 /***********************************************************************
5844 * DispCallFunc (OLEAUT32.@)
5846 * Invokes a function of the specified calling convention, passing the
5847 * specified arguments and returns the result.
5850 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5851 * oVft [I] The offset in the vtable. See notes.
5852 * cc [I] Calling convention of the function to call.
5853 * vtReturn [I] The return type of the function.
5854 * cActuals [I] Number of parameters.
5855 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5856 * prgpvarg [I] The arguments to pass.
5857 * pvargResult [O] The return value of the function. Can be NULL.
5861 * Failure: HRESULT code.
5864 * The HRESULT return value of this function is not affected by the return
5865 * value of the user supplied function, which is returned in pvargResult.
5867 * If pvInstance is NULL then a non-object function is to be called and oVft
5868 * is the address of the function to call.
5870 * The cc parameter can be one of the following values:
5883 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5884 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5886 int argsize, argspos;
5891 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5892 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5893 pvargResult, V_VT(pvargResult));
5897 argsize++; /* for This pointer */
5899 for (i=0;i<cActuals;i++)
5901 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5902 dump_Variant(prgpvarg[i]);
5903 argsize += _dispargsize(prgvt[i]);
5905 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5910 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5914 for (i=0;i<cActuals;i++)
5916 VARIANT *arg = prgpvarg[i];
5917 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5918 if (prgvt[i] == VT_VARIANT)
5919 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5921 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5922 argspos += _dispargsize(prgvt[i]);
5927 FARPROC *vtable = *(FARPROC**)pvInstance;
5928 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5931 /* if we aren't invoking an object then the function pointer is stored
5933 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5935 if (pvargResult && (vtReturn != VT_EMPTY))
5937 TRACE("Method returned 0x%08x\n",hres);
5938 V_VT(pvargResult) = vtReturn;
5939 V_UI4(pvargResult) = hres;
5942 HeapFree(GetProcessHeap(),0,args);
5946 #define INVBUF_ELEMENT_SIZE \
5947 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5948 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5949 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5950 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5951 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5952 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5953 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5954 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5956 static HRESULT WINAPI ITypeInfo_fnInvoke(
5961 DISPPARAMS *pDispParams,
5962 VARIANT *pVarResult,
5963 EXCEPINFO *pExcepInfo,
5966 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5968 unsigned int var_index;
5971 const TLBFuncDesc *pFuncInfo;
5973 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5974 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5979 ERR("NULL pDispParams not allowed\n");
5980 return E_INVALIDARG;
5983 dump_DispParms(pDispParams);
5985 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5987 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5988 pDispParams->cNamedArgs, pDispParams->cArgs);
5989 return E_INVALIDARG;
5992 /* we do this instead of using GetFuncDesc since it will return a fake
5993 * FUNCDESC for dispinterfaces and we want the real function description */
5994 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5995 if ((memid == pFuncInfo->funcdesc.memid) &&
5996 (wFlags & pFuncInfo->funcdesc.invkind))
6000 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6004 TRACE("invoking:\n");
6005 dump_TLBFuncDescOne(pFuncInfo);
6008 switch (func_desc->funckind) {
6009 case FUNC_PUREVIRTUAL:
6010 case FUNC_VIRTUAL: {
6011 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6013 VARIANT retval; /* pointer for storing byref retvals in */
6014 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6015 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6016 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6017 UINT cNamedArgs = pDispParams->cNamedArgs;
6018 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6022 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6024 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6026 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6027 hres = DISP_E_PARAMNOTFOUND;
6030 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6032 rgdispidNamedArgs++;
6035 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6037 ERR("functions with the vararg attribute do not support named arguments\n");
6038 hres = DISP_E_NONAMEDARGS;
6042 for (i = 0; i < func_desc->cParams; i++)
6044 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6045 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6050 TRACE("changing args\n");
6051 for (i = 0; i < func_desc->cParams; i++)
6053 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6054 VARIANTARG *src_arg;
6060 for (j = 0; j < cNamedArgs; j++)
6061 if (rgdispidNamedArgs[j] == i)
6063 src_arg = &pDispParams->rgvarg[j];
6068 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
6070 if (wParamFlags & PARAMFLAG_FRETVAL)
6072 /* under most conditions the caller is not allowed to
6073 * pass in a dispparam arg in the index of what would be
6074 * the retval parameter. however, there is an exception
6075 * where the extra parameter is used in an extra
6076 * IDispatch::Invoke below */
6077 if ((i < pDispParams->cArgs) &&
6078 ((func_desc->cParams != 1) || !pVarResult ||
6079 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6081 hres = DISP_E_BADPARAMCOUNT;
6085 /* note: this check is placed so that if the caller passes
6086 * in a VARIANTARG for the retval we just ignore it, like
6088 if (i == func_desc->cParams - 1)
6091 arg = prgpvarg[i] = &rgvarg[i];
6092 memset(arg, 0, sizeof(*arg));
6093 V_VT(arg) = rgvt[i];
6094 memset(&retval, 0, sizeof(retval));
6095 V_BYREF(arg) = &retval;
6099 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6100 hres = E_UNEXPECTED;
6106 dump_Variant(src_arg);
6108 if (rgvt[i] == VT_VARIANT)
6109 hres = VariantCopy(&rgvarg[i], src_arg);
6110 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6112 if (rgvt[i] == V_VT(src_arg))
6113 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6116 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6117 hres = VariantCopy(&missing_arg[i], src_arg);
6118 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6120 V_VT(&rgvarg[i]) = rgvt[i];
6122 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6125 SAFEARRAYBOUND bound;
6129 bound.cElements = pDispParams->cArgs-i;
6130 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6132 ERR("SafeArrayCreate failed\n");
6135 hres = SafeArrayAccessData(a, (LPVOID)&v);
6138 ERR("SafeArrayAccessData failed with %x\n", hres);
6141 for (j = 0; j < bound.cElements; j++)
6142 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6143 hres = SafeArrayUnaccessData(a);
6146 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6149 V_ARRAY(&rgvarg[i]) = a;
6150 V_VT(&rgvarg[i]) = rgvt[i];
6152 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6154 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6155 V_VT(&missing_arg[i]) = V_VT(src_arg);
6156 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6157 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6158 V_VT(&rgvarg[i]) = rgvt[i];
6160 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6162 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6163 V_VT(&rgvarg[i]) = rgvt[i];
6167 /* FIXME: this doesn't work for VT_BYREF arguments if
6168 * they are not the same type as in the paramdesc */
6169 V_VT(&rgvarg[i]) = V_VT(src_arg);
6170 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6171 V_VT(&rgvarg[i]) = rgvt[i];
6176 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6177 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6178 debugstr_VT(src_arg), debugstr_VF(src_arg));
6181 prgpvarg[i] = &rgvarg[i];
6183 else if (wParamFlags & PARAMFLAG_FOPT)
6186 arg = prgpvarg[i] = &rgvarg[i];
6187 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6189 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6195 VARIANTARG *missing_arg;
6196 /* if the function wants a pointer to a variant then
6197 * set that up, otherwise just pass the VT_ERROR in
6198 * the argument by value */
6199 if (rgvt[i] & VT_BYREF)
6201 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6202 V_VT(arg) = VT_VARIANT | VT_BYREF;
6203 V_VARIANTREF(arg) = missing_arg;
6207 V_VT(missing_arg) = VT_ERROR;
6208 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6213 hres = DISP_E_BADPARAMCOUNT;
6217 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6219 /* VT_VOID is a special case for return types, so it is not
6220 * handled in the general function */
6221 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6222 V_VT(&varresult) = VT_EMPTY;
6225 V_VT(&varresult) = 0;
6226 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6227 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6230 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6231 V_VT(&varresult), func_desc->cParams, rgvt,
6232 prgpvarg, &varresult);
6234 for (i = 0; i < func_desc->cParams; i++)
6236 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6237 if (wParamFlags & PARAMFLAG_FRETVAL)
6241 TRACE("[retval] value: ");
6242 dump_Variant(prgpvarg[i]);
6247 VariantInit(pVarResult);
6248 /* deref return value */
6249 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6252 /* free data stored in varresult. Note that
6253 * VariantClear doesn't do what we want because we are
6254 * working with byref types. */
6255 /* FIXME: clear safearrays, bstrs, records and
6256 * variants here too */
6257 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6258 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6260 if(*V_UNKNOWNREF(prgpvarg[i]))
6261 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6265 else if (i < pDispParams->cArgs)
6267 if (wParamFlags & PARAMFLAG_FOUT)
6269 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6271 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6272 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6276 ERR("failed to convert param %d to vt %d\n", i,
6277 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6281 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6282 func_desc->cParamsOpt < 0 &&
6283 i == func_desc->cParams-1)
6285 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6288 hres = SafeArrayGetUBound(a, 1, &ubound);
6291 ERR("SafeArrayGetUBound failed with %x\n", hres);
6294 hres = SafeArrayAccessData(a, (LPVOID)&v);
6297 ERR("SafeArrayAccessData failed with %x\n", hres);
6300 for (j = 0; j <= ubound; j++)
6301 VariantClear(&v[j]);
6302 hres = SafeArrayUnaccessData(a);
6305 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6309 VariantClear(&rgvarg[i]);
6311 else if (wParamFlags & PARAMFLAG_FOPT)
6313 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6314 VariantClear(&rgvarg[i]);
6318 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6320 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6321 hres = DISP_E_EXCEPTION;
6324 IErrorInfo *pErrorInfo;
6325 pExcepInfo->scode = V_ERROR(&varresult);
6326 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6328 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6329 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6330 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6331 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6333 IErrorInfo_Release(pErrorInfo);
6337 if (V_VT(&varresult) != VT_ERROR)
6339 TRACE("varresult value: ");
6340 dump_Variant(&varresult);
6344 VariantClear(pVarResult);
6345 *pVarResult = varresult;
6348 VariantClear(&varresult);
6351 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6352 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6353 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6354 (pDispParams->cArgs != 0))
6356 if (V_VT(pVarResult) == VT_DISPATCH)
6358 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6359 /* Note: not VariantClear; we still need the dispatch
6360 * pointer to be valid */
6361 VariantInit(pVarResult);
6362 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6363 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6364 pDispParams, pVarResult, pExcepInfo, pArgErr);
6365 IDispatch_Release(pDispatch);
6369 VariantClear(pVarResult);
6370 hres = DISP_E_NOTACOLLECTION;
6375 HeapFree(GetProcessHeap(), 0, buffer);
6378 case FUNC_DISPATCH: {
6381 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6382 if (SUCCEEDED(hres)) {
6383 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6384 hres = IDispatch_Invoke(
6385 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6386 pVarResult,pExcepInfo,pArgErr
6389 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6390 IDispatch_Release(disp);
6392 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6396 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6401 TRACE("-- 0x%08x\n", hres);
6404 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6407 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6408 if(FAILED(hres)) return hres;
6410 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6411 dump_VARDESC(var_desc);
6412 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6416 /* not found, look for it in inherited interfaces */
6417 ITypeInfo2_GetTypeKind(iface, &type_kind);
6418 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6419 if(This->impltypelist) {
6420 /* recursive search */
6422 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6423 if(SUCCEEDED(hres)){
6424 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6425 ITypeInfo_Release(pTInfo);
6428 WARN("Could not search inherited interface!\n");
6431 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6432 return DISP_E_MEMBERNOTFOUND;
6435 /* ITypeInfo::GetDocumentation
6437 * Retrieves the documentation string, the complete Help file name and path,
6438 * and the context ID for the Help topic for a specified type description.
6440 * (Can be tested by the Visual Basic Editor in Word for instance.)
6442 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6443 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6444 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6446 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6447 const TLBFuncDesc *pFDesc;
6448 const TLBVarDesc *pVDesc;
6449 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6450 " HelpContext(%p) HelpFile(%p)\n",
6451 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6452 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6454 *pBstrName=SysAllocString(This->Name);
6456 *pBstrDocString=SysAllocString(This->DocString);
6458 *pdwHelpContext=This->dwHelpContext;
6460 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6462 }else {/* for a member */
6463 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6464 if(pFDesc->funcdesc.memid==memid){
6466 *pBstrName = SysAllocString(pFDesc->Name);
6468 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6470 *pdwHelpContext=pFDesc->helpcontext;
6473 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6474 if(pVDesc->vardesc.memid==memid){
6476 *pBstrName = SysAllocString(pVDesc->Name);
6478 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6480 *pdwHelpContext=pVDesc->HelpContext;
6485 if(This->impltypelist &&
6486 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6487 /* recursive search */
6490 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6492 if(SUCCEEDED(result)) {
6493 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6494 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6495 ITypeInfo_Release(pTInfo);
6498 WARN("Could not search inherited interface!\n");
6501 WARN("member %d not found\n", memid);
6502 return TYPE_E_ELEMENTNOTFOUND;
6505 /* ITypeInfo::GetDllEntry
6507 * Retrieves a description or specification of an entry point for a function
6510 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6511 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6514 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6515 const TLBFuncDesc *pFDesc;
6517 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6519 if (pBstrDllName) *pBstrDllName = NULL;
6520 if (pBstrName) *pBstrName = NULL;
6521 if (pwOrdinal) *pwOrdinal = 0;
6523 if (This->TypeAttr.typekind != TKIND_MODULE)
6524 return TYPE_E_BADMODULEKIND;
6526 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6527 if(pFDesc->funcdesc.memid==memid){
6528 dump_TypeInfo(This);
6530 dump_TLBFuncDescOne(pFDesc);
6533 *pBstrDllName = SysAllocString(This->DllName);
6535 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6537 *pBstrName = SysAllocString(pFDesc->Entry);
6545 *pwOrdinal = (DWORD)pFDesc->Entry;
6548 return TYPE_E_ELEMENTNOTFOUND;
6551 /* internal function to make the inherited interfaces' methods appear
6552 * part of the interface */
6553 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6554 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6556 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6559 TRACE("%p, 0x%x\n", iface, *hRefType);
6561 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6563 ITypeInfo *pSubTypeInfo;
6565 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6569 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6571 ITypeInfo_Release(pSubTypeInfo);
6575 *hRefType -= DISPATCH_HREF_OFFSET;
6577 if (!(*hRefType & DISPATCH_HREF_MASK))
6578 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6583 /* ITypeInfo::GetRefTypeInfo
6585 * If a type description references other type descriptions, it retrieves
6586 * the referenced type descriptions.
6588 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6591 ITypeInfo **ppTInfo)
6593 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6594 HRESULT result = E_FAIL;
6596 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6598 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6599 ITypeInfo_AddRef(*ppTInfo);
6602 else if (hRefType == -1 &&
6603 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6604 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6606 /* when we meet a DUAL dispinterface, we must create the interface
6609 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6612 /* the interface version contains the same information as the dispinterface
6613 * copy the contents of the structs.
6615 *pTypeInfoImpl = *This;
6616 pTypeInfoImpl->ref = 0;
6618 /* change the type to interface */
6619 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6621 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6623 /* we use data structures from This, so we need to keep a reference
6624 * to it to stop it being destroyed and signal to the new instance to
6625 * not free its data structures when it is destroyed */
6626 pTypeInfoImpl->no_free_data = TRUE;
6627 pTypeInfoImpl->next = This;
6628 ITypeInfo_AddRef((ITypeInfo*) This);
6630 ITypeInfo_AddRef(*ppTInfo);
6634 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6635 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6636 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6638 HREFTYPE href_dispatch = hRefType;
6639 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6641 TLBRefType *ref_type;
6642 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6644 if(ref_type->reference == hRefType)
6647 if(&ref_type->entry == &This->pTypeLib->ref_list)
6649 FIXME("Can't find pRefType for ref %x\n", hRefType);
6652 if(hRefType != -1) {
6653 ITypeLib *pTLib = NULL;
6655 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6657 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6659 if(ref_type->pImpTLInfo->pImpTypeLib) {
6660 TRACE("typeinfo in imported typelib that is already loaded\n");
6661 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6662 ITypeLib2_AddRef(pTLib);
6665 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6666 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6667 ref_type->pImpTLInfo->wVersionMajor,
6668 ref_type->pImpTLInfo->wVersionMinor,
6669 ref_type->pImpTLInfo->lcid,
6672 if(FAILED(result)) {
6673 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6674 result=LoadTypeLib(libnam, &pTLib);
6675 SysFreeString(libnam);
6677 if(SUCCEEDED(result)) {
6678 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6679 ITypeLib2_AddRef(pTLib);
6683 if(SUCCEEDED(result)) {
6684 if(ref_type->index == TLB_REF_USE_GUID)
6685 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6689 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6693 ITypeLib2_Release(pTLib);
6698 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6699 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6703 /* ITypeInfo::AddressOfMember
6705 * Retrieves the addresses of static functions or variables, such as those
6708 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6709 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6711 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6717 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6719 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6723 module = LoadLibraryW(dll);
6726 ERR("couldn't load %s\n", debugstr_w(dll));
6728 SysFreeString(entry);
6729 return STG_E_FILENOTFOUND;
6731 /* FIXME: store library somewhere where we can free it */
6736 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6737 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6738 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6740 *ppv = GetProcAddress(module, entryA);
6742 ERR("function not found %s\n", debugstr_a(entryA));
6744 HeapFree(GetProcessHeap(), 0, entryA);
6748 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6750 ERR("function not found %d\n", ordinal);
6754 SysFreeString(entry);
6757 return TYPE_E_DLLFUNCTIONNOTFOUND;
6762 /* ITypeInfo::CreateInstance
6764 * Creates a new instance of a type that describes a component object class
6767 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6768 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6770 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6774 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6780 WARN("Not able to aggregate\n");
6781 return CLASS_E_NOAGGREGATION;
6784 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6785 if(FAILED(hr)) return hr;
6787 if(pTA->typekind != TKIND_COCLASS)
6789 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6795 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6798 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6799 TRACE("GetActiveObject rets %08x\n", hr);
6802 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6803 IUnknown_Release(pUnk);
6808 hr = CoCreateInstance(&pTA->guid, NULL,
6809 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6813 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6817 /* ITypeInfo::GetMops
6819 * Retrieves marshalling information.
6821 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6824 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6825 FIXME("(%p) stub!\n", This);
6829 /* ITypeInfo::GetContainingTypeLib
6831 * Retrieves the containing type library and the index of the type description
6832 * within that type library.
6834 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6835 ITypeLib * *ppTLib, UINT *pIndex)
6837 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6839 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6841 *pIndex=This->index;
6842 TRACE("returning pIndex=%d\n", *pIndex);
6846 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6847 ITypeLib2_AddRef(*ppTLib);
6848 TRACE("returning ppTLib=%p\n", *ppTLib);
6854 /* ITypeInfo::ReleaseTypeAttr
6856 * Releases a TYPEATTR previously returned by GetTypeAttr.
6859 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6860 TYPEATTR* pTypeAttr)
6862 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6863 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6864 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6867 /* ITypeInfo::ReleaseFuncDesc
6869 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6871 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6873 FUNCDESC *pFuncDesc)
6875 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6878 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6880 for (i = 0; i < pFuncDesc->cParams; i++)
6881 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6882 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6884 SysFreeString((BSTR)pFuncDesc);
6887 /* ITypeInfo::ReleaseVarDesc
6889 * Releases a VARDESC previously returned by GetVarDesc.
6891 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6894 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6895 TRACE("(%p)->(%p)\n", This, pVarDesc);
6897 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6898 if (pVarDesc->varkind == VAR_CONST)
6899 VariantClear(pVarDesc->u.lpvarValue);
6900 SysFreeString((BSTR)pVarDesc);
6903 /* ITypeInfo2::GetTypeKind
6905 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6908 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6909 TYPEKIND *pTypeKind)
6911 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6912 *pTypeKind=This->TypeAttr.typekind;
6913 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6917 /* ITypeInfo2::GetTypeFlags
6919 * Returns the type flags without any allocations. This returns a DWORD type
6920 * flag, which expands the type flags without growing the TYPEATTR (type
6924 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6926 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6927 *pTypeFlags=This->TypeAttr.wTypeFlags;
6928 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6932 /* ITypeInfo2::GetFuncIndexOfMemId
6933 * Binds to a specific member based on a known DISPID, where the member name
6934 * is not known (for example, when binding to a default member).
6937 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6938 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6940 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6941 const TLBFuncDesc *pFuncInfo;
6945 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6946 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6952 result = TYPE_E_ELEMENTNOTFOUND;
6954 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6955 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6959 /* TypeInfo2::GetVarIndexOfMemId
6961 * Binds to a specific member based on a known DISPID, where the member name
6962 * is not known (for example, when binding to a default member).
6965 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6966 MEMBERID memid, UINT *pVarIndex)
6968 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6969 TLBVarDesc *pVarInfo;
6972 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6973 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6979 result = TYPE_E_ELEMENTNOTFOUND;
6981 TRACE("(%p) memid 0x%08x -> %s\n", This,
6982 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6986 /* ITypeInfo2::GetCustData
6988 * Gets the custom data
6990 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6995 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6996 TLBCustData *pCData;
6998 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6999 if( IsEqualIID(guid, &pCData->guid)) break;
7001 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7005 VariantInit( pVarVal);
7006 VariantCopy( pVarVal, &pCData->data);
7009 return E_INVALIDARG; /* FIXME: correct? */
7012 /* ITypeInfo2::GetFuncCustData
7014 * Gets the custom data
7016 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7022 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7023 TLBCustData *pCData=NULL;
7024 TLBFuncDesc * pFDesc;
7026 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7027 pFDesc=pFDesc->next);
7030 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7031 if( IsEqualIID(guid, &pCData->guid)) break;
7033 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7036 VariantInit( pVarVal);
7037 VariantCopy( pVarVal, &pCData->data);
7040 return E_INVALIDARG; /* FIXME: correct? */
7043 /* ITypeInfo2::GetParamCustData
7045 * Gets the custom data
7047 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7054 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7055 TLBCustData *pCData=NULL;
7056 TLBFuncDesc * pFDesc;
7059 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7061 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7062 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7063 pCData = pCData->next)
7064 if( IsEqualIID(guid, &pCData->guid)) break;
7066 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7070 VariantInit( pVarVal);
7071 VariantCopy( pVarVal, &pCData->data);
7074 return E_INVALIDARG; /* FIXME: correct? */
7077 /* ITypeInfo2::GetVarCustData
7079 * Gets the custom data
7081 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7087 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7088 TLBCustData *pCData=NULL;
7089 TLBVarDesc * pVDesc;
7092 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7096 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7098 if( IsEqualIID(guid, &pCData->guid)) break;
7102 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7106 VariantInit( pVarVal);
7107 VariantCopy( pVarVal, &pCData->data);
7110 return E_INVALIDARG; /* FIXME: correct? */
7113 /* ITypeInfo2::GetImplCustData
7115 * Gets the custom data
7117 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7123 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7124 TLBCustData *pCData=NULL;
7125 TLBImplType * pRDesc;
7128 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7132 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7134 if( IsEqualIID(guid, &pCData->guid)) break;
7138 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7142 VariantInit( pVarVal);
7143 VariantCopy( pVarVal, &pCData->data);
7146 return E_INVALIDARG; /* FIXME: correct? */
7149 /* ITypeInfo2::GetDocumentation2
7151 * Retrieves the documentation string, the complete Help file name and path,
7152 * the localization context to use, and the context ID for the library Help
7153 * topic in the Help file.
7156 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7160 BSTR *pbstrHelpString,
7161 DWORD *pdwHelpStringContext,
7162 BSTR *pbstrHelpStringDll)
7164 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7165 const TLBFuncDesc *pFDesc;
7166 const TLBVarDesc *pVDesc;
7167 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7168 "HelpStringContext(%p) HelpStringDll(%p)\n",
7169 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7170 pbstrHelpStringDll );
7171 /* the help string should be obtained from the helpstringdll,
7172 * using the _DLLGetDocumentation function, based on the supplied
7173 * lcid. Nice to do sometime...
7175 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7177 *pbstrHelpString=SysAllocString(This->Name);
7178 if(pdwHelpStringContext)
7179 *pdwHelpStringContext=This->dwHelpStringContext;
7180 if(pbstrHelpStringDll)
7181 *pbstrHelpStringDll=
7182 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7184 }else {/* for a member */
7185 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7186 if(pFDesc->funcdesc.memid==memid){
7188 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7189 if(pdwHelpStringContext)
7190 *pdwHelpStringContext=pFDesc->HelpStringContext;
7191 if(pbstrHelpStringDll)
7192 *pbstrHelpStringDll=
7193 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7196 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7197 if(pVDesc->vardesc.memid==memid){
7199 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7200 if(pdwHelpStringContext)
7201 *pdwHelpStringContext=pVDesc->HelpStringContext;
7202 if(pbstrHelpStringDll)
7203 *pbstrHelpStringDll=
7204 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7208 return TYPE_E_ELEMENTNOTFOUND;
7211 /* ITypeInfo2::GetAllCustData
7213 * Gets all custom data items for the Type info.
7216 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7218 CUSTDATA *pCustData)
7220 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7221 TLBCustData *pCData;
7224 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7226 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7227 if(pCustData->prgCustData ){
7228 pCustData->cCustData=This->ctCustData;
7229 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7230 pCustData->prgCustData[i].guid=pCData->guid;
7231 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7234 ERR(" OUT OF MEMORY!\n");
7235 return E_OUTOFMEMORY;
7240 /* ITypeInfo2::GetAllFuncCustData
7242 * Gets all custom data items for the specified Function
7245 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7248 CUSTDATA *pCustData)
7250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7251 TLBCustData *pCData;
7252 TLBFuncDesc * pFDesc;
7254 TRACE("(%p) index %d\n", This, index);
7255 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7256 pFDesc=pFDesc->next)
7259 pCustData->prgCustData =
7260 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7261 if(pCustData->prgCustData ){
7262 pCustData->cCustData=pFDesc->ctCustData;
7263 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7264 pCData = pCData->next){
7265 pCustData->prgCustData[i].guid=pCData->guid;
7266 VariantCopy(& pCustData->prgCustData[i].varValue,
7270 ERR(" OUT OF MEMORY!\n");
7271 return E_OUTOFMEMORY;
7275 return TYPE_E_ELEMENTNOTFOUND;
7278 /* ITypeInfo2::GetAllParamCustData
7280 * Gets all custom data items for the Functions
7283 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7284 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7286 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7287 TLBCustData *pCData=NULL;
7288 TLBFuncDesc * pFDesc;
7290 TRACE("(%p) index %d\n", This, indexFunc);
7291 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7292 pFDesc=pFDesc->next)
7294 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7295 pCustData->prgCustData =
7296 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7297 sizeof(CUSTDATAITEM));
7298 if(pCustData->prgCustData ){
7299 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7300 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7301 pCData; i++, pCData = pCData->next){
7302 pCustData->prgCustData[i].guid=pCData->guid;
7303 VariantCopy(& pCustData->prgCustData[i].varValue,
7307 ERR(" OUT OF MEMORY!\n");
7308 return E_OUTOFMEMORY;
7312 return TYPE_E_ELEMENTNOTFOUND;
7315 /* ITypeInfo2::GetAllVarCustData
7317 * Gets all custom data items for the specified Variable
7320 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7321 UINT index, CUSTDATA *pCustData)
7323 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7324 TLBCustData *pCData;
7325 TLBVarDesc * pVDesc;
7327 TRACE("(%p) index %d\n", This, index);
7328 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7329 pVDesc=pVDesc->next)
7332 pCustData->prgCustData =
7333 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7334 if(pCustData->prgCustData ){
7335 pCustData->cCustData=pVDesc->ctCustData;
7336 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7337 pCData = pCData->next){
7338 pCustData->prgCustData[i].guid=pCData->guid;
7339 VariantCopy(& pCustData->prgCustData[i].varValue,
7343 ERR(" OUT OF MEMORY!\n");
7344 return E_OUTOFMEMORY;
7348 return TYPE_E_ELEMENTNOTFOUND;
7351 /* ITypeInfo2::GetAllImplCustData
7353 * Gets all custom data items for the specified implementation type
7356 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7359 CUSTDATA *pCustData)
7361 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7362 TLBCustData *pCData;
7363 TLBImplType * pRDesc;
7365 TRACE("(%p) index %d\n", This, index);
7366 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7367 pRDesc=pRDesc->next)
7370 pCustData->prgCustData =
7371 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7372 if(pCustData->prgCustData ){
7373 pCustData->cCustData=pRDesc->ctCustData;
7374 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7375 pCData = pCData->next){
7376 pCustData->prgCustData[i].guid=pCData->guid;
7377 VariantCopy(& pCustData->prgCustData[i].varValue,
7381 ERR(" OUT OF MEMORY!\n");
7382 return E_OUTOFMEMORY;
7386 return TYPE_E_ELEMENTNOTFOUND;
7389 static const ITypeInfo2Vtbl tinfvt =
7392 ITypeInfo_fnQueryInterface,
7394 ITypeInfo_fnRelease,
7396 ITypeInfo_fnGetTypeAttr,
7397 ITypeInfo_fnGetTypeComp,
7398 ITypeInfo_fnGetFuncDesc,
7399 ITypeInfo_fnGetVarDesc,
7400 ITypeInfo_fnGetNames,
7401 ITypeInfo_fnGetRefTypeOfImplType,
7402 ITypeInfo_fnGetImplTypeFlags,
7403 ITypeInfo_fnGetIDsOfNames,
7405 ITypeInfo_fnGetDocumentation,
7406 ITypeInfo_fnGetDllEntry,
7407 ITypeInfo_fnGetRefTypeInfo,
7408 ITypeInfo_fnAddressOfMember,
7409 ITypeInfo_fnCreateInstance,
7410 ITypeInfo_fnGetMops,
7411 ITypeInfo_fnGetContainingTypeLib,
7412 ITypeInfo_fnReleaseTypeAttr,
7413 ITypeInfo_fnReleaseFuncDesc,
7414 ITypeInfo_fnReleaseVarDesc,
7416 ITypeInfo2_fnGetTypeKind,
7417 ITypeInfo2_fnGetTypeFlags,
7418 ITypeInfo2_fnGetFuncIndexOfMemId,
7419 ITypeInfo2_fnGetVarIndexOfMemId,
7420 ITypeInfo2_fnGetCustData,
7421 ITypeInfo2_fnGetFuncCustData,
7422 ITypeInfo2_fnGetParamCustData,
7423 ITypeInfo2_fnGetVarCustData,
7424 ITypeInfo2_fnGetImplTypeCustData,
7425 ITypeInfo2_fnGetDocumentation2,
7426 ITypeInfo2_fnGetAllCustData,
7427 ITypeInfo2_fnGetAllFuncCustData,
7428 ITypeInfo2_fnGetAllParamCustData,
7429 ITypeInfo2_fnGetAllVarCustData,
7430 ITypeInfo2_fnGetAllImplTypeCustData,
7433 /******************************************************************************
7434 * CreateDispTypeInfo [OLEAUT32.31]
7436 * Build type information for an object so it can be called through an
7437 * IDispatch interface.
7440 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7441 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7444 * This call allows an objects methods to be accessed through IDispatch, by
7445 * building an ITypeInfo object that IDispatch can use to call through.
7447 HRESULT WINAPI CreateDispTypeInfo(
7448 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7449 LCID lcid, /* [I] Locale Id */
7450 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7452 ITypeInfoImpl *pTIClass, *pTIIface;
7453 ITypeLibImpl *pTypeLibImpl;
7454 unsigned int param, func;
7455 TLBFuncDesc **ppFuncDesc;
7459 pTypeLibImpl = TypeLibImpl_Constructor();
7460 if (!pTypeLibImpl) return E_FAIL;
7462 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7463 pTIIface->pTypeLib = pTypeLibImpl;
7464 pTIIface->index = 0;
7465 pTIIface->Name = NULL;
7466 pTIIface->dwHelpContext = -1;
7467 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7468 pTIIface->TypeAttr.lcid = lcid;
7469 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7470 pTIIface->TypeAttr.wMajorVerNum = 0;
7471 pTIIface->TypeAttr.wMinorVerNum = 0;
7472 pTIIface->TypeAttr.cbAlignment = 2;
7473 pTIIface->TypeAttr.cbSizeInstance = -1;
7474 pTIIface->TypeAttr.cbSizeVft = -1;
7475 pTIIface->TypeAttr.cFuncs = 0;
7476 pTIIface->TypeAttr.cImplTypes = 0;
7477 pTIIface->TypeAttr.cVars = 0;
7478 pTIIface->TypeAttr.wTypeFlags = 0;
7480 ppFuncDesc = &pTIIface->funclist;
7481 for(func = 0; func < pidata->cMembers; func++) {
7482 METHODDATA *md = pidata->pmethdata + func;
7483 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7484 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7485 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7486 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7487 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7488 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7489 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7490 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7491 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7492 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7493 (*ppFuncDesc)->funcdesc.cScodes = 0;
7494 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7495 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7496 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7497 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7498 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7499 md->cArgs * sizeof(ELEMDESC));
7500 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7501 md->cArgs * sizeof(TLBParDesc));
7502 for(param = 0; param < md->cArgs; param++) {
7503 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7504 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7506 (*ppFuncDesc)->helpcontext = 0;
7507 (*ppFuncDesc)->HelpStringContext = 0;
7508 (*ppFuncDesc)->HelpString = NULL;
7509 (*ppFuncDesc)->Entry = NULL;
7510 (*ppFuncDesc)->ctCustData = 0;
7511 (*ppFuncDesc)->pCustData = NULL;
7512 (*ppFuncDesc)->next = NULL;
7513 pTIIface->TypeAttr.cFuncs++;
7514 ppFuncDesc = &(*ppFuncDesc)->next;
7517 dump_TypeInfo(pTIIface);
7519 pTypeLibImpl->pTypeInfo = pTIIface;
7520 pTypeLibImpl->TypeInfoCount++;
7522 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7523 pTIClass->pTypeLib = pTypeLibImpl;
7524 pTIClass->index = 1;
7525 pTIClass->Name = NULL;
7526 pTIClass->dwHelpContext = -1;
7527 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7528 pTIClass->TypeAttr.lcid = lcid;
7529 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7530 pTIClass->TypeAttr.wMajorVerNum = 0;
7531 pTIClass->TypeAttr.wMinorVerNum = 0;
7532 pTIClass->TypeAttr.cbAlignment = 2;
7533 pTIClass->TypeAttr.cbSizeInstance = -1;
7534 pTIClass->TypeAttr.cbSizeVft = -1;
7535 pTIClass->TypeAttr.cFuncs = 0;
7536 pTIClass->TypeAttr.cImplTypes = 1;
7537 pTIClass->TypeAttr.cVars = 0;
7538 pTIClass->TypeAttr.wTypeFlags = 0;
7540 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7541 pTIClass->impltypelist->hRef = 0;
7543 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7546 ref->pImpTLInfo = TLB_REF_INTERNAL;
7547 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7549 dump_TypeInfo(pTIClass);
7551 pTIIface->next = pTIClass;
7552 pTypeLibImpl->TypeInfoCount++;
7554 *pptinfo = (ITypeInfo*)pTIClass;
7556 ITypeInfo_AddRef(*pptinfo);
7557 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7563 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7565 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7567 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7570 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7572 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7574 return ITypeInfo_AddRef((ITypeInfo *)This);
7577 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7579 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7581 return ITypeInfo_Release((ITypeInfo *)This);
7584 static HRESULT WINAPI ITypeComp_fnBind(
7589 ITypeInfo ** ppTInfo,
7590 DESCKIND * pDescKind,
7593 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7594 const TLBFuncDesc *pFDesc;
7595 const TLBVarDesc *pVDesc;
7596 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7598 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7600 *pDescKind = DESCKIND_NONE;
7601 pBindPtr->lpfuncdesc = NULL;
7604 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7605 if (!strcmpiW(pFDesc->Name, szName)) {
7606 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7609 /* name found, but wrong flags */
7610 hr = TYPE_E_TYPEMISMATCH;
7615 HRESULT hr = TLB_AllocAndInitFuncDesc(
7617 &pBindPtr->lpfuncdesc,
7618 This->TypeAttr.typekind == TKIND_DISPATCH);
7621 *pDescKind = DESCKIND_FUNCDESC;
7622 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7623 ITypeInfo_AddRef(*ppTInfo);
7626 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7627 if (!strcmpiW(pVDesc->Name, szName)) {
7628 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7631 *pDescKind = DESCKIND_VARDESC;
7632 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7633 ITypeInfo_AddRef(*ppTInfo);
7638 /* FIXME: search each inherited interface, not just the first */
7639 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7640 /* recursive search */
7644 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7647 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7648 ITypeInfo_Release(pTInfo);
7652 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7653 ITypeComp_Release(pTComp);
7656 WARN("Could not search inherited interface!\n");
7658 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7662 static HRESULT WINAPI ITypeComp_fnBindType(
7666 ITypeInfo ** ppTInfo,
7667 ITypeComp ** ppTComp)
7669 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7671 /* strange behaviour (does nothing) but like the
7674 if (!ppTInfo || !ppTComp)
7683 static const ITypeCompVtbl tcompvt =
7686 ITypeComp_fnQueryInterface,
7688 ITypeComp_fnRelease,
7691 ITypeComp_fnBindType