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 structures */
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,
2029 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2031 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2033 if(ref->reference == offset) return;
2036 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2037 list_add_tail(&pTL->ref_list, &ref->entry);
2039 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2040 /* external typelib */
2041 MSFT_ImpInfo impinfo;
2042 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2044 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2046 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2047 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2048 while (pImpLib){ /* search the known offsets of all import libraries */
2049 if(pImpLib->offset==impinfo.oImpFile) break;
2050 pImpLib=pImpLib->next;
2053 ref->reference = offset;
2054 ref->pImpTLInfo = pImpLib;
2055 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2056 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2057 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2058 ref->index = TLB_REF_USE_GUID;
2060 ref->index = impinfo.oGuid;
2062 ERR("Cannot find a reference\n");
2063 ref->reference = -1;
2064 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2067 /* in this typelib */
2068 ref->index = MSFT_HREFTYPE_INDEX(offset);
2069 ref->reference = offset;
2070 ref->pImpTLInfo = TLB_REF_INTERNAL;
2074 /* process Implemented Interfaces of a com class */
2075 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2079 MSFT_RefRecord refrec;
2080 TLBImplType **ppImpl = &pTI->impltypelist;
2082 TRACE_(typelib)("\n");
2084 for(i=0;i<count;i++){
2085 if(offset<0) break; /* paranoia */
2086 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2087 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2088 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2089 (*ppImpl)->hRef = refrec.reftype;
2090 (*ppImpl)->implflags=refrec.flags;
2091 (*ppImpl)->ctCustData=
2092 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2093 offset=refrec.onext;
2094 ppImpl=&((*ppImpl)->next);
2098 * process a typeinfo record
2100 static ITypeInfoImpl * MSFT_DoTypeInfo(
2103 ITypeLibImpl * pLibInfo)
2105 MSFT_TypeInfoBase tiBase;
2106 ITypeInfoImpl *ptiRet;
2108 TRACE_(typelib)("count=%u\n", count);
2110 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2111 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2112 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2114 /* this is where we are coming from */
2115 ptiRet->pTypeLib = pLibInfo;
2116 ptiRet->index=count;
2117 /* fill in the typeattr fields */
2119 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2120 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2121 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2122 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2123 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2124 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2125 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2126 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2127 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2128 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2129 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2130 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2131 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2132 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2133 MSFT_GetTdesc(pcx, tiBase.datatype1,
2134 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2137 /* IDLDESC idldescType; *//* never saw this one != zero */
2139 /* name, eventually add to a hash table */
2140 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2141 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2142 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2144 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2145 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2146 ptiRet->dwHelpContext=tiBase.helpcontext;
2148 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2149 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2151 /* note: InfoType's Help file and HelpStringDll come from the containing
2152 * library. Further HelpString and Docstring appear to be the same thing :(
2155 if(ptiRet->TypeAttr.cFuncs >0 )
2156 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2157 ptiRet->TypeAttr.cVars,
2158 tiBase.memoffset, & ptiRet->funclist);
2160 if(ptiRet->TypeAttr.cVars >0 )
2161 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2162 ptiRet->TypeAttr.cVars,
2163 tiBase.memoffset, & ptiRet->varlist);
2164 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2165 switch(ptiRet->TypeAttr.typekind)
2168 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2171 case TKIND_DISPATCH:
2172 /* This is not -1 when the interface is a non-base dual interface or
2173 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2174 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2178 if (tiBase.datatype1 != -1)
2180 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2181 ptiRet->impltypelist->hRef = tiBase.datatype1;
2182 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2186 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2187 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2188 ptiRet->impltypelist->hRef = tiBase.datatype1;
2193 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2195 TRACE_(typelib)("%s guid: %s kind:%s\n",
2196 debugstr_w(ptiRet->Name),
2197 debugstr_guid(&ptiRet->TypeAttr.guid),
2198 typekind_desc[ptiRet->TypeAttr.typekind]);
2203 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2204 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2205 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2208 static ITypeLibImpl *tlb_cache_first;
2209 static CRITICAL_SECTION cache_section;
2210 static CRITICAL_SECTION_DEBUG cache_section_debug =
2212 0, 0, &cache_section,
2213 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2214 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2216 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2219 typedef struct TLB_PEFile
2221 const IUnknownVtbl *lpvtbl;
2224 HRSRC typelib_resource;
2225 HGLOBAL typelib_global;
2226 LPVOID typelib_base;
2229 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2231 if (IsEqualIID(riid, &IID_IUnknown))
2234 IUnknown_AddRef(iface);
2238 return E_NOINTERFACE;
2241 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2243 TLB_PEFile *This = (TLB_PEFile *)iface;
2244 return InterlockedIncrement(&This->refs);
2247 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2249 TLB_PEFile *This = (TLB_PEFile *)iface;
2250 ULONG refs = InterlockedDecrement(&This->refs);
2253 if (This->typelib_global)
2254 FreeResource(This->typelib_global);
2256 FreeLibrary(This->dll);
2257 HeapFree(GetProcessHeap(), 0, This);
2262 static const IUnknownVtbl TLB_PEFile_Vtable =
2264 TLB_PEFile_QueryInterface,
2269 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2273 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2275 return E_OUTOFMEMORY;
2277 This->lpvtbl = &TLB_PEFile_Vtable;
2280 This->typelib_resource = NULL;
2281 This->typelib_global = NULL;
2282 This->typelib_base = NULL;
2284 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2285 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2289 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2290 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2291 if (This->typelib_resource)
2293 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2294 if (This->typelib_global)
2296 This->typelib_base = LockResource(This->typelib_global);
2298 if (This->typelib_base)
2300 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2301 *ppBase = This->typelib_base;
2302 *ppFile = (IUnknown *)&This->lpvtbl;
2309 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2310 return TYPE_E_CANTLOADLIBRARY;
2314 typedef struct TLB_Mapping
2316 const IUnknownVtbl *lpvtbl;
2320 LPVOID typelib_base;
2323 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2325 if (IsEqualIID(riid, &IID_IUnknown))
2328 IUnknown_AddRef(iface);
2332 return E_NOINTERFACE;
2335 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2337 TLB_Mapping *This = (TLB_Mapping *)iface;
2338 return InterlockedIncrement(&This->refs);
2341 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2343 TLB_Mapping *This = (TLB_Mapping *)iface;
2344 ULONG refs = InterlockedDecrement(&This->refs);
2347 if (This->typelib_base)
2348 UnmapViewOfFile(This->typelib_base);
2350 CloseHandle(This->mapping);
2351 if (This->file != INVALID_HANDLE_VALUE)
2352 CloseHandle(This->file);
2353 HeapFree(GetProcessHeap(), 0, This);
2358 static const IUnknownVtbl TLB_Mapping_Vtable =
2360 TLB_Mapping_QueryInterface,
2365 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2369 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2371 return E_OUTOFMEMORY;
2373 This->lpvtbl = &TLB_Mapping_Vtable;
2375 This->file = INVALID_HANDLE_VALUE;
2376 This->mapping = NULL;
2377 This->typelib_base = NULL;
2379 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2380 if (INVALID_HANDLE_VALUE != This->file)
2382 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2385 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2386 if(This->typelib_base)
2388 /* retrieve file size */
2389 *pdwTLBLength = GetFileSize(This->file, NULL);
2390 *ppBase = This->typelib_base;
2391 *ppFile = (IUnknown *)&This->lpvtbl;
2397 IUnknown_Release((IUnknown *)&This->lpvtbl);
2398 return TYPE_E_CANTLOADLIBRARY;
2401 /****************************************************************************
2404 * find the type of the typelib file and map the typelib resource into
2407 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2408 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2409 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2411 ITypeLibImpl *entry;
2414 LPWSTR index_str, file = (LPWSTR)pszFileName;
2415 LPVOID pBase = NULL;
2416 DWORD dwTLBLength = 0;
2417 IUnknown *pFile = NULL;
2421 index_str = strrchrW(pszFileName, '\\');
2422 if(index_str && *++index_str != '\0')
2425 long idx = strtolW(index_str, &end_ptr, 10);
2426 if(*end_ptr == '\0')
2428 int str_len = index_str - pszFileName - 1;
2430 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2431 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2436 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2438 if(strchrW(file, '\\'))
2440 lstrcpyW(pszPath, file);
2444 int len = GetSystemDirectoryW(pszPath, cchPath);
2445 pszPath[len] = '\\';
2446 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2450 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2452 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2454 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2455 EnterCriticalSection(&cache_section);
2456 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2458 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2460 TRACE("cache hit\n");
2461 *ppTypeLib = (ITypeLib2*)entry;
2462 ITypeLib_AddRef(*ppTypeLib);
2463 LeaveCriticalSection(&cache_section);
2467 LeaveCriticalSection(&cache_section);
2469 /* now actually load and parse the typelib */
2471 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2472 if (ret == TYPE_E_CANTLOADLIBRARY)
2473 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2476 if (dwTLBLength >= 4)
2478 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2479 if (dwSignature == MSFT_SIGNATURE)
2480 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2481 else if (dwSignature == SLTG_SIGNATURE)
2482 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2485 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2486 ret = TYPE_E_CANTLOADLIBRARY;
2490 ret = TYPE_E_CANTLOADLIBRARY;
2491 IUnknown_Release(pFile);
2495 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2497 TRACE("adding to cache\n");
2498 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2499 lstrcpyW(impl->path, pszPath);
2500 /* We should really canonicalise the path here. */
2501 impl->index = index;
2503 /* FIXME: check if it has added already in the meantime */
2504 EnterCriticalSection(&cache_section);
2505 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2507 tlb_cache_first = impl;
2508 LeaveCriticalSection(&cache_section);
2511 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2516 /*================== ITypeLib(2) Methods ===================================*/
2518 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2520 ITypeLibImpl* pTypeLibImpl;
2522 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2523 if (!pTypeLibImpl) return NULL;
2525 pTypeLibImpl->lpVtbl = &tlbvt;
2526 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2527 pTypeLibImpl->ref = 1;
2529 list_init(&pTypeLibImpl->ref_list);
2530 pTypeLibImpl->dispatch_href = -1;
2532 return pTypeLibImpl;
2535 /****************************************************************************
2536 * ITypeLib2_Constructor_MSFT
2538 * loading an MSFT typelib from an in-memory image
2540 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2544 MSFT_Header tlbHeader;
2545 MSFT_SegDir tlbSegDir;
2546 ITypeLibImpl * pTypeLibImpl;
2548 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2550 pTypeLibImpl = TypeLibImpl_Constructor();
2551 if (!pTypeLibImpl) return NULL;
2553 /* get pointer to beginning of typelib data */
2557 cx.pLibInfo = pTypeLibImpl;
2558 cx.length = dwTLBLength;
2561 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2562 TRACE_(typelib)("header:\n");
2563 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2564 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2565 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2568 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2570 /* there is a small amount of information here until the next important
2572 * the segment directory . Try to calculate the amount of data */
2573 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2575 /* now read the segment directory */
2576 TRACE("read segment directory (at %ld)\n",lPSegDir);
2577 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2578 cx.pTblDir = &tlbSegDir;
2580 /* just check two entries */
2581 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2583 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2584 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2588 /* now fill our internal data */
2589 /* TLIBATTR fields */
2590 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2592 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2593 /* Windows seems to have zero here, is this correct? */
2594 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2595 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2597 pTypeLibImpl->LibAttr.lcid = 0;
2599 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2600 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2601 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2602 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2604 /* name, eventually add to a hash table */
2605 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2608 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2609 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2611 if( tlbHeader.varflags & HELPDLLFLAG)
2614 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2615 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2618 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2621 if(tlbHeader.CustomDataOffset >= 0)
2623 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2626 /* fill in type descriptions */
2627 if(tlbSegDir.pTypdescTab.length > 0)
2629 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2631 pTypeLibImpl->ctTypeDesc = cTD;
2632 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2633 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2636 /* FIXME: add several sanity checks here */
2637 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2638 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2640 /* FIXME: check safearray */
2642 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2644 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2646 else if(td[0] == VT_CARRAY)
2648 /* array descr table here */
2649 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2651 else if(td[0] == VT_USERDEFINED)
2653 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2655 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2658 /* second time around to fill the array subscript info */
2661 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2662 if(tlbSegDir.pArrayDescriptions.offset>0)
2664 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2665 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2668 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2670 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2672 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2674 for(j = 0; j<td[2]; j++)
2676 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2677 sizeof(INT), &cx, DO_NOT_SEEK);
2678 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2679 sizeof(INT), &cx, DO_NOT_SEEK);
2684 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2685 ERR("didn't find array description data\n");
2690 /* imported type libs */
2691 if(tlbSegDir.pImpFiles.offset>0)
2693 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2694 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2697 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2702 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2703 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2704 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2706 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2707 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2708 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2709 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2712 name = TLB_Alloc(size+1);
2713 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2714 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2715 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2716 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2719 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2720 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2722 ppImpLib = &(*ppImpLib)->next;
2726 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2727 if(pTypeLibImpl->dispatch_href != -1)
2728 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2731 if(tlbHeader.nrtypeinfos >= 0 )
2733 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2734 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2737 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2739 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2741 ppTI = &((*ppTI)->next);
2742 (pTypeLibImpl->TypeInfoCount)++;
2746 TRACE("(%p)\n", pTypeLibImpl);
2747 return (ITypeLib2*) pTypeLibImpl;
2751 static BSTR TLB_MultiByteToBSTR(const char *ptr)
2757 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2758 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2759 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2760 ret = SysAllocString(nameW);
2761 HeapFree(GetProcessHeap(), 0, nameW);
2765 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2771 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2772 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2776 guid->Data4[0] = s >> 8;
2777 guid->Data4[1] = s & 0xff;
2780 for(i = 0; i < 6; i++) {
2781 memcpy(b, str + 24 + 2 * i, 2);
2782 guid->Data4[i + 2] = strtol(b, NULL, 16);
2787 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
2794 bytelen = *(const WORD*)ptr;
2795 if(bytelen == 0xffff) return 2;
2796 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2797 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2798 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2799 *pBstr = SysAllocStringLen(nameW, len);
2800 HeapFree(GetProcessHeap(), 0, nameW);
2804 static WORD SLTG_ReadStringA(const char *ptr, char **str)
2809 bytelen = *(const WORD*)ptr;
2810 if(bytelen == 0xffff) return 2;
2811 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2812 memcpy(*str, ptr + 2, bytelen);
2813 (*str)[bytelen] = '\0';
2817 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2819 char *ptr = pLibBlk;
2822 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2823 FIXME("libblk magic = %04x\n", w);
2828 if((w = *(WORD*)ptr) != 0xffff) {
2829 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2834 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2836 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2838 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2841 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2844 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2845 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2847 pTypeLibImpl->LibAttr.lcid = 0;
2850 ptr += 4; /* skip res12 */
2852 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2855 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2858 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2861 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2862 ptr += sizeof(GUID);
2864 return ptr - (char*)pLibBlk;
2867 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2872 } sltg_ref_lookup_t;
2874 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
2875 HREFTYPE *typelib_ref)
2877 if(typeinfo_ref < table->num)
2879 *typelib_ref = table->refs[typeinfo_ref];
2883 ERR("Unable to find reference\n");
2888 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
2893 if((*pType & 0xe00) == 0xe00) {
2895 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2897 pTD = pTD->u.lptdesc;
2899 switch(*pType & 0x3f) {
2902 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2904 pTD = pTD->u.lptdesc;
2907 case VT_USERDEFINED:
2908 pTD->vt = VT_USERDEFINED;
2909 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2915 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2918 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2920 pTD->vt = VT_CARRAY;
2921 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2923 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2924 pTD->u.lpadesc->cDims = pSA->cDims;
2925 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2926 pSA->cDims * sizeof(SAFEARRAYBOUND));
2928 pTD = &pTD->u.lpadesc->tdescElem;
2934 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2938 pTD->vt = VT_SAFEARRAY;
2939 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2941 pTD = pTD->u.lptdesc;
2945 pTD->vt = *pType & 0x3f;
2954 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
2955 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
2957 /* Handle [in/out] first */
2958 if((*pType & 0xc000) == 0xc000)
2959 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2960 else if(*pType & 0x8000)
2961 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2962 else if(*pType & 0x4000)
2963 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2965 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2968 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2971 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2973 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2977 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2982 TLBRefType *ref_type;
2983 sltg_ref_lookup_t *table;
2984 HREFTYPE typelib_ref;
2986 if(pRef->magic != SLTG_REF_MAGIC) {
2987 FIXME("Ref magic = %x\n", pRef->magic);
2990 name = ( (char*)(&pRef->names) + pRef->number);
2992 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2993 table->num = pRef->number >> 3;
2995 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2997 /* We don't want the first href to be 0 */
2998 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3000 for(ref = 0; ref < pRef->number >> 3; ref++) {
3002 unsigned int lib_offs, type_num;
3004 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3006 name += SLTG_ReadStringA(name, &refname);
3007 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3008 FIXME("Can't sscanf ref\n");
3009 if(lib_offs != 0xffff) {
3010 TLBImpLib **import = &pTL->pImpLibs;
3013 if((*import)->offset == lib_offs)
3015 import = &(*import)->next;
3018 char fname[MAX_PATH+1];
3021 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3023 (*import)->offset = lib_offs;
3024 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3026 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3027 &(*import)->wVersionMajor,
3028 &(*import)->wVersionMinor,
3029 &(*import)->lcid, fname) != 4) {
3030 FIXME("can't sscanf ref %s\n",
3031 pNameTable + lib_offs + 40);
3033 len = strlen(fname);
3034 if(fname[len-1] != '#')
3035 FIXME("fname = %s\n", fname);
3036 fname[len-1] = '\0';
3037 (*import)->name = TLB_MultiByteToBSTR(fname);
3039 ref_type->pImpTLInfo = *import;
3041 /* Store a reference to IDispatch */
3042 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3043 pTL->dispatch_href = typelib_ref;
3045 } else { /* internal ref */
3046 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3048 ref_type->reference = typelib_ref;
3049 ref_type->index = type_num;
3051 HeapFree(GetProcessHeap(), 0, refname);
3052 list_add_tail(&pTL->ref_list, &ref_type->entry);
3054 table->refs[ref] = typelib_ref;
3057 if((BYTE)*name != SLTG_REF_MAGIC)
3058 FIXME("End of ref block magic = %x\n", *name);
3059 dump_TLBRefType(pTL);
3063 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3064 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3066 SLTG_ImplInfo *info;
3067 TLBImplType **ppImplType = &pTI->impltypelist;
3068 /* I don't really get this structure, usually it's 0x16 bytes
3069 long, but iuser.tlb contains some that are 0x18 bytes long.
3070 That's ok because we can use the next ptr to jump to the next
3071 one. But how do we know the length of the last one? The WORD
3072 at offs 0x8 might be the clue. For now I'm just assuming that
3073 the last one is the regular 0x16 bytes. */
3075 info = (SLTG_ImplInfo*)pBlk;
3077 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3078 sizeof(**ppImplType));
3079 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3080 (*ppImplType)->implflags = info->impltypeflags;
3081 pTI->TypeAttr.cImplTypes++;
3082 ppImplType = &(*ppImplType)->next;
3084 if(info->next == 0xffff)
3087 FIXME("Interface inheriting more than one interface\n");
3088 info = (SLTG_ImplInfo*)(pBlk + info->next);
3090 info++; /* see comment at top of function */
3094 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3095 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3097 TLBVarDesc **ppVarDesc = &pTI->varlist;
3098 BSTR bstrPrevName = NULL;
3099 SLTG_Variable *pItem;
3104 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3105 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3107 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3108 sizeof(**ppVarDesc));
3109 (*ppVarDesc)->vardesc.memid = pItem->memid;
3111 if (pItem->magic != SLTG_VAR_MAGIC &&
3112 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3113 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3117 if (pItem->name == 0xfffe)
3118 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3120 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3122 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3123 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3125 if (pItem->flags & 0x40) {
3126 TRACE_(typelib)("VAR_DISPATCH\n");
3127 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3129 else if (pItem->flags & 0x10) {
3130 TRACE_(typelib)("VAR_CONST\n");
3131 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3132 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3134 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3135 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3136 *(INT*)(pBlk + pItem->byte_offs);
3139 TRACE_(typelib)("VAR_PERINSTANCE\n");
3140 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3141 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3144 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3145 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3147 if (pItem->flags & 0x80)
3148 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3150 if(pItem->flags & 0x02)
3151 pType = &pItem->type;
3153 pType = (WORD*)(pBlk + pItem->type);
3155 if (pItem->flags & ~0xd2)
3156 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
3158 SLTG_DoElem(pType, pBlk,
3159 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3161 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3163 bstrPrevName = (*ppVarDesc)->Name;
3164 ppVarDesc = &((*ppVarDesc)->next);
3166 pTI->TypeAttr.cVars = cVars;
3169 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3170 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3172 SLTG_Function *pFunc;
3174 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3176 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3177 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3182 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3183 sizeof(**ppFuncDesc));
3185 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3186 case SLTG_FUNCTION_MAGIC:
3187 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3189 case SLTG_DISPATCH_FUNCTION_MAGIC:
3190 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3192 case SLTG_STATIC_FUNCTION_MAGIC:
3193 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3196 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3197 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3201 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3203 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3204 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3205 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3206 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3207 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3208 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3210 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3211 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3213 if(pFunc->retnextopt & 0x80)
3214 pType = &pFunc->rettype;
3216 pType = (WORD*)(pBlk + pFunc->rettype);
3218 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3220 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3221 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3222 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3223 (*ppFuncDesc)->pParamDesc =
3224 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3225 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3227 pArg = (WORD*)(pBlk + pFunc->arg_off);
3229 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3230 char *paramName = pNameTable + *pArg;
3232 /* If arg type follows then paramName points to the 2nd
3233 letter of the name, else the next WORD is an offset to
3234 the arg type and paramName points to the first letter.
3235 So let's take one char off paramName and see if we're
3236 pointing at an alpha-numeric char. However if *pArg is
3237 0xffff or 0xfffe then the param has no name, the former
3238 meaning that the next WORD is the type, the latter
3239 meaning that the next WORD is an offset to the type. */
3244 else if(*pArg == 0xfffe) {
3248 else if(paramName[-1] && !isalnum(paramName[-1]))
3253 if(HaveOffs) { /* the next word is an offset to type */
3254 pType = (WORD*)(pBlk + *pArg);
3255 SLTG_DoElem(pType, pBlk,
3256 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3261 pArg = SLTG_DoElem(pArg, pBlk,
3262 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3265 /* Are we an optional param ? */
3266 if((*ppFuncDesc)->funcdesc.cParams - param <=
3267 (*ppFuncDesc)->funcdesc.cParamsOpt)
3268 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3271 (*ppFuncDesc)->pParamDesc[param].Name =
3272 TLB_MultiByteToBSTR(paramName);
3276 ppFuncDesc = &((*ppFuncDesc)->next);
3277 if(pFunc->next == 0xffff) break;
3279 pTI->TypeAttr.cFuncs = cFuncs;
3282 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3283 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3284 SLTG_TypeInfoTail *pTITail)
3287 sltg_ref_lookup_t *ref_lookup = NULL;
3289 if(pTIHeader->href_table != 0xffffffff) {
3290 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3296 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3297 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3299 HeapFree(GetProcessHeap(), 0, ref_lookup);
3303 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3304 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3305 const SLTG_TypeInfoTail *pTITail)
3308 sltg_ref_lookup_t *ref_lookup = NULL;
3310 if(pTIHeader->href_table != 0xffffffff) {
3311 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3317 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3318 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3321 if (pTITail->funcs_off != 0xffff)
3322 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3324 HeapFree(GetProcessHeap(), 0, ref_lookup);
3326 if (TRACE_ON(typelib))
3327 dump_TLBFuncDesc(pTI->funclist);
3330 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3331 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3332 const SLTG_TypeInfoTail *pTITail)
3334 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3337 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3338 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3339 const SLTG_TypeInfoTail *pTITail)
3342 sltg_ref_lookup_t *ref_lookup = NULL;
3344 if (pTITail->simple_alias) {
3345 /* if simple alias, no more processing required */
3346 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3350 if(pTIHeader->href_table != 0xffffffff) {
3351 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3355 /* otherwise it is an offset to a type */
3356 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3358 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3360 HeapFree(GetProcessHeap(), 0, ref_lookup);
3363 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3364 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3365 const SLTG_TypeInfoTail *pTITail)
3367 sltg_ref_lookup_t *ref_lookup = NULL;
3368 if (pTIHeader->href_table != 0xffffffff)
3369 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3372 if (pTITail->vars_off != 0xffff)
3373 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3375 if (pTITail->funcs_off != 0xffff)
3376 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3378 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3379 * of dispinterface functions including the IDispatch ones, so
3380 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3381 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3383 HeapFree(GetProcessHeap(), 0, ref_lookup);
3384 if (TRACE_ON(typelib))
3385 dump_TLBFuncDesc(pTI->funclist);
3388 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3389 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3390 const SLTG_TypeInfoTail *pTITail)
3392 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3395 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3396 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3397 const SLTG_TypeInfoTail *pTITail)
3399 sltg_ref_lookup_t *ref_lookup = NULL;
3400 if (pTIHeader->href_table != 0xffffffff)
3401 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3404 if (pTITail->vars_off != 0xffff)
3405 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3407 if (pTITail->funcs_off != 0xffff)
3408 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3409 HeapFree(GetProcessHeap(), 0, ref_lookup);
3412 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3413 managable copy of it into this */
3426 } SLTG_InternalOtherTypeInfo;
3428 /****************************************************************************
3429 * ITypeLib2_Constructor_SLTG
3431 * loading a SLTG typelib from an in-memory image
3433 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3435 ITypeLibImpl *pTypeLibImpl;
3436 SLTG_Header *pHeader;
3437 SLTG_BlkEntry *pBlkEntry;
3441 LPVOID pBlk, pFirstBlk;
3442 SLTG_LibBlk *pLibBlk;
3443 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3444 char *pAfterOTIBlks = NULL;
3445 char *pNameTable, *ptr;
3448 ITypeInfoImpl **ppTypeInfoImpl;
3450 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3453 pTypeLibImpl = TypeLibImpl_Constructor();
3454 if (!pTypeLibImpl) return NULL;
3458 TRACE_(typelib)("header:\n");
3459 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3460 pHeader->nrOfFileBlks );
3461 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3462 FIXME("Header type magic 0x%08x not supported.\n",
3463 pHeader->SLTG_magic);
3467 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3468 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3470 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3471 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3473 /* Next we have a magic block */
3474 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3476 /* Let's see if we're still in sync */
3477 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3478 sizeof(SLTG_COMPOBJ_MAGIC))) {
3479 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3482 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3483 sizeof(SLTG_DIR_MAGIC))) {
3484 FIXME("dir magic = %s\n", pMagic->dir_magic);
3488 pIndex = (SLTG_Index*)(pMagic+1);
3490 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3492 pFirstBlk = (LPVOID)(pPad9 + 1);
3494 /* We'll set up a ptr to the main library block, which is the last one. */
3496 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3497 pBlkEntry[order].next != 0;
3498 order = pBlkEntry[order].next - 1, i++) {
3499 pBlk = (char*)pBlk + pBlkEntry[order].len;
3503 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3505 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3510 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3512 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3513 sizeof(*pOtherTypeInfoBlks) *
3514 pTypeLibImpl->TypeInfoCount);
3517 ptr = (char*)pLibBlk + len;
3519 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3523 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3525 w = *(WORD*)(ptr + 2);
3528 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3530 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3531 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3533 w = *(WORD*)(ptr + 4 + len);
3535 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3537 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3539 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3540 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3542 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3543 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3544 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3546 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3548 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3551 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3552 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3553 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3554 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3555 len += sizeof(SLTG_OtherTypeInfo);
3559 pAfterOTIBlks = ptr;
3561 /* Skip this WORD and get the next DWORD */
3562 len = *(DWORD*)(pAfterOTIBlks + 2);
3564 /* Now add this to pLibBLk look at what we're pointing at and
3565 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3566 dust and we should be pointing at the beginning of the name
3569 pNameTable = (char*)pLibBlk + len;
3571 switch(*(WORD*)pNameTable) {
3578 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3582 pNameTable += 0x216;
3586 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3588 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3591 /* Hopefully we now have enough ptrs set up to actually read in
3592 some TypeInfos. It's not clear which order to do them in, so
3593 I'll just follow the links along the BlkEntry chain and read
3594 them in the order in which they are in the file */
3596 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3598 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3599 pBlkEntry[order].next != 0;
3600 order = pBlkEntry[order].next - 1, i++) {
3602 SLTG_TypeInfoHeader *pTIHeader;
3603 SLTG_TypeInfoTail *pTITail;
3604 SLTG_MemberHeader *pMemHeader;
3606 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3607 pOtherTypeInfoBlks[i].index_name)) {
3608 FIXME("Index strings don't match\n");
3613 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3614 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3617 TRACE("pTIHeader->res06 = %x, pTIHeader->res0e = %x, pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3618 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3620 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3621 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3622 (*ppTypeInfoImpl)->index = i;
3623 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3624 pOtherTypeInfoBlks[i].name_offs +
3626 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3627 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3628 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3629 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3630 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3631 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3632 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3634 if((pTIHeader->typeflags1 & 7) != 2)
3635 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3636 if(pTIHeader->typeflags3 != 2)
3637 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3639 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3640 debugstr_w((*ppTypeInfoImpl)->Name),
3641 typekind_desc[pTIHeader->typekind],
3642 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3643 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3645 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3647 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3649 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3650 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3651 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3653 switch(pTIHeader->typekind) {
3655 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3656 pTIHeader, pTITail);
3660 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3661 pTIHeader, pTITail);
3664 case TKIND_INTERFACE:
3665 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3666 pTIHeader, pTITail);
3670 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3671 pTIHeader, pTITail);
3675 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3676 pTIHeader, pTITail);
3679 case TKIND_DISPATCH:
3680 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3681 pTIHeader, pTITail);
3685 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3686 pTIHeader, pTITail);
3690 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3695 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3696 but we've already set those */
3697 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3712 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3713 pBlk = (char*)pBlk + pBlkEntry[order].len;
3716 if(i != pTypeLibImpl->TypeInfoCount) {
3717 FIXME("Somehow processed %d TypeInfos\n", i);
3721 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3722 return (ITypeLib2*)pTypeLibImpl;
3725 /* ITypeLib::QueryInterface
3727 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3732 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3734 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3737 if(IsEqualIID(riid, &IID_IUnknown) ||
3738 IsEqualIID(riid,&IID_ITypeLib)||
3739 IsEqualIID(riid,&IID_ITypeLib2))
3746 ITypeLib2_AddRef(iface);
3747 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3750 TRACE("-- Interface: E_NOINTERFACE\n");
3751 return E_NOINTERFACE;
3756 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3758 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3759 ULONG ref = InterlockedIncrement(&This->ref);
3761 TRACE("(%p)->ref was %u\n",This, ref - 1);
3766 /* ITypeLib::Release
3768 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3770 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3771 ULONG ref = InterlockedDecrement(&This->ref);
3773 TRACE("(%p)->(%u)\n",This, ref);
3777 TLBImpLib *pImpLib, *pImpLibNext;
3778 TLBCustData *pCustData, *pCustDataNext;
3779 TLBRefType *ref_type;
3783 /* remove cache entry */
3786 TRACE("removing from cache list\n");
3787 EnterCriticalSection(&cache_section);
3788 if (This->next) This->next->prev = This->prev;
3789 if (This->prev) This->prev->next = This->next;
3790 else tlb_cache_first = This->next;
3791 LeaveCriticalSection(&cache_section);
3792 HeapFree(GetProcessHeap(), 0, This->path);
3794 TRACE(" destroying ITypeLib(%p)\n",This);
3798 SysFreeString(This->Name);
3802 if (This->DocString)
3804 SysFreeString(This->DocString);
3805 This->DocString = NULL;
3810 SysFreeString(This->HelpFile);
3811 This->HelpFile = NULL;
3814 if (This->HelpStringDll)
3816 SysFreeString(This->HelpStringDll);
3817 This->HelpStringDll = NULL;
3820 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3822 VariantClear(&pCustData->data);
3824 pCustDataNext = pCustData->next;
3825 TLB_Free(pCustData);
3828 for (i = 0; i < This->ctTypeDesc; i++)
3829 if (This->pTypeDesc[i].vt == VT_CARRAY)
3830 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3832 TLB_Free(This->pTypeDesc);
3834 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3836 if (pImpLib->pImpTypeLib)
3837 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3838 TLB_Free(pImpLib->name);
3840 pImpLibNext = pImpLib->next;
3844 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3846 list_remove(&ref_type->entry);
3850 if (This->pTypeInfo) /* can be NULL */
3851 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3852 HeapFree(GetProcessHeap(),0,This);
3859 /* ITypeLib::GetTypeInfoCount
3861 * Returns the number of type descriptions in the type library
3863 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3865 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3866 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3867 return This->TypeInfoCount;
3870 /* ITypeLib::GetTypeInfo
3872 * retrieves the specified type description in the library.
3874 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3877 ITypeInfo **ppTInfo)
3881 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3882 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3884 TRACE("(%p)->(index=%d)\n", This, index);
3886 if (!ppTInfo) return E_INVALIDARG;
3888 /* search element n in list */
3889 for(i=0; i < index; i++)
3891 pTypeInfo = pTypeInfo->next;
3894 TRACE("-- element not found\n");
3895 return TYPE_E_ELEMENTNOTFOUND;
3899 *ppTInfo = (ITypeInfo *) pTypeInfo;
3901 ITypeInfo_AddRef(*ppTInfo);
3902 TRACE("-- found (%p)\n",*ppTInfo);
3907 /* ITypeLibs::GetTypeInfoType
3909 * Retrieves the type of a type description.
3911 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3916 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3918 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3920 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
3921 return TYPE_E_ELEMENTNOTFOUND;
3923 TRACE("(%p) index %d\n", This, index);
3925 if(!pTKind) return E_INVALIDARG;
3927 /* search element n in list */
3928 for(i=0; i < index; i++)
3932 TRACE("-- element not found\n");
3933 return TYPE_E_ELEMENTNOTFOUND;
3935 pTInfo = pTInfo->next;
3938 *pTKind = pTInfo->TypeAttr.typekind;
3939 TRACE("-- found Type (%d)\n", *pTKind);
3943 /* ITypeLib::GetTypeInfoOfGuid
3945 * Retrieves the type description that corresponds to the specified GUID.
3948 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3951 ITypeInfo **ppTInfo)
3953 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3954 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3956 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3960 WARN("-- element not found\n");
3961 return TYPE_E_ELEMENTNOTFOUND;
3964 /* search linked list for guid */
3965 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3967 pTypeInfo = pTypeInfo->next;
3971 /* end of list reached */
3972 WARN("-- element not found\n");
3973 return TYPE_E_ELEMENTNOTFOUND;
3977 TRACE("-- found (%p, %s)\n",
3979 debugstr_w(pTypeInfo->Name));
3981 *ppTInfo = (ITypeInfo*)pTypeInfo;
3982 ITypeInfo_AddRef(*ppTInfo);
3986 /* ITypeLib::GetLibAttr
3988 * Retrieves the structure that contains the library's attributes.
3991 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3993 LPTLIBATTR *ppTLibAttr)
3995 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3996 TRACE("(%p)\n",This);
3997 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3998 **ppTLibAttr = This->LibAttr;
4002 /* ITypeLib::GetTypeComp
4004 * Enables a client compiler to bind to a library's types, variables,
4005 * constants, and global functions.
4008 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4010 ITypeComp **ppTComp)
4012 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4014 TRACE("(%p)->(%p)\n",This,ppTComp);
4015 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4016 ITypeComp_AddRef(*ppTComp);
4021 /* ITypeLib::GetDocumentation
4023 * Retrieves the library's documentation string, the complete Help file name
4024 * and path, and the context identifier for the library Help topic in the Help
4027 * On a successful return all non-null BSTR pointers will have been set,
4030 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4034 BSTR *pBstrDocString,
4035 DWORD *pdwHelpContext,
4036 BSTR *pBstrHelpFile)
4038 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4040 HRESULT result = E_INVALIDARG;
4045 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4047 pBstrName, pBstrDocString,
4048 pdwHelpContext, pBstrHelpFile);
4052 /* documentation for the typelib */
4057 if(!(*pBstrName = SysAllocString(This->Name)))
4065 if (This->DocString)
4067 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4070 else if (This->Name)
4072 if(!(*pBstrDocString = SysAllocString(This->Name)))
4076 *pBstrDocString = NULL;
4080 *pdwHelpContext = This->dwHelpContext;
4086 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4090 *pBstrHelpFile = NULL;
4097 /* for a typeinfo */
4098 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4100 if(SUCCEEDED(result))
4102 result = ITypeInfo_GetDocumentation(pTInfo,
4106 pdwHelpContext, pBstrHelpFile);
4108 ITypeInfo_Release(pTInfo);
4113 if (pBstrDocString) SysFreeString (*pBstrDocString);
4115 if (pBstrName) SysFreeString (*pBstrName);
4117 return STG_E_INSUFFICIENTMEMORY;
4122 * Indicates whether a passed-in string contains the name of a type or member
4123 * described in the library.
4126 static HRESULT WINAPI ITypeLib2_fnIsName(
4132 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4133 ITypeInfoImpl *pTInfo;
4134 TLBFuncDesc *pFInfo;
4137 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4139 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4143 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4144 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4145 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4146 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4147 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4148 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4149 goto ITypeLib2_fnIsName_exit;
4151 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4152 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4157 ITypeLib2_fnIsName_exit:
4158 TRACE("(%p)slow! search for %s: %s found!\n", This,
4159 debugstr_w(szNameBuf), *pfName?"NOT":"");
4164 /* ITypeLib::FindName
4166 * Finds occurrences of a type description in a type library. This may be used
4167 * to quickly verify that a name exists in a type library.
4170 static HRESULT WINAPI ITypeLib2_fnFindName(
4174 ITypeInfo **ppTInfo,
4178 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4179 ITypeInfoImpl *pTInfo;
4180 TLBFuncDesc *pFInfo;
4183 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4185 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4186 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4187 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4188 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4189 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4190 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4191 goto ITypeLib2_fnFindName_exit;
4194 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4195 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4197 ITypeLib2_fnFindName_exit:
4198 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4199 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4202 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4203 This, *pcFound, debugstr_w(szNameBuf), j);
4210 /* ITypeLib::ReleaseTLibAttr
4212 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4215 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4217 TLIBATTR *pTLibAttr)
4219 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4220 TRACE("freeing (%p)\n",This);
4221 HeapFree(GetProcessHeap(),0,pTLibAttr);
4225 /* ITypeLib2::GetCustData
4227 * gets the custom data
4229 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4234 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4235 TLBCustData *pCData;
4237 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4239 if( IsEqualIID(guid, &pCData->guid)) break;
4242 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4246 VariantInit( pVarVal);
4247 VariantCopy( pVarVal, &pCData->data);
4250 return E_INVALIDARG; /* FIXME: correct? */
4253 /* ITypeLib2::GetLibStatistics
4255 * Returns statistics about a type library that are required for efficient
4256 * sizing of hash tables.
4259 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4261 ULONG *pcUniqueNames,
4262 ULONG *pcchUniqueNames)
4264 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4266 FIXME("(%p): stub!\n", This);
4268 if(pcUniqueNames) *pcUniqueNames=1;
4269 if(pcchUniqueNames) *pcchUniqueNames=1;
4273 /* ITypeLib2::GetDocumentation2
4275 * Retrieves the library's documentation string, the complete Help file name
4276 * and path, the localization context to use, and the context ID for the
4277 * library Help topic in the Help file.
4280 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4284 BSTR *pbstrHelpString,
4285 DWORD *pdwHelpStringContext,
4286 BSTR *pbstrHelpStringDll)
4288 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4292 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4294 /* the help string should be obtained from the helpstringdll,
4295 * using the _DLLGetDocumentation function, based on the supplied
4296 * lcid. Nice to do sometime...
4300 /* documentation for the typelib */
4302 *pbstrHelpString=SysAllocString(This->DocString);
4303 if(pdwHelpStringContext)
4304 *pdwHelpStringContext=This->dwHelpContext;
4305 if(pbstrHelpStringDll)
4306 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4312 /* for a typeinfo */
4313 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4315 if(SUCCEEDED(result))
4317 ITypeInfo2 * pTInfo2;
4318 result = ITypeInfo_QueryInterface(pTInfo,
4320 (LPVOID*) &pTInfo2);
4322 if(SUCCEEDED(result))
4324 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4328 pdwHelpStringContext,
4329 pbstrHelpStringDll);
4331 ITypeInfo2_Release(pTInfo2);
4334 ITypeInfo_Release(pTInfo);
4340 /* ITypeLib2::GetAllCustData
4342 * Gets all custom data items for the library.
4345 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4347 CUSTDATA *pCustData)
4349 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4350 TLBCustData *pCData;
4352 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4353 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4354 if(pCustData->prgCustData ){
4355 pCustData->cCustData=This->ctCustData;
4356 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4357 pCustData->prgCustData[i].guid=pCData->guid;
4358 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4361 ERR(" OUT OF MEMORY!\n");
4362 return E_OUTOFMEMORY;
4367 static const ITypeLib2Vtbl tlbvt = {
4368 ITypeLib2_fnQueryInterface,
4370 ITypeLib2_fnRelease,
4371 ITypeLib2_fnGetTypeInfoCount,
4372 ITypeLib2_fnGetTypeInfo,
4373 ITypeLib2_fnGetTypeInfoType,
4374 ITypeLib2_fnGetTypeInfoOfGuid,
4375 ITypeLib2_fnGetLibAttr,
4376 ITypeLib2_fnGetTypeComp,
4377 ITypeLib2_fnGetDocumentation,
4379 ITypeLib2_fnFindName,
4380 ITypeLib2_fnReleaseTLibAttr,
4382 ITypeLib2_fnGetCustData,
4383 ITypeLib2_fnGetLibStatistics,
4384 ITypeLib2_fnGetDocumentation2,
4385 ITypeLib2_fnGetAllCustData
4389 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4391 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4393 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4396 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4398 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4400 return ITypeLib2_AddRef((ITypeLib2 *)This);
4403 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4405 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4407 return ITypeLib2_Release((ITypeLib2 *)This);
4410 static HRESULT WINAPI ITypeLibComp_fnBind(
4415 ITypeInfo ** ppTInfo,
4416 DESCKIND * pDescKind,
4419 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4420 ITypeInfoImpl *pTypeInfo;
4422 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4424 *pDescKind = DESCKIND_NONE;
4425 pBindPtr->lptcomp = NULL;
4428 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4430 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4432 /* FIXME: check wFlags here? */
4433 /* FIXME: we should use a hash table to look this info up using lHash
4434 * instead of an O(n) search */
4435 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4436 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4438 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4440 *pDescKind = DESCKIND_TYPECOMP;
4441 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4442 ITypeComp_AddRef(pBindPtr->lptcomp);
4443 TRACE("module or enum: %s\n", debugstr_w(szName));
4448 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4449 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4451 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4454 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4455 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4457 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4462 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4463 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4465 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4467 ITypeInfo *subtypeinfo;
4469 DESCKIND subdesckind;
4471 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4472 &subtypeinfo, &subdesckind, &subbindptr);
4473 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4475 TYPEDESC tdesc_appobject =
4478 (TYPEDESC *)pTypeInfo->hreftype
4482 const VARDESC vardesc_appobject =
4485 NULL, /* lpstrSchema */
4500 VAR_STATIC /* varkind */
4503 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4505 /* cleanup things filled in by Bind call so we can put our
4506 * application object data in there instead */
4507 switch (subdesckind)
4509 case DESCKIND_FUNCDESC:
4510 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4512 case DESCKIND_VARDESC:
4513 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4518 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4520 if (pTypeInfo->hreftype == -1)
4521 FIXME("no hreftype for interface %p\n", pTypeInfo);
4523 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4527 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4528 *ppTInfo = (ITypeInfo *)pTypeInfo;
4529 ITypeInfo_AddRef(*ppTInfo);
4535 TRACE("name not found %s\n", debugstr_w(szName));
4539 static HRESULT WINAPI ITypeLibComp_fnBindType(
4543 ITypeInfo ** ppTInfo,
4544 ITypeComp ** ppTComp)
4546 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4550 static const ITypeCompVtbl tlbtcvt =
4553 ITypeLibComp_fnQueryInterface,
4554 ITypeLibComp_fnAddRef,
4555 ITypeLibComp_fnRelease,
4557 ITypeLibComp_fnBind,
4558 ITypeLibComp_fnBindType
4561 /*================== ITypeInfo(2) Methods ===================================*/
4562 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4564 ITypeInfoImpl * pTypeInfoImpl;
4566 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4569 pTypeInfoImpl->lpVtbl = &tinfvt;
4570 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4571 pTypeInfoImpl->ref=1;
4572 pTypeInfoImpl->hreftype = -1;
4573 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4574 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4576 TRACE("(%p)\n", pTypeInfoImpl);
4577 return (ITypeInfo2*) pTypeInfoImpl;
4580 /* ITypeInfo::QueryInterface
4582 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4587 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4589 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4592 if(IsEqualIID(riid, &IID_IUnknown) ||
4593 IsEqualIID(riid,&IID_ITypeInfo)||
4594 IsEqualIID(riid,&IID_ITypeInfo2))
4598 ITypeInfo_AddRef(iface);
4599 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4602 TRACE("-- Interface: E_NOINTERFACE\n");
4603 return E_NOINTERFACE;
4606 /* ITypeInfo::AddRef
4608 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4610 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4611 ULONG ref = InterlockedIncrement(&This->ref);
4613 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4615 TRACE("(%p)->ref is %u\n",This, ref);
4619 /* ITypeInfo::Release
4621 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4623 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4624 ULONG ref = InterlockedDecrement(&This->ref);
4626 TRACE("(%p)->(%u)\n",This, ref);
4629 /* We don't release ITypeLib when ref=0 because
4630 it means that function is called by ITypeLib2_Release */
4631 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4633 TLBFuncDesc *pFInfo, *pFInfoNext;
4634 TLBVarDesc *pVInfo, *pVInfoNext;
4635 TLBImplType *pImpl, *pImplNext;
4637 TRACE("destroying ITypeInfo(%p)\n",This);
4639 if (This->no_free_data)
4644 SysFreeString(This->Name);
4648 if (This->DocString)
4650 SysFreeString(This->DocString);
4651 This->DocString = 0;
4656 SysFreeString(This->DllName);
4660 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4663 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4665 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4666 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4668 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4669 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4671 SysFreeString(pFInfo->pParamDesc[i].Name);
4673 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4674 TLB_Free(pFInfo->pParamDesc);
4675 TLB_FreeCustData(pFInfo->pCustData);
4676 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4677 SysFreeString(pFInfo->Entry);
4678 SysFreeString(pFInfo->HelpString);
4679 SysFreeString(pFInfo->Name);
4681 pFInfoNext = pFInfo->next;
4684 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4686 if (pVInfo->vardesc.varkind == VAR_CONST)
4688 VariantClear(pVInfo->vardesc.u.lpvarValue);
4689 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4691 TLB_FreeCustData(pVInfo->pCustData);
4692 SysFreeString(pVInfo->Name);
4693 pVInfoNext = pVInfo->next;
4696 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4698 TLB_FreeCustData(pImpl->pCustData);
4699 pImplNext = pImpl->next;
4702 TLB_FreeCustData(This->pCustData);
4707 ITypeInfo_Release((ITypeInfo*)This->next);
4710 HeapFree(GetProcessHeap(),0,This);
4716 /* ITypeInfo::GetTypeAttr
4718 * Retrieves a TYPEATTR structure that contains the attributes of the type
4722 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4723 LPTYPEATTR *ppTypeAttr)
4725 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4728 TRACE("(%p)\n",This);
4730 size = sizeof(**ppTypeAttr);
4731 if (This->TypeAttr.typekind == TKIND_ALIAS)
4732 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4734 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4736 return E_OUTOFMEMORY;
4738 **ppTypeAttr = This->TypeAttr;
4740 if (This->TypeAttr.typekind == TKIND_ALIAS)
4741 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4742 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4744 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4745 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4747 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4748 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4753 /* ITypeInfo::GetTypeComp
4755 * Retrieves the ITypeComp interface for the type description, which enables a
4756 * client compiler to bind to the type description's members.
4759 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4760 ITypeComp * *ppTComp)
4762 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4764 TRACE("(%p)->(%p)\n", This, ppTComp);
4766 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4767 ITypeComp_AddRef(*ppTComp);
4771 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4773 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4774 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4775 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4779 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4782 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4783 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4785 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4786 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4787 *buffer += sizeof(PARAMDESCEX);
4788 *pparamdescex_dest = *pparamdescex_src;
4789 VariantInit(&pparamdescex_dest->varDefaultValue);
4790 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4791 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4794 dest->u.paramdesc.pparamdescex = NULL;
4798 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4800 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4801 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4804 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4808 SIZE_T size = sizeof(*src);
4812 size += sizeof(*src->lprgscode) * src->cScodes;
4813 size += TLB_SizeElemDesc(&src->elemdescFunc);
4814 for (i = 0; i < src->cParams; i++)
4816 size += sizeof(ELEMDESC);
4817 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4820 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4821 if (!dest) return E_OUTOFMEMORY;
4824 if (dispinterface) /* overwrite funckind */
4825 dest->funckind = FUNC_DISPATCH;
4826 buffer = (char *)(dest + 1);
4828 dest->lprgscode = (SCODE *)buffer;
4829 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4830 buffer += sizeof(*src->lprgscode) * src->cScodes;
4832 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4835 SysFreeString((BSTR)dest);
4839 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4840 buffer += sizeof(ELEMDESC) * src->cParams;
4841 for (i = 0; i < src->cParams; i++)
4843 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4849 /* undo the above actions */
4850 for (i = i - 1; i >= 0; i--)
4851 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4852 TLB_FreeElemDesc(&dest->elemdescFunc);
4853 SysFreeString((BSTR)dest);
4857 /* special treatment for dispinterfaces: this makes functions appear
4858 * to return their [retval] value when it is really returning an
4860 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4862 if (dest->cParams &&
4863 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4865 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4866 if (elemdesc->tdesc.vt != VT_PTR)
4868 ERR("elemdesc should have started with VT_PTR instead of:\n");
4870 dump_ELEMDESC(elemdesc);
4871 return E_UNEXPECTED;
4874 /* copy last parameter to the return value. we are using a flat
4875 * buffer so there is no danger of leaking memory in
4877 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4879 /* remove the last parameter */
4883 /* otherwise this function is made to appear to have no return
4885 dest->elemdescFunc.tdesc.vt = VT_VOID;
4893 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4895 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4896 const TLBFuncDesc *pFDesc;
4899 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4904 *ppFuncDesc = &pFDesc->funcdesc;
4908 return TYPE_E_ELEMENTNOTFOUND;
4911 /* internal function to make the inherited interfaces' methods appear
4912 * part of the interface */
4913 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4914 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4916 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4918 UINT implemented_funcs = 0;
4923 *hrefoffset = DISPATCH_HREF_OFFSET;
4925 if(This->impltypelist)
4927 ITypeInfo *pSubTypeInfo;
4930 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4934 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4937 &sub_funcs, hrefoffset);
4938 implemented_funcs += sub_funcs;
4939 ITypeInfo_Release(pSubTypeInfo);
4942 *hrefoffset += DISPATCH_HREF_OFFSET;
4946 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4950 if (index < implemented_funcs)
4951 return E_INVALIDARG;
4952 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4956 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4958 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4961 switch (pTypeDesc->vt)
4963 case VT_USERDEFINED:
4964 pTypeDesc->u.hreftype += hrefoffset;
4968 pTypeDesc = pTypeDesc->u.lptdesc;
4971 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
4979 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
4982 for (i = 0; i < pFuncDesc->cParams; i++)
4983 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
4984 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
4987 /* ITypeInfo::GetFuncDesc
4989 * Retrieves the FUNCDESC structure that contains information about a
4990 * specified function.
4993 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4994 LPFUNCDESC *ppFuncDesc)
4996 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4997 const FUNCDESC *internal_funcdesc;
4999 UINT hrefoffset = 0;
5001 TRACE("(%p) index %d\n", This, index);
5003 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5004 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5005 &internal_funcdesc, NULL,
5008 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5009 &internal_funcdesc);
5012 WARN("description for function %d not found\n", index);
5016 hr = TLB_AllocAndInitFuncDesc(
5019 This->TypeAttr.typekind == TKIND_DISPATCH);
5021 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5022 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5024 TRACE("-- 0x%08x\n", hr);
5028 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5032 SIZE_T size = sizeof(*src);
5035 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5036 if (src->varkind == VAR_CONST)
5037 size += sizeof(VARIANT);
5038 size += TLB_SizeElemDesc(&src->elemdescVar);
5040 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5041 if (!dest) return E_OUTOFMEMORY;
5044 buffer = (char *)(dest + 1);
5045 if (src->lpstrSchema)
5048 dest->lpstrSchema = (LPOLESTR)buffer;
5049 len = strlenW(src->lpstrSchema);
5050 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5051 buffer += (len + 1) * sizeof(WCHAR);
5054 if (src->varkind == VAR_CONST)
5058 dest->u.lpvarValue = (VARIANT *)buffer;
5059 *dest->u.lpvarValue = *src->u.lpvarValue;
5060 buffer += sizeof(VARIANT);
5061 VariantInit(dest->u.lpvarValue);
5062 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5065 SysFreeString((BSTR)dest_ptr);
5069 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5072 if (src->varkind == VAR_CONST)
5073 VariantClear(dest->u.lpvarValue);
5074 SysFreeString((BSTR)dest);
5081 /* ITypeInfo::GetVarDesc
5083 * Retrieves a VARDESC structure that describes the specified variable.
5086 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5087 LPVARDESC *ppVarDesc)
5089 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5091 const TLBVarDesc *pVDesc;
5093 TRACE("(%p) index %d\n", This, index);
5095 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5099 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5101 return E_INVALIDARG;
5104 /* ITypeInfo_GetNames
5106 * Retrieves the variable with the specified member ID (or the name of the
5107 * property or method and its parameters) that correspond to the specified
5110 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5111 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5113 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5114 const TLBFuncDesc *pFDesc;
5115 const TLBVarDesc *pVDesc;
5117 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5118 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5121 /* function found, now return function and parameter names */
5122 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5125 *rgBstrNames=SysAllocString(pFDesc->Name);
5127 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5133 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5136 *rgBstrNames=SysAllocString(pVDesc->Name);
5141 if(This->impltypelist &&
5142 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5143 /* recursive search */
5146 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5148 if(SUCCEEDED(result))
5150 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5151 ITypeInfo_Release(pTInfo);
5154 WARN("Could not search inherited interface!\n");
5158 WARN("no names found\n");
5161 return TYPE_E_ELEMENTNOTFOUND;
5168 /* ITypeInfo::GetRefTypeOfImplType
5170 * If a type description describes a COM class, it retrieves the type
5171 * description of the implemented interface types. For an interface,
5172 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5176 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5181 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5184 const TLBImplType *pImpl = This->impltypelist;
5186 TRACE("(%p) index %d\n", This, index);
5187 if (TRACE_ON(ole)) dump_TypeInfo(This);
5191 /* only valid on dual interfaces;
5192 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5194 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5196 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5197 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5203 hr = TYPE_E_ELEMENTNOTFOUND;
5206 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5208 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5209 *pRefType = This->pTypeLib->dispatch_href;
5213 /* get element n from linked list */
5214 for(i=0; pImpl && i<index; i++)
5216 pImpl = pImpl->next;
5220 *pRefType = pImpl->hRef;
5222 hr = TYPE_E_ELEMENTNOTFOUND;
5228 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5230 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5236 /* ITypeInfo::GetImplTypeFlags
5238 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5239 * or base interface in a type description.
5241 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5242 UINT index, INT *pImplTypeFlags)
5244 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5248 TRACE("(%p) index %d\n", This, index);
5249 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5250 i++, pImpl=pImpl->next)
5252 if(i==index && pImpl){
5253 *pImplTypeFlags=pImpl->implflags;
5257 return TYPE_E_ELEMENTNOTFOUND;
5261 * Maps between member names and member IDs, and parameter names and
5264 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5265 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5267 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5268 const TLBFuncDesc *pFDesc;
5269 const TLBVarDesc *pVDesc;
5273 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5276 /* init out parameters in case of failure */
5277 for (i = 0; i < cNames; i++)
5278 pMemId[i] = MEMBERID_NIL;
5280 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5282 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5283 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5284 for(i=1; i < cNames; i++){
5285 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5286 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5288 if( j<pFDesc->funcdesc.cParams)
5291 ret=DISP_E_UNKNOWNNAME;
5293 TRACE("-- 0x%08x\n", ret);
5297 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5298 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5299 if(cNames) *pMemId=pVDesc->vardesc.memid;
5303 /* not found, see if it can be found in an inherited interface */
5304 if(This->impltypelist) {
5305 /* recursive search */
5307 ret=ITypeInfo_GetRefTypeInfo(iface,
5308 This->impltypelist->hRef, &pTInfo);
5310 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5311 ITypeInfo_Release(pTInfo);
5314 WARN("Could not search inherited interface!\n");
5316 WARN("no names found\n");
5317 return DISP_E_UNKNOWNNAME;
5320 /* ITypeInfo::Invoke
5322 * Invokes a method, or accesses a property of an object, that implements the
5323 * interface described by the type description.
5326 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5329 if (TRACE_ON(ole)) {
5331 TRACE("Calling %p(",func);
5332 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5344 res = func(args[0]);
5347 res = func(args[0],args[1]);
5350 res = func(args[0],args[1],args[2]);
5353 res = func(args[0],args[1],args[2],args[3]);
5356 res = func(args[0],args[1],args[2],args[3],args[4]);
5359 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5362 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5365 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5368 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5371 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5374 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5377 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]);
5380 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]);
5383 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]);
5386 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]);
5389 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]);
5392 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]);
5395 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]);
5398 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]);
5401 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]);
5404 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]);
5407 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]);
5410 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]);
5413 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]);
5416 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]);
5419 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]);
5422 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]);
5425 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]);
5428 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]);
5431 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]);
5434 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5440 FIXME("unsupported calling convention %d\n",callconv);
5444 TRACE("returns %08x\n",res);
5448 extern int _argsize(DWORD vt);
5450 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5453 ITypeInfo *tinfo2 = NULL;
5454 TYPEATTR *tattr = NULL;
5456 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5459 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5461 tdesc->u.hreftype, hr);
5464 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5467 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5468 ITypeInfo_Release(tinfo2);
5472 switch (tattr->typekind)
5479 tdesc = &tattr->tdescAlias;
5480 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5483 case TKIND_INTERFACE:
5484 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5490 case TKIND_DISPATCH:
5499 FIXME("TKIND_RECORD unhandled.\n");
5504 FIXME("TKIND_UNION unhandled.\n");
5509 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5513 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5514 ITypeInfo_Release(tinfo2);
5518 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5522 /* enforce only one level of pointer indirection */
5523 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5525 tdesc = tdesc->u.lptdesc;
5527 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5528 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5529 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5530 if ((tdesc->vt == VT_USERDEFINED) ||
5531 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5533 VARTYPE vt_userdefined = 0;
5534 const TYPEDESC *tdesc_userdefined = tdesc;
5535 if (tdesc->vt == VT_PTR)
5537 vt_userdefined = VT_BYREF;
5538 tdesc_userdefined = tdesc->u.lptdesc;
5540 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5542 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5543 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5545 *vt |= vt_userdefined;
5557 case VT_USERDEFINED:
5558 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5565 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5566 hr = DISP_E_BADVARTYPE;
5570 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5579 /***********************************************************************
5580 * DispCallFunc (OLEAUT32.@)
5582 * Invokes a function of the specified calling convention, passing the
5583 * specified arguments and returns the result.
5586 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5587 * oVft [I] The offset in the vtable. See notes.
5588 * cc [I] Calling convention of the function to call.
5589 * vtReturn [I] The return type of the function.
5590 * cActuals [I] Number of parameters.
5591 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5592 * prgpvarg [I] The arguments to pass.
5593 * pvargResult [O] The return value of the function. Can be NULL.
5597 * Failure: HRESULT code.
5600 * The HRESULT return value of this function is not affected by the return
5601 * value of the user supplied function, which is returned in pvargResult.
5603 * If pvInstance is NULL then a non-object function is to be called and oVft
5604 * is the address of the function to call.
5606 * The cc parameter can be one of the following values:
5619 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5620 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5622 int i, argsize, argspos;
5626 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5627 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5628 pvargResult, V_VT(pvargResult));
5632 argsize++; /* for This pointer */
5634 for (i=0;i<cActuals;i++)
5636 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5637 dump_Variant(prgpvarg[i]);
5638 argsize += _argsize(prgvt[i]);
5640 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5645 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5649 for (i=0;i<cActuals;i++)
5651 VARIANT *arg = prgpvarg[i];
5652 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5653 if (prgvt[i] == VT_VARIANT)
5654 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5656 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5657 argspos += _argsize(prgvt[i]);
5662 FARPROC *vtable = *(FARPROC**)pvInstance;
5663 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5666 /* if we aren't invoking an object then the function pointer is stored
5668 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5670 if (pvargResult && (vtReturn != VT_EMPTY))
5672 TRACE("Method returned 0x%08x\n",hres);
5673 V_VT(pvargResult) = vtReturn;
5674 V_UI4(pvargResult) = hres;
5677 HeapFree(GetProcessHeap(),0,args);
5681 #define INVBUF_ELEMENT_SIZE \
5682 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5683 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5684 ((VARIANTARG *)(buffer))
5685 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5686 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5687 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5688 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5689 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5690 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5692 static HRESULT WINAPI ITypeInfo_fnInvoke(
5697 DISPPARAMS *pDispParams,
5698 VARIANT *pVarResult,
5699 EXCEPINFO *pExcepInfo,
5702 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5704 unsigned int var_index;
5707 const TLBFuncDesc *pFuncInfo;
5709 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5710 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5715 ERR("NULL pDispParams not allowed\n");
5716 return E_INVALIDARG;
5719 dump_DispParms(pDispParams);
5721 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5723 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5724 pDispParams->cNamedArgs, pDispParams->cArgs);
5725 return E_INVALIDARG;
5728 /* we do this instead of using GetFuncDesc since it will return a fake
5729 * FUNCDESC for dispinterfaces and we want the real function description */
5730 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5731 if ((memid == pFuncInfo->funcdesc.memid) &&
5732 (wFlags & pFuncInfo->funcdesc.invkind))
5736 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5740 TRACE("invoking:\n");
5741 dump_TLBFuncDescOne(pFuncInfo);
5744 switch (func_desc->funckind) {
5745 case FUNC_PUREVIRTUAL:
5746 case FUNC_VIRTUAL: {
5747 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5749 VARIANT retval; /* pointer for storing byref retvals in */
5750 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5751 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5752 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5753 UINT cNamedArgs = pDispParams->cNamedArgs;
5754 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5758 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5760 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5762 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5763 hres = DISP_E_PARAMNOTFOUND;
5766 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5768 rgdispidNamedArgs++;
5771 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5773 ERR("functions with the vararg attribute do not support named arguments\n");
5774 hres = DISP_E_NONAMEDARGS;
5778 for (i = 0; i < func_desc->cParams; i++)
5780 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5781 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5786 TRACE("changing args\n");
5787 for (i = 0; i < func_desc->cParams; i++)
5789 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5790 VARIANTARG *src_arg;
5796 for (j = 0; j < cNamedArgs; j++)
5797 if (rgdispidNamedArgs[j] == i)
5799 src_arg = &pDispParams->rgvarg[j];
5804 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5806 if (wParamFlags & PARAMFLAG_FRETVAL)
5808 /* under most conditions the caller is not allowed to
5809 * pass in a dispparam arg in the index of what would be
5810 * the retval parameter. however, there is an exception
5811 * where the extra parameter is used in an extra
5812 * IDispatch::Invoke below */
5813 if ((i < pDispParams->cArgs) &&
5814 ((func_desc->cParams != 1) || !pVarResult ||
5815 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5817 hres = DISP_E_BADPARAMCOUNT;
5821 /* note: this check is placed so that if the caller passes
5822 * in a VARIANTARG for the retval we just ignore it, like
5824 if (i == func_desc->cParams - 1)
5827 arg = prgpvarg[i] = &rgvarg[i];
5828 memset(arg, 0, sizeof(*arg));
5829 V_VT(arg) = rgvt[i];
5830 memset(&retval, 0, sizeof(retval));
5831 V_BYREF(arg) = &retval;
5835 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5836 hres = E_UNEXPECTED;
5842 dump_Variant(src_arg);
5844 if (rgvt[i] == VT_VARIANT)
5845 hres = VariantCopy(&rgvarg[i], src_arg);
5846 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5848 if (rgvt[i] == V_VT(src_arg))
5849 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5852 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5853 hres = VariantCopy(&missing_arg[i], src_arg);
5854 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5856 V_VT(&rgvarg[i]) = rgvt[i];
5858 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5861 SAFEARRAYBOUND bound;
5865 bound.cElements = pDispParams->cArgs-i;
5866 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5868 ERR("SafeArrayCreate failed\n");
5871 hres = SafeArrayAccessData(a, (LPVOID)&v);
5874 ERR("SafeArrayAccessData failed with %x\n", hres);
5877 for (j = 0; j < bound.cElements; j++)
5878 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5879 hres = SafeArrayUnaccessData(a);
5882 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5885 V_ARRAY(&rgvarg[i]) = a;
5886 V_VT(&rgvarg[i]) = rgvt[i];
5888 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5890 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5891 V_VT(&missing_arg[i]) = V_VT(src_arg);
5892 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5893 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5894 V_VT(&rgvarg[i]) = rgvt[i];
5896 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5898 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5899 V_VT(&rgvarg[i]) = rgvt[i];
5903 /* FIXME: this doesn't work for VT_BYREF arguments if
5904 * they are not the same type as in the paramdesc */
5905 V_VT(&rgvarg[i]) = V_VT(src_arg);
5906 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5907 V_VT(&rgvarg[i]) = rgvt[i];
5912 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5913 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5914 debugstr_VT(src_arg), debugstr_VF(src_arg));
5917 prgpvarg[i] = &rgvarg[i];
5919 else if (wParamFlags & PARAMFLAG_FOPT)
5922 arg = prgpvarg[i] = &rgvarg[i];
5923 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5925 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5931 VARIANTARG *missing_arg;
5932 /* if the function wants a pointer to a variant then
5933 * set that up, otherwise just pass the VT_ERROR in
5934 * the argument by value */
5935 if (rgvt[i] & VT_BYREF)
5937 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5938 V_VT(arg) = VT_VARIANT | VT_BYREF;
5939 V_VARIANTREF(arg) = missing_arg;
5943 V_VT(missing_arg) = VT_ERROR;
5944 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5949 hres = DISP_E_BADPARAMCOUNT;
5953 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5955 /* VT_VOID is a special case for return types, so it is not
5956 * handled in the general function */
5957 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5958 V_VT(&varresult) = VT_EMPTY;
5961 V_VT(&varresult) = 0;
5962 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5963 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5966 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5967 V_VT(&varresult), func_desc->cParams, rgvt,
5968 prgpvarg, &varresult);
5970 for (i = 0; i < func_desc->cParams; i++)
5972 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5973 if (wParamFlags & PARAMFLAG_FRETVAL)
5977 TRACE("[retval] value: ");
5978 dump_Variant(prgpvarg[i]);
5983 VariantInit(pVarResult);
5984 /* deref return value */
5985 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5988 /* free data stored in varresult. Note that
5989 * VariantClear doesn't do what we want because we are
5990 * working with byref types. */
5991 /* FIXME: clear safearrays, bstrs, records and
5992 * variants here too */
5993 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5994 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5996 if(*V_UNKNOWNREF(prgpvarg[i]))
5997 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6001 else if (i < pDispParams->cArgs)
6003 if (wParamFlags & PARAMFLAG_FOUT)
6005 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6007 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6008 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6012 ERR("failed to convert param %d to vt %d\n", i,
6013 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6017 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6018 func_desc->cParamsOpt < 0 &&
6019 i == func_desc->cParams-1)
6021 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6024 hres = SafeArrayGetUBound(a, 1, &ubound);
6027 ERR("SafeArrayGetUBound failed with %x\n", hres);
6030 hres = SafeArrayAccessData(a, (LPVOID)&v);
6033 ERR("SafeArrayAccessData failed with %x\n", hres);
6036 for (j = 0; j <= ubound; j++)
6037 VariantClear(&v[j]);
6038 hres = SafeArrayUnaccessData(a);
6041 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6045 VariantClear(&rgvarg[i]);
6047 else if (wParamFlags & PARAMFLAG_FOPT)
6049 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6050 VariantClear(&rgvarg[i]);
6054 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6056 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6057 hres = DISP_E_EXCEPTION;
6060 IErrorInfo *pErrorInfo;
6061 pExcepInfo->scode = V_ERROR(&varresult);
6062 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6064 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6065 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6066 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6067 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6069 IErrorInfo_Release(pErrorInfo);
6073 if (V_VT(&varresult) != VT_ERROR)
6075 TRACE("varresult value: ");
6076 dump_Variant(&varresult);
6080 VariantClear(pVarResult);
6081 *pVarResult = varresult;
6084 VariantClear(&varresult);
6087 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6088 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6089 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6090 (pDispParams->cArgs != 0))
6092 if (V_VT(pVarResult) == VT_DISPATCH)
6094 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6095 /* Note: not VariantClear; we still need the dispatch
6096 * pointer to be valid */
6097 VariantInit(pVarResult);
6098 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6099 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6100 pDispParams, pVarResult, pExcepInfo, pArgErr);
6101 IDispatch_Release(pDispatch);
6105 VariantClear(pVarResult);
6106 hres = DISP_E_NOTACOLLECTION;
6111 HeapFree(GetProcessHeap(), 0, buffer);
6114 case FUNC_DISPATCH: {
6117 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6118 if (SUCCEEDED(hres)) {
6119 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6120 hres = IDispatch_Invoke(
6121 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6122 pVarResult,pExcepInfo,pArgErr
6125 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6126 IDispatch_Release(disp);
6128 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6132 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6137 TRACE("-- 0x%08x\n", hres);
6140 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6143 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6144 if(FAILED(hres)) return hres;
6146 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6147 dump_VARDESC(var_desc);
6148 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6152 /* not found, look for it in inherited interfaces */
6153 ITypeInfo2_GetTypeKind(iface, &type_kind);
6154 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6155 if(This->impltypelist) {
6156 /* recursive search */
6158 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6159 if(SUCCEEDED(hres)){
6160 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6161 ITypeInfo_Release(pTInfo);
6164 WARN("Could not search inherited interface!\n");
6167 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6168 return DISP_E_MEMBERNOTFOUND;
6171 /* ITypeInfo::GetDocumentation
6173 * Retrieves the documentation string, the complete Help file name and path,
6174 * and the context ID for the Help topic for a specified type description.
6176 * (Can be tested by the Visual Basic Editor in Word for instance.)
6178 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6179 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6180 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6182 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6183 const TLBFuncDesc *pFDesc;
6184 const TLBVarDesc *pVDesc;
6185 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6186 " HelpContext(%p) HelpFile(%p)\n",
6187 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6188 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6190 *pBstrName=SysAllocString(This->Name);
6192 *pBstrDocString=SysAllocString(This->DocString);
6194 *pdwHelpContext=This->dwHelpContext;
6196 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6198 }else {/* for a member */
6199 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6200 if(pFDesc->funcdesc.memid==memid){
6202 *pBstrName = SysAllocString(pFDesc->Name);
6204 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6206 *pdwHelpContext=pFDesc->helpcontext;
6209 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6210 if(pVDesc->vardesc.memid==memid){
6212 *pBstrName = SysAllocString(pVDesc->Name);
6214 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6216 *pdwHelpContext=pVDesc->HelpContext;
6221 if(This->impltypelist &&
6222 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6223 /* recursive search */
6226 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6228 if(SUCCEEDED(result)) {
6229 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6230 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6231 ITypeInfo_Release(pTInfo);
6234 WARN("Could not search inherited interface!\n");
6237 WARN("member %d not found\n", memid);
6238 return TYPE_E_ELEMENTNOTFOUND;
6241 /* ITypeInfo::GetDllEntry
6243 * Retrieves a description or specification of an entry point for a function
6246 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6247 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6251 const TLBFuncDesc *pFDesc;
6253 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6255 if (pBstrDllName) *pBstrDllName = NULL;
6256 if (pBstrName) *pBstrName = NULL;
6257 if (pwOrdinal) *pwOrdinal = 0;
6259 if (This->TypeAttr.typekind != TKIND_MODULE)
6260 return TYPE_E_BADMODULEKIND;
6262 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6263 if(pFDesc->funcdesc.memid==memid){
6264 dump_TypeInfo(This);
6266 dump_TLBFuncDescOne(pFDesc);
6269 *pBstrDllName = SysAllocString(This->DllName);
6271 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6273 *pBstrName = SysAllocString(pFDesc->Entry);
6281 *pwOrdinal = (DWORD)pFDesc->Entry;
6284 return TYPE_E_ELEMENTNOTFOUND;
6287 /* internal function to make the inherited interfaces' methods appear
6288 * part of the interface */
6289 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6290 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6292 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6295 TRACE("%p, 0x%x\n", iface, *hRefType);
6297 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6299 ITypeInfo *pSubTypeInfo;
6301 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6305 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6307 ITypeInfo_Release(pSubTypeInfo);
6311 *hRefType -= DISPATCH_HREF_OFFSET;
6313 if (!(*hRefType & DISPATCH_HREF_MASK))
6314 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6319 /* ITypeInfo::GetRefTypeInfo
6321 * If a type description references other type descriptions, it retrieves
6322 * the referenced type descriptions.
6324 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6327 ITypeInfo **ppTInfo)
6329 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6330 HRESULT result = E_FAIL;
6332 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6334 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6335 ITypeInfo_AddRef(*ppTInfo);
6338 else if (hRefType == -1 &&
6339 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6340 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6342 /* when we meet a DUAL dispinterface, we must create the interface
6345 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6348 /* the interface version contains the same information as the dispinterface
6349 * copy the contents of the structs.
6351 *pTypeInfoImpl = *This;
6352 pTypeInfoImpl->ref = 0;
6354 /* change the type to interface */
6355 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6357 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6359 /* we use data structures from This, so we need to keep a reference
6360 * to it to stop it being destroyed and signal to the new instance to
6361 * not free its data structures when it is destroyed */
6362 pTypeInfoImpl->no_free_data = TRUE;
6363 pTypeInfoImpl->next = This;
6364 ITypeInfo_AddRef((ITypeInfo*) This);
6366 ITypeInfo_AddRef(*ppTInfo);
6370 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6371 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6372 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6374 HREFTYPE href_dispatch = hRefType;
6375 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6377 TLBRefType *ref_type;
6378 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6380 if(ref_type->reference == hRefType)
6383 if(&ref_type->entry == &This->pTypeLib->ref_list)
6385 FIXME("Can't find pRefType for ref %x\n", hRefType);
6388 if(hRefType != -1) {
6389 ITypeLib *pTLib = NULL;
6391 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6393 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6395 if(ref_type->pImpTLInfo->pImpTypeLib) {
6396 TRACE("typeinfo in imported typelib that is already loaded\n");
6397 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6398 ITypeLib2_AddRef(pTLib);
6401 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6402 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6403 ref_type->pImpTLInfo->wVersionMajor,
6404 ref_type->pImpTLInfo->wVersionMinor,
6405 ref_type->pImpTLInfo->lcid,
6408 if(!SUCCEEDED(result)) {
6409 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6410 result=LoadTypeLib(libnam, &pTLib);
6411 SysFreeString(libnam);
6413 if(SUCCEEDED(result)) {
6414 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6415 ITypeLib2_AddRef(pTLib);
6419 if(SUCCEEDED(result)) {
6420 if(ref_type->index == TLB_REF_USE_GUID)
6421 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6425 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6429 ITypeLib2_Release(pTLib);
6434 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6435 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6439 /* ITypeInfo::AddressOfMember
6441 * Retrieves the addresses of static functions or variables, such as those
6444 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6445 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6447 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6453 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6455 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6459 module = LoadLibraryW(dll);
6462 ERR("couldn't load %s\n", debugstr_w(dll));
6464 if (entry) SysFreeString(entry);
6465 return STG_E_FILENOTFOUND;
6467 /* FIXME: store library somewhere where we can free it */
6472 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6473 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6474 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6476 *ppv = GetProcAddress(module, entryA);
6478 ERR("function not found %s\n", debugstr_a(entryA));
6480 HeapFree(GetProcessHeap(), 0, entryA);
6484 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6486 ERR("function not found %d\n", ordinal);
6490 if (entry) SysFreeString(entry);
6493 return TYPE_E_DLLFUNCTIONNOTFOUND;
6498 /* ITypeInfo::CreateInstance
6500 * Creates a new instance of a type that describes a component object class
6503 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6504 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6506 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6510 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6516 WARN("Not able to aggregate\n");
6517 return CLASS_E_NOAGGREGATION;
6520 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6521 if(FAILED(hr)) return hr;
6523 if(pTA->typekind != TKIND_COCLASS)
6525 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6531 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6534 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6535 TRACE("GetActiveObject rets %08x\n", hr);
6538 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6539 IUnknown_Release(pUnk);
6544 hr = CoCreateInstance(&pTA->guid, NULL,
6545 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6549 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6553 /* ITypeInfo::GetMops
6555 * Retrieves marshalling information.
6557 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6560 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6561 FIXME("(%p) stub!\n", This);
6565 /* ITypeInfo::GetContainingTypeLib
6567 * Retrieves the containing type library and the index of the type description
6568 * within that type library.
6570 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6571 ITypeLib * *ppTLib, UINT *pIndex)
6573 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6575 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6577 *pIndex=This->index;
6578 TRACE("returning pIndex=%d\n", *pIndex);
6582 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6583 ITypeLib2_AddRef(*ppTLib);
6584 TRACE("returning ppTLib=%p\n", *ppTLib);
6590 /* ITypeInfo::ReleaseTypeAttr
6592 * Releases a TYPEATTR previously returned by GetTypeAttr.
6595 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6596 TYPEATTR* pTypeAttr)
6598 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6599 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6600 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6603 /* ITypeInfo::ReleaseFuncDesc
6605 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6607 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6609 FUNCDESC *pFuncDesc)
6611 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6614 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6616 for (i = 0; i < pFuncDesc->cParams; i++)
6617 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6618 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6620 SysFreeString((BSTR)pFuncDesc);
6623 /* ITypeInfo::ReleaseVarDesc
6625 * Releases a VARDESC previously returned by GetVarDesc.
6627 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6630 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6631 TRACE("(%p)->(%p)\n", This, pVarDesc);
6633 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6634 if (pVarDesc->varkind == VAR_CONST)
6635 VariantClear(pVarDesc->u.lpvarValue);
6636 SysFreeString((BSTR)pVarDesc);
6639 /* ITypeInfo2::GetTypeKind
6641 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6644 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6645 TYPEKIND *pTypeKind)
6647 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6648 *pTypeKind=This->TypeAttr.typekind;
6649 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6653 /* ITypeInfo2::GetTypeFlags
6655 * Returns the type flags without any allocations. This returns a DWORD type
6656 * flag, which expands the type flags without growing the TYPEATTR (type
6660 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6662 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6663 *pTypeFlags=This->TypeAttr.wTypeFlags;
6664 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6668 /* ITypeInfo2::GetFuncIndexOfMemId
6669 * Binds to a specific member based on a known DISPID, where the member name
6670 * is not known (for example, when binding to a default member).
6673 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6674 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6676 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6677 const TLBFuncDesc *pFuncInfo;
6681 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6682 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6688 result = TYPE_E_ELEMENTNOTFOUND;
6690 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6691 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6695 /* TypeInfo2::GetVarIndexOfMemId
6697 * Binds to a specific member based on a known DISPID, where the member name
6698 * is not known (for example, when binding to a default member).
6701 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6702 MEMBERID memid, UINT *pVarIndex)
6704 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6705 TLBVarDesc *pVarInfo;
6708 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6709 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6715 result = TYPE_E_ELEMENTNOTFOUND;
6717 TRACE("(%p) memid 0x%08x -> %s\n", This,
6718 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6722 /* ITypeInfo2::GetCustData
6724 * Gets the custom data
6726 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6731 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6732 TLBCustData *pCData;
6734 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6735 if( IsEqualIID(guid, &pCData->guid)) break;
6737 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6741 VariantInit( pVarVal);
6742 VariantCopy( pVarVal, &pCData->data);
6745 return E_INVALIDARG; /* FIXME: correct? */
6748 /* ITypeInfo2::GetFuncCustData
6750 * Gets the custom data
6752 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6758 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6759 TLBCustData *pCData=NULL;
6760 TLBFuncDesc * pFDesc;
6762 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6763 pFDesc=pFDesc->next);
6766 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6767 if( IsEqualIID(guid, &pCData->guid)) break;
6769 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6772 VariantInit( pVarVal);
6773 VariantCopy( pVarVal, &pCData->data);
6776 return E_INVALIDARG; /* FIXME: correct? */
6779 /* ITypeInfo2::GetParamCustData
6781 * Gets the custom data
6783 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6790 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6791 TLBCustData *pCData=NULL;
6792 TLBFuncDesc * pFDesc;
6795 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6797 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
6798 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6799 pCData = pCData->next)
6800 if( IsEqualIID(guid, &pCData->guid)) break;
6802 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6806 VariantInit( pVarVal);
6807 VariantCopy( pVarVal, &pCData->data);
6810 return E_INVALIDARG; /* FIXME: correct? */
6813 /* ITypeInfo2::GetVarCustData
6815 * Gets the custom data
6817 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6823 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6824 TLBCustData *pCData=NULL;
6825 TLBVarDesc * pVDesc;
6828 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6832 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6834 if( IsEqualIID(guid, &pCData->guid)) break;
6838 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6842 VariantInit( pVarVal);
6843 VariantCopy( pVarVal, &pCData->data);
6846 return E_INVALIDARG; /* FIXME: correct? */
6849 /* ITypeInfo2::GetImplCustData
6851 * Gets the custom data
6853 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6859 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6860 TLBCustData *pCData=NULL;
6861 TLBImplType * pRDesc;
6864 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6868 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6870 if( IsEqualIID(guid, &pCData->guid)) break;
6874 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6878 VariantInit( pVarVal);
6879 VariantCopy( pVarVal, &pCData->data);
6882 return E_INVALIDARG; /* FIXME: correct? */
6885 /* ITypeInfo2::GetDocumentation2
6887 * Retrieves the documentation string, the complete Help file name and path,
6888 * the localization context to use, and the context ID for the library Help
6889 * topic in the Help file.
6892 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6896 BSTR *pbstrHelpString,
6897 DWORD *pdwHelpStringContext,
6898 BSTR *pbstrHelpStringDll)
6900 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6901 const TLBFuncDesc *pFDesc;
6902 const TLBVarDesc *pVDesc;
6903 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6904 "HelpStringContext(%p) HelpStringDll(%p)\n",
6905 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6906 pbstrHelpStringDll );
6907 /* the help string should be obtained from the helpstringdll,
6908 * using the _DLLGetDocumentation function, based on the supplied
6909 * lcid. Nice to do sometime...
6911 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6913 *pbstrHelpString=SysAllocString(This->Name);
6914 if(pdwHelpStringContext)
6915 *pdwHelpStringContext=This->dwHelpStringContext;
6916 if(pbstrHelpStringDll)
6917 *pbstrHelpStringDll=
6918 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6920 }else {/* for a member */
6921 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6922 if(pFDesc->funcdesc.memid==memid){
6924 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6925 if(pdwHelpStringContext)
6926 *pdwHelpStringContext=pFDesc->HelpStringContext;
6927 if(pbstrHelpStringDll)
6928 *pbstrHelpStringDll=
6929 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6932 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6933 if(pVDesc->vardesc.memid==memid){
6935 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6936 if(pdwHelpStringContext)
6937 *pdwHelpStringContext=pVDesc->HelpStringContext;
6938 if(pbstrHelpStringDll)
6939 *pbstrHelpStringDll=
6940 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6944 return TYPE_E_ELEMENTNOTFOUND;
6947 /* ITypeInfo2::GetAllCustData
6949 * Gets all custom data items for the Type info.
6952 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6954 CUSTDATA *pCustData)
6956 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6957 TLBCustData *pCData;
6960 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6962 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6963 if(pCustData->prgCustData ){
6964 pCustData->cCustData=This->ctCustData;
6965 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6966 pCustData->prgCustData[i].guid=pCData->guid;
6967 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6970 ERR(" OUT OF MEMORY!\n");
6971 return E_OUTOFMEMORY;
6976 /* ITypeInfo2::GetAllFuncCustData
6978 * Gets all custom data items for the specified Function
6981 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6984 CUSTDATA *pCustData)
6986 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6987 TLBCustData *pCData;
6988 TLBFuncDesc * pFDesc;
6990 TRACE("(%p) index %d\n", This, index);
6991 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6992 pFDesc=pFDesc->next)
6995 pCustData->prgCustData =
6996 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6997 if(pCustData->prgCustData ){
6998 pCustData->cCustData=pFDesc->ctCustData;
6999 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7000 pCData = pCData->next){
7001 pCustData->prgCustData[i].guid=pCData->guid;
7002 VariantCopy(& pCustData->prgCustData[i].varValue,
7006 ERR(" OUT OF MEMORY!\n");
7007 return E_OUTOFMEMORY;
7011 return TYPE_E_ELEMENTNOTFOUND;
7014 /* ITypeInfo2::GetAllParamCustData
7016 * Gets all custom data items for the Functions
7019 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7020 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7022 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7023 TLBCustData *pCData=NULL;
7024 TLBFuncDesc * pFDesc;
7026 TRACE("(%p) index %d\n", This, indexFunc);
7027 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7028 pFDesc=pFDesc->next)
7030 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7031 pCustData->prgCustData =
7032 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7033 sizeof(CUSTDATAITEM));
7034 if(pCustData->prgCustData ){
7035 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7036 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7037 pCData; i++, pCData = pCData->next){
7038 pCustData->prgCustData[i].guid=pCData->guid;
7039 VariantCopy(& pCustData->prgCustData[i].varValue,
7043 ERR(" OUT OF MEMORY!\n");
7044 return E_OUTOFMEMORY;
7048 return TYPE_E_ELEMENTNOTFOUND;
7051 /* ITypeInfo2::GetAllVarCustData
7053 * Gets all custom data items for the specified Variable
7056 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7057 UINT index, CUSTDATA *pCustData)
7059 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7060 TLBCustData *pCData;
7061 TLBVarDesc * pVDesc;
7063 TRACE("(%p) index %d\n", This, index);
7064 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7065 pVDesc=pVDesc->next)
7068 pCustData->prgCustData =
7069 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7070 if(pCustData->prgCustData ){
7071 pCustData->cCustData=pVDesc->ctCustData;
7072 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7073 pCData = pCData->next){
7074 pCustData->prgCustData[i].guid=pCData->guid;
7075 VariantCopy(& pCustData->prgCustData[i].varValue,
7079 ERR(" OUT OF MEMORY!\n");
7080 return E_OUTOFMEMORY;
7084 return TYPE_E_ELEMENTNOTFOUND;
7087 /* ITypeInfo2::GetAllImplCustData
7089 * Gets all custom data items for the specified implementation type
7092 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7095 CUSTDATA *pCustData)
7097 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7098 TLBCustData *pCData;
7099 TLBImplType * pRDesc;
7101 TRACE("(%p) index %d\n", This, index);
7102 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7103 pRDesc=pRDesc->next)
7106 pCustData->prgCustData =
7107 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7108 if(pCustData->prgCustData ){
7109 pCustData->cCustData=pRDesc->ctCustData;
7110 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7111 pCData = pCData->next){
7112 pCustData->prgCustData[i].guid=pCData->guid;
7113 VariantCopy(& pCustData->prgCustData[i].varValue,
7117 ERR(" OUT OF MEMORY!\n");
7118 return E_OUTOFMEMORY;
7122 return TYPE_E_ELEMENTNOTFOUND;
7125 static const ITypeInfo2Vtbl tinfvt =
7128 ITypeInfo_fnQueryInterface,
7130 ITypeInfo_fnRelease,
7132 ITypeInfo_fnGetTypeAttr,
7133 ITypeInfo_fnGetTypeComp,
7134 ITypeInfo_fnGetFuncDesc,
7135 ITypeInfo_fnGetVarDesc,
7136 ITypeInfo_fnGetNames,
7137 ITypeInfo_fnGetRefTypeOfImplType,
7138 ITypeInfo_fnGetImplTypeFlags,
7139 ITypeInfo_fnGetIDsOfNames,
7141 ITypeInfo_fnGetDocumentation,
7142 ITypeInfo_fnGetDllEntry,
7143 ITypeInfo_fnGetRefTypeInfo,
7144 ITypeInfo_fnAddressOfMember,
7145 ITypeInfo_fnCreateInstance,
7146 ITypeInfo_fnGetMops,
7147 ITypeInfo_fnGetContainingTypeLib,
7148 ITypeInfo_fnReleaseTypeAttr,
7149 ITypeInfo_fnReleaseFuncDesc,
7150 ITypeInfo_fnReleaseVarDesc,
7152 ITypeInfo2_fnGetTypeKind,
7153 ITypeInfo2_fnGetTypeFlags,
7154 ITypeInfo2_fnGetFuncIndexOfMemId,
7155 ITypeInfo2_fnGetVarIndexOfMemId,
7156 ITypeInfo2_fnGetCustData,
7157 ITypeInfo2_fnGetFuncCustData,
7158 ITypeInfo2_fnGetParamCustData,
7159 ITypeInfo2_fnGetVarCustData,
7160 ITypeInfo2_fnGetImplTypeCustData,
7161 ITypeInfo2_fnGetDocumentation2,
7162 ITypeInfo2_fnGetAllCustData,
7163 ITypeInfo2_fnGetAllFuncCustData,
7164 ITypeInfo2_fnGetAllParamCustData,
7165 ITypeInfo2_fnGetAllVarCustData,
7166 ITypeInfo2_fnGetAllImplTypeCustData,
7169 /******************************************************************************
7170 * CreateDispTypeInfo [OLEAUT32.31]
7172 * Build type information for an object so it can be called through an
7173 * IDispatch interface.
7176 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7177 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7180 * This call allows an objects methods to be accessed through IDispatch, by
7181 * building an ITypeInfo object that IDispatch can use to call through.
7183 HRESULT WINAPI CreateDispTypeInfo(
7184 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7185 LCID lcid, /* [I] Locale Id */
7186 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7188 ITypeInfoImpl *pTIClass, *pTIIface;
7189 ITypeLibImpl *pTypeLibImpl;
7191 TLBFuncDesc **ppFuncDesc;
7195 pTypeLibImpl = TypeLibImpl_Constructor();
7196 if (!pTypeLibImpl) return E_FAIL;
7198 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7199 pTIIface->pTypeLib = pTypeLibImpl;
7200 pTIIface->index = 0;
7201 pTIIface->Name = NULL;
7202 pTIIface->dwHelpContext = -1;
7203 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7204 pTIIface->TypeAttr.lcid = lcid;
7205 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7206 pTIIface->TypeAttr.wMajorVerNum = 0;
7207 pTIIface->TypeAttr.wMinorVerNum = 0;
7208 pTIIface->TypeAttr.cbAlignment = 2;
7209 pTIIface->TypeAttr.cbSizeInstance = -1;
7210 pTIIface->TypeAttr.cbSizeVft = -1;
7211 pTIIface->TypeAttr.cFuncs = 0;
7212 pTIIface->TypeAttr.cImplTypes = 0;
7213 pTIIface->TypeAttr.cVars = 0;
7214 pTIIface->TypeAttr.wTypeFlags = 0;
7216 ppFuncDesc = &pTIIface->funclist;
7217 for(func = 0; func < pidata->cMembers; func++) {
7218 METHODDATA *md = pidata->pmethdata + func;
7219 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7220 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7221 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7222 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7223 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7224 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7225 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7226 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7227 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7228 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7229 (*ppFuncDesc)->funcdesc.cScodes = 0;
7230 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7231 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7232 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7233 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7234 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7235 md->cArgs * sizeof(ELEMDESC));
7236 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7237 md->cArgs * sizeof(TLBParDesc));
7238 for(param = 0; param < md->cArgs; param++) {
7239 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7240 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7242 (*ppFuncDesc)->helpcontext = 0;
7243 (*ppFuncDesc)->HelpStringContext = 0;
7244 (*ppFuncDesc)->HelpString = NULL;
7245 (*ppFuncDesc)->Entry = NULL;
7246 (*ppFuncDesc)->ctCustData = 0;
7247 (*ppFuncDesc)->pCustData = NULL;
7248 (*ppFuncDesc)->next = NULL;
7249 pTIIface->TypeAttr.cFuncs++;
7250 ppFuncDesc = &(*ppFuncDesc)->next;
7253 dump_TypeInfo(pTIIface);
7255 pTypeLibImpl->pTypeInfo = pTIIface;
7256 pTypeLibImpl->TypeInfoCount++;
7258 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7259 pTIClass->pTypeLib = pTypeLibImpl;
7260 pTIClass->index = 1;
7261 pTIClass->Name = NULL;
7262 pTIClass->dwHelpContext = -1;
7263 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7264 pTIClass->TypeAttr.lcid = lcid;
7265 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7266 pTIClass->TypeAttr.wMajorVerNum = 0;
7267 pTIClass->TypeAttr.wMinorVerNum = 0;
7268 pTIClass->TypeAttr.cbAlignment = 2;
7269 pTIClass->TypeAttr.cbSizeInstance = -1;
7270 pTIClass->TypeAttr.cbSizeVft = -1;
7271 pTIClass->TypeAttr.cFuncs = 0;
7272 pTIClass->TypeAttr.cImplTypes = 1;
7273 pTIClass->TypeAttr.cVars = 0;
7274 pTIClass->TypeAttr.wTypeFlags = 0;
7276 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7277 pTIClass->impltypelist->hRef = 0;
7279 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7282 ref->pImpTLInfo = TLB_REF_INTERNAL;
7283 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7285 dump_TypeInfo(pTIClass);
7287 pTIIface->next = pTIClass;
7288 pTypeLibImpl->TypeInfoCount++;
7290 *pptinfo = (ITypeInfo*)pTIClass;
7292 ITypeInfo_AddRef(*pptinfo);
7293 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7299 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7301 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7303 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7306 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7308 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7310 return ITypeInfo_AddRef((ITypeInfo *)This);
7313 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7315 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7317 return ITypeInfo_Release((ITypeInfo *)This);
7320 static HRESULT WINAPI ITypeComp_fnBind(
7325 ITypeInfo ** ppTInfo,
7326 DESCKIND * pDescKind,
7329 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7330 const TLBFuncDesc *pFDesc;
7331 const TLBVarDesc *pVDesc;
7332 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7334 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7336 *pDescKind = DESCKIND_NONE;
7337 pBindPtr->lpfuncdesc = NULL;
7340 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7341 if (!strcmpiW(pFDesc->Name, szName)) {
7342 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7345 /* name found, but wrong flags */
7346 hr = TYPE_E_TYPEMISMATCH;
7351 HRESULT hr = TLB_AllocAndInitFuncDesc(
7353 &pBindPtr->lpfuncdesc,
7354 This->TypeAttr.typekind == TKIND_DISPATCH);
7357 *pDescKind = DESCKIND_FUNCDESC;
7358 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7359 ITypeInfo_AddRef(*ppTInfo);
7362 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7363 if (!strcmpiW(pVDesc->Name, szName)) {
7364 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7367 *pDescKind = DESCKIND_VARDESC;
7368 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7369 ITypeInfo_AddRef(*ppTInfo);
7374 /* FIXME: search each inherited interface, not just the first */
7375 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7376 /* recursive search */
7380 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7383 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7384 ITypeInfo_Release(pTInfo);
7388 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7389 ITypeComp_Release(pTComp);
7392 WARN("Could not search inherited interface!\n");
7394 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7398 static HRESULT WINAPI ITypeComp_fnBindType(
7402 ITypeInfo ** ppTInfo,
7403 ITypeComp ** ppTComp)
7405 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7407 /* strange behaviour (does nothing) but like the
7410 if (!ppTInfo || !ppTComp)
7419 static const ITypeCompVtbl tcompvt =
7422 ITypeComp_fnQueryInterface,
7424 ITypeComp_fnRelease,
7427 ITypeComp_fnBindType