4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
44 * -. lousy fatal error handling
49 #include "wine/port.h"
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
68 #include "wine/unicode.h"
71 #include "wine/debug.h"
73 #include "wine/list.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
79 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
81 /****************************************************************************
84 * Takes p_iVal (which is in little endian) and returns it
85 * in the host machine's byte order.
87 #ifdef WORDS_BIGENDIAN
88 static WORD FromLEWord(WORD p_iVal)
90 return (((p_iVal & 0x00FF) << 8) |
91 ((p_iVal & 0xFF00) >> 8));
95 static DWORD FromLEDWord(DWORD p_iVal)
97 return (((p_iVal & 0x000000FF) << 24) |
98 ((p_iVal & 0x0000FF00) << 8) |
99 ((p_iVal & 0x00FF0000) >> 8) |
100 ((p_iVal & 0xFF000000) >> 24));
103 #define FromLEWord(X) (X)
104 #define FromLEDWord(X) (X)
107 #define DISPATCH_HREF_OFFSET 0x01000000
108 #define DISPATCH_HREF_MASK 0xff000000
110 /****************************************************************************
113 * Fix byte order in any structure if necessary
115 #ifdef WORDS_BIGENDIAN
116 static void FromLEWords(void *p_Val, int p_iSize)
120 p_iSize /= sizeof(WORD);
123 *Val = FromLEWord(*Val);
130 static void FromLEDWords(void *p_Val, int p_iSize)
134 p_iSize /= sizeof(DWORD);
137 *Val = FromLEDWord(*Val);
143 #define FromLEWords(X,Y) /*nothing*/
144 #define FromLEDWords(X,Y) /*nothing*/
148 * Find a typelib key which matches a requested maj.min version.
150 static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin )
152 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
159 memcpy( buffer, typelibW, sizeof(typelibW) );
160 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
162 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
165 len = sizeof(key_name);
167 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
171 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
173 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
180 break; /* exact match */
182 if (v_min > best_min) best_min = v_min;
185 len = sizeof(key_name);
196 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
197 /* buffer must be at least 60 characters long */
198 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
200 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
201 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
203 memcpy( buffer, TypelibW, sizeof(TypelibW) );
204 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
205 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
209 /* get the path of an interface key, in the form "Interface\\<guid>" */
210 /* buffer must be at least 50 characters long */
211 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
213 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
215 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
216 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
220 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
221 /* buffer must be at least 16 characters long */
222 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
224 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
225 static const WCHAR win16W[] = {'w','i','n','1','6',0};
226 static const WCHAR win32W[] = {'w','i','n','3','2',0};
228 sprintfW( buffer, LcidFormatW, lcid );
231 case SYS_WIN16: strcatW( buffer, win16W ); break;
232 case SYS_WIN32: strcatW( buffer, win32W ); break;
234 TRACE("Typelib is for unsupported syskind %i\n", syskind);
240 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
243 /****************************************************************************
244 * QueryPathOfRegTypeLib [OLEAUT32.164]
246 * Gets the path to a registered type library.
249 * guid [I] referenced guid
250 * wMaj [I] major version
251 * wMin [I] minor version
253 * path [O] path of typelib
257 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
258 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
261 HRESULT WINAPI QueryPathOfRegTypeLib(
268 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
272 WCHAR Path[MAX_PATH];
275 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
277 if (!find_typelib_key( guid, wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
278 get_typelib_key( guid, wMaj, wMin, buffer );
280 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
281 if (res == ERROR_FILE_NOT_FOUND)
283 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
284 return TYPE_E_LIBNOTREGISTERED;
286 else if (res != ERROR_SUCCESS)
288 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
289 return TYPE_E_REGISTRYACCESS;
294 LONG dwPathLen = sizeof(Path);
296 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
298 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
302 else if (myLCID == lcid)
304 /* try with sub-langid */
305 myLCID = SUBLANGID(lcid);
307 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
309 /* try with system langid */
319 *path = SysAllocString( Path );
324 TRACE_(typelib)("-- 0x%08x\n", hr);
328 /******************************************************************************
329 * CreateTypeLib [OLEAUT32.160] creates a typelib
335 HRESULT WINAPI CreateTypeLib(
336 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
338 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
342 /******************************************************************************
343 * LoadTypeLib [OLEAUT32.161]
345 * Loads a type library
348 * szFile [I] Name of file to load from.
349 * pptLib [O] Pointer that receives ITypeLib object on success.
356 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
358 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
360 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
361 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
364 /******************************************************************************
365 * LoadTypeLibEx [OLEAUT32.183]
367 * Loads and optionally registers a type library
373 HRESULT WINAPI LoadTypeLibEx(
374 LPCOLESTR szFile, /* [in] Name of file to load from */
375 REGKIND regkind, /* [in] Specify kind of registration */
376 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
378 WCHAR szPath[MAX_PATH+1];
381 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
385 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
390 case REGKIND_DEFAULT:
391 /* don't register typelibs supplied with full path. Experimentation confirms the following */
392 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
393 (szFile[0] && (szFile[1] == ':'))) break;
394 /* else fall-through */
396 case REGKIND_REGISTER:
397 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
399 IUnknown_Release(*pptLib);
407 TRACE(" returns %08x\n",res);
411 /******************************************************************************
412 * LoadRegTypeLib [OLEAUT32.162]
414 * Loads a registered type library.
417 * rguid [I] GUID of the registered type library.
418 * wVerMajor [I] major version.
419 * wVerMinor [I] minor version.
420 * lcid [I] locale ID.
421 * ppTLib [O] pointer that receives an ITypeLib object on success.
425 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
428 HRESULT WINAPI LoadRegTypeLib(
440 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
444 res= LoadTypeLib(bstr, ppTLib);
448 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
454 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
455 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
456 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
457 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
458 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
459 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
461 /******************************************************************************
462 * RegisterTypeLib [OLEAUT32.163]
463 * Adds information about a type library to the System Registry
465 * Docs: ITypeLib FAR * ptlib
466 * Docs: OLECHAR FAR* szFullPath
467 * Docs: OLECHAR FAR* szHelpDir
473 HRESULT WINAPI RegisterTypeLib(
474 ITypeLib * ptlib, /* [in] Pointer to the library*/
475 OLECHAR * szFullPath, /* [in] full Path of the library*/
476 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
479 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
480 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
481 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
491 if (ptlib == NULL || szFullPath == NULL)
494 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
497 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
500 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
501 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
505 /* Set the human-readable name of the typelib */
506 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
508 if (RegSetValueExW(key, NULL, 0, REG_SZ,
509 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
517 /* Make up the name of the typelib path subkey */
518 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
520 /* Create the typelib path subkey */
521 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
522 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
524 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
525 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
533 /* Create the flags subkey */
534 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
535 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
537 /* FIXME: is %u correct? */
538 static const WCHAR formatW[] = {'%','u',0};
540 sprintfW(buf, formatW, attr->wLibFlags);
541 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
542 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
550 /* create the helpdir subkey */
551 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
552 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
554 BOOL freeHelpDir = FALSE;
557 /* if we created a new key, and helpDir was null, set the helpdir
558 to the directory which contains the typelib. However,
559 if we just opened an existing key, we leave the helpdir alone */
560 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
561 szHelpDir = SysAllocString(szFullPath);
562 pIndexStr = strrchrW(szHelpDir, '\\');
569 /* if we have an szHelpDir, set it! */
570 if (szHelpDir != NULL) {
571 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
572 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
578 if (freeHelpDir) SysFreeString(szHelpDir);
590 /* register OLE Automation-compatible interfaces for this typelib */
591 types = ITypeLib_GetTypeInfoCount(ptlib);
592 for (tidx=0; tidx<types; tidx++) {
593 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
594 LPOLESTR name = NULL;
595 ITypeInfo *tinfo = NULL;
597 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
600 case TKIND_INTERFACE:
601 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
602 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
606 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
607 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
611 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
616 TYPEATTR *tattr = NULL;
617 ITypeInfo_GetTypeAttr(tinfo, &tattr);
620 TRACE_(typelib)("guid=%s, flags=%04x (",
621 debugstr_guid(&tattr->guid),
624 if (TRACE_ON(typelib)) {
625 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
645 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
647 /* register interface<->typelib coupling */
648 get_interface_key( &tattr->guid, keyName );
649 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
650 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
653 RegSetValueExW(key, NULL, 0, REG_SZ,
654 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
656 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
657 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
658 RegSetValueExW(subKey, NULL, 0, REG_SZ,
659 (const BYTE *)PSOA, sizeof PSOA);
663 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
664 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
665 RegSetValueExW(subKey, NULL, 0, REG_SZ,
666 (const BYTE *)PSOA, sizeof PSOA);
670 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
671 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
674 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
675 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
677 StringFromGUID2(&attr->guid, buffer, 40);
678 RegSetValueExW(subKey, NULL, 0, REG_SZ,
679 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
680 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
681 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
682 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
690 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
693 ITypeInfo_Release(tinfo);
700 ITypeLib_ReleaseTLibAttr(ptlib, attr);
706 /******************************************************************************
707 * UnRegisterTypeLib [OLEAUT32.186]
708 * Removes information about a type library from the System Registry
715 HRESULT WINAPI UnRegisterTypeLib(
716 REFGUID libid, /* [in] Guid of the library */
717 WORD wVerMajor, /* [in] major version */
718 WORD wVerMinor, /* [in] minor version */
719 LCID lcid, /* [in] locale id */
722 BSTR tlibPath = NULL;
725 WCHAR subKeyName[50];
728 BOOL deleteOtherStuff;
731 TYPEATTR* typeAttr = NULL;
733 ITypeInfo* typeInfo = NULL;
734 ITypeLib* typeLib = NULL;
737 TRACE("(IID: %s)\n",debugstr_guid(libid));
739 /* Create the path to the key */
740 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
742 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
744 TRACE("Unsupported syskind %i\n", syskind);
745 result = E_INVALIDARG;
749 /* get the path to the typelib on disk */
750 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
751 result = E_INVALIDARG;
755 /* Try and open the key to the type library. */
756 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
757 result = E_INVALIDARG;
761 /* Try and load the type library */
762 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
763 result = TYPE_E_INVALIDSTATE;
767 /* remove any types registered with this typelib */
768 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
769 for (i=0; i<numTypes; i++) {
770 /* get the kind of type */
771 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
775 /* skip non-interfaces, and get type info for the type */
776 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
779 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
782 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
786 /* the path to the type */
787 get_interface_key( &typeAttr->guid, subKeyName );
789 /* Delete its bits */
790 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
793 RegDeleteKeyW(subKey, ProxyStubClsidW);
794 RegDeleteKeyW(subKey, ProxyStubClsid32W);
795 RegDeleteKeyW(subKey, TypeLibW);
798 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
801 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
803 if (typeInfo) ITypeInfo_Release(typeInfo);
807 /* Now, delete the type library path subkey */
808 get_lcid_subkey( lcid, syskind, subKeyName );
809 RegDeleteKeyW(key, subKeyName);
810 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
811 RegDeleteKeyW(key, subKeyName);
813 /* check if there is anything besides the FLAGS/HELPDIR keys.
814 If there is, we don't delete them */
815 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
816 deleteOtherStuff = TRUE;
818 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
819 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
821 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
822 if (!strcmpW(subKeyName, FLAGSW)) continue;
823 if (!strcmpW(subKeyName, HELPDIRW)) continue;
824 deleteOtherStuff = FALSE;
828 /* only delete the other parts of the key if we're absolutely sure */
829 if (deleteOtherStuff) {
830 RegDeleteKeyW(key, FLAGSW);
831 RegDeleteKeyW(key, HELPDIRW);
835 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
836 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
837 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
841 if (tlibPath) SysFreeString(tlibPath);
842 if (typeLib) ITypeLib_Release(typeLib);
843 if (subKey) RegCloseKey(subKey);
844 if (key) RegCloseKey(key);
848 /*======================= ITypeLib implementation =======================*/
850 typedef struct tagTLBCustData
854 struct tagTLBCustData* next;
857 /* data structure for import typelibs */
858 typedef struct tagTLBImpLib
860 int offset; /* offset in the file (MSFT)
861 offset in nametable (SLTG)
862 just used to identify library while reading
864 GUID guid; /* libid */
865 BSTR name; /* name */
867 LCID lcid; /* lcid of imported typelib */
869 WORD wVersionMajor; /* major version number */
870 WORD wVersionMinor; /* minor version number */
872 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
873 NULL if not yet loaded */
874 struct tagTLBImpLib * next;
877 /* internal ITypeLib data */
878 typedef struct tagITypeLibImpl
880 const ITypeLib2Vtbl *lpVtbl;
881 const ITypeCompVtbl *lpVtblTypeComp;
883 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
885 /* strings can be stored in tlb as multibyte strings BUT they are *always*
886 * exported to the application as a UNICODE string.
892 unsigned long dwHelpContext;
893 int TypeInfoCount; /* nr of typeinfo's in librarry */
894 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
895 int ctCustData; /* number of items in cust data list */
896 TLBCustData * pCustData; /* linked list to cust data */
897 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
898 int ctTypeDesc; /* number of items in type desc array */
899 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
900 library. Only used while reading MSFT
902 struct list ref_list; /* list of ref types in this typelib */
903 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
906 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
907 struct tagITypeLibImpl *next, *prev;
912 static const ITypeLib2Vtbl tlbvt;
913 static const ITypeCompVtbl tlbtcvt;
915 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
917 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
920 /* ITypeLib methods */
921 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
922 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
924 /*======================= ITypeInfo implementation =======================*/
926 /* data for referenced types */
927 typedef struct tagTLBRefType
929 INT index; /* Type index for internal ref or for external ref
930 it the format is SLTG. -2 indicates to
933 GUID guid; /* guid of the referenced type */
934 /* if index == TLB_REF_USE_GUID */
936 HREFTYPE reference; /* The href of this ref */
937 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
938 TLB_REF_INTERNAL for internal refs
939 TLB_REF_NOT_FOUND for broken refs */
944 #define TLB_REF_USE_GUID -2
946 #define TLB_REF_INTERNAL (void*)-2
947 #define TLB_REF_NOT_FOUND (void*)-1
949 /* internal Parameter data */
950 typedef struct tagTLBParDesc
954 TLBCustData * pCustData; /* linked list to cust data */
957 /* internal Function data */
958 typedef struct tagTLBFuncDesc
960 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
961 BSTR Name; /* the name of this function */
962 TLBParDesc *pParamDesc; /* array with param names and custom data */
964 int HelpStringContext;
966 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
968 TLBCustData * pCustData; /* linked list to cust data; */
969 struct tagTLBFuncDesc * next;
972 /* internal Variable data */
973 typedef struct tagTLBVarDesc
975 VARDESC vardesc; /* lots of info on the variable and its attributes. */
976 BSTR Name; /* the name of this variable */
978 int HelpStringContext; /* FIXME: where? */
981 TLBCustData * pCustData;/* linked list to cust data; */
982 struct tagTLBVarDesc * next;
985 /* internal implemented interface data */
986 typedef struct tagTLBImplType
988 HREFTYPE hRef; /* hRef of interface */
989 int implflags; /* IMPLFLAG_*s */
991 TLBCustData * pCustData;/* linked list to custom data; */
992 struct tagTLBImplType *next;
995 /* internal TypeInfo data */
996 typedef struct tagITypeInfoImpl
998 const ITypeInfo2Vtbl *lpVtbl;
999 const ITypeCompVtbl *lpVtblTypeComp;
1001 BOOL no_free_data; /* don't free data structurees */
1002 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1003 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1004 int index; /* index in this typelib; */
1005 HREFTYPE hreftype; /* hreftype for app object binding */
1006 /* type libs seem to store the doc strings in ascii
1007 * so why should we do it in unicode?
1012 unsigned long dwHelpContext;
1013 unsigned long dwHelpStringContext;
1016 TLBFuncDesc * funclist; /* linked list with function descriptions */
1019 TLBVarDesc * varlist; /* linked list with variable descriptions */
1021 /* Implemented Interfaces */
1022 TLBImplType * impltypelist;
1025 TLBCustData * pCustData; /* linked list to cust data; */
1026 struct tagITypeInfoImpl * next;
1029 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1031 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1034 static const ITypeInfo2Vtbl tinfvt;
1035 static const ITypeCompVtbl tcompvt;
1037 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1039 typedef struct tagTLBContext
1041 unsigned int oStart; /* start of TLB in file */
1042 unsigned int pos; /* current pos */
1043 unsigned int length; /* total length */
1044 void *mapping; /* memory mapping */
1045 MSFT_SegDir * pTblDir;
1046 ITypeLibImpl* pLibInfo;
1050 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1055 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1056 if (pTD->vt & VT_RESERVED)
1057 szVarType += strlen(strcpy(szVarType, "reserved | "));
1058 if (pTD->vt & VT_BYREF)
1059 szVarType += strlen(strcpy(szVarType, "ref to "));
1060 if (pTD->vt & VT_ARRAY)
1061 szVarType += strlen(strcpy(szVarType, "array of "));
1062 if (pTD->vt & VT_VECTOR)
1063 szVarType += strlen(strcpy(szVarType, "vector of "));
1064 switch(pTD->vt & VT_TYPEMASK) {
1065 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1066 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1067 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1068 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1069 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1070 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1071 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1072 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1073 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1074 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1075 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1076 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1077 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1078 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1079 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1080 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1081 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1082 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1083 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1084 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1085 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1086 pTD->u.hreftype); break;
1087 case VT_PTR: sprintf(szVarType, "ptr to ");
1088 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1090 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1091 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1093 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1094 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1095 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1098 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1102 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1104 USHORT flags = edesc->u.paramdesc.wParamFlags;
1105 dump_TypeDesc(&edesc->tdesc,buf);
1106 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1107 MESSAGE("\t\tu.paramdesc.wParamFlags");
1108 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1109 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1110 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1111 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1112 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1113 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1114 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1115 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1116 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1118 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1120 MESSAGE("memid is %08x\n",funcdesc->memid);
1121 for (i=0;i<funcdesc->cParams;i++) {
1122 MESSAGE("Param %d:\n",i);
1123 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1125 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1126 switch (funcdesc->funckind) {
1127 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1128 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1129 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1130 case FUNC_STATIC: MESSAGE("static");break;
1131 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1132 default: MESSAGE("unknown");break;
1134 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1135 switch (funcdesc->invkind) {
1136 case INVOKE_FUNC: MESSAGE("func");break;
1137 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1138 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1139 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1141 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1142 switch (funcdesc->callconv) {
1143 case CC_CDECL: MESSAGE("cdecl");break;
1144 case CC_PASCAL: MESSAGE("pascal");break;
1145 case CC_STDCALL: MESSAGE("stdcall");break;
1146 case CC_SYSCALL: MESSAGE("syscall");break;
1149 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1150 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1151 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1153 MESSAGE("\telemdescFunc (return value type):\n");
1154 dump_ELEMDESC(&funcdesc->elemdescFunc);
1157 static const char * const typekind_desc[] =
1170 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1173 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1174 for (i=0;i<pfd->funcdesc.cParams;i++)
1175 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1178 dump_FUNCDESC(&(pfd->funcdesc));
1180 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1181 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1183 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1187 dump_TLBFuncDescOne(pfd);
1191 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1195 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1200 static void dump_TLBImpLib(const TLBImpLib *import)
1202 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1203 debugstr_w(import->name));
1204 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1205 import->wVersionMinor, import->lcid, import->offset);
1208 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1212 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1214 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1215 if(ref->index == -1)
1216 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1218 TRACE_(typelib)("type no: %d\n", ref->index);
1220 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1222 TRACE_(typelib)("in lib\n");
1223 dump_TLBImpLib(ref->pImpTLInfo);
1228 static void dump_TLBImplType(const TLBImplType * impl)
1232 "implementing/inheriting interface hRef = %x implflags %x\n",
1233 impl->hRef, impl->implflags);
1238 static void dump_Variant(const VARIANT * pvar)
1242 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1246 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1247 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1249 TRACE(",%p", V_BYREF(pvar));
1251 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1253 TRACE(",%p", V_ARRAY(pvar));
1255 else switch (V_TYPE(pvar))
1257 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1258 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1259 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1260 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1262 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1264 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1265 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1266 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1267 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1268 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1269 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1270 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1271 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1272 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1273 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1274 V_CY(pvar).s.Lo); break;
1276 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1277 TRACE(",<invalid>");
1279 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1280 st.wHour, st.wMinute, st.wSecond);
1284 case VT_USERDEFINED:
1286 case VT_NULL: break;
1287 default: TRACE(",?"); break;
1293 static void dump_DispParms(const DISPPARAMS * pdp)
1297 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1299 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1301 TRACE("named args:\n");
1302 for (index = 0; index < pdp->cNamedArgs; index++)
1303 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1306 if (pdp->cArgs && pdp->rgvarg)
1309 for (index = 0; index < pdp->cArgs; index++)
1310 dump_Variant( &pdp->rgvarg[index] );
1314 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1316 TRACE("%p ref=%u\n", pty, pty->ref);
1317 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1318 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1319 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1320 TRACE("fct:%u var:%u impl:%u\n",
1321 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1322 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1323 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1324 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1326 dump_TLBFuncDesc(pty->funclist);
1327 dump_TLBVarDesc(pty->varlist);
1328 dump_TLBImplType(pty->impltypelist);
1331 static void dump_VARDESC(const VARDESC *v)
1333 MESSAGE("memid %d\n",v->memid);
1334 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1335 MESSAGE("oInst %d\n",v->u.oInst);
1336 dump_ELEMDESC(&(v->elemdescVar));
1337 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1338 MESSAGE("varkind %d\n",v->varkind);
1341 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1343 /* VT_LPWSTR is largest type that */
1344 /* may appear in type description*/
1345 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1346 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1347 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1348 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1349 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1350 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1354 static void TLB_abort(void)
1358 static void * TLB_Alloc(unsigned size)
1361 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1363 ERR("cannot allocate memory\n");
1368 static void TLB_Free(void * ptr)
1370 HeapFree(GetProcessHeap(), 0, ptr);
1373 /* returns the size required for a deep copy of a typedesc into a
1375 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1379 if (alloc_initial_space)
1380 size += sizeof(TYPEDESC);
1386 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1389 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1390 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1396 /* deep copy a typedesc into a flat buffer */
1397 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1402 buffer = (char *)buffer + sizeof(TYPEDESC);
1411 dest->u.lptdesc = buffer;
1412 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1415 dest->u.lpadesc = buffer;
1416 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1417 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1418 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1424 /* free custom data allocated by MSFT_CustData */
1425 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1427 TLBCustData *pCustDataNext;
1428 for (; pCustData; pCustData = pCustDataNext)
1430 VariantClear(&pCustData->data);
1432 pCustDataNext = pCustData->next;
1433 TLB_Free(pCustData);
1437 /**********************************************************************
1439 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1441 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1446 static inline void MSFT_Seek(TLBContext *pcx, long where)
1448 if (where != DO_NOT_SEEK)
1450 where += pcx->oStart;
1451 if (where > pcx->length)
1454 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1462 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1464 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1465 pcx->pos, count, pcx->oStart, pcx->length, where);
1467 MSFT_Seek(pcx, where);
1468 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1469 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1474 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1479 ret = MSFT_Read(buffer, count, pcx, where);
1480 FromLEDWords(buffer, ret);
1485 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1490 ret = MSFT_Read(buffer, count, pcx, where);
1491 FromLEWords(buffer, ret);
1496 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1498 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1499 memset(pGuid,0, sizeof(GUID));
1502 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1503 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1504 pGuid->Data2 = FromLEWord(pGuid->Data2);
1505 pGuid->Data3 = FromLEWord(pGuid->Data3);
1506 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1509 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1511 MSFT_NameIntro niName;
1515 ERR_(typelib)("bad offset %d\n", offset);
1519 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1520 pcx->pTblDir->pNametab.offset+offset);
1522 return niName.hreftype;
1525 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1528 MSFT_NameIntro niName;
1530 BSTR bstrName = NULL;
1534 ERR_(typelib)("bad offset %d\n", offset);
1537 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1538 pcx->pTblDir->pNametab.offset+offset);
1539 niName.namelen &= 0xFF; /* FIXME: correct ? */
1540 name=TLB_Alloc((niName.namelen & 0xff) +1);
1541 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1542 name[niName.namelen & 0xff]='\0';
1544 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1547 /* no invalid characters in string */
1550 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1552 /* don't check for invalid character since this has been done previously */
1553 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1557 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1561 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1568 if(offset<0) return NULL;
1569 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1570 if(length <= 0) return 0;
1571 string=TLB_Alloc(length +1);
1572 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1573 string[length]='\0';
1575 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1576 string, -1, NULL, 0);
1578 /* no invalid characters in string */
1581 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1583 /* don't check for invalid character since this has been done previously */
1584 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1588 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1592 * read a value and fill a VARIANT structure
1594 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1598 TRACE_(typelib)("\n");
1600 if(offset <0) { /* data are packed in here */
1601 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1602 V_I4(pVar) = offset & 0x3ffffff;
1605 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1606 pcx->pTblDir->pCustData.offset + offset );
1607 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1608 switch (V_VT(pVar)){
1609 case VT_EMPTY: /* FIXME: is this right? */
1610 case VT_NULL: /* FIXME: is this right? */
1611 case VT_I2 : /* this should not happen */
1622 case VT_VOID : /* FIXME: is this right? */
1630 case VT_DECIMAL : /* FIXME: is this right? */
1633 /* pointer types with known behaviour */
1636 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1639 DWORD origPos = MSFT_Tell(pcx), nullPos;
1642 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1644 nullPos = MSFT_Tell(pcx);
1645 size = nullPos - origPos;
1646 MSFT_Seek(pcx, origPos);
1648 ptr=TLB_Alloc(size);/* allocate temp buffer */
1649 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1650 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1651 /* FIXME: do we need a AtoW conversion here? */
1652 V_UNION(pVar, bstrVal[size])='\0';
1653 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1657 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1664 case VT_USERDEFINED :
1670 case VT_STREAMED_OBJECT :
1671 case VT_STORED_OBJECT :
1672 case VT_BLOB_OBJECT :
1677 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1681 if(size>0) /* (big|small) endian correct? */
1682 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1686 * create a linked list with custom data
1688 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1694 TRACE_(typelib)("\n");
1698 pNew=TLB_Alloc(sizeof(TLBCustData));
1699 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1700 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1701 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1702 /* add new custom data at head of the list */
1703 pNew->next=*ppCustData;
1705 offset = entry.next;
1710 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1714 pTd->vt=type & VT_TYPEMASK;
1716 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1718 if(pTd->vt == VT_USERDEFINED)
1719 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1721 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1724 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1726 /* resolve referenced type if any */
1729 switch (lpTypeDesc->vt)
1732 lpTypeDesc = lpTypeDesc->u.lptdesc;
1736 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1739 case VT_USERDEFINED:
1740 MSFT_DoRefType(pcx, pTI->pTypeLib,
1741 lpTypeDesc->u.hreftype);
1753 MSFT_DoFuncs(TLBContext* pcx,
1758 TLBFuncDesc** pptfd)
1761 * member information is stored in a data structure at offset
1762 * indicated by the memoffset field of the typeinfo structure
1763 * There are several distinctive parts.
1764 * The first part starts with a field that holds the total length
1765 * of this (first) part excluding this field. Then follow the records,
1766 * for each member there is one record.
1768 * The first entry is always the length of the record (including this
1770 * The rest of the record depends on the type of the member. If there is
1771 * a field indicating the member type (function, variable, interface, etc)
1772 * I have not found it yet. At this time we depend on the information
1773 * in the type info and the usual order how things are stored.
1775 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1778 * Third is an equal sized array with file offsets to the name entry
1781 * The fourth and last (?) part is an array with offsets to the records
1782 * in the first part of this file segment.
1785 int infolen, nameoffset, reclength, nrattributes, i;
1786 int recoffset = offset + sizeof(INT);
1788 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1789 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1790 TLBFuncDesc *ptfd_prev = NULL;
1792 TRACE_(typelib)("\n");
1794 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1796 for ( i = 0; i < cFuncs ; i++ )
1798 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1800 /* name, eventually add to a hash table */
1801 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1802 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1804 /* nameoffset is sometimes -1 on the second half of a propget/propput
1805 * pair of functions */
1806 if ((nameoffset == -1) && (i > 0))
1807 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1809 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1811 /* read the function information record */
1812 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1814 reclength &= 0xffff;
1816 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1818 /* do the attributes */
1819 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1822 if ( nrattributes > 0 )
1824 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1826 if ( nrattributes > 1 )
1828 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1829 pFuncRec->OptAttr[1]) ;
1831 if ( nrattributes > 2 )
1833 if ( pFuncRec->FKCCIC & 0x2000 )
1835 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1836 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1837 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1841 (*pptfd)->Entry = MSFT_ReadString(pcx,
1842 pFuncRec->OptAttr[2]);
1844 if( nrattributes > 5 )
1846 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1848 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1851 pFuncRec->OptAttr[6],
1852 &(*pptfd)->pCustData);
1858 (*pptfd)->Entry = (BSTR)-1;
1863 /* fill the FuncDesc Structure */
1864 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1865 offset + infolen + ( i + 1) * sizeof(INT));
1867 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1868 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1869 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1870 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1871 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1872 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1873 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1877 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1879 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1881 /* do the parameters/arguments */
1882 if(pFuncRec->nrargs)
1885 MSFT_ParameterInfo paraminfo;
1887 (*pptfd)->funcdesc.lprgelemdescParam =
1888 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1890 (*pptfd)->pParamDesc =
1891 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1893 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1894 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1896 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1898 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1905 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1908 if (paraminfo.oName == -1)
1909 /* this occurs for [propput] or [propget] methods, so
1910 * we should just set the name of the parameter to the
1911 * name of the method. */
1912 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1914 (*pptfd)->pParamDesc[j].Name =
1915 MSFT_ReadName( pcx, paraminfo.oName );
1916 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1918 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1921 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1922 (pFuncRec->FKCCIC & 0x1000) )
1924 INT* pInt = (INT *)((char *)pFuncRec +
1926 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1928 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1930 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1931 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1933 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1937 elemdesc->u.paramdesc.pparamdescex = NULL;
1939 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1942 pFuncRec->OptAttr[7+j],
1943 &(*pptfd)->pParamDesc[j].pCustData);
1946 /* SEEK value = jump to offset,
1947 * from there jump to the end of record,
1948 * go back by (j-1) arguments
1950 MSFT_ReadLEDWords( ¶minfo ,
1951 sizeof(MSFT_ParameterInfo), pcx,
1952 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1953 * sizeof(MSFT_ParameterInfo)));
1957 /* scode is not used: archaic win16 stuff FIXME: right? */
1958 (*pptfd)->funcdesc.cScodes = 0 ;
1959 (*pptfd)->funcdesc.lprgscode = NULL ;
1962 pptfd = & ((*pptfd)->next);
1963 recoffset += reclength;
1965 HeapFree(GetProcessHeap(), 0, recbuf);
1968 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1969 int cVars, int offset, TLBVarDesc ** pptvd)
1971 int infolen, nameoffset, reclength;
1973 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1977 TRACE_(typelib)("\n");
1979 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1980 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1981 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1982 recoffset += offset+sizeof(INT);
1983 for(i=0;i<cVars;i++){
1984 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1985 /* name, eventually add to a hash table */
1986 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1987 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1988 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1989 /* read the variable information record */
1990 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1992 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1994 if(reclength >(6*sizeof(INT)) )
1995 (*pptvd)->HelpContext=pVarRec->HelpContext;
1996 if(reclength >(7*sizeof(INT)) )
1997 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1998 if(reclength >(8*sizeof(INT)) )
1999 if(reclength >(9*sizeof(INT)) )
2000 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2001 /* fill the VarDesc Structure */
2002 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2003 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2004 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2005 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2006 MSFT_GetTdesc(pcx, pVarRec->DataType,
2007 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2008 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2009 if(pVarRec->VarKind == VAR_CONST ){
2010 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2011 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2012 pVarRec->OffsValue, pcx);
2014 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2015 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2016 pptvd=&((*pptvd)->next);
2017 recoffset += reclength;
2020 /* fill in data for a hreftype (offset). When the referenced type is contained
2021 * in the typelib, it's just an (file) offset in the type info base dir.
2022 * If comes from import, it's an offset+1 in the ImpInfo table
2024 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2030 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2032 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2034 if(ref->reference == offset) return;
2037 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2038 list_add_tail(&pTL->ref_list, &ref->entry);
2040 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2041 /* external typelib */
2042 MSFT_ImpInfo impinfo;
2043 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2045 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2047 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2048 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2049 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
2050 if(pImpLib->offset==impinfo.oImpFile) break;
2051 pImpLib=pImpLib->next;
2054 ref->reference = offset;
2055 ref->pImpTLInfo = pImpLib;
2056 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2057 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2058 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2059 ref->index = TLB_REF_USE_GUID;
2061 ref->index = impinfo.oGuid;
2063 ERR("Cannot find a reference\n");
2064 ref->reference = -1;
2065 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2068 /* in this typelib */
2069 ref->index = MSFT_HREFTYPE_INDEX(offset);
2070 ref->reference = offset;
2071 ref->pImpTLInfo = TLB_REF_INTERNAL;
2075 /* process Implemented Interfaces of a com class */
2076 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2080 MSFT_RefRecord refrec;
2081 TLBImplType **ppImpl = &pTI->impltypelist;
2083 TRACE_(typelib)("\n");
2085 for(i=0;i<count;i++){
2086 if(offset<0) break; /* paranoia */
2087 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2088 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2089 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2090 (*ppImpl)->hRef = refrec.reftype;
2091 (*ppImpl)->implflags=refrec.flags;
2092 (*ppImpl)->ctCustData=
2093 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2094 offset=refrec.onext;
2095 ppImpl=&((*ppImpl)->next);
2099 * process a typeinfo record
2101 static ITypeInfoImpl * MSFT_DoTypeInfo(
2104 ITypeLibImpl * pLibInfo)
2106 MSFT_TypeInfoBase tiBase;
2107 ITypeInfoImpl *ptiRet;
2109 TRACE_(typelib)("count=%u\n", count);
2111 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2112 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2113 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2115 /* this is where we are coming from */
2116 ptiRet->pTypeLib = pLibInfo;
2117 ptiRet->index=count;
2118 /* fill in the typeattr fields */
2120 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2121 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2122 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2123 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2124 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2125 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2126 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2127 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2128 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2129 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2130 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2131 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2132 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2133 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2134 MSFT_GetTdesc(pcx, tiBase.datatype1,
2135 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2138 /* IDLDESC idldescType; *//* never saw this one != zero */
2140 /* name, eventually add to a hash table */
2141 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2142 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2143 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2145 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2146 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2147 ptiRet->dwHelpContext=tiBase.helpcontext;
2149 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2150 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2152 /* note: InfoType's Help file and HelpStringDll come from the containing
2153 * library. Further HelpString and Docstring appear to be the same thing :(
2156 if(ptiRet->TypeAttr.cFuncs >0 )
2157 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2158 ptiRet->TypeAttr.cVars,
2159 tiBase.memoffset, & ptiRet->funclist);
2161 if(ptiRet->TypeAttr.cVars >0 )
2162 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2163 ptiRet->TypeAttr.cVars,
2164 tiBase.memoffset, & ptiRet->varlist);
2165 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2166 switch(ptiRet->TypeAttr.typekind)
2169 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2172 case TKIND_DISPATCH:
2173 /* This is not -1 when the interface is a non-base dual interface or
2174 when a dispinterface wraps an interface ie the idl 'dispinterface x {interface y;};'.
2175 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2179 if (tiBase.datatype1 != -1)
2181 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2182 ptiRet->impltypelist->hRef = tiBase.datatype1;
2183 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2187 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2188 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2189 ptiRet->impltypelist->hRef = tiBase.datatype1;
2194 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2196 TRACE_(typelib)("%s guid: %s kind:%s\n",
2197 debugstr_w(ptiRet->Name),
2198 debugstr_guid(&ptiRet->TypeAttr.guid),
2199 typekind_desc[ptiRet->TypeAttr.typekind]);
2204 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2205 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2206 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2209 static ITypeLibImpl *tlb_cache_first;
2210 static CRITICAL_SECTION cache_section;
2211 static CRITICAL_SECTION_DEBUG cache_section_debug =
2213 0, 0, &cache_section,
2214 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2215 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2217 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2220 typedef struct TLB_PEFile
2222 const IUnknownVtbl *lpvtbl;
2225 HRSRC typelib_resource;
2226 HGLOBAL typelib_global;
2227 LPVOID typelib_base;
2230 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2232 if (IsEqualIID(riid, &IID_IUnknown))
2235 IUnknown_AddRef(iface);
2239 return E_NOINTERFACE;
2242 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2244 TLB_PEFile *This = (TLB_PEFile *)iface;
2245 return InterlockedIncrement(&This->refs);
2248 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2250 TLB_PEFile *This = (TLB_PEFile *)iface;
2251 ULONG refs = InterlockedDecrement(&This->refs);
2254 if (This->typelib_global)
2255 FreeResource(This->typelib_global);
2257 FreeLibrary(This->dll);
2258 HeapFree(GetProcessHeap(), 0, This);
2263 static const IUnknownVtbl TLB_PEFile_Vtable =
2265 TLB_PEFile_QueryInterface,
2270 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2274 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2276 return E_OUTOFMEMORY;
2278 This->lpvtbl = &TLB_PEFile_Vtable;
2281 This->typelib_resource = NULL;
2282 This->typelib_global = NULL;
2283 This->typelib_base = NULL;
2285 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2286 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2290 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2291 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2292 if (This->typelib_resource)
2294 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2295 if (This->typelib_global)
2297 This->typelib_base = LockResource(This->typelib_global);
2299 if (This->typelib_base)
2301 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2302 *ppBase = This->typelib_base;
2303 *ppFile = (IUnknown *)&This->lpvtbl;
2310 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2311 return TYPE_E_CANTLOADLIBRARY;
2315 typedef struct TLB_Mapping
2317 const IUnknownVtbl *lpvtbl;
2321 LPVOID typelib_base;
2324 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2326 if (IsEqualIID(riid, &IID_IUnknown))
2329 IUnknown_AddRef(iface);
2333 return E_NOINTERFACE;
2336 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2338 TLB_Mapping *This = (TLB_Mapping *)iface;
2339 return InterlockedIncrement(&This->refs);
2342 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2344 TLB_Mapping *This = (TLB_Mapping *)iface;
2345 ULONG refs = InterlockedDecrement(&This->refs);
2348 if (This->typelib_base)
2349 UnmapViewOfFile(This->typelib_base);
2351 CloseHandle(This->mapping);
2352 if (This->file != INVALID_HANDLE_VALUE)
2353 CloseHandle(This->file);
2354 HeapFree(GetProcessHeap(), 0, This);
2359 static const IUnknownVtbl TLB_Mapping_Vtable =
2361 TLB_Mapping_QueryInterface,
2366 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2370 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2372 return E_OUTOFMEMORY;
2374 This->lpvtbl = &TLB_Mapping_Vtable;
2376 This->file = INVALID_HANDLE_VALUE;
2377 This->mapping = NULL;
2378 This->typelib_base = NULL;
2380 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2381 if (INVALID_HANDLE_VALUE != This->file)
2383 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2386 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2387 if(This->typelib_base)
2389 /* retrieve file size */
2390 *pdwTLBLength = GetFileSize(This->file, NULL);
2391 *ppBase = This->typelib_base;
2392 *ppFile = (IUnknown *)&This->lpvtbl;
2398 IUnknown_Release((IUnknown *)&This->lpvtbl);
2399 return TYPE_E_CANTLOADLIBRARY;
2402 /****************************************************************************
2405 * find the type of the typelib file and map the typelib resource into
2408 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2409 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2410 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2412 ITypeLibImpl *entry;
2415 LPWSTR index_str, file = (LPWSTR)pszFileName;
2416 LPVOID pBase = NULL;
2417 DWORD dwTLBLength = 0;
2418 IUnknown *pFile = NULL;
2422 index_str = strrchrW(pszFileName, '\\');
2423 if(index_str && *++index_str != '\0')
2426 long idx = strtolW(index_str, &end_ptr, 10);
2427 if(*end_ptr == '\0')
2429 int str_len = index_str - pszFileName - 1;
2431 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2432 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2437 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2439 if(strchrW(file, '\\'))
2441 lstrcpyW(pszPath, file);
2445 int len = GetSystemDirectoryW(pszPath, cchPath);
2446 pszPath[len] = '\\';
2447 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2451 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2453 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2455 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2456 EnterCriticalSection(&cache_section);
2457 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2459 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2461 TRACE("cache hit\n");
2462 *ppTypeLib = (ITypeLib2*)entry;
2463 ITypeLib_AddRef(*ppTypeLib);
2464 LeaveCriticalSection(&cache_section);
2468 LeaveCriticalSection(&cache_section);
2470 /* now actually load and parse the typelib */
2472 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2473 if (ret == TYPE_E_CANTLOADLIBRARY)
2474 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2477 if (dwTLBLength >= 4)
2479 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2480 if (dwSignature == MSFT_SIGNATURE)
2481 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2482 else if (dwSignature == SLTG_SIGNATURE)
2483 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2486 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2487 ret = TYPE_E_CANTLOADLIBRARY;
2491 ret = TYPE_E_CANTLOADLIBRARY;
2492 IUnknown_Release(pFile);
2496 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2498 TRACE("adding to cache\n");
2499 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2500 lstrcpyW(impl->path, pszPath);
2501 /* We should really canonicalise the path here. */
2502 impl->index = index;
2504 /* FIXME: check if it has added already in the meantime */
2505 EnterCriticalSection(&cache_section);
2506 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2508 tlb_cache_first = impl;
2509 LeaveCriticalSection(&cache_section);
2512 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2517 /*================== ITypeLib(2) Methods ===================================*/
2519 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2521 ITypeLibImpl* pTypeLibImpl;
2523 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2524 if (!pTypeLibImpl) return NULL;
2526 pTypeLibImpl->lpVtbl = &tlbvt;
2527 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2528 pTypeLibImpl->ref = 1;
2530 list_init(&pTypeLibImpl->ref_list);
2531 pTypeLibImpl->dispatch_href = -1;
2533 return pTypeLibImpl;
2536 /****************************************************************************
2537 * ITypeLib2_Constructor_MSFT
2539 * loading an MSFT typelib from an in-memory image
2541 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2545 MSFT_Header tlbHeader;
2546 MSFT_SegDir tlbSegDir;
2547 ITypeLibImpl * pTypeLibImpl;
2549 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2551 pTypeLibImpl = TypeLibImpl_Constructor();
2552 if (!pTypeLibImpl) return NULL;
2554 /* get pointer to beginning of typelib data */
2558 cx.pLibInfo = pTypeLibImpl;
2559 cx.length = dwTLBLength;
2562 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2563 TRACE_(typelib)("header:\n");
2564 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2565 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2566 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2569 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2571 /* there is a small amount of information here until the next important
2573 * the segment directory . Try to calculate the amount of data */
2574 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2576 /* now read the segment directory */
2577 TRACE("read segment directory (at %ld)\n",lPSegDir);
2578 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2579 cx.pTblDir = &tlbSegDir;
2581 /* just check two entries */
2582 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2584 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2585 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2589 /* now fill our internal data */
2590 /* TLIBATTR fields */
2591 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2593 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2594 /* Windows seems to have zero here, is this correct? */
2595 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2596 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2598 pTypeLibImpl->LibAttr.lcid = 0;
2600 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2601 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2602 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2603 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2605 /* name, eventually add to a hash table */
2606 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2609 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2610 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2612 if( tlbHeader.varflags & HELPDLLFLAG)
2615 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2616 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2619 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2622 if(tlbHeader.CustomDataOffset >= 0)
2624 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2627 /* fill in typedescriptions */
2628 if(tlbSegDir.pTypdescTab.length > 0)
2630 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2632 pTypeLibImpl->ctTypeDesc = cTD;
2633 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2634 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2637 /* FIXME: add several sanity checks here */
2638 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2639 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2641 /* FIXME: check safearray */
2643 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2645 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2647 else if(td[0] == VT_CARRAY)
2649 /* array descr table here */
2650 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2652 else if(td[0] == VT_USERDEFINED)
2654 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2656 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2659 /* second time around to fill the array subscript info */
2662 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2663 if(tlbSegDir.pArrayDescriptions.offset>0)
2665 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2666 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2669 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2671 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2673 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2675 for(j = 0; j<td[2]; j++)
2677 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2678 sizeof(INT), &cx, DO_NOT_SEEK);
2679 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2680 sizeof(INT), &cx, DO_NOT_SEEK);
2685 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2686 ERR("didn't find array description data\n");
2691 /* imported type libs */
2692 if(tlbSegDir.pImpFiles.offset>0)
2694 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2695 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2698 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2703 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2704 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2705 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2707 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2708 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2709 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2710 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2713 name = TLB_Alloc(size+1);
2714 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2715 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2716 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2717 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2720 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2721 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2723 ppImpLib = &(*ppImpLib)->next;
2727 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2728 if(pTypeLibImpl->dispatch_href != -1)
2729 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2732 if(tlbHeader.nrtypeinfos >= 0 )
2734 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2735 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2738 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2740 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2742 ppTI = &((*ppTI)->next);
2743 (pTypeLibImpl->TypeInfoCount)++;
2747 TRACE("(%p)\n", pTypeLibImpl);
2748 return (ITypeLib2*) pTypeLibImpl;
2752 static BSTR TLB_MultiByteToBSTR(const char *ptr)
2758 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2759 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2760 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2761 ret = SysAllocString(nameW);
2762 HeapFree(GetProcessHeap(), 0, nameW);
2766 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2772 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2773 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2777 guid->Data4[0] = s >> 8;
2778 guid->Data4[1] = s & 0xff;
2781 for(i = 0; i < 6; i++) {
2782 memcpy(b, str + 24 + 2 * i, 2);
2783 guid->Data4[i + 2] = strtol(b, NULL, 16);
2788 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
2795 bytelen = *(const WORD*)ptr;
2796 if(bytelen == 0xffff) return 2;
2797 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2798 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2799 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2800 *pBstr = SysAllocStringLen(nameW, len);
2801 HeapFree(GetProcessHeap(), 0, nameW);
2805 static WORD SLTG_ReadStringA(const char *ptr, char **str)
2810 bytelen = *(const WORD*)ptr;
2811 if(bytelen == 0xffff) return 2;
2812 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2813 memcpy(*str, ptr + 2, bytelen);
2814 (*str)[bytelen] = '\0';
2818 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2820 char *ptr = pLibBlk;
2823 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2824 FIXME("libblk magic = %04x\n", w);
2829 if((w = *(WORD*)ptr) != 0xffff) {
2830 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2835 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2837 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2839 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2842 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2845 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2846 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2848 pTypeLibImpl->LibAttr.lcid = 0;
2851 ptr += 4; /* skip res12 */
2853 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2856 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2859 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2862 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2863 ptr += sizeof(GUID);
2865 return ptr - (char*)pLibBlk;
2868 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2873 } sltg_ref_lookup_t;
2875 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
2876 HREFTYPE *typelib_ref)
2878 if(typeinfo_ref < table->num)
2880 *typelib_ref = table->refs[typeinfo_ref];
2884 ERR("Unable to find reference\n");
2889 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
2894 if((*pType & 0xe00) == 0xe00) {
2896 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2898 pTD = pTD->u.lptdesc;
2900 switch(*pType & 0x3f) {
2903 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2905 pTD = pTD->u.lptdesc;
2908 case VT_USERDEFINED:
2909 pTD->vt = VT_USERDEFINED;
2910 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2916 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2919 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2921 pTD->vt = VT_CARRAY;
2922 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2924 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2925 pTD->u.lpadesc->cDims = pSA->cDims;
2926 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2927 pSA->cDims * sizeof(SAFEARRAYBOUND));
2929 pTD = &pTD->u.lpadesc->tdescElem;
2935 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2939 pTD->vt = VT_SAFEARRAY;
2940 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2942 pTD = pTD->u.lptdesc;
2946 pTD->vt = *pType & 0x3f;
2955 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
2956 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
2958 /* Handle [in/out] first */
2959 if((*pType & 0xc000) == 0xc000)
2960 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2961 else if(*pType & 0x8000)
2962 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2963 else if(*pType & 0x4000)
2964 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2966 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2969 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2972 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2974 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2978 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2983 TLBRefType *ref_type;
2984 sltg_ref_lookup_t *table;
2985 HREFTYPE typelib_ref;
2987 if(pRef->magic != SLTG_REF_MAGIC) {
2988 FIXME("Ref magic = %x\n", pRef->magic);
2991 name = ( (char*)(&pRef->names) + pRef->number);
2993 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2994 table->num = pRef->number >> 3;
2996 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2998 /* We don't want the first href to be 0 */
2999 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3001 for(ref = 0; ref < pRef->number >> 3; ref++) {
3003 unsigned int lib_offs, type_num;
3005 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3007 name += SLTG_ReadStringA(name, &refname);
3008 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3009 FIXME("Can't sscanf ref\n");
3010 if(lib_offs != 0xffff) {
3011 TLBImpLib **import = &pTL->pImpLibs;
3014 if((*import)->offset == lib_offs)
3016 import = &(*import)->next;
3019 char fname[MAX_PATH+1];
3022 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3024 (*import)->offset = lib_offs;
3025 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3027 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3028 &(*import)->wVersionMajor,
3029 &(*import)->wVersionMinor,
3030 &(*import)->lcid, fname) != 4) {
3031 FIXME("can't sscanf ref %s\n",
3032 pNameTable + lib_offs + 40);
3034 len = strlen(fname);
3035 if(fname[len-1] != '#')
3036 FIXME("fname = %s\n", fname);
3037 fname[len-1] = '\0';
3038 (*import)->name = TLB_MultiByteToBSTR(fname);
3040 ref_type->pImpTLInfo = *import;
3042 /* Store a reference to IDispatch */
3043 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3044 pTL->dispatch_href = typelib_ref;
3046 } else { /* internal ref */
3047 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3049 ref_type->reference = typelib_ref;
3050 ref_type->index = type_num;
3052 HeapFree(GetProcessHeap(), 0, refname);
3053 list_add_tail(&pTL->ref_list, &ref_type->entry);
3055 table->refs[ref] = typelib_ref;
3058 if((BYTE)*name != SLTG_REF_MAGIC)
3059 FIXME("End of ref block magic = %x\n", *name);
3060 dump_TLBRefType(pTL);
3064 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3065 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3067 SLTG_ImplInfo *info;
3068 TLBImplType **ppImplType = &pTI->impltypelist;
3069 /* I don't really get this structure, usually it's 0x16 bytes
3070 long, but iuser.tlb contains some that are 0x18 bytes long.
3071 That's ok because we can use the next ptr to jump to the next
3072 one. But how do we know the length of the last one? The WORD
3073 at offs 0x8 might be the clue. For now I'm just assuming that
3074 the last one is the regular 0x16 bytes. */
3076 info = (SLTG_ImplInfo*)pBlk;
3078 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3079 sizeof(**ppImplType));
3080 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3081 (*ppImplType)->implflags = info->impltypeflags;
3082 pTI->TypeAttr.cImplTypes++;
3083 ppImplType = &(*ppImplType)->next;
3085 if(info->next == 0xffff)
3088 FIXME("Interface inheriting more than one interface\n");
3089 info = (SLTG_ImplInfo*)(pBlk + info->next);
3091 info++; /* see comment at top of function */
3095 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3096 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3098 TLBVarDesc **ppVarDesc = &pTI->varlist;
3099 BSTR bstrPrevName = NULL;
3100 SLTG_Variable *pItem;
3105 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3106 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3108 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3109 sizeof(**ppVarDesc));
3110 (*ppVarDesc)->vardesc.memid = pItem->memid;
3112 if (pItem->magic != SLTG_VAR_MAGIC &&
3113 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3114 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3118 if (pItem->name == 0xfffe)
3119 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3121 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3123 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3124 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3126 if (pItem->flags & 0x40) {
3127 TRACE_(typelib)("VAR_DISPATCH\n");
3128 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3130 else if (pItem->flags & 0x10) {
3131 TRACE_(typelib)("VAR_CONST\n");
3132 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3133 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3135 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3136 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3137 *(INT*)(pBlk + pItem->byte_offs);
3140 TRACE_(typelib)("VAR_PERINSTANCE\n");
3141 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3142 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3145 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3146 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3148 if (pItem->flags & 0x80)
3149 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3151 if(pItem->flags & 0x02)
3152 pType = &pItem->type;
3154 pType = (WORD*)(pBlk + pItem->type);
3156 if (pItem->flags & ~0xd2)
3157 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
3159 SLTG_DoElem(pType, pBlk,
3160 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3162 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3164 bstrPrevName = (*ppVarDesc)->Name;
3165 ppVarDesc = &((*ppVarDesc)->next);
3167 pTI->TypeAttr.cVars = cVars;
3170 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3171 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3173 SLTG_Function *pFunc;
3175 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3177 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3178 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3183 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3184 sizeof(**ppFuncDesc));
3186 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3187 case SLTG_FUNCTION_MAGIC:
3188 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3190 case SLTG_DISPATCH_FUNCTION_MAGIC:
3191 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3193 case SLTG_STATIC_FUNCTION_MAGIC:
3194 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3197 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3198 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3202 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3204 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3205 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3206 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3207 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3208 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3209 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3211 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3212 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3214 if(pFunc->retnextopt & 0x80)
3215 pType = &pFunc->rettype;
3217 pType = (WORD*)(pBlk + pFunc->rettype);
3219 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3221 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3222 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3223 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3224 (*ppFuncDesc)->pParamDesc =
3225 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3226 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3228 pArg = (WORD*)(pBlk + pFunc->arg_off);
3230 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3231 char *paramName = pNameTable + *pArg;
3233 /* If arg type follows then paramName points to the 2nd
3234 letter of the name, else the next WORD is an offset to
3235 the arg type and paramName points to the first letter.
3236 So let's take one char off paramName and see if we're
3237 pointing at an alpha-numeric char. However if *pArg is
3238 0xffff or 0xfffe then the param has no name, the former
3239 meaning that the next WORD is the type, the latter
3240 meaning that the next WORD is an offset to the type. */
3245 else if(*pArg == 0xfffe) {
3249 else if(paramName[-1] && !isalnum(paramName[-1]))
3254 if(HaveOffs) { /* the next word is an offset to type */
3255 pType = (WORD*)(pBlk + *pArg);
3256 SLTG_DoElem(pType, pBlk,
3257 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3262 pArg = SLTG_DoElem(pArg, pBlk,
3263 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3266 /* Are we an optional param ? */
3267 if((*ppFuncDesc)->funcdesc.cParams - param <=
3268 (*ppFuncDesc)->funcdesc.cParamsOpt)
3269 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3272 (*ppFuncDesc)->pParamDesc[param].Name =
3273 TLB_MultiByteToBSTR(paramName);
3277 ppFuncDesc = &((*ppFuncDesc)->next);
3278 if(pFunc->next == 0xffff) break;
3280 pTI->TypeAttr.cFuncs = cFuncs;
3283 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3284 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3285 SLTG_TypeInfoTail *pTITail)
3287 char *pFirstItem, *pNextItem;
3288 sltg_ref_lookup_t *ref_lookup = NULL;
3290 if(pTIHeader->href_table != 0xffffffff) {
3291 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3295 pFirstItem = pNextItem = pBlk;
3297 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3298 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3300 HeapFree(GetProcessHeap(), 0, ref_lookup);
3304 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3305 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3306 const SLTG_TypeInfoTail *pTITail)
3308 char *pFirstItem, *pNextItem;
3309 sltg_ref_lookup_t *ref_lookup = NULL;
3311 if(pTIHeader->href_table != 0xffffffff) {
3312 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3316 pFirstItem = pNextItem = pBlk;
3318 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3319 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3322 if (pTITail->funcs_off != 0xffff)
3323 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3325 HeapFree(GetProcessHeap(), 0, ref_lookup);
3327 if (TRACE_ON(typelib))
3328 dump_TLBFuncDesc(pTI->funclist);
3331 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3332 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3333 const SLTG_TypeInfoTail *pTITail)
3335 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3338 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3339 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3340 const SLTG_TypeInfoTail *pTITail)
3343 sltg_ref_lookup_t *ref_lookup = NULL;
3345 if (pTITail->simple_alias) {
3346 /* if simple alias, no more processing required */
3347 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3351 if(pTIHeader->href_table != 0xffffffff) {
3352 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3356 /* otherwise it is an offset to a type */
3357 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3359 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3361 HeapFree(GetProcessHeap(), 0, ref_lookup);
3364 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3365 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3366 const SLTG_TypeInfoTail *pTITail)
3368 sltg_ref_lookup_t *ref_lookup = NULL;
3369 if (pTIHeader->href_table != 0xffffffff)
3370 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3373 if (pTITail->vars_off != 0xffff)
3374 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3376 if (pTITail->funcs_off != 0xffff)
3377 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3379 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3380 * of dispinterface functons including the IDispatch ones, so
3381 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3382 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3384 HeapFree(GetProcessHeap(), 0, ref_lookup);
3385 if (TRACE_ON(typelib))
3386 dump_TLBFuncDesc(pTI->funclist);
3389 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3390 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3391 const SLTG_TypeInfoTail *pTITail)
3393 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3396 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3397 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3398 const SLTG_TypeInfoTail *pTITail)
3400 sltg_ref_lookup_t *ref_lookup = NULL;
3401 if (pTIHeader->href_table != 0xffffffff)
3402 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3405 if (pTITail->vars_off != 0xffff)
3406 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3408 if (pTITail->funcs_off != 0xffff)
3409 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3410 HeapFree(GetProcessHeap(), 0, ref_lookup);
3413 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3414 managable copy of it into this */
3427 } SLTG_InternalOtherTypeInfo;
3429 /****************************************************************************
3430 * ITypeLib2_Constructor_SLTG
3432 * loading a SLTG typelib from an in-memory image
3434 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3436 ITypeLibImpl *pTypeLibImpl;
3437 SLTG_Header *pHeader;
3438 SLTG_BlkEntry *pBlkEntry;
3442 LPVOID pBlk, pFirstBlk;
3443 SLTG_LibBlk *pLibBlk;
3444 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3445 char *pAfterOTIBlks = NULL;
3446 char *pNameTable, *ptr;
3449 ITypeInfoImpl **ppTypeInfoImpl;
3451 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3454 pTypeLibImpl = TypeLibImpl_Constructor();
3455 if (!pTypeLibImpl) return NULL;
3459 TRACE_(typelib)("header:\n");
3460 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3461 pHeader->nrOfFileBlks );
3462 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3463 FIXME("Header type magic 0x%08x not supported.\n",
3464 pHeader->SLTG_magic);
3468 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3469 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3471 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3472 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3474 /* Next we have a magic block */
3475 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3477 /* Let's see if we're still in sync */
3478 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3479 sizeof(SLTG_COMPOBJ_MAGIC))) {
3480 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3483 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3484 sizeof(SLTG_DIR_MAGIC))) {
3485 FIXME("dir magic = %s\n", pMagic->dir_magic);
3489 pIndex = (SLTG_Index*)(pMagic+1);
3491 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3493 pFirstBlk = (LPVOID)(pPad9 + 1);
3495 /* We'll set up a ptr to the main library block, which is the last one. */
3497 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3498 pBlkEntry[order].next != 0;
3499 order = pBlkEntry[order].next - 1, i++) {
3500 pBlk = (char*)pBlk + pBlkEntry[order].len;
3504 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3506 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3511 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3513 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3514 sizeof(*pOtherTypeInfoBlks) *
3515 pTypeLibImpl->TypeInfoCount);
3518 ptr = (char*)pLibBlk + len;
3520 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3524 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3526 w = *(WORD*)(ptr + 2);
3529 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3531 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3532 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3534 w = *(WORD*)(ptr + 4 + len);
3536 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3538 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3540 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3541 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3543 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3544 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3545 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3547 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3549 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3552 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3553 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3554 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3555 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3556 len += sizeof(SLTG_OtherTypeInfo);
3560 pAfterOTIBlks = ptr;
3562 /* Skip this WORD and get the next DWORD */
3563 len = *(DWORD*)(pAfterOTIBlks + 2);
3565 /* Now add this to pLibBLk look at what we're pointing at and
3566 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3567 dust and we should be pointing at the beginning of the name
3570 pNameTable = (char*)pLibBlk + len;
3572 switch(*(WORD*)pNameTable) {
3579 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3583 pNameTable += 0x216;
3587 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3589 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3592 /* Hopefully we now have enough ptrs set up to actually read in
3593 some TypeInfos. It's not clear which order to do them in, so
3594 I'll just follow the links along the BlkEntry chain and read
3595 them in the order in which they are in the file */
3597 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3599 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3600 pBlkEntry[order].next != 0;
3601 order = pBlkEntry[order].next - 1, i++) {
3603 SLTG_TypeInfoHeader *pTIHeader;
3604 SLTG_TypeInfoTail *pTITail;
3605 SLTG_MemberHeader *pMemHeader;
3607 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3608 pOtherTypeInfoBlks[i].index_name)) {
3609 FIXME("Index strings don't match\n");
3614 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3615 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3618 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3619 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3621 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3622 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3623 (*ppTypeInfoImpl)->index = i;
3624 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3625 pOtherTypeInfoBlks[i].name_offs +
3627 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3628 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3629 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3630 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3631 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3632 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3633 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3635 if((pTIHeader->typeflags1 & 7) != 2)
3636 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3637 if(pTIHeader->typeflags3 != 2)
3638 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3640 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3641 debugstr_w((*ppTypeInfoImpl)->Name),
3642 typekind_desc[pTIHeader->typekind],
3643 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3644 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3646 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3648 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3650 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3651 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3652 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3654 switch(pTIHeader->typekind) {
3656 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3657 pTIHeader, pTITail);
3661 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3662 pTIHeader, pTITail);
3665 case TKIND_INTERFACE:
3666 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3667 pTIHeader, pTITail);
3671 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3672 pTIHeader, pTITail);
3676 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3677 pTIHeader, pTITail);
3680 case TKIND_DISPATCH:
3681 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3682 pTIHeader, pTITail);
3686 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3687 pTIHeader, pTITail);
3691 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3696 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3697 but we've already set those */
3698 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3713 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3714 pBlk = (char*)pBlk + pBlkEntry[order].len;
3717 if(i != pTypeLibImpl->TypeInfoCount) {
3718 FIXME("Somehow processed %d TypeInfos\n", i);
3722 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3723 return (ITypeLib2*)pTypeLibImpl;
3726 /* ITypeLib::QueryInterface
3728 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3733 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3735 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3738 if(IsEqualIID(riid, &IID_IUnknown) ||
3739 IsEqualIID(riid,&IID_ITypeLib)||
3740 IsEqualIID(riid,&IID_ITypeLib2))
3747 ITypeLib2_AddRef(iface);
3748 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3751 TRACE("-- Interface: E_NOINTERFACE\n");
3752 return E_NOINTERFACE;
3757 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3759 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3760 ULONG ref = InterlockedIncrement(&This->ref);
3762 TRACE("(%p)->ref was %u\n",This, ref - 1);
3767 /* ITypeLib::Release
3769 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3771 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3772 ULONG ref = InterlockedDecrement(&This->ref);
3774 TRACE("(%p)->(%u)\n",This, ref);
3778 TLBImpLib *pImpLib, *pImpLibNext;
3779 TLBCustData *pCustData, *pCustDataNext;
3780 TLBRefType *ref_type;
3784 /* remove cache entry */
3787 TRACE("removing from cache list\n");
3788 EnterCriticalSection(&cache_section);
3789 if (This->next) This->next->prev = This->prev;
3790 if (This->prev) This->prev->next = This->next;
3791 else tlb_cache_first = This->next;
3792 LeaveCriticalSection(&cache_section);
3793 HeapFree(GetProcessHeap(), 0, This->path);
3795 TRACE(" destroying ITypeLib(%p)\n",This);
3799 SysFreeString(This->Name);
3803 if (This->DocString)
3805 SysFreeString(This->DocString);
3806 This->DocString = NULL;
3811 SysFreeString(This->HelpFile);
3812 This->HelpFile = NULL;
3815 if (This->HelpStringDll)
3817 SysFreeString(This->HelpStringDll);
3818 This->HelpStringDll = NULL;
3821 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3823 VariantClear(&pCustData->data);
3825 pCustDataNext = pCustData->next;
3826 TLB_Free(pCustData);
3829 for (i = 0; i < This->ctTypeDesc; i++)
3830 if (This->pTypeDesc[i].vt == VT_CARRAY)
3831 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3833 TLB_Free(This->pTypeDesc);
3835 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3837 if (pImpLib->pImpTypeLib)
3838 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3839 TLB_Free(pImpLib->name);
3841 pImpLibNext = pImpLib->next;
3845 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3847 list_remove(&ref_type->entry);
3851 if (This->pTypeInfo) /* can be NULL */
3852 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3853 HeapFree(GetProcessHeap(),0,This);
3860 /* ITypeLib::GetTypeInfoCount
3862 * Returns the number of type descriptions in the type library
3864 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3866 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3867 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3868 return This->TypeInfoCount;
3871 /* ITypeLib::GetTypeInfo
3873 * retrieves the specified type description in the library.
3875 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3878 ITypeInfo **ppTInfo)
3882 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3883 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3885 TRACE("(%p)->(index=%d)\n", This, index);
3887 if (!ppTInfo) return E_INVALIDARG;
3889 /* search element n in list */
3890 for(i=0; i < index; i++)
3892 pTypeInfo = pTypeInfo->next;
3895 TRACE("-- element not found\n");
3896 return TYPE_E_ELEMENTNOTFOUND;
3900 *ppTInfo = (ITypeInfo *) pTypeInfo;
3902 ITypeInfo_AddRef(*ppTInfo);
3903 TRACE("-- found (%p)\n",*ppTInfo);
3908 /* ITypeLibs::GetTypeInfoType
3910 * Retrieves the type of a type description.
3912 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3917 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3919 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3921 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
3922 return TYPE_E_ELEMENTNOTFOUND;
3924 TRACE("(%p) index %d\n", This, index);
3926 if(!pTKind) return E_INVALIDARG;
3928 /* search element n in list */
3929 for(i=0; i < index; i++)
3933 TRACE("-- element not found\n");
3934 return TYPE_E_ELEMENTNOTFOUND;
3936 pTInfo = pTInfo->next;
3939 *pTKind = pTInfo->TypeAttr.typekind;
3940 TRACE("-- found Type (%d)\n", *pTKind);
3944 /* ITypeLib::GetTypeInfoOfGuid
3946 * Retrieves the type description that corresponds to the specified GUID.
3949 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3952 ITypeInfo **ppTInfo)
3954 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3955 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3957 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3961 WARN("-- element not found\n");
3962 return TYPE_E_ELEMENTNOTFOUND;
3965 /* search linked list for guid */
3966 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3968 pTypeInfo = pTypeInfo->next;
3972 /* end of list reached */
3973 WARN("-- element not found\n");
3974 return TYPE_E_ELEMENTNOTFOUND;
3978 TRACE("-- found (%p, %s)\n",
3980 debugstr_w(pTypeInfo->Name));
3982 *ppTInfo = (ITypeInfo*)pTypeInfo;
3983 ITypeInfo_AddRef(*ppTInfo);
3987 /* ITypeLib::GetLibAttr
3989 * Retrieves the structure that contains the library's attributes.
3992 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3994 LPTLIBATTR *ppTLibAttr)
3996 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3997 TRACE("(%p)\n",This);
3998 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3999 **ppTLibAttr = This->LibAttr;
4003 /* ITypeLib::GetTypeComp
4005 * Enables a client compiler to bind to a library's types, variables,
4006 * constants, and global functions.
4009 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4011 ITypeComp **ppTComp)
4013 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4015 TRACE("(%p)->(%p)\n",This,ppTComp);
4016 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4017 ITypeComp_AddRef(*ppTComp);
4022 /* ITypeLib::GetDocumentation
4024 * Retrieves the library's documentation string, the complete Help file name
4025 * and path, and the context identifier for the library Help topic in the Help
4028 * On a successful return all non-null BSTR pointers will have been set,
4031 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4035 BSTR *pBstrDocString,
4036 DWORD *pdwHelpContext,
4037 BSTR *pBstrHelpFile)
4039 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4041 HRESULT result = E_INVALIDARG;
4046 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4048 pBstrName, pBstrDocString,
4049 pdwHelpContext, pBstrHelpFile);
4053 /* documentation for the typelib */
4058 if(!(*pBstrName = SysAllocString(This->Name)))
4066 if (This->DocString)
4068 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4071 else if (This->Name)
4073 if(!(*pBstrDocString = SysAllocString(This->Name)))
4077 *pBstrDocString = NULL;
4081 *pdwHelpContext = This->dwHelpContext;
4087 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4091 *pBstrHelpFile = NULL;
4098 /* for a typeinfo */
4099 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4101 if(SUCCEEDED(result))
4103 result = ITypeInfo_GetDocumentation(pTInfo,
4107 pdwHelpContext, pBstrHelpFile);
4109 ITypeInfo_Release(pTInfo);
4114 if (pBstrDocString) SysFreeString (*pBstrDocString);
4116 if (pBstrName) SysFreeString (*pBstrName);
4118 return STG_E_INSUFFICIENTMEMORY;
4123 * Indicates whether a passed-in string contains the name of a type or member
4124 * described in the library.
4127 static HRESULT WINAPI ITypeLib2_fnIsName(
4133 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4134 ITypeInfoImpl *pTInfo;
4135 TLBFuncDesc *pFInfo;
4138 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4140 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4144 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4145 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4146 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4147 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4148 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4149 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4150 goto ITypeLib2_fnIsName_exit;
4152 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4153 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4158 ITypeLib2_fnIsName_exit:
4159 TRACE("(%p)slow! search for %s: %s found!\n", This,
4160 debugstr_w(szNameBuf), *pfName?"NOT":"");
4165 /* ITypeLib::FindName
4167 * Finds occurrences of a type description in a type library. This may be used
4168 * to quickly verify that a name exists in a type library.
4171 static HRESULT WINAPI ITypeLib2_fnFindName(
4175 ITypeInfo **ppTInfo,
4179 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4180 ITypeInfoImpl *pTInfo;
4181 TLBFuncDesc *pFInfo;
4184 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4186 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4187 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4188 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4189 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4190 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4191 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4192 goto ITypeLib2_fnFindName_exit;
4195 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4196 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4198 ITypeLib2_fnFindName_exit:
4199 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4200 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4203 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4204 This, *pcFound, debugstr_w(szNameBuf), j);
4211 /* ITypeLib::ReleaseTLibAttr
4213 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4216 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4218 TLIBATTR *pTLibAttr)
4220 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4221 TRACE("freeing (%p)\n",This);
4222 HeapFree(GetProcessHeap(),0,pTLibAttr);
4226 /* ITypeLib2::GetCustData
4228 * gets the custom data
4230 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4235 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4236 TLBCustData *pCData;
4238 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4240 if( IsEqualIID(guid, &pCData->guid)) break;
4243 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4247 VariantInit( pVarVal);
4248 VariantCopy( pVarVal, &pCData->data);
4251 return E_INVALIDARG; /* FIXME: correct? */
4254 /* ITypeLib2::GetLibStatistics
4256 * Returns statistics about a type library that are required for efficient
4257 * sizing of hash tables.
4260 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4262 ULONG *pcUniqueNames,
4263 ULONG *pcchUniqueNames)
4265 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4267 FIXME("(%p): stub!\n", This);
4269 if(pcUniqueNames) *pcUniqueNames=1;
4270 if(pcchUniqueNames) *pcchUniqueNames=1;
4274 /* ITypeLib2::GetDocumentation2
4276 * Retrieves the library's documentation string, the complete Help file name
4277 * and path, the localization context to use, and the context ID for the
4278 * library Help topic in the Help file.
4281 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4285 BSTR *pbstrHelpString,
4286 DWORD *pdwHelpStringContext,
4287 BSTR *pbstrHelpStringDll)
4289 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4293 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4295 /* the help string should be obtained from the helpstringdll,
4296 * using the _DLLGetDocumentation function, based on the supplied
4297 * lcid. Nice to do sometime...
4301 /* documentation for the typelib */
4303 *pbstrHelpString=SysAllocString(This->DocString);
4304 if(pdwHelpStringContext)
4305 *pdwHelpStringContext=This->dwHelpContext;
4306 if(pbstrHelpStringDll)
4307 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4313 /* for a typeinfo */
4314 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4316 if(SUCCEEDED(result))
4318 ITypeInfo2 * pTInfo2;
4319 result = ITypeInfo_QueryInterface(pTInfo,
4321 (LPVOID*) &pTInfo2);
4323 if(SUCCEEDED(result))
4325 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4329 pdwHelpStringContext,
4330 pbstrHelpStringDll);
4332 ITypeInfo2_Release(pTInfo2);
4335 ITypeInfo_Release(pTInfo);
4341 /* ITypeLib2::GetAllCustData
4343 * Gets all custom data items for the library.
4346 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4348 CUSTDATA *pCustData)
4350 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4351 TLBCustData *pCData;
4353 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4354 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4355 if(pCustData->prgCustData ){
4356 pCustData->cCustData=This->ctCustData;
4357 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4358 pCustData->prgCustData[i].guid=pCData->guid;
4359 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4362 ERR(" OUT OF MEMORY!\n");
4363 return E_OUTOFMEMORY;
4368 static const ITypeLib2Vtbl tlbvt = {
4369 ITypeLib2_fnQueryInterface,
4371 ITypeLib2_fnRelease,
4372 ITypeLib2_fnGetTypeInfoCount,
4373 ITypeLib2_fnGetTypeInfo,
4374 ITypeLib2_fnGetTypeInfoType,
4375 ITypeLib2_fnGetTypeInfoOfGuid,
4376 ITypeLib2_fnGetLibAttr,
4377 ITypeLib2_fnGetTypeComp,
4378 ITypeLib2_fnGetDocumentation,
4380 ITypeLib2_fnFindName,
4381 ITypeLib2_fnReleaseTLibAttr,
4383 ITypeLib2_fnGetCustData,
4384 ITypeLib2_fnGetLibStatistics,
4385 ITypeLib2_fnGetDocumentation2,
4386 ITypeLib2_fnGetAllCustData
4390 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4392 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4394 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4397 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4399 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4401 return ITypeLib2_AddRef((ITypeLib2 *)This);
4404 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4406 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4408 return ITypeLib2_Release((ITypeLib2 *)This);
4411 static HRESULT WINAPI ITypeLibComp_fnBind(
4416 ITypeInfo ** ppTInfo,
4417 DESCKIND * pDescKind,
4420 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4421 ITypeInfoImpl *pTypeInfo;
4423 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4425 *pDescKind = DESCKIND_NONE;
4426 pBindPtr->lptcomp = NULL;
4429 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4431 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4433 /* FIXME: check wFlags here? */
4434 /* FIXME: we should use a hash table to look this info up using lHash
4435 * instead of an O(n) search */
4436 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4437 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4439 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4441 *pDescKind = DESCKIND_TYPECOMP;
4442 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4443 ITypeComp_AddRef(pBindPtr->lptcomp);
4444 TRACE("module or enum: %s\n", debugstr_w(szName));
4449 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4450 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4452 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4455 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4456 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4458 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4463 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4464 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4466 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4468 ITypeInfo *subtypeinfo;
4470 DESCKIND subdesckind;
4472 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4473 &subtypeinfo, &subdesckind, &subbindptr);
4474 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4476 TYPEDESC tdesc_appobject =
4479 (TYPEDESC *)pTypeInfo->hreftype
4483 const VARDESC vardesc_appobject =
4486 NULL, /* lpstrSchema */
4501 VAR_STATIC /* varkind */
4504 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4506 /* cleanup things filled in by Bind call so we can put our
4507 * application object data in there instead */
4508 switch (subdesckind)
4510 case DESCKIND_FUNCDESC:
4511 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4513 case DESCKIND_VARDESC:
4514 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4519 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4521 if (pTypeInfo->hreftype == -1)
4522 FIXME("no hreftype for interface %p\n", pTypeInfo);
4524 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4528 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4529 *ppTInfo = (ITypeInfo *)pTypeInfo;
4530 ITypeInfo_AddRef(*ppTInfo);
4536 TRACE("name not found %s\n", debugstr_w(szName));
4540 static HRESULT WINAPI ITypeLibComp_fnBindType(
4544 ITypeInfo ** ppTInfo,
4545 ITypeComp ** ppTComp)
4547 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4551 static const ITypeCompVtbl tlbtcvt =
4554 ITypeLibComp_fnQueryInterface,
4555 ITypeLibComp_fnAddRef,
4556 ITypeLibComp_fnRelease,
4558 ITypeLibComp_fnBind,
4559 ITypeLibComp_fnBindType
4562 /*================== ITypeInfo(2) Methods ===================================*/
4563 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4565 ITypeInfoImpl * pTypeInfoImpl;
4567 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4570 pTypeInfoImpl->lpVtbl = &tinfvt;
4571 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4572 pTypeInfoImpl->ref=1;
4573 pTypeInfoImpl->hreftype = -1;
4574 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4575 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4577 TRACE("(%p)\n", pTypeInfoImpl);
4578 return (ITypeInfo2*) pTypeInfoImpl;
4581 /* ITypeInfo::QueryInterface
4583 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4588 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4590 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4593 if(IsEqualIID(riid, &IID_IUnknown) ||
4594 IsEqualIID(riid,&IID_ITypeInfo)||
4595 IsEqualIID(riid,&IID_ITypeInfo2))
4599 ITypeInfo_AddRef(iface);
4600 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4603 TRACE("-- Interface: E_NOINTERFACE\n");
4604 return E_NOINTERFACE;
4607 /* ITypeInfo::AddRef
4609 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4611 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4612 ULONG ref = InterlockedIncrement(&This->ref);
4614 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4616 TRACE("(%p)->ref is %u\n",This, ref);
4620 /* ITypeInfo::Release
4622 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4624 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4625 ULONG ref = InterlockedDecrement(&This->ref);
4627 TRACE("(%p)->(%u)\n",This, ref);
4630 /* We don't release ITypeLib when ref=0 because
4631 it means that function is called by ITypeLib2_Release */
4632 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4634 TLBFuncDesc *pFInfo, *pFInfoNext;
4635 TLBVarDesc *pVInfo, *pVInfoNext;
4636 TLBImplType *pImpl, *pImplNext;
4638 TRACE("destroying ITypeInfo(%p)\n",This);
4640 if (This->no_free_data)
4645 SysFreeString(This->Name);
4649 if (This->DocString)
4651 SysFreeString(This->DocString);
4652 This->DocString = 0;
4657 SysFreeString(This->DllName);
4661 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4664 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4666 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4667 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4669 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4670 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4672 SysFreeString(pFInfo->pParamDesc[i].Name);
4674 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4675 TLB_Free(pFInfo->pParamDesc);
4676 TLB_FreeCustData(pFInfo->pCustData);
4677 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4678 SysFreeString(pFInfo->Entry);
4679 SysFreeString(pFInfo->HelpString);
4680 SysFreeString(pFInfo->Name);
4682 pFInfoNext = pFInfo->next;
4685 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4687 if (pVInfo->vardesc.varkind == VAR_CONST)
4689 VariantClear(pVInfo->vardesc.u.lpvarValue);
4690 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4692 TLB_FreeCustData(pVInfo->pCustData);
4693 SysFreeString(pVInfo->Name);
4694 pVInfoNext = pVInfo->next;
4697 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4699 TLB_FreeCustData(pImpl->pCustData);
4700 pImplNext = pImpl->next;
4703 TLB_FreeCustData(This->pCustData);
4708 ITypeInfo_Release((ITypeInfo*)This->next);
4711 HeapFree(GetProcessHeap(),0,This);
4717 /* ITypeInfo::GetTypeAttr
4719 * Retrieves a TYPEATTR structure that contains the attributes of the type
4723 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4724 LPTYPEATTR *ppTypeAttr)
4726 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4729 TRACE("(%p)\n",This);
4731 size = sizeof(**ppTypeAttr);
4732 if (This->TypeAttr.typekind == TKIND_ALIAS)
4733 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4735 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4737 return E_OUTOFMEMORY;
4739 **ppTypeAttr = This->TypeAttr;
4741 if (This->TypeAttr.typekind == TKIND_ALIAS)
4742 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4743 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4745 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4746 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4748 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4749 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4754 /* ITypeInfo::GetTypeComp
4756 * Retrieves the ITypeComp interface for the type description, which enables a
4757 * client compiler to bind to the type description's members.
4760 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4761 ITypeComp * *ppTComp)
4763 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4765 TRACE("(%p)->(%p)\n", This, ppTComp);
4767 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4768 ITypeComp_AddRef(*ppTComp);
4772 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4774 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4775 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4776 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4780 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4783 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4784 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4786 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4787 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4788 *buffer += sizeof(PARAMDESCEX);
4789 *pparamdescex_dest = *pparamdescex_src;
4790 VariantInit(&pparamdescex_dest->varDefaultValue);
4791 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4792 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4795 dest->u.paramdesc.pparamdescex = NULL;
4799 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4801 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4802 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4805 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4809 SIZE_T size = sizeof(*src);
4813 size += sizeof(*src->lprgscode) * src->cScodes;
4814 size += TLB_SizeElemDesc(&src->elemdescFunc);
4815 for (i = 0; i < src->cParams; i++)
4817 size += sizeof(ELEMDESC);
4818 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4821 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4822 if (!dest) return E_OUTOFMEMORY;
4825 if (dispinterface) /* overwrite funckind */
4826 dest->funckind = FUNC_DISPATCH;
4827 buffer = (char *)(dest + 1);
4829 dest->lprgscode = (SCODE *)buffer;
4830 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4831 buffer += sizeof(*src->lprgscode) * src->cScodes;
4833 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4836 SysFreeString((BSTR)dest);
4840 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4841 buffer += sizeof(ELEMDESC) * src->cParams;
4842 for (i = 0; i < src->cParams; i++)
4844 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4850 /* undo the above actions */
4851 for (i = i - 1; i >= 0; i--)
4852 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4853 TLB_FreeElemDesc(&dest->elemdescFunc);
4854 SysFreeString((BSTR)dest);
4858 /* special treatment for dispinterfaces: this makes functions appear
4859 * to return their [retval] value when it is really returning an
4861 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4863 if (dest->cParams &&
4864 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4866 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4867 if (elemdesc->tdesc.vt != VT_PTR)
4869 ERR("elemdesc should have started with VT_PTR instead of:\n");
4871 dump_ELEMDESC(elemdesc);
4872 return E_UNEXPECTED;
4875 /* copy last parameter to the return value. we are using a flat
4876 * buffer so there is no danger of leaking memory in
4878 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4880 /* remove the last parameter */
4884 /* otherwise this function is made to appear to have no return
4886 dest->elemdescFunc.tdesc.vt = VT_VOID;
4894 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4896 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4897 const TLBFuncDesc *pFDesc;
4900 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4905 *ppFuncDesc = &pFDesc->funcdesc;
4909 return TYPE_E_ELEMENTNOTFOUND;
4912 /* internal function to make the inherited interfaces' methods appear
4913 * part of the interface */
4914 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4915 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4917 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4919 UINT implemented_funcs = 0;
4924 *hrefoffset = DISPATCH_HREF_OFFSET;
4926 if(This->impltypelist)
4928 ITypeInfo *pSubTypeInfo;
4931 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4935 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4938 &sub_funcs, hrefoffset);
4939 implemented_funcs += sub_funcs;
4940 ITypeInfo_Release(pSubTypeInfo);
4943 *hrefoffset += DISPATCH_HREF_OFFSET;
4947 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4951 if (index < implemented_funcs)
4952 return E_INVALIDARG;
4953 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4957 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4959 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4962 switch (pTypeDesc->vt)
4964 case VT_USERDEFINED:
4965 pTypeDesc->u.hreftype += hrefoffset;
4969 pTypeDesc = pTypeDesc->u.lptdesc;
4972 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
4980 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
4983 for (i = 0; i < pFuncDesc->cParams; i++)
4984 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
4985 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
4988 /* ITypeInfo::GetFuncDesc
4990 * Retrieves the FUNCDESC structure that contains information about a
4991 * specified function.
4994 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4995 LPFUNCDESC *ppFuncDesc)
4997 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4998 const FUNCDESC *internal_funcdesc;
5000 UINT hrefoffset = 0;
5002 TRACE("(%p) index %d\n", This, index);
5004 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5005 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5006 &internal_funcdesc, NULL,
5009 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5010 &internal_funcdesc);
5013 WARN("description for function %d not found\n", index);
5017 hr = TLB_AllocAndInitFuncDesc(
5020 This->TypeAttr.typekind == TKIND_DISPATCH);
5022 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5023 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5025 TRACE("-- 0x%08x\n", hr);
5029 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5033 SIZE_T size = sizeof(*src);
5036 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5037 if (src->varkind == VAR_CONST)
5038 size += sizeof(VARIANT);
5039 size += TLB_SizeElemDesc(&src->elemdescVar);
5041 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5042 if (!dest) return E_OUTOFMEMORY;
5045 buffer = (char *)(dest + 1);
5046 if (src->lpstrSchema)
5049 dest->lpstrSchema = (LPOLESTR)buffer;
5050 len = strlenW(src->lpstrSchema);
5051 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5052 buffer += (len + 1) * sizeof(WCHAR);
5055 if (src->varkind == VAR_CONST)
5059 dest->u.lpvarValue = (VARIANT *)buffer;
5060 *dest->u.lpvarValue = *src->u.lpvarValue;
5061 buffer += sizeof(VARIANT);
5062 VariantInit(dest->u.lpvarValue);
5063 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5066 SysFreeString((BSTR)dest_ptr);
5070 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5073 if (src->varkind == VAR_CONST)
5074 VariantClear(dest->u.lpvarValue);
5075 SysFreeString((BSTR)dest);
5082 /* ITypeInfo::GetVarDesc
5084 * Retrieves a VARDESC structure that describes the specified variable.
5087 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5088 LPVARDESC *ppVarDesc)
5090 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5092 const TLBVarDesc *pVDesc;
5094 TRACE("(%p) index %d\n", This, index);
5096 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5100 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5102 return E_INVALIDARG;
5105 /* ITypeInfo_GetNames
5107 * Retrieves the variable with the specified member ID (or the name of the
5108 * property or method and its parameters) that correspond to the specified
5111 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5112 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5114 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5115 const TLBFuncDesc *pFDesc;
5116 const TLBVarDesc *pVDesc;
5118 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5119 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5122 /* function found, now return function and parameter names */
5123 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5126 *rgBstrNames=SysAllocString(pFDesc->Name);
5128 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5134 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5137 *rgBstrNames=SysAllocString(pVDesc->Name);
5142 if(This->impltypelist &&
5143 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5144 /* recursive search */
5147 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5149 if(SUCCEEDED(result))
5151 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5152 ITypeInfo_Release(pTInfo);
5155 WARN("Could not search inherited interface!\n");
5159 WARN("no names found\n");
5162 return TYPE_E_ELEMENTNOTFOUND;
5169 /* ITypeInfo::GetRefTypeOfImplType
5171 * If a type description describes a COM class, it retrieves the type
5172 * description of the implemented interface types. For an interface,
5173 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5177 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5182 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5185 const TLBImplType *pImpl = This->impltypelist;
5187 TRACE("(%p) index %d\n", This, index);
5188 if (TRACE_ON(ole)) dump_TypeInfo(This);
5192 /* only valid on dual interfaces;
5193 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5195 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5197 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5198 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5204 hr = TYPE_E_ELEMENTNOTFOUND;
5207 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5209 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5210 *pRefType = This->pTypeLib->dispatch_href;
5214 /* get element n from linked list */
5215 for(i=0; pImpl && i<index; i++)
5217 pImpl = pImpl->next;
5221 *pRefType = pImpl->hRef;
5223 hr = TYPE_E_ELEMENTNOTFOUND;
5229 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5231 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5237 /* ITypeInfo::GetImplTypeFlags
5239 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5240 * or base interface in a type description.
5242 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5243 UINT index, INT *pImplTypeFlags)
5245 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5249 TRACE("(%p) index %d\n", This, index);
5250 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5251 i++, pImpl=pImpl->next)
5253 if(i==index && pImpl){
5254 *pImplTypeFlags=pImpl->implflags;
5258 return TYPE_E_ELEMENTNOTFOUND;
5262 * Maps between member names and member IDs, and parameter names and
5265 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5266 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5268 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5269 const TLBFuncDesc *pFDesc;
5270 const TLBVarDesc *pVDesc;
5274 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5277 /* init out parameters in case of failure */
5278 for (i = 0; i < cNames; i++)
5279 pMemId[i] = MEMBERID_NIL;
5281 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5283 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5284 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5285 for(i=1; i < cNames; i++){
5286 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5287 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5289 if( j<pFDesc->funcdesc.cParams)
5292 ret=DISP_E_UNKNOWNNAME;
5294 TRACE("-- 0x%08x\n", ret);
5298 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5299 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5300 if(cNames) *pMemId=pVDesc->vardesc.memid;
5304 /* not found, see if it can be found in an inherited interface */
5305 if(This->impltypelist) {
5306 /* recursive search */
5308 ret=ITypeInfo_GetRefTypeInfo(iface,
5309 This->impltypelist->hRef, &pTInfo);
5311 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5312 ITypeInfo_Release(pTInfo);
5315 WARN("Could not search inherited interface!\n");
5317 WARN("no names found\n");
5318 return DISP_E_UNKNOWNNAME;
5321 /* ITypeInfo::Invoke
5323 * Invokes a method, or accesses a property of an object, that implements the
5324 * interface described by the type description.
5327 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5330 if (TRACE_ON(ole)) {
5332 TRACE("Calling %p(",func);
5333 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5345 res = func(args[0]);
5348 res = func(args[0],args[1]);
5351 res = func(args[0],args[1],args[2]);
5354 res = func(args[0],args[1],args[2],args[3]);
5357 res = func(args[0],args[1],args[2],args[3],args[4]);
5360 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5363 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5366 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5369 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5372 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5375 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5378 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]);
5381 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]);
5384 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]);
5387 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]);
5390 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]);
5393 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]);
5396 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]);
5399 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]);
5402 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]);
5405 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]);
5408 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]);
5411 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]);
5414 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]);
5417 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]);
5420 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]);
5423 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]);
5426 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]);
5429 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]);
5432 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]);
5435 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5441 FIXME("unsupported calling convention %d\n",callconv);
5445 TRACE("returns %08x\n",res);
5449 extern int _argsize(DWORD vt);
5451 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5454 ITypeInfo *tinfo2 = NULL;
5455 TYPEATTR *tattr = NULL;
5457 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5460 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5462 tdesc->u.hreftype, hr);
5465 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5468 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5469 ITypeInfo_Release(tinfo2);
5473 switch (tattr->typekind)
5480 tdesc = &tattr->tdescAlias;
5481 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5484 case TKIND_INTERFACE:
5485 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5491 case TKIND_DISPATCH:
5500 FIXME("TKIND_RECORD unhandled.\n");
5505 FIXME("TKIND_UNION unhandled.\n");
5510 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5514 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5515 ITypeInfo_Release(tinfo2);
5519 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5523 /* enforce only one level of pointer indirection */
5524 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5526 tdesc = tdesc->u.lptdesc;
5528 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5529 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5530 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5531 if ((tdesc->vt == VT_USERDEFINED) ||
5532 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5534 VARTYPE vt_userdefined = 0;
5535 const TYPEDESC *tdesc_userdefined = tdesc;
5536 if (tdesc->vt == VT_PTR)
5538 vt_userdefined = VT_BYREF;
5539 tdesc_userdefined = tdesc->u.lptdesc;
5541 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5543 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5544 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5546 *vt |= vt_userdefined;
5558 case VT_USERDEFINED:
5559 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5566 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5567 hr = DISP_E_BADVARTYPE;
5571 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5580 /***********************************************************************
5581 * DispCallFunc (OLEAUT32.@)
5583 * Invokes a function of the specifed calling convention, passing the
5584 * specified arguments and returns the result.
5587 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5588 * oVft [I] The offset in the vtable. See notes.
5589 * cc [I] Calling convention of the function to call.
5590 * vtReturn [I] The return type of the function.
5591 * cActuals [I] Number of parameters.
5592 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5593 * prgpvarg [I] The arguments to pass.
5594 * pvargResult [O] The return value of the function. Can be NULL.
5598 * Failure: HRESULT code.
5601 * The HRESULT return value of this function is not affected by the return
5602 * value of the user supplied function, which is returned in pvargResult.
5604 * If pvInstance is NULL then a non-object function is to be called and oVft
5605 * is the address of the function to call.
5607 * The cc parameter can be one of the following values:
5620 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5621 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5623 int i, argsize, argspos;
5627 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5628 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5629 pvargResult, V_VT(pvargResult));
5633 argsize++; /* for This pointer */
5635 for (i=0;i<cActuals;i++)
5637 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5638 dump_Variant(prgpvarg[i]);
5639 argsize += _argsize(prgvt[i]);
5641 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5646 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5650 for (i=0;i<cActuals;i++)
5652 VARIANT *arg = prgpvarg[i];
5653 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5654 if (prgvt[i] == VT_VARIANT)
5655 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5657 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5658 argspos += _argsize(prgvt[i]);
5663 FARPROC *vtable = *(FARPROC**)pvInstance;
5664 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5667 /* if we aren't invoking an object then the function pointer is stored
5669 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5671 if (pvargResult && (vtReturn != VT_EMPTY))
5673 TRACE("Method returned 0x%08x\n",hres);
5674 V_VT(pvargResult) = vtReturn;
5675 V_UI4(pvargResult) = hres;
5678 HeapFree(GetProcessHeap(),0,args);
5682 #define INVBUF_ELEMENT_SIZE \
5683 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5684 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5685 ((VARIANTARG *)(buffer))
5686 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5687 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5688 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5689 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5690 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5691 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5693 static HRESULT WINAPI ITypeInfo_fnInvoke(
5698 DISPPARAMS *pDispParams,
5699 VARIANT *pVarResult,
5700 EXCEPINFO *pExcepInfo,
5703 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5705 unsigned int var_index;
5708 const TLBFuncDesc *pFuncInfo;
5710 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5711 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5716 ERR("NULL pDispParams not allowed\n");
5717 return E_INVALIDARG;
5720 dump_DispParms(pDispParams);
5722 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5724 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5725 pDispParams->cNamedArgs, pDispParams->cArgs);
5726 return E_INVALIDARG;
5729 /* we do this instead of using GetFuncDesc since it will return a fake
5730 * FUNCDESC for dispinterfaces and we want the real function description */
5731 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5732 if ((memid == pFuncInfo->funcdesc.memid) &&
5733 (wFlags & pFuncInfo->funcdesc.invkind))
5737 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5741 TRACE("invoking:\n");
5742 dump_TLBFuncDescOne(pFuncInfo);
5745 switch (func_desc->funckind) {
5746 case FUNC_PUREVIRTUAL:
5747 case FUNC_VIRTUAL: {
5748 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5750 VARIANT retval; /* pointer for storing byref retvals in */
5751 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5752 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5753 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5754 UINT cNamedArgs = pDispParams->cNamedArgs;
5755 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5759 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5761 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5763 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5764 hres = DISP_E_PARAMNOTFOUND;
5767 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5769 rgdispidNamedArgs++;
5772 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5774 ERR("functions with the vararg attribute do not support named arguments\n");
5775 hres = DISP_E_NONAMEDARGS;
5779 for (i = 0; i < func_desc->cParams; i++)
5781 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5782 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5787 TRACE("changing args\n");
5788 for (i = 0; i < func_desc->cParams; i++)
5790 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5791 VARIANTARG *src_arg;
5797 for (j = 0; j < cNamedArgs; j++)
5798 if (rgdispidNamedArgs[j] == i)
5800 src_arg = &pDispParams->rgvarg[j];
5805 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5807 if (wParamFlags & PARAMFLAG_FRETVAL)
5809 /* under most conditions the caller is not allowed to
5810 * pass in a dispparam arg in the index of what would be
5811 * the retval parameter. however, there is an exception
5812 * where the extra parameter is used in an extra
5813 * IDispatch::Invoke below */
5814 if ((i < pDispParams->cArgs) &&
5815 ((func_desc->cParams != 1) || !pVarResult ||
5816 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5818 hres = DISP_E_BADPARAMCOUNT;
5822 /* note: this check is placed so that if the caller passes
5823 * in a VARIANTARG for the retval we just ignore it, like
5825 if (i == func_desc->cParams - 1)
5828 arg = prgpvarg[i] = &rgvarg[i];
5829 memset(arg, 0, sizeof(*arg));
5830 V_VT(arg) = rgvt[i];
5831 memset(&retval, 0, sizeof(retval));
5832 V_BYREF(arg) = &retval;
5836 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5837 hres = E_UNEXPECTED;
5843 dump_Variant(src_arg);
5845 if (rgvt[i] == VT_VARIANT)
5846 hres = VariantCopy(&rgvarg[i], src_arg);
5847 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5849 if (rgvt[i] == V_VT(src_arg))
5850 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5853 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5854 hres = VariantCopy(&missing_arg[i], src_arg);
5855 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5857 V_VT(&rgvarg[i]) = rgvt[i];
5859 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5862 SAFEARRAYBOUND bound;
5866 bound.cElements = pDispParams->cArgs-i;
5867 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5869 ERR("SafeArrayCreate failed\n");
5872 hres = SafeArrayAccessData(a, (LPVOID)&v);
5875 ERR("SafeArrayAccessData failed with %x\n", hres);
5878 for (j = 0; j < bound.cElements; j++)
5879 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5880 hres = SafeArrayUnaccessData(a);
5883 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5886 V_ARRAY(&rgvarg[i]) = a;
5887 V_VT(&rgvarg[i]) = rgvt[i];
5889 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5891 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5892 V_VT(&missing_arg[i]) = V_VT(src_arg);
5893 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5894 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5895 V_VT(&rgvarg[i]) = rgvt[i];
5897 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5899 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5900 V_VT(&rgvarg[i]) = rgvt[i];
5904 /* FIXME: this doesn't work for VT_BYREF arguments if
5905 * they are not the same type as in the paramdesc */
5906 V_VT(&rgvarg[i]) = V_VT(src_arg);
5907 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5908 V_VT(&rgvarg[i]) = rgvt[i];
5913 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5914 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5915 debugstr_VT(src_arg), debugstr_VF(src_arg));
5918 prgpvarg[i] = &rgvarg[i];
5920 else if (wParamFlags & PARAMFLAG_FOPT)
5923 arg = prgpvarg[i] = &rgvarg[i];
5924 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5926 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5932 VARIANTARG *missing_arg;
5933 /* if the function wants a pointer to a variant then
5934 * set that up, otherwise just pass the VT_ERROR in
5935 * the argument by value */
5936 if (rgvt[i] & VT_BYREF)
5938 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5939 V_VT(arg) = VT_VARIANT | VT_BYREF;
5940 V_VARIANTREF(arg) = missing_arg;
5944 V_VT(missing_arg) = VT_ERROR;
5945 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5950 hres = DISP_E_BADPARAMCOUNT;
5954 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5956 /* VT_VOID is a special case for return types, so it is not
5957 * handled in the general function */
5958 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5959 V_VT(&varresult) = VT_EMPTY;
5962 V_VT(&varresult) = 0;
5963 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5964 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5967 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5968 V_VT(&varresult), func_desc->cParams, rgvt,
5969 prgpvarg, &varresult);
5971 for (i = 0; i < func_desc->cParams; i++)
5973 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5974 if (wParamFlags & PARAMFLAG_FRETVAL)
5978 TRACE("[retval] value: ");
5979 dump_Variant(prgpvarg[i]);
5984 VariantInit(pVarResult);
5985 /* deref return value */
5986 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5989 /* free data stored in varresult. Note that
5990 * VariantClear doesn't do what we want because we are
5991 * working with byref types. */
5992 /* FIXME: clear safearrays, bstrs, records and
5993 * variants here too */
5994 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5995 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5997 if(*V_UNKNOWNREF(prgpvarg[i]))
5998 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6002 else if (i < pDispParams->cArgs)
6004 if (wParamFlags & PARAMFLAG_FOUT)
6006 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6008 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6009 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6013 ERR("failed to convert param %d to vt %d\n", i,
6014 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6018 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6019 func_desc->cParamsOpt < 0 &&
6020 i == func_desc->cParams-1)
6022 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6025 hres = SafeArrayGetUBound(a, 1, &ubound);
6028 ERR("SafeArrayGetUBound failed with %x\n", hres);
6031 hres = SafeArrayAccessData(a, (LPVOID)&v);
6034 ERR("SafeArrayAccessData failed with %x\n", hres);
6037 for (j = 0; j <= ubound; j++)
6038 VariantClear(&v[j]);
6039 hres = SafeArrayUnaccessData(a);
6042 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6046 VariantClear(&rgvarg[i]);
6048 else if (wParamFlags & PARAMFLAG_FOPT)
6050 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6051 VariantClear(&rgvarg[i]);
6055 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6057 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6058 hres = DISP_E_EXCEPTION;
6061 IErrorInfo *pErrorInfo;
6062 pExcepInfo->scode = V_ERROR(&varresult);
6063 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6065 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6066 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6067 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6068 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6070 IErrorInfo_Release(pErrorInfo);
6074 if (V_VT(&varresult) != VT_ERROR)
6076 TRACE("varresult value: ");
6077 dump_Variant(&varresult);
6081 VariantClear(pVarResult);
6082 *pVarResult = varresult;
6085 VariantClear(&varresult);
6088 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6089 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6090 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6091 (pDispParams->cArgs != 0))
6093 if (V_VT(pVarResult) == VT_DISPATCH)
6095 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6096 /* Note: not VariantClear; we still need the dispatch
6097 * pointer to be valid */
6098 VariantInit(pVarResult);
6099 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6100 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6101 pDispParams, pVarResult, pExcepInfo, pArgErr);
6102 IDispatch_Release(pDispatch);
6106 VariantClear(pVarResult);
6107 hres = DISP_E_NOTACOLLECTION;
6112 HeapFree(GetProcessHeap(), 0, buffer);
6115 case FUNC_DISPATCH: {
6118 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6119 if (SUCCEEDED(hres)) {
6120 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6121 hres = IDispatch_Invoke(
6122 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6123 pVarResult,pExcepInfo,pArgErr
6126 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6127 IDispatch_Release(disp);
6129 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6133 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6138 TRACE("-- 0x%08x\n", hres);
6141 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6144 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6145 if(FAILED(hres)) return hres;
6147 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6148 dump_VARDESC(var_desc);
6149 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6153 /* not found, look for it in inherited interfaces */
6154 ITypeInfo2_GetTypeKind(iface, &type_kind);
6155 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6156 if(This->impltypelist) {
6157 /* recursive search */
6159 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6160 if(SUCCEEDED(hres)){
6161 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6162 ITypeInfo_Release(pTInfo);
6165 WARN("Could not search inherited interface!\n");
6168 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6169 return DISP_E_MEMBERNOTFOUND;
6172 /* ITypeInfo::GetDocumentation
6174 * Retrieves the documentation string, the complete Help file name and path,
6175 * and the context ID for the Help topic for a specified type description.
6177 * (Can be tested by the Visual Basic Editor in Word for instance.)
6179 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6180 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6181 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6183 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6184 const TLBFuncDesc *pFDesc;
6185 const TLBVarDesc *pVDesc;
6186 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6187 " HelpContext(%p) HelpFile(%p)\n",
6188 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6189 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6191 *pBstrName=SysAllocString(This->Name);
6193 *pBstrDocString=SysAllocString(This->DocString);
6195 *pdwHelpContext=This->dwHelpContext;
6197 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6199 }else {/* for a member */
6200 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6201 if(pFDesc->funcdesc.memid==memid){
6203 *pBstrName = SysAllocString(pFDesc->Name);
6205 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6207 *pdwHelpContext=pFDesc->helpcontext;
6210 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6211 if(pVDesc->vardesc.memid==memid){
6213 *pBstrName = SysAllocString(pVDesc->Name);
6215 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6217 *pdwHelpContext=pVDesc->HelpContext;
6222 if(This->impltypelist &&
6223 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6224 /* recursive search */
6227 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6229 if(SUCCEEDED(result)) {
6230 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6231 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6232 ITypeInfo_Release(pTInfo);
6235 WARN("Could not search inherited interface!\n");
6238 WARN("member %d not found\n", memid);
6239 return TYPE_E_ELEMENTNOTFOUND;
6242 /* ITypeInfo::GetDllEntry
6244 * Retrieves a description or specification of an entry point for a function
6247 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6248 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6251 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6252 const TLBFuncDesc *pFDesc;
6254 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6256 if (pBstrDllName) *pBstrDllName = NULL;
6257 if (pBstrName) *pBstrName = NULL;
6258 if (pwOrdinal) *pwOrdinal = 0;
6260 if (This->TypeAttr.typekind != TKIND_MODULE)
6261 return TYPE_E_BADMODULEKIND;
6263 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6264 if(pFDesc->funcdesc.memid==memid){
6265 dump_TypeInfo(This);
6267 dump_TLBFuncDescOne(pFDesc);
6270 *pBstrDllName = SysAllocString(This->DllName);
6272 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6274 *pBstrName = SysAllocString(pFDesc->Entry);
6282 *pwOrdinal = (DWORD)pFDesc->Entry;
6285 return TYPE_E_ELEMENTNOTFOUND;
6288 /* internal function to make the inherited interfaces' methods appear
6289 * part of the interface */
6290 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6291 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6293 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6296 TRACE("%p, 0x%x\n", iface, *hRefType);
6298 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6300 ITypeInfo *pSubTypeInfo;
6302 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6306 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6308 ITypeInfo_Release(pSubTypeInfo);
6312 *hRefType -= DISPATCH_HREF_OFFSET;
6314 if (!(*hRefType & DISPATCH_HREF_MASK))
6315 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6320 /* ITypeInfo::GetRefTypeInfo
6322 * If a type description references other type descriptions, it retrieves
6323 * the referenced type descriptions.
6325 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6328 ITypeInfo **ppTInfo)
6330 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6331 HRESULT result = E_FAIL;
6333 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6335 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6336 ITypeInfo_AddRef(*ppTInfo);
6339 else if (hRefType == -1 &&
6340 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6341 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6343 /* when we meet a DUAL dispinterface, we must create the interface
6346 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6349 /* the interface version contains the same information as the dispinterface
6350 * copy the contents of the structs.
6352 *pTypeInfoImpl = *This;
6353 pTypeInfoImpl->ref = 0;
6355 /* change the type to interface */
6356 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6358 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6360 /* we use data structures from This, so we need to keep a reference
6361 * to it to stop it being destroyed and signal to the new instance to
6362 * not free its data structures when it is destroyed */
6363 pTypeInfoImpl->no_free_data = TRUE;
6364 pTypeInfoImpl->next = This;
6365 ITypeInfo_AddRef((ITypeInfo*) This);
6367 ITypeInfo_AddRef(*ppTInfo);
6371 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6372 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6373 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6375 HREFTYPE href_dispatch = hRefType;
6376 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6378 TLBRefType *ref_type;
6379 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6381 if(ref_type->reference == hRefType)
6384 if(&ref_type->entry == &This->pTypeLib->ref_list)
6386 FIXME("Can't find pRefType for ref %x\n", hRefType);
6389 if(hRefType != -1) {
6390 ITypeLib *pTLib = NULL;
6392 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6394 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6396 if(ref_type->pImpTLInfo->pImpTypeLib) {
6397 TRACE("typeinfo in imported typelib that is already loaded\n");
6398 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6399 ITypeLib2_AddRef(pTLib);
6402 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6403 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6404 ref_type->pImpTLInfo->wVersionMajor,
6405 ref_type->pImpTLInfo->wVersionMinor,
6406 ref_type->pImpTLInfo->lcid,
6409 if(!SUCCEEDED(result)) {
6410 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6411 result=LoadTypeLib(libnam, &pTLib);
6412 SysFreeString(libnam);
6414 if(SUCCEEDED(result)) {
6415 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6416 ITypeLib2_AddRef(pTLib);
6420 if(SUCCEEDED(result)) {
6421 if(ref_type->index == TLB_REF_USE_GUID)
6422 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6426 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6430 ITypeLib2_Release(pTLib);
6435 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6436 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6440 /* ITypeInfo::AddressOfMember
6442 * Retrieves the addresses of static functions or variables, such as those
6445 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6446 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6448 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6454 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6456 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6460 module = LoadLibraryW(dll);
6463 ERR("couldn't load %s\n", debugstr_w(dll));
6465 if (entry) SysFreeString(entry);
6466 return STG_E_FILENOTFOUND;
6468 /* FIXME: store library somewhere where we can free it */
6473 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6474 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6475 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6477 *ppv = GetProcAddress(module, entryA);
6479 ERR("function not found %s\n", debugstr_a(entryA));
6481 HeapFree(GetProcessHeap(), 0, entryA);
6485 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6487 ERR("function not found %d\n", ordinal);
6491 if (entry) SysFreeString(entry);
6494 return TYPE_E_DLLFUNCTIONNOTFOUND;
6499 /* ITypeInfo::CreateInstance
6501 * Creates a new instance of a type that describes a component object class
6504 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6505 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6507 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6511 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6517 WARN("Not able to aggregate\n");
6518 return CLASS_E_NOAGGREGATION;
6521 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6522 if(FAILED(hr)) return hr;
6524 if(pTA->typekind != TKIND_COCLASS)
6526 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6532 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6535 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6536 TRACE("GetActiveObject rets %08x\n", hr);
6539 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6540 IUnknown_Release(pUnk);
6545 hr = CoCreateInstance(&pTA->guid, NULL,
6546 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6550 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6554 /* ITypeInfo::GetMops
6556 * Retrieves marshalling information.
6558 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6561 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6562 FIXME("(%p) stub!\n", This);
6566 /* ITypeInfo::GetContainingTypeLib
6568 * Retrieves the containing type library and the index of the type description
6569 * within that type library.
6571 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6572 ITypeLib * *ppTLib, UINT *pIndex)
6574 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6576 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6578 *pIndex=This->index;
6579 TRACE("returning pIndex=%d\n", *pIndex);
6583 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6584 ITypeLib2_AddRef(*ppTLib);
6585 TRACE("returning ppTLib=%p\n", *ppTLib);
6591 /* ITypeInfo::ReleaseTypeAttr
6593 * Releases a TYPEATTR previously returned by GetTypeAttr.
6596 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6597 TYPEATTR* pTypeAttr)
6599 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6600 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6601 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6604 /* ITypeInfo::ReleaseFuncDesc
6606 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6608 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6610 FUNCDESC *pFuncDesc)
6612 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6615 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6617 for (i = 0; i < pFuncDesc->cParams; i++)
6618 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6619 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6621 SysFreeString((BSTR)pFuncDesc);
6624 /* ITypeInfo::ReleaseVarDesc
6626 * Releases a VARDESC previously returned by GetVarDesc.
6628 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6631 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6632 TRACE("(%p)->(%p)\n", This, pVarDesc);
6634 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6635 if (pVarDesc->varkind == VAR_CONST)
6636 VariantClear(pVarDesc->u.lpvarValue);
6637 SysFreeString((BSTR)pVarDesc);
6640 /* ITypeInfo2::GetTypeKind
6642 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6645 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6646 TYPEKIND *pTypeKind)
6648 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6649 *pTypeKind=This->TypeAttr.typekind;
6650 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6654 /* ITypeInfo2::GetTypeFlags
6656 * Returns the type flags without any allocations. This returns a DWORD type
6657 * flag, which expands the type flags without growing the TYPEATTR (type
6661 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6663 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6664 *pTypeFlags=This->TypeAttr.wTypeFlags;
6665 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6669 /* ITypeInfo2::GetFuncIndexOfMemId
6670 * Binds to a specific member based on a known DISPID, where the member name
6671 * is not known (for example, when binding to a default member).
6674 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6675 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6677 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6678 const TLBFuncDesc *pFuncInfo;
6682 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6683 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6689 result = TYPE_E_ELEMENTNOTFOUND;
6691 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6692 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6696 /* TypeInfo2::GetVarIndexOfMemId
6698 * Binds to a specific member based on a known DISPID, where the member name
6699 * is not known (for example, when binding to a default member).
6702 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6703 MEMBERID memid, UINT *pVarIndex)
6705 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6706 TLBVarDesc *pVarInfo;
6709 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6710 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6716 result = TYPE_E_ELEMENTNOTFOUND;
6718 TRACE("(%p) memid 0x%08x -> %s\n", This,
6719 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6723 /* ITypeInfo2::GetCustData
6725 * Gets the custom data
6727 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6732 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6733 TLBCustData *pCData;
6735 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6736 if( IsEqualIID(guid, &pCData->guid)) break;
6738 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6742 VariantInit( pVarVal);
6743 VariantCopy( pVarVal, &pCData->data);
6746 return E_INVALIDARG; /* FIXME: correct? */
6749 /* ITypeInfo2::GetFuncCustData
6751 * Gets the custom data
6753 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6759 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6760 TLBCustData *pCData=NULL;
6761 TLBFuncDesc * pFDesc;
6763 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6764 pFDesc=pFDesc->next);
6767 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6768 if( IsEqualIID(guid, &pCData->guid)) break;
6770 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6773 VariantInit( pVarVal);
6774 VariantCopy( pVarVal, &pCData->data);
6777 return E_INVALIDARG; /* FIXME: correct? */
6780 /* ITypeInfo2::GetParamCustData
6782 * Gets the custom data
6784 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6791 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6792 TLBCustData *pCData=NULL;
6793 TLBFuncDesc * pFDesc;
6796 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6798 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
6799 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6800 pCData = pCData->next)
6801 if( IsEqualIID(guid, &pCData->guid)) break;
6803 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6807 VariantInit( pVarVal);
6808 VariantCopy( pVarVal, &pCData->data);
6811 return E_INVALIDARG; /* FIXME: correct? */
6814 /* ITypeInfo2::GetVarCustData
6816 * Gets the custom data
6818 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6824 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6825 TLBCustData *pCData=NULL;
6826 TLBVarDesc * pVDesc;
6829 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6833 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6835 if( IsEqualIID(guid, &pCData->guid)) break;
6839 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6843 VariantInit( pVarVal);
6844 VariantCopy( pVarVal, &pCData->data);
6847 return E_INVALIDARG; /* FIXME: correct? */
6850 /* ITypeInfo2::GetImplCustData
6852 * Gets the custom data
6854 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6860 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6861 TLBCustData *pCData=NULL;
6862 TLBImplType * pRDesc;
6865 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6869 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6871 if( IsEqualIID(guid, &pCData->guid)) break;
6875 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6879 VariantInit( pVarVal);
6880 VariantCopy( pVarVal, &pCData->data);
6883 return E_INVALIDARG; /* FIXME: correct? */
6886 /* ITypeInfo2::GetDocumentation2
6888 * Retrieves the documentation string, the complete Help file name and path,
6889 * the localization context to use, and the context ID for the library Help
6890 * topic in the Help file.
6893 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6897 BSTR *pbstrHelpString,
6898 DWORD *pdwHelpStringContext,
6899 BSTR *pbstrHelpStringDll)
6901 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6902 const TLBFuncDesc *pFDesc;
6903 const TLBVarDesc *pVDesc;
6904 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6905 "HelpStringContext(%p) HelpStringDll(%p)\n",
6906 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6907 pbstrHelpStringDll );
6908 /* the help string should be obtained from the helpstringdll,
6909 * using the _DLLGetDocumentation function, based on the supplied
6910 * lcid. Nice to do sometime...
6912 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6914 *pbstrHelpString=SysAllocString(This->Name);
6915 if(pdwHelpStringContext)
6916 *pdwHelpStringContext=This->dwHelpStringContext;
6917 if(pbstrHelpStringDll)
6918 *pbstrHelpStringDll=
6919 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6921 }else {/* for a member */
6922 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6923 if(pFDesc->funcdesc.memid==memid){
6925 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6926 if(pdwHelpStringContext)
6927 *pdwHelpStringContext=pFDesc->HelpStringContext;
6928 if(pbstrHelpStringDll)
6929 *pbstrHelpStringDll=
6930 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6933 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6934 if(pVDesc->vardesc.memid==memid){
6936 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6937 if(pdwHelpStringContext)
6938 *pdwHelpStringContext=pVDesc->HelpStringContext;
6939 if(pbstrHelpStringDll)
6940 *pbstrHelpStringDll=
6941 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6945 return TYPE_E_ELEMENTNOTFOUND;
6948 /* ITypeInfo2::GetAllCustData
6950 * Gets all custom data items for the Type info.
6953 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6955 CUSTDATA *pCustData)
6957 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6958 TLBCustData *pCData;
6961 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6963 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6964 if(pCustData->prgCustData ){
6965 pCustData->cCustData=This->ctCustData;
6966 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6967 pCustData->prgCustData[i].guid=pCData->guid;
6968 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6971 ERR(" OUT OF MEMORY!\n");
6972 return E_OUTOFMEMORY;
6977 /* ITypeInfo2::GetAllFuncCustData
6979 * Gets all custom data items for the specified Function
6982 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6985 CUSTDATA *pCustData)
6987 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6988 TLBCustData *pCData;
6989 TLBFuncDesc * pFDesc;
6991 TRACE("(%p) index %d\n", This, index);
6992 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6993 pFDesc=pFDesc->next)
6996 pCustData->prgCustData =
6997 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6998 if(pCustData->prgCustData ){
6999 pCustData->cCustData=pFDesc->ctCustData;
7000 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7001 pCData = pCData->next){
7002 pCustData->prgCustData[i].guid=pCData->guid;
7003 VariantCopy(& pCustData->prgCustData[i].varValue,
7007 ERR(" OUT OF MEMORY!\n");
7008 return E_OUTOFMEMORY;
7012 return TYPE_E_ELEMENTNOTFOUND;
7015 /* ITypeInfo2::GetAllParamCustData
7017 * Gets all custom data items for the Functions
7020 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7021 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7023 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7024 TLBCustData *pCData=NULL;
7025 TLBFuncDesc * pFDesc;
7027 TRACE("(%p) index %d\n", This, indexFunc);
7028 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7029 pFDesc=pFDesc->next)
7031 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7032 pCustData->prgCustData =
7033 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7034 sizeof(CUSTDATAITEM));
7035 if(pCustData->prgCustData ){
7036 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7037 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7038 pCData; i++, pCData = pCData->next){
7039 pCustData->prgCustData[i].guid=pCData->guid;
7040 VariantCopy(& pCustData->prgCustData[i].varValue,
7044 ERR(" OUT OF MEMORY!\n");
7045 return E_OUTOFMEMORY;
7049 return TYPE_E_ELEMENTNOTFOUND;
7052 /* ITypeInfo2::GetAllVarCustData
7054 * Gets all custom data items for the specified Variable
7057 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7058 UINT index, CUSTDATA *pCustData)
7060 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7061 TLBCustData *pCData;
7062 TLBVarDesc * pVDesc;
7064 TRACE("(%p) index %d\n", This, index);
7065 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7066 pVDesc=pVDesc->next)
7069 pCustData->prgCustData =
7070 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7071 if(pCustData->prgCustData ){
7072 pCustData->cCustData=pVDesc->ctCustData;
7073 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7074 pCData = pCData->next){
7075 pCustData->prgCustData[i].guid=pCData->guid;
7076 VariantCopy(& pCustData->prgCustData[i].varValue,
7080 ERR(" OUT OF MEMORY!\n");
7081 return E_OUTOFMEMORY;
7085 return TYPE_E_ELEMENTNOTFOUND;
7088 /* ITypeInfo2::GetAllImplCustData
7090 * Gets all custom data items for the specified implementation type
7093 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7096 CUSTDATA *pCustData)
7098 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7099 TLBCustData *pCData;
7100 TLBImplType * pRDesc;
7102 TRACE("(%p) index %d\n", This, index);
7103 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7104 pRDesc=pRDesc->next)
7107 pCustData->prgCustData =
7108 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7109 if(pCustData->prgCustData ){
7110 pCustData->cCustData=pRDesc->ctCustData;
7111 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7112 pCData = pCData->next){
7113 pCustData->prgCustData[i].guid=pCData->guid;
7114 VariantCopy(& pCustData->prgCustData[i].varValue,
7118 ERR(" OUT OF MEMORY!\n");
7119 return E_OUTOFMEMORY;
7123 return TYPE_E_ELEMENTNOTFOUND;
7126 static const ITypeInfo2Vtbl tinfvt =
7129 ITypeInfo_fnQueryInterface,
7131 ITypeInfo_fnRelease,
7133 ITypeInfo_fnGetTypeAttr,
7134 ITypeInfo_fnGetTypeComp,
7135 ITypeInfo_fnGetFuncDesc,
7136 ITypeInfo_fnGetVarDesc,
7137 ITypeInfo_fnGetNames,
7138 ITypeInfo_fnGetRefTypeOfImplType,
7139 ITypeInfo_fnGetImplTypeFlags,
7140 ITypeInfo_fnGetIDsOfNames,
7142 ITypeInfo_fnGetDocumentation,
7143 ITypeInfo_fnGetDllEntry,
7144 ITypeInfo_fnGetRefTypeInfo,
7145 ITypeInfo_fnAddressOfMember,
7146 ITypeInfo_fnCreateInstance,
7147 ITypeInfo_fnGetMops,
7148 ITypeInfo_fnGetContainingTypeLib,
7149 ITypeInfo_fnReleaseTypeAttr,
7150 ITypeInfo_fnReleaseFuncDesc,
7151 ITypeInfo_fnReleaseVarDesc,
7153 ITypeInfo2_fnGetTypeKind,
7154 ITypeInfo2_fnGetTypeFlags,
7155 ITypeInfo2_fnGetFuncIndexOfMemId,
7156 ITypeInfo2_fnGetVarIndexOfMemId,
7157 ITypeInfo2_fnGetCustData,
7158 ITypeInfo2_fnGetFuncCustData,
7159 ITypeInfo2_fnGetParamCustData,
7160 ITypeInfo2_fnGetVarCustData,
7161 ITypeInfo2_fnGetImplTypeCustData,
7162 ITypeInfo2_fnGetDocumentation2,
7163 ITypeInfo2_fnGetAllCustData,
7164 ITypeInfo2_fnGetAllFuncCustData,
7165 ITypeInfo2_fnGetAllParamCustData,
7166 ITypeInfo2_fnGetAllVarCustData,
7167 ITypeInfo2_fnGetAllImplTypeCustData,
7170 /******************************************************************************
7171 * CreateDispTypeInfo [OLEAUT32.31]
7173 * Build type information for an object so it can be called through an
7174 * IDispatch interface.
7177 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7178 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7181 * This call allows an objects methods to be accessed through IDispatch, by
7182 * building an ITypeInfo object that IDispatch can use to call through.
7184 HRESULT WINAPI CreateDispTypeInfo(
7185 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7186 LCID lcid, /* [I] Locale Id */
7187 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7189 ITypeInfoImpl *pTIClass, *pTIIface;
7190 ITypeLibImpl *pTypeLibImpl;
7192 TLBFuncDesc **ppFuncDesc;
7196 pTypeLibImpl = TypeLibImpl_Constructor();
7197 if (!pTypeLibImpl) return E_FAIL;
7199 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7200 pTIIface->pTypeLib = pTypeLibImpl;
7201 pTIIface->index = 0;
7202 pTIIface->Name = NULL;
7203 pTIIface->dwHelpContext = -1;
7204 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7205 pTIIface->TypeAttr.lcid = lcid;
7206 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7207 pTIIface->TypeAttr.wMajorVerNum = 0;
7208 pTIIface->TypeAttr.wMinorVerNum = 0;
7209 pTIIface->TypeAttr.cbAlignment = 2;
7210 pTIIface->TypeAttr.cbSizeInstance = -1;
7211 pTIIface->TypeAttr.cbSizeVft = -1;
7212 pTIIface->TypeAttr.cFuncs = 0;
7213 pTIIface->TypeAttr.cImplTypes = 0;
7214 pTIIface->TypeAttr.cVars = 0;
7215 pTIIface->TypeAttr.wTypeFlags = 0;
7217 ppFuncDesc = &pTIIface->funclist;
7218 for(func = 0; func < pidata->cMembers; func++) {
7219 METHODDATA *md = pidata->pmethdata + func;
7220 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7221 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7222 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7223 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7224 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7225 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7226 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7227 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7228 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7229 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7230 (*ppFuncDesc)->funcdesc.cScodes = 0;
7231 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7232 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7233 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7234 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7235 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7236 md->cArgs * sizeof(ELEMDESC));
7237 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7238 md->cArgs * sizeof(TLBParDesc));
7239 for(param = 0; param < md->cArgs; param++) {
7240 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7241 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7243 (*ppFuncDesc)->helpcontext = 0;
7244 (*ppFuncDesc)->HelpStringContext = 0;
7245 (*ppFuncDesc)->HelpString = NULL;
7246 (*ppFuncDesc)->Entry = NULL;
7247 (*ppFuncDesc)->ctCustData = 0;
7248 (*ppFuncDesc)->pCustData = NULL;
7249 (*ppFuncDesc)->next = NULL;
7250 pTIIface->TypeAttr.cFuncs++;
7251 ppFuncDesc = &(*ppFuncDesc)->next;
7254 dump_TypeInfo(pTIIface);
7256 pTypeLibImpl->pTypeInfo = pTIIface;
7257 pTypeLibImpl->TypeInfoCount++;
7259 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7260 pTIClass->pTypeLib = pTypeLibImpl;
7261 pTIClass->index = 1;
7262 pTIClass->Name = NULL;
7263 pTIClass->dwHelpContext = -1;
7264 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7265 pTIClass->TypeAttr.lcid = lcid;
7266 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7267 pTIClass->TypeAttr.wMajorVerNum = 0;
7268 pTIClass->TypeAttr.wMinorVerNum = 0;
7269 pTIClass->TypeAttr.cbAlignment = 2;
7270 pTIClass->TypeAttr.cbSizeInstance = -1;
7271 pTIClass->TypeAttr.cbSizeVft = -1;
7272 pTIClass->TypeAttr.cFuncs = 0;
7273 pTIClass->TypeAttr.cImplTypes = 1;
7274 pTIClass->TypeAttr.cVars = 0;
7275 pTIClass->TypeAttr.wTypeFlags = 0;
7277 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7278 pTIClass->impltypelist->hRef = 0;
7280 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7283 ref->pImpTLInfo = TLB_REF_INTERNAL;
7284 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7286 dump_TypeInfo(pTIClass);
7288 pTIIface->next = pTIClass;
7289 pTypeLibImpl->TypeInfoCount++;
7291 *pptinfo = (ITypeInfo*)pTIClass;
7293 ITypeInfo_AddRef(*pptinfo);
7294 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7300 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7302 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7304 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7307 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7309 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7311 return ITypeInfo_AddRef((ITypeInfo *)This);
7314 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7316 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7318 return ITypeInfo_Release((ITypeInfo *)This);
7321 static HRESULT WINAPI ITypeComp_fnBind(
7326 ITypeInfo ** ppTInfo,
7327 DESCKIND * pDescKind,
7330 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7331 const TLBFuncDesc *pFDesc;
7332 const TLBVarDesc *pVDesc;
7333 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7335 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7337 *pDescKind = DESCKIND_NONE;
7338 pBindPtr->lpfuncdesc = NULL;
7341 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7342 if (!strcmpiW(pFDesc->Name, szName)) {
7343 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7346 /* name found, but wrong flags */
7347 hr = TYPE_E_TYPEMISMATCH;
7352 HRESULT hr = TLB_AllocAndInitFuncDesc(
7354 &pBindPtr->lpfuncdesc,
7355 This->TypeAttr.typekind == TKIND_DISPATCH);
7358 *pDescKind = DESCKIND_FUNCDESC;
7359 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7360 ITypeInfo_AddRef(*ppTInfo);
7363 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7364 if (!strcmpiW(pVDesc->Name, szName)) {
7365 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7368 *pDescKind = DESCKIND_VARDESC;
7369 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7370 ITypeInfo_AddRef(*ppTInfo);
7375 /* FIXME: search each inherited interface, not just the first */
7376 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7377 /* recursive search */
7381 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7384 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7385 ITypeInfo_Release(pTInfo);
7389 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7390 ITypeComp_Release(pTComp);
7393 WARN("Could not search inherited interface!\n");
7395 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7399 static HRESULT WINAPI ITypeComp_fnBindType(
7403 ITypeInfo ** ppTInfo,
7404 ITypeComp ** ppTComp)
7406 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7408 /* strange behaviour (does nothing) but like the
7411 if (!ppTInfo || !ppTComp)
7420 static const ITypeCompVtbl tcompvt =
7423 ITypeComp_fnQueryInterface,
7425 ITypeComp_fnRelease,
7428 ITypeComp_fnBindType