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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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.
32 * So when you release the dispinterface, you delete the vtable-interface structures
33 * as well... fortunately, clean up of structures is not implemented.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
38 * - some garbage is read from function names on some very rare occasions.
40 * --------------------------------------------------------------------------------------
41 * Known problems left from previous implementation (1999, Rein Klazes) :
43 * -. Data structures are straightforward, but slow for look-ups.
44 * -. (related) nothing is hashed
45 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
46 * of them I don't know yet how to implement them.
47 * -. Most error return values are just guessed not checked with windows
49 * -. didn't bother with a c++ interface
50 * -. lousy fatal error handling
51 * -. some methods just return pointers to internal data structures, this is
52 * partly laziness, partly I want to check how windows does it.
57 #include "wine/port.h"
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
76 #include "wine/unicode.h"
79 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(ole);
83 WINE_DECLARE_DEBUG_CHANNEL(typelib);
85 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
86 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
88 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
89 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
91 /****************************************************************************
94 * Takes p_iVal (which is in little endian) and returns it
95 * in the host machine's byte order.
97 #ifdef WORDS_BIGENDIAN
98 static WORD FromLEWord(WORD p_iVal)
100 return (((p_iVal & 0x00FF) << 8) |
101 ((p_iVal & 0xFF00) >> 8));
105 static DWORD FromLEDWord(DWORD p_iVal)
107 return (((p_iVal & 0x000000FF) << 24) |
108 ((p_iVal & 0x0000FF00) << 8) |
109 ((p_iVal & 0x00FF0000) >> 8) |
110 ((p_iVal & 0xFF000000) >> 24));
113 #define FromLEWord(X) (X)
114 #define FromLEDWord(X) (X)
118 /****************************************************************************
121 * Fix byte order in any structure if necessary
123 #ifdef WORDS_BIGENDIAN
124 static void FromLEWords(void *p_Val, int p_iSize)
128 p_iSize /= sizeof(WORD);
131 *Val = FromLEWord(*Val);
138 static void FromLEDWords(void *p_Val, int p_iSize)
142 p_iSize /= sizeof(DWORD);
145 *Val = FromLEDWord(*Val);
151 #define FromLEWords(X,Y) /*nothing*/
152 #define FromLEDWords(X,Y) /*nothing*/
155 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
156 /* buffer must be at least 60 characters long */
157 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
159 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
160 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
162 memcpy( buffer, TypelibW, sizeof(TypelibW) );
163 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
164 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
168 /* get the path of an interface key, in the form "Interface\\<guid>" */
169 /* buffer must be at least 50 characters long */
170 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
172 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
174 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
175 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
179 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
180 /* buffer must be at least 16 characters long */
181 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
183 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
184 static const WCHAR win16W[] = {'w','i','n','1','6',0};
185 static const WCHAR win32W[] = {'w','i','n','3','2',0};
187 sprintfW( buffer, LcidFormatW, lcid );
190 case SYS_WIN16: strcatW( buffer, win16W ); break;
191 case SYS_WIN32: strcatW( buffer, win32W ); break;
193 TRACE("Typelib is for unsupported syskind %i\n", syskind);
199 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
202 /****************************************************************************
203 * QueryPathOfRegTypeLib [OLEAUT32.164]
205 * Gets the path to a registered type library.
208 * guid [I] referenced guid
209 * wMaj [I] major version
210 * wMin [I] minor version
212 * path [O] path of typelib
216 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
217 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
220 HRESULT WINAPI QueryPathOfRegTypeLib(
227 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
231 WCHAR Path[MAX_PATH];
234 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
236 get_typelib_key( guid, wMaj, wMin, buffer );
238 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
239 if (res == ERROR_FILE_NOT_FOUND)
241 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
242 return TYPE_E_LIBNOTREGISTERED;
244 else if (res != ERROR_SUCCESS)
246 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
247 return TYPE_E_REGISTRYACCESS;
252 LONG dwPathLen = sizeof(Path);
254 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
256 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
260 else if (myLCID == lcid)
262 /* try with sub-langid */
263 myLCID = SUBLANGID(lcid);
265 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
267 /* try with system langid */
277 *path = SysAllocString( Path );
282 TRACE_(typelib)("-- 0x%08lx\n", hr);
286 /******************************************************************************
287 * CreateTypeLib [OLEAUT32.160] creates a typelib
293 HRESULT WINAPI CreateTypeLib(
294 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
296 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
300 /******************************************************************************
301 * LoadTypeLib [OLEAUT32.161]
303 * Loads a type library
306 * szFile [I] Name of file to load from.
307 * pptLib [O] Pointer that receives ITypeLib object on success.
314 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
316 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
318 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
319 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
322 /******************************************************************************
323 * LoadTypeLibEx [OLEAUT32.183]
325 * Loads and optionally registers a type library
331 HRESULT WINAPI LoadTypeLibEx(
332 LPCOLESTR szFile, /* [in] Name of file to load from */
333 REGKIND regkind, /* [in] Specify kind of registration */
334 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
336 WCHAR szPath[MAX_PATH+1];
339 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
343 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
348 case REGKIND_DEFAULT:
349 /* don't register typelibs supplied with full path. Experimentation confirms the following */
350 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
351 (szFile[0] && (szFile[1] == ':'))) break;
352 /* else fall-through */
354 case REGKIND_REGISTER:
355 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
357 IUnknown_Release(*pptLib);
365 TRACE(" returns %08lx\n",res);
369 /******************************************************************************
370 * LoadRegTypeLib [OLEAUT32.162]
372 * Loads a registered type library.
375 * rguid [I] GUID of the registered type library.
376 * wVerMajor [I] major version.
377 * wVerMinor [I] minor version.
378 * lcid [I] locale ID.
379 * ppTLib [O] pointer that receives an ITypeLib object on success.
383 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
386 HRESULT WINAPI LoadRegTypeLib(
398 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
402 res= LoadTypeLib(bstr, ppTLib);
406 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
412 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
413 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
414 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
415 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
416 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
417 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
419 /******************************************************************************
420 * RegisterTypeLib [OLEAUT32.163]
421 * Adds information about a type library to the System Registry
423 * Docs: ITypeLib FAR * ptlib
424 * Docs: OLECHAR FAR* szFullPath
425 * Docs: OLECHAR FAR* szHelpDir
431 HRESULT WINAPI RegisterTypeLib(
432 ITypeLib * ptlib, /* [in] Pointer to the library*/
433 OLECHAR * szFullPath, /* [in] full Path of the library*/
434 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
437 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
438 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
439 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
449 if (ptlib == NULL || szFullPath == NULL)
452 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
455 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
458 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
459 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
463 /* Set the human-readable name of the typelib */
464 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
466 if (RegSetValueExW(key, NULL, 0, REG_SZ,
467 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
475 /* Make up the name of the typelib path subkey */
476 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
478 /* Create the typelib path subkey */
479 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
480 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
482 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
483 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
491 /* Create the flags subkey */
492 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
493 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
495 /* FIXME: is %u correct? */
496 static const WCHAR formatW[] = {'%','u',0};
498 sprintfW(buf, formatW, attr->wLibFlags);
499 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
500 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
508 /* create the helpdir subkey */
509 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
510 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
512 BOOL freeHelpDir = FALSE;
515 /* if we created a new key, and helpDir was null, set the helpdir
516 to the directory which contains the typelib. However,
517 if we just opened an existing key, we leave the helpdir alone */
518 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
519 szHelpDir = SysAllocString(szFullPath);
520 pIndexStr = strrchrW(szHelpDir, '\\');
527 /* if we have an szHelpDir, set it! */
528 if (szHelpDir != NULL) {
529 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
530 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
536 if (freeHelpDir) SysFreeString(szHelpDir);
548 /* register OLE Automation-compatible interfaces for this typelib */
549 types = ITypeLib_GetTypeInfoCount(ptlib);
550 for (tidx=0; tidx<types; tidx++) {
551 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
552 LPOLESTR name = NULL;
553 ITypeInfo *tinfo = NULL;
555 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
558 case TKIND_INTERFACE:
559 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
560 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
564 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
565 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
569 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
574 TYPEATTR *tattr = NULL;
575 ITypeInfo_GetTypeAttr(tinfo, &tattr);
578 TRACE_(typelib)("guid=%s, flags=%04x (",
579 debugstr_guid(&tattr->guid),
582 if (TRACE_ON(typelib)) {
583 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
603 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
605 /* register interface<->typelib coupling */
606 get_interface_key( &tattr->guid, keyName );
607 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
608 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
611 RegSetValueExW(key, NULL, 0, REG_SZ,
612 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
614 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
615 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
616 RegSetValueExW(subKey, NULL, 0, REG_SZ,
617 (BYTE*)PSOA, sizeof PSOA);
621 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
622 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
623 RegSetValueExW(subKey, NULL, 0, REG_SZ,
624 (BYTE*)PSOA, sizeof PSOA);
628 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
629 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
632 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
633 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
635 StringFromGUID2(&attr->guid, buffer, 40);
636 RegSetValueExW(subKey, NULL, 0, REG_SZ,
637 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
638 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
639 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
640 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
648 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
651 ITypeInfo_Release(tinfo);
658 ITypeLib_ReleaseTLibAttr(ptlib, attr);
664 /******************************************************************************
665 * UnRegisterTypeLib [OLEAUT32.186]
666 * Removes information about a type library from the System Registry
673 HRESULT WINAPI UnRegisterTypeLib(
674 REFGUID libid, /* [in] Guid of the library */
675 WORD wVerMajor, /* [in] major version */
676 WORD wVerMinor, /* [in] minor version */
677 LCID lcid, /* [in] locale id */
680 BSTR tlibPath = NULL;
683 WCHAR subKeyName[50];
686 BOOL deleteOtherStuff;
689 TYPEATTR* typeAttr = NULL;
691 ITypeInfo* typeInfo = NULL;
692 ITypeLib* typeLib = NULL;
695 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
697 /* Create the path to the key */
698 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
700 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
702 TRACE("Unsupported syskind %i\n", syskind);
703 result = E_INVALIDARG;
707 /* get the path to the typelib on disk */
708 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
709 result = E_INVALIDARG;
713 /* Try and open the key to the type library. */
714 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
715 result = E_INVALIDARG;
719 /* Try and load the type library */
720 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
721 result = TYPE_E_INVALIDSTATE;
725 /* remove any types registered with this typelib */
726 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
727 for (i=0; i<numTypes; i++) {
728 /* get the kind of type */
729 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
733 /* skip non-interfaces, and get type info for the type */
734 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
737 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
740 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
744 /* the path to the type */
745 get_interface_key( &typeAttr->guid, subKeyName );
747 /* Delete its bits */
748 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
751 RegDeleteKeyW(subKey, ProxyStubClsidW);
752 RegDeleteKeyW(subKey, ProxyStubClsid32W);
753 RegDeleteKeyW(subKey, TypeLibW);
756 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
759 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
761 if (typeInfo) ITypeInfo_Release(typeInfo);
765 /* Now, delete the type library path subkey */
766 get_lcid_subkey( lcid, syskind, subKeyName );
767 RegDeleteKeyW(key, subKeyName);
768 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
769 RegDeleteKeyW(key, subKeyName);
771 /* check if there is anything besides the FLAGS/HELPDIR keys.
772 If there is, we don't delete them */
773 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
774 deleteOtherStuff = TRUE;
776 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
777 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
779 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
780 if (!strcmpW(subKeyName, FLAGSW)) continue;
781 if (!strcmpW(subKeyName, HELPDIRW)) continue;
782 deleteOtherStuff = FALSE;
786 /* only delete the other parts of the key if we're absolutely sure */
787 if (deleteOtherStuff) {
788 RegDeleteKeyW(key, FLAGSW);
789 RegDeleteKeyW(key, HELPDIRW);
793 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
794 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
795 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
799 if (tlibPath) SysFreeString(tlibPath);
800 if (typeLib) ITypeLib_Release(typeLib);
801 if (subKey) RegCloseKey(subKey);
802 if (key) RegCloseKey(key);
806 /*======================= ITypeLib implementation =======================*/
808 typedef struct tagTLBCustData
812 struct tagTLBCustData* next;
815 /* data structure for import typelibs */
816 typedef struct tagTLBImpLib
818 int offset; /* offset in the file (MSFT)
819 offset in nametable (SLTG)
820 just used to identify library while reading
822 GUID guid; /* libid */
823 BSTR name; /* name */
825 LCID lcid; /* lcid of imported typelib */
827 WORD wVersionMajor; /* major version number */
828 WORD wVersionMinor; /* minor version number */
830 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
831 NULL if not yet loaded */
832 struct tagTLBImpLib * next;
835 /* internal ITypeLib data */
836 typedef struct tagITypeLibImpl
838 const ITypeLib2Vtbl *lpVtbl;
839 const ITypeCompVtbl *lpVtblTypeComp;
841 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
843 /* strings can be stored in tlb as multibyte strings BUT they are *always*
844 * exported to the application as a UNICODE string.
850 unsigned long dwHelpContext;
851 int TypeInfoCount; /* nr of typeinfo's in librarry */
852 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
853 int ctCustData; /* number of items in cust data list */
854 TLBCustData * pCustData; /* linked list to cust data */
855 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
856 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
857 libary. Only used while read MSFT
860 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
861 struct tagITypeLibImpl *next, *prev;
866 static const ITypeLib2Vtbl tlbvt;
867 static const ITypeCompVtbl tlbtcvt;
869 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
871 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
874 /* ITypeLib methods */
875 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
876 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
878 /*======================= ITypeInfo implementation =======================*/
880 /* data for referenced types */
881 typedef struct tagTLBRefType
883 INT index; /* Type index for internal ref or for external ref
884 it the format is SLTG. -2 indicates to
887 GUID guid; /* guid of the referenced type */
888 /* if index == TLB_REF_USE_GUID */
890 HREFTYPE reference; /* The href of this ref */
891 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
892 TLB_REF_INTERNAL for internal refs
893 TLB_REF_NOT_FOUND for broken refs */
895 struct tagTLBRefType * next;
898 #define TLB_REF_USE_GUID -2
900 #define TLB_REF_INTERNAL (void*)-2
901 #define TLB_REF_NOT_FOUND (void*)-1
903 /* internal Parameter data */
904 typedef struct tagTLBParDesc
908 TLBCustData * pCustData; /* linked list to cust data */
911 /* internal Function data */
912 typedef struct tagTLBFuncDesc
914 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
915 BSTR Name; /* the name of this function */
916 TLBParDesc *pParamDesc; /* array with param names and custom data */
918 int HelpStringContext;
920 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
922 TLBCustData * pCustData; /* linked list to cust data; */
923 struct tagTLBFuncDesc * next;
926 /* internal Variable data */
927 typedef struct tagTLBVarDesc
929 VARDESC vardesc; /* lots of info on the variable and its attributes. */
930 BSTR Name; /* the name of this variable */
932 int HelpStringContext; /* FIXME: where? */
935 TLBCustData * pCustData;/* linked list to cust data; */
936 struct tagTLBVarDesc * next;
939 /* internal implemented interface data */
940 typedef struct tagTLBImplType
942 HREFTYPE hRef; /* hRef of interface */
943 int implflags; /* IMPLFLAG_*s */
945 TLBCustData * pCustData;/* linked list to custom data; */
946 struct tagTLBImplType *next;
949 /* internal TypeInfo data */
950 typedef struct tagITypeInfoImpl
952 const ITypeInfo2Vtbl *lpVtbl;
953 const ITypeCompVtbl *lpVtblTypeComp;
955 TYPEATTR TypeAttr ; /* _lots_ of type information. */
956 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
957 int index; /* index in this typelib; */
958 HREFTYPE hreftype; /* hreftype for app object binding */
959 /* type libs seem to store the doc strings in ascii
960 * so why should we do it in unicode?
965 unsigned long dwHelpContext;
966 unsigned long dwHelpStringContext;
969 TLBFuncDesc * funclist; /* linked list with function descriptions */
972 TLBVarDesc * varlist; /* linked list with variable descriptions */
974 /* Implemented Interfaces */
975 TLBImplType * impltypelist;
977 TLBRefType * reflist;
979 TLBCustData * pCustData; /* linked list to cust data; */
980 struct tagITypeInfoImpl * next;
983 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
985 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
988 static const ITypeInfo2Vtbl tinfvt;
989 static const ITypeCompVtbl tcompvt;
991 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
993 typedef struct tagTLBContext
995 unsigned int oStart; /* start of TLB in file */
996 unsigned int pos; /* current pos */
997 unsigned int length; /* total length */
998 void *mapping; /* memory mapping */
999 MSFT_SegDir * pTblDir;
1000 ITypeLibImpl* pLibInfo;
1004 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1009 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1010 if (pTD->vt & VT_RESERVED)
1011 szVarType += strlen(strcpy(szVarType, "reserved | "));
1012 if (pTD->vt & VT_BYREF)
1013 szVarType += strlen(strcpy(szVarType, "ref to "));
1014 if (pTD->vt & VT_ARRAY)
1015 szVarType += strlen(strcpy(szVarType, "array of "));
1016 if (pTD->vt & VT_VECTOR)
1017 szVarType += strlen(strcpy(szVarType, "vector of "));
1018 switch(pTD->vt & VT_TYPEMASK) {
1019 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1020 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1021 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1022 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1023 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1024 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1025 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1026 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1027 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1028 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1029 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1030 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1031 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1032 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1033 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1034 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1035 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1036 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1037 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1038 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1039 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1040 pTD->u.hreftype); break;
1041 case VT_PTR: sprintf(szVarType, "ptr to ");
1042 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1044 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1045 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1047 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1048 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1049 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1052 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1056 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1058 USHORT flags = edesc->u.paramdesc.wParamFlags;
1059 dump_TypeDesc(&edesc->tdesc,buf);
1060 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1061 MESSAGE("\t\tu.paramdesc.wParamFlags");
1062 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1063 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1064 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1065 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1066 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1067 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1068 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1069 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1070 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1072 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1074 MESSAGE("memid is %08lx\n",funcdesc->memid);
1075 for (i=0;i<funcdesc->cParams;i++) {
1076 MESSAGE("Param %d:\n",i);
1077 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1079 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1080 switch (funcdesc->funckind) {
1081 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1082 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1083 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1084 case FUNC_STATIC: MESSAGE("static");break;
1085 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1086 default: MESSAGE("unknown");break;
1088 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1089 switch (funcdesc->invkind) {
1090 case INVOKE_FUNC: MESSAGE("func");break;
1091 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1092 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1093 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1095 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1096 switch (funcdesc->callconv) {
1097 case CC_CDECL: MESSAGE("cdecl");break;
1098 case CC_PASCAL: MESSAGE("pascal");break;
1099 case CC_STDCALL: MESSAGE("stdcall");break;
1100 case CC_SYSCALL: MESSAGE("syscall");break;
1103 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1104 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1105 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1107 MESSAGE("\telemdescFunc (return value type):\n");
1108 dump_ELEMDESC(&funcdesc->elemdescFunc);
1111 static const char * typekind_desc[] =
1124 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1127 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1128 for (i=0;i<pfd->funcdesc.cParams;i++)
1129 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1132 dump_FUNCDESC(&(pfd->funcdesc));
1134 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1135 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1137 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1141 dump_TLBFuncDescOne(pfd);
1145 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1149 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1154 static void dump_TLBImpLib(const TLBImpLib *import)
1156 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1157 debugstr_w(import->name));
1158 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1159 import->wVersionMinor, import->lcid, import->offset);
1162 static void dump_TLBRefType(const TLBRefType * prt)
1166 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1167 if(prt->index == -1)
1168 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1170 TRACE_(typelib)("type no: %d\n", prt->index);
1172 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1173 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1174 TRACE_(typelib)("in lib\n");
1175 dump_TLBImpLib(prt->pImpTLInfo);
1181 static void dump_TLBImplType(const TLBImplType * impl)
1185 "implementing/inheriting interface hRef = %lx implflags %x\n",
1186 impl->hRef, impl->implflags);
1191 void dump_Variant(const VARIANT * pvar)
1195 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1199 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1200 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1202 TRACE(",%p", V_BYREF(pvar));
1204 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1206 TRACE(",%p", V_ARRAY(pvar));
1208 else switch (V_TYPE(pvar))
1210 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1211 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1212 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1213 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1215 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1217 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1218 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1219 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1220 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1221 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1222 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1223 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1224 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1225 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1226 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1227 V_CY(pvar).s.Lo); break;
1229 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1230 TRACE(",<invalid>");
1232 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1233 st.wHour, st.wMinute, st.wSecond);
1237 case VT_USERDEFINED:
1239 case VT_NULL: break;
1240 default: TRACE(",?"); break;
1246 static void dump_DispParms(const DISPPARAMS * pdp)
1250 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1252 while (index < pdp->cArgs)
1254 dump_Variant( &pdp->rgvarg[index] );
1259 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1261 TRACE("%p ref=%lu\n", pty, pty->ref);
1262 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1263 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1264 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1265 TRACE("fct:%u var:%u impl:%u\n",
1266 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1267 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1268 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1269 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1271 dump_TLBFuncDesc(pty->funclist);
1272 dump_TLBVarDesc(pty->varlist);
1273 dump_TLBImplType(pty->impltypelist);
1276 static void dump_VARDESC(const VARDESC *v)
1278 MESSAGE("memid %ld\n",v->memid);
1279 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1280 MESSAGE("oInst %ld\n",v->u.oInst);
1281 dump_ELEMDESC(&(v->elemdescVar));
1282 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1283 MESSAGE("varkind %d\n",v->varkind);
1286 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1288 /* VT_LPWSTR is largest type that */
1289 /* may appear in type description*/
1290 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1291 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1292 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1293 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1294 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1295 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1299 static void TLB_abort(void)
1303 static void * TLB_Alloc(unsigned size)
1306 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1308 ERR("cannot allocate memory\n");
1313 static void TLB_Free(void * ptr)
1315 HeapFree(GetProcessHeap(), 0, ptr);
1318 /* returns the size required for a deep copy of a typedesc into a
1320 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1324 if (alloc_initial_space)
1325 size += sizeof(TYPEDESC);
1331 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1334 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1335 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1341 /* deep copy a typedesc into a flat buffer */
1342 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1347 buffer = (char *)buffer + sizeof(TYPEDESC);
1356 dest->u.lptdesc = buffer;
1357 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1360 dest->u.lpadesc = buffer;
1361 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1362 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1363 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1369 /**********************************************************************
1371 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1374 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1376 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1377 pcx->pos, count, pcx->oStart, pcx->length, where);
1379 if (where != DO_NOT_SEEK)
1381 where += pcx->oStart;
1382 if (where > pcx->length)
1385 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1390 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1391 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1396 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1401 ret = MSFT_Read(buffer, count, pcx, where);
1402 FromLEDWords(buffer, ret);
1407 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1412 ret = MSFT_Read(buffer, count, pcx, where);
1413 FromLEWords(buffer, ret);
1418 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1420 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1421 memset(pGuid,0, sizeof(GUID));
1424 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1425 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1426 pGuid->Data2 = FromLEWord(pGuid->Data2);
1427 pGuid->Data3 = FromLEWord(pGuid->Data3);
1428 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1431 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1433 MSFT_NameIntro niName;
1437 ERR_(typelib)("bad offset %d\n", offset);
1441 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1442 pcx->pTblDir->pNametab.offset+offset);
1444 return niName.hreftype;
1447 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1450 MSFT_NameIntro niName;
1452 WCHAR* pwstring = NULL;
1453 BSTR bstrName = NULL;
1457 ERR_(typelib)("bad offset %d\n", offset);
1460 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1461 pcx->pTblDir->pNametab.offset+offset);
1462 niName.namelen &= 0xFF; /* FIXME: correct ? */
1463 name=TLB_Alloc((niName.namelen & 0xff) +1);
1464 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1465 name[niName.namelen & 0xff]='\0';
1467 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1470 /* no invalid characters in string */
1473 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1475 /* don't check for invalid character since this has been done previously */
1476 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1478 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1479 lengthInChars = SysStringLen(bstrName);
1480 HeapFree(GetProcessHeap(), 0, pwstring);
1483 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1487 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1494 if(offset<0) return NULL;
1495 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1496 if(length <= 0) return 0;
1497 string=TLB_Alloc(length +1);
1498 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1499 string[length]='\0';
1501 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1502 string, -1, NULL, 0);
1504 /* no invalid characters in string */
1507 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1509 /* don't check for invalid character since this has been done previously */
1510 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1512 bstr = SysAllocStringLen(pwstring, lengthInChars);
1513 lengthInChars = SysStringLen(bstr);
1514 HeapFree(GetProcessHeap(), 0, pwstring);
1517 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1521 * read a value and fill a VARIANT structure
1523 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1527 TRACE_(typelib)("\n");
1529 if(offset <0) { /* data are packed in here */
1530 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1531 V_I4(pVar) = offset & 0x3ffffff;
1534 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1535 pcx->pTblDir->pCustData.offset + offset );
1536 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1537 switch (V_VT(pVar)){
1538 case VT_EMPTY: /* FIXME: is this right? */
1539 case VT_NULL: /* FIXME: is this right? */
1540 case VT_I2 : /* this should not happen */
1551 case VT_VOID : /* FIXME: is this right? */
1559 case VT_DECIMAL : /* FIXME: is this right? */
1562 /* pointer types with known behaviour */
1565 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1567 FIXME("BSTR length = %d?\n", size);
1569 ptr=TLB_Alloc(size);/* allocate temp buffer */
1570 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1571 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1572 /* FIXME: do we need a AtoW conversion here? */
1573 V_UNION(pVar, bstrVal[size])=L'\0';
1574 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1579 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1586 case VT_USERDEFINED :
1592 case VT_STREAMED_OBJECT :
1593 case VT_STORED_OBJECT :
1594 case VT_BLOB_OBJECT :
1599 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1603 if(size>0) /* (big|small) endian correct? */
1604 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1608 * create a linked list with custom data
1610 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1616 TRACE_(typelib)("\n");
1620 pNew=TLB_Alloc(sizeof(TLBCustData));
1621 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1622 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1623 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1624 /* add new custom data at head of the list */
1625 pNew->next=*ppCustData;
1627 offset = entry.next;
1632 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1636 pTd->vt=type & VT_TYPEMASK;
1638 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1640 if(pTd->vt == VT_USERDEFINED)
1641 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1643 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1647 MSFT_DoFuncs(TLBContext* pcx,
1652 TLBFuncDesc** pptfd)
1655 * member information is stored in a data structure at offset
1656 * indicated by the memoffset field of the typeinfo structure
1657 * There are several distinctive parts.
1658 * The first part starts with a field that holds the total length
1659 * of this (first) part excluding this field. Then follow the records,
1660 * for each member there is one record.
1662 * The first entry is always the length of the record (including this
1664 * The rest of the record depends on the type of the member. If there is
1665 * a field indicating the member type (function, variable, interface, etc)
1666 * I have not found it yet. At this time we depend on the information
1667 * in the type info and the usual order how things are stored.
1669 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1672 * Third is an equal sized array with file offsets to the name entry
1675 * The fourth and last (?) part is an array with offsets to the records
1676 * in the first part of this file segment.
1679 int infolen, nameoffset, reclength, nrattributes, i;
1680 int recoffset = offset + sizeof(INT);
1683 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1684 TLBFuncDesc *ptfd_prev = NULL;
1686 TRACE_(typelib)("\n");
1688 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1690 for ( i = 0; i < cFuncs ; i++ )
1692 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1694 /* name, eventually add to a hash table */
1695 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1696 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1698 /* nameoffset is sometimes -1 on the second half of a propget/propput
1699 * pair of functions */
1700 if ((nameoffset == -1) && (i > 0))
1701 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1703 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1705 /* read the function information record */
1706 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1710 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1712 /* do the attributes */
1713 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1716 if ( nrattributes > 0 )
1718 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1720 if ( nrattributes > 1 )
1722 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1723 pFuncRec->OptAttr[1]) ;
1725 if ( nrattributes > 2 )
1727 if ( pFuncRec->FKCCIC & 0x2000 )
1729 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1733 (*pptfd)->Entry = MSFT_ReadString(pcx,
1734 pFuncRec->OptAttr[2]);
1736 if( nrattributes > 5 )
1738 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1740 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1743 pFuncRec->OptAttr[6],
1744 &(*pptfd)->pCustData);
1751 /* fill the FuncDesc Structure */
1752 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1753 offset + infolen + ( i + 1) * sizeof(INT));
1755 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1756 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1757 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1758 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1759 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1760 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1761 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1765 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1768 /* do the parameters/arguments */
1769 if(pFuncRec->nrargs)
1772 MSFT_ParameterInfo paraminfo;
1774 (*pptfd)->funcdesc.lprgelemdescParam =
1775 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1777 (*pptfd)->pParamDesc =
1778 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1780 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1781 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1783 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1785 TYPEDESC *lpArgTypeDesc;
1786 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1793 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1796 if (paraminfo.oName == -1)
1797 /* this occurs for [propput] or [propget] methods, so
1798 * we should just set the name of the parameter to the
1799 * name of the method. */
1800 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1802 (*pptfd)->pParamDesc[j].Name =
1803 MSFT_ReadName( pcx, paraminfo.oName );
1804 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1806 lpArgTypeDesc = &elemdesc->tdesc;
1808 /* resolve referenced type if any */
1809 while ( lpArgTypeDesc != NULL )
1811 switch ( lpArgTypeDesc->vt )
1814 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1818 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1821 case VT_USERDEFINED:
1822 MSFT_DoRefType(pcx, pTI,
1823 lpArgTypeDesc->u.hreftype);
1825 lpArgTypeDesc = NULL;
1829 lpArgTypeDesc = NULL;
1834 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1835 (pFuncRec->FKCCIC & 0x1000) )
1837 INT* pInt = (INT *)((char *)pFuncRec +
1839 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1841 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1843 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1844 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1846 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1850 elemdesc->u.paramdesc.pparamdescex = NULL;
1852 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1855 pFuncRec->OptAttr[7+j],
1856 &(*pptfd)->pParamDesc[j].pCustData);
1859 /* SEEK value = jump to offset,
1860 * from there jump to the end of record,
1861 * go back by (j-1) arguments
1863 MSFT_ReadLEDWords( ¶minfo ,
1864 sizeof(MSFT_ParameterInfo), pcx,
1865 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1866 * sizeof(MSFT_ParameterInfo)));
1870 /* scode is not used: archaic win16 stuff FIXME: right? */
1871 (*pptfd)->funcdesc.cScodes = 0 ;
1872 (*pptfd)->funcdesc.lprgscode = NULL ;
1875 pptfd = & ((*pptfd)->next);
1876 recoffset += reclength;
1880 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1881 int cVars, int offset, TLBVarDesc ** pptvd)
1883 int infolen, nameoffset, reclength;
1885 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1889 TRACE_(typelib)("\n");
1891 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1892 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1893 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1894 recoffset += offset+sizeof(INT);
1895 for(i=0;i<cVars;i++){
1896 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1897 /* name, eventually add to a hash table */
1898 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1899 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1900 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1901 /* read the variable information record */
1902 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1904 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1906 if(reclength >(6*sizeof(INT)) )
1907 (*pptvd)->HelpContext=pVarRec->HelpContext;
1908 if(reclength >(7*sizeof(INT)) )
1909 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1910 if(reclength >(8*sizeof(INT)) )
1911 if(reclength >(9*sizeof(INT)) )
1912 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1913 /* fill the VarDesc Structure */
1914 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1915 offset + infolen + ( i + 1) * sizeof(INT));
1916 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1917 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1918 MSFT_GetTdesc(pcx, pVarRec->DataType,
1919 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1920 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1921 if(pVarRec->VarKind == VAR_CONST ){
1922 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1923 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1924 pVarRec->OffsValue, pcx);
1926 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1927 pptvd=&((*pptvd)->next);
1928 recoffset += reclength;
1931 /* fill in data for a hreftype (offset). When the referenced type is contained
1932 * in the typelib, it's just an (file) offset in the type info base dir.
1933 * If comes from import, it's an offset+1 in the ImpInfo table
1935 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1939 TLBRefType **ppRefType = &pTI->reflist;
1941 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1944 if((*ppRefType)->reference == offset)
1946 ppRefType = &(*ppRefType)->next;
1949 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1950 sizeof(**ppRefType));
1952 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1953 /* external typelib */
1954 MSFT_ImpInfo impinfo;
1955 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1957 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1959 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1960 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1961 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1962 if(pImpLib->offset==impinfo.oImpFile) break;
1963 pImpLib=pImpLib->next;
1966 (*ppRefType)->reference=offset;
1967 (*ppRefType)->pImpTLInfo = pImpLib;
1968 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1969 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1970 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
1971 (*ppRefType)->index = TLB_REF_USE_GUID;
1973 (*ppRefType)->index = impinfo.oGuid;
1975 ERR("Cannot find a reference\n");
1976 (*ppRefType)->reference=-1;
1977 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1980 /* in this typelib */
1981 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1982 (*ppRefType)->reference=offset;
1983 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1987 /* process Implemented Interfaces of a com class */
1988 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1992 MSFT_RefRecord refrec;
1993 TLBImplType **ppImpl = &pTI->impltypelist;
1995 TRACE_(typelib)("\n");
1997 for(i=0;i<count;i++){
1998 if(offset<0) break; /* paranoia */
1999 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2000 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2001 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2002 (*ppImpl)->hRef = refrec.reftype;
2003 (*ppImpl)->implflags=refrec.flags;
2004 (*ppImpl)->ctCustData=
2005 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2006 offset=refrec.onext;
2007 ppImpl=&((*ppImpl)->next);
2011 * process a typeinfo record
2013 static ITypeInfoImpl * MSFT_DoTypeInfo(
2017 ITypeLibImpl * pLibInfo)
2019 MSFT_TypeInfoBase tiBase;
2020 ITypeInfoImpl *ptiRet;
2022 TRACE_(typelib)("count=%u\n", count);
2024 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2025 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2026 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2028 /* this is where we are coming from */
2029 ptiRet->pTypeLib = pLibInfo;
2030 ptiRet->index=count;
2031 /* fill in the typeattr fields */
2032 WARN("Assign constructor/destructor memid\n");
2034 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2035 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2036 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2037 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2038 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2039 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2040 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2041 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2042 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2043 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2044 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2045 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2046 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2047 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2048 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2049 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2050 MSFT_GetTdesc(pcx, tiBase.datatype1,
2051 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2054 /* IDLDESC idldescType; *//* never saw this one != zero */
2056 /* name, eventually add to a hash table */
2057 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2058 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2059 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2061 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2062 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2063 ptiRet->dwHelpContext=tiBase.helpcontext;
2065 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2066 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2068 /* note: InfoType's Help file and HelpStringDll come from the containing
2069 * library. Further HelpString and Docstring appear to be the same thing :(
2072 if(ptiRet->TypeAttr.cFuncs >0 )
2073 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2074 ptiRet->TypeAttr.cVars,
2075 tiBase.memoffset, & ptiRet->funclist);
2077 if(ptiRet->TypeAttr.cVars >0 )
2078 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2079 ptiRet->TypeAttr.cVars,
2080 tiBase.memoffset, & ptiRet->varlist);
2081 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2082 switch(ptiRet->TypeAttr.typekind)
2085 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2088 case TKIND_DISPATCH:
2089 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2091 if (tiBase.datatype1 != -1)
2093 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2094 ptiRet->impltypelist->hRef = tiBase.datatype1;
2098 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2099 ptiRet->impltypelist->hRef = dispatch_href;
2103 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2104 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2105 ptiRet->impltypelist->hRef = tiBase.datatype1;
2110 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2112 TRACE_(typelib)("%s guid: %s kind:%s\n",
2113 debugstr_w(ptiRet->Name),
2114 debugstr_guid(&ptiRet->TypeAttr.guid),
2115 typekind_desc[ptiRet->TypeAttr.typekind]);
2120 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2121 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2122 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2125 static ITypeLibImpl *tlb_cache_first;
2126 static CRITICAL_SECTION cache_section;
2127 static CRITICAL_SECTION_DEBUG cache_section_debug =
2129 0, 0, &cache_section,
2130 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2131 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2133 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2136 /****************************************************************************
2139 * find the type of the typelib file and map the typelib resource into
2142 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2143 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2144 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2146 ITypeLibImpl *entry;
2147 int ret = TYPE_E_CANTLOADLIBRARY;
2153 lstrcpynW(pszPath, pszFileName, cchPath);
2155 /* first try loading as a dll and access the typelib as a resource */
2156 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2157 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2160 /* it may have been specified with resource index appended to the
2161 * path, so remove it and try again */
2162 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2163 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2165 index = atoiW(pIndexStr);
2166 pszPath[pIndexStr - pszFileName - 1] = '\0';
2168 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2169 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2173 /* get the path to the specified typelib file */
2176 /* otherwise, try loading as a regular file */
2177 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2178 return TYPE_E_CANTLOADLIBRARY;
2181 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2183 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2184 EnterCriticalSection(&cache_section);
2185 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2187 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2189 TRACE("cache hit\n");
2190 *ppTypeLib = (ITypeLib2*)entry;
2191 ITypeLib_AddRef(*ppTypeLib);
2192 LeaveCriticalSection(&cache_section);
2196 LeaveCriticalSection(&cache_section);
2198 /* now actually load and parse the typelib */
2201 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2202 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2205 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2208 LPVOID pBase = LockResource(hGlobal);
2209 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2213 /* try to load as incore resource */
2214 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2215 if (dwSignature == MSFT_SIGNATURE)
2216 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2217 else if (dwSignature == SLTG_SIGNATURE)
2218 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2220 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2222 FreeResource( hGlobal );
2225 FreeLibrary(hinstDLL);
2229 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2230 if (INVALID_HANDLE_VALUE != hFile)
2232 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2235 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2238 /* retrieve file size */
2239 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2240 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2242 if (dwSignature == MSFT_SIGNATURE)
2243 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2244 else if (dwSignature == SLTG_SIGNATURE)
2245 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2247 UnmapViewOfFile(pBase);
2249 CloseHandle(hMapping);
2256 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2258 TRACE("adding to cache\n");
2259 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2260 lstrcpyW(impl->path, pszPath);
2261 /* We should really canonicalise the path here. */
2262 impl->index = index;
2264 /* FIXME: check if it has added already in the meantime */
2265 EnterCriticalSection(&cache_section);
2266 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2268 tlb_cache_first = impl;
2269 LeaveCriticalSection(&cache_section);
2272 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2277 /*================== ITypeLib(2) Methods ===================================*/
2279 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2281 ITypeLibImpl* pTypeLibImpl;
2283 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2284 if (!pTypeLibImpl) return NULL;
2286 pTypeLibImpl->lpVtbl = &tlbvt;
2287 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2288 pTypeLibImpl->ref = 1;
2290 return pTypeLibImpl;
2293 /****************************************************************************
2294 * ITypeLib2_Constructor_MSFT
2296 * loading an MSFT typelib from an in-memory image
2298 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2302 MSFT_Header tlbHeader;
2303 MSFT_SegDir tlbSegDir;
2304 ITypeLibImpl * pTypeLibImpl;
2306 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2308 pTypeLibImpl = TypeLibImpl_Constructor();
2309 if (!pTypeLibImpl) return NULL;
2311 /* get pointer to beginning of typelib data */
2315 cx.pLibInfo = pTypeLibImpl;
2316 cx.length = dwTLBLength;
2319 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2320 TRACE_(typelib)("header:\n");
2321 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2322 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2323 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2326 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2328 /* there is a small amount of information here until the next important
2330 * the segment directory . Try to calculate the amount of data */
2331 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2333 /* now read the segment directory */
2334 TRACE("read segment directory (at %ld)\n",lPSegDir);
2335 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2336 cx.pTblDir = &tlbSegDir;
2338 /* just check two entries */
2339 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2341 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2342 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2346 /* now fill our internal data */
2347 /* TLIBATTR fields */
2348 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2350 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2351 /* Windows seems to have zero here, is this correct? */
2352 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2353 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2355 pTypeLibImpl->LibAttr.lcid = 0;
2357 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2358 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2359 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2360 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2362 /* name, eventually add to a hash table */
2363 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2366 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2367 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2369 if( tlbHeader.varflags & HELPDLLFLAG)
2372 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2373 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2376 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2379 if(tlbHeader.CustomDataOffset >= 0)
2381 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2384 /* fill in typedescriptions */
2385 if(tlbSegDir.pTypdescTab.length > 0)
2387 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2389 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2390 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2393 /* FIXME: add several sanity checks here */
2394 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2395 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2397 /* FIXME: check safearray */
2399 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2401 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2403 else if(td[0] == VT_CARRAY)
2405 /* array descr table here */
2406 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2408 else if(td[0] == VT_USERDEFINED)
2410 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2412 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2415 /* second time around to fill the array subscript info */
2418 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2419 if(tlbSegDir.pArrayDescriptions.offset>0)
2421 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2422 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2425 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2427 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2429 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2431 for(j = 0; j<td[2]; j++)
2433 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2434 sizeof(INT), &cx, DO_NOT_SEEK);
2435 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2436 sizeof(INT), &cx, DO_NOT_SEEK);
2441 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2442 ERR("didn't find array description data\n");
2447 /* imported type libs */
2448 if(tlbSegDir.pImpFiles.offset>0)
2450 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2451 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2454 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2459 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2460 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2461 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2463 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2464 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2465 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2466 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2469 name = TLB_Alloc(size+1);
2470 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2471 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2472 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2473 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2476 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2477 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2479 ppImpLib = &(*ppImpLib)->next;
2484 if(tlbHeader.nrtypeinfos >= 0 )
2486 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2487 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2490 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2492 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2494 ppTI = &((*ppTI)->next);
2495 (pTypeLibImpl->TypeInfoCount)++;
2499 TRACE("(%p)\n", pTypeLibImpl);
2500 return (ITypeLib2*) pTypeLibImpl;
2504 static BSTR TLB_MultiByteToBSTR(char *ptr)
2510 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2511 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2512 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2513 ret = SysAllocString(nameW);
2514 HeapFree(GetProcessHeap(), 0, nameW);
2518 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2524 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2525 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2529 guid->Data4[0] = s >> 8;
2530 guid->Data4[1] = s & 0xff;
2533 for(i = 0; i < 6; i++) {
2534 memcpy(b, str + 24 + 2 * i, 2);
2535 guid->Data4[i + 2] = strtol(b, NULL, 16);
2540 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2547 bytelen = *(WORD*)ptr;
2548 if(bytelen == 0xffff) return 2;
2549 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2550 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2551 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2552 *pBstr = SysAllocStringLen(nameW, len);
2553 HeapFree(GetProcessHeap(), 0, nameW);
2557 static WORD SLTG_ReadStringA(char *ptr, char **str)
2562 bytelen = *(WORD*)ptr;
2563 if(bytelen == 0xffff) return 2;
2564 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2565 memcpy(*str, ptr + 2, bytelen);
2566 (*str)[bytelen] = '\0';
2570 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2572 char *ptr = pLibBlk;
2575 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2576 FIXME("libblk magic = %04x\n", w);
2581 if((w = *(WORD*)ptr) != 0xffff) {
2582 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2587 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2589 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2591 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2594 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2597 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2598 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2600 pTypeLibImpl->LibAttr.lcid = 0;
2603 ptr += 4; /* skip res12 */
2605 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2608 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2611 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2614 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2615 ptr += sizeof(GUID);
2617 return ptr - (char*)pLibBlk;
2620 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2623 TYPEDESC *pTD = &pElem->tdesc;
2625 /* Handle [in/out] first */
2626 if((*pType & 0xc000) == 0xc000)
2627 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2628 else if(*pType & 0x8000)
2629 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2630 else if(*pType & 0x4000)
2631 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2633 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2636 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2639 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2642 if((*pType & 0xe00) == 0xe00) {
2644 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2646 pTD = pTD->u.lptdesc;
2648 switch(*pType & 0x7f) {
2651 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2653 pTD = pTD->u.lptdesc;
2656 case VT_USERDEFINED:
2657 pTD->vt = VT_USERDEFINED;
2658 pTD->u.hreftype = *(++pType) / 4;
2664 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2667 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2669 pTD->vt = VT_CARRAY;
2670 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2672 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2673 pTD->u.lpadesc->cDims = pSA->cDims;
2674 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2675 pSA->cDims * sizeof(SAFEARRAYBOUND));
2677 pTD = &pTD->u.lpadesc->tdescElem;
2683 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2687 pTD->vt = VT_SAFEARRAY;
2688 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2690 pTD = pTD->u.lptdesc;
2694 pTD->vt = *pType & 0x7f;
2704 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2709 TLBRefType **ppRefType;
2711 if(pRef->magic != SLTG_REF_MAGIC) {
2712 FIXME("Ref magic = %x\n", pRef->magic);
2715 name = ( (char*)(&pRef->names) + pRef->number);
2717 ppRefType = &pTI->reflist;
2718 for(ref = 0; ref < pRef->number >> 3; ref++) {
2720 unsigned int lib_offs, type_num;
2722 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2723 sizeof(**ppRefType));
2725 name += SLTG_ReadStringA(name, &refname);
2726 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2727 FIXME("Can't sscanf ref\n");
2728 if(lib_offs != 0xffff) {
2729 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2732 if((*import)->offset == lib_offs)
2734 import = &(*import)->next;
2737 char fname[MAX_PATH+1];
2740 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2742 (*import)->offset = lib_offs;
2743 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2745 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2746 &(*import)->wVersionMajor,
2747 &(*import)->wVersionMinor,
2748 &(*import)->lcid, fname) != 4) {
2749 FIXME("can't sscanf ref %s\n",
2750 pNameTable + lib_offs + 40);
2752 len = strlen(fname);
2753 if(fname[len-1] != '#')
2754 FIXME("fname = %s\n", fname);
2755 fname[len-1] = '\0';
2756 (*import)->name = TLB_MultiByteToBSTR(fname);
2758 (*ppRefType)->pImpTLInfo = *import;
2759 } else { /* internal ref */
2760 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2762 (*ppRefType)->reference = ref;
2763 (*ppRefType)->index = type_num;
2765 HeapFree(GetProcessHeap(), 0, refname);
2766 ppRefType = &(*ppRefType)->next;
2768 if((BYTE)*name != SLTG_REF_MAGIC)
2769 FIXME("End of ref block magic = %x\n", *name);
2770 dump_TLBRefType(pTI->reflist);
2773 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2776 SLTG_ImplInfo *info;
2777 TLBImplType **ppImplType = &pTI->impltypelist;
2778 /* I don't really get this structure, usually it's 0x16 bytes
2779 long, but iuser.tlb contains some that are 0x18 bytes long.
2780 That's ok because we can use the next ptr to jump to the next
2781 one. But how do we know the length of the last one? The WORD
2782 at offs 0x8 might be the clue. For now I'm just assuming that
2783 the last one is the regular 0x16 bytes. */
2785 info = (SLTG_ImplInfo*)pBlk;
2787 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2788 sizeof(**ppImplType));
2789 (*ppImplType)->hRef = info->ref;
2790 (*ppImplType)->implflags = info->impltypeflags;
2791 pTI->TypeAttr.cImplTypes++;
2792 ppImplType = &(*ppImplType)->next;
2794 if(info->next == 0xffff)
2797 FIXME("Interface inheriting more than one interface\n");
2798 info = (SLTG_ImplInfo*)(pBlk + info->next);
2800 info++; /* see comment at top of function */
2804 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2807 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2808 SLTG_MemberHeader *pMemHeader;
2809 char *pFirstItem, *pNextItem;
2811 if(pTIHeader->href_table != 0xffffffff) {
2812 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2817 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2819 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2821 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2822 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2825 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2829 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2832 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2833 SLTG_MemberHeader *pMemHeader;
2834 SLTG_Function *pFunc;
2835 char *pFirstItem, *pNextItem;
2836 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2839 if(pTIHeader->href_table != 0xffffffff) {
2840 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2844 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2846 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2848 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2849 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2852 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2853 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2858 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2859 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2860 FIXME("func magic = %02x\n", pFunc->magic);
2863 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2864 sizeof(**ppFuncDesc));
2865 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2867 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2868 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2869 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2870 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2871 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2872 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2874 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2875 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2877 if(pFunc->retnextopt & 0x80)
2878 pType = &pFunc->rettype;
2880 pType = (WORD*)(pFirstItem + pFunc->rettype);
2883 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2885 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2886 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2887 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2888 (*ppFuncDesc)->pParamDesc =
2889 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2890 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2892 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2894 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2895 char *paramName = pNameTable + *pArg;
2897 /* If arg type follows then paramName points to the 2nd
2898 letter of the name, else the next WORD is an offset to
2899 the arg type and paramName points to the first letter.
2900 So let's take one char off paramName and see if we're
2901 pointing at an alpha-numeric char. However if *pArg is
2902 0xffff or 0xfffe then the param has no name, the former
2903 meaning that the next WORD is the type, the latter
2904 meaning the the next WORD is an offset to the type. */
2909 else if(*pArg == 0xfffe) {
2913 else if(paramName[-1] && !isalnum(paramName[-1]))
2918 if(HaveOffs) { /* the next word is an offset to type */
2919 pType = (WORD*)(pFirstItem + *pArg);
2920 SLTG_DoType(pType, pFirstItem,
2921 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2926 pArg = SLTG_DoType(pArg, pFirstItem,
2927 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2930 /* Are we an optional param ? */
2931 if((*ppFuncDesc)->funcdesc.cParams - param <=
2932 (*ppFuncDesc)->funcdesc.cParamsOpt)
2933 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2936 (*ppFuncDesc)->pParamDesc[param].Name =
2937 TLB_MultiByteToBSTR(paramName);
2941 ppFuncDesc = &((*ppFuncDesc)->next);
2942 if(pFunc->next == 0xffff) break;
2944 pTI->TypeAttr.cFuncs = num;
2945 if (TRACE_ON(typelib))
2946 dump_TLBFuncDesc(pTI->funclist);
2947 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2950 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2953 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2954 SLTG_MemberHeader *pMemHeader;
2955 SLTG_RecordItem *pItem;
2957 TLBVarDesc **ppVarDesc = &pTI->varlist;
2962 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2964 pFirstItem = (char*)(pMemHeader + 1);
2965 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2966 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2967 if(pItem->magic != SLTG_RECORD_MAGIC) {
2968 FIXME("record magic = %02x\n", pItem->magic);
2971 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2972 sizeof(**ppVarDesc));
2973 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2974 (*ppVarDesc)->vardesc.memid = pItem->memid;
2975 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2976 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2978 if(pItem->typepos == 0x02)
2979 pType = &pItem->type;
2980 else if(pItem->typepos == 0x00)
2981 pType = (WORD*)(pFirstItem + pItem->type);
2983 FIXME("typepos = %02x\n", pItem->typepos);
2987 SLTG_DoType(pType, pFirstItem,
2988 &(*ppVarDesc)->vardesc.elemdescVar);
2990 /* FIXME("helpcontext, helpstring\n"); */
2992 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2994 ppVarDesc = &((*ppVarDesc)->next);
2995 if(pItem->next == 0xffff) break;
2997 pTI->TypeAttr.cVars = num;
2998 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3001 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3004 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3005 SLTG_MemberHeader *pMemHeader;
3006 SLTG_AliasItem *pItem;
3009 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3010 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3013 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3014 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3015 if (pItem->vt == 0xffff) {
3016 if (i<(pMemHeader->cbExtra/4-1))
3017 FIXME("Endmarker too early in process alias data!\n");
3021 FIXME("Chain extends over last entry?\n");
3024 if (pItem->vt == VT_USERDEFINED) {
3025 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3026 /* guessing here ... */
3027 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3028 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3031 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3032 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3036 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3039 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3042 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3043 SLTG_MemberHeader *pMemHeader;
3044 SLTG_AliasItem *pItem;
3046 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3047 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3048 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3049 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3050 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3053 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3056 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3057 SLTG_MemberHeader *pMemHeader;
3058 SLTG_EnumItem *pItem;
3060 TLBVarDesc **ppVarDesc = &pTI->varlist;
3063 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3065 pFirstItem = (char*)(pMemHeader + 1);
3066 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3067 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3068 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3069 FIXME("enumitem magic = %04x\n", pItem->magic);
3072 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3073 sizeof(**ppVarDesc));
3074 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3075 (*ppVarDesc)->vardesc.memid = pItem->memid;
3076 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3078 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3079 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3080 *(INT*)(pItem->value + pFirstItem);
3081 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3082 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3083 /* FIXME("helpcontext, helpstring\n"); */
3085 ppVarDesc = &((*ppVarDesc)->next);
3086 if(pItem->next == 0xffff) break;
3088 pTI->TypeAttr.cVars = num;
3089 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3092 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3093 managable copy of it into this */
3106 } SLTG_InternalOtherTypeInfo;
3108 /****************************************************************************
3109 * ITypeLib2_Constructor_SLTG
3111 * loading a SLTG typelib from an in-memory image
3113 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3115 ITypeLibImpl *pTypeLibImpl;
3116 SLTG_Header *pHeader;
3117 SLTG_BlkEntry *pBlkEntry;
3121 LPVOID pBlk, pFirstBlk;
3122 SLTG_LibBlk *pLibBlk;
3123 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3124 char *pAfterOTIBlks = NULL;
3125 char *pNameTable, *ptr;
3128 ITypeInfoImpl **ppTypeInfoImpl;
3130 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3133 pTypeLibImpl = TypeLibImpl_Constructor();
3134 if (!pTypeLibImpl) return NULL;
3138 TRACE_(typelib)("header:\n");
3139 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3140 pHeader->nrOfFileBlks );
3141 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3142 FIXME("Header type magic 0x%08lx not supported.\n",
3143 pHeader->SLTG_magic);
3147 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3148 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3150 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3151 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3153 /* Next we have a magic block */
3154 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3156 /* Let's see if we're still in sync */
3157 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3158 sizeof(SLTG_COMPOBJ_MAGIC))) {
3159 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3162 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3163 sizeof(SLTG_DIR_MAGIC))) {
3164 FIXME("dir magic = %s\n", pMagic->dir_magic);
3168 pIndex = (SLTG_Index*)(pMagic+1);
3170 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3172 pFirstBlk = (LPVOID)(pPad9 + 1);
3174 /* We'll set up a ptr to the main library block, which is the last one. */
3176 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3177 pBlkEntry[order].next != 0;
3178 order = pBlkEntry[order].next - 1, i++) {
3179 pBlk = (char*)pBlk + pBlkEntry[order].len;
3183 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3185 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3190 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3192 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3193 sizeof(*pOtherTypeInfoBlks) *
3194 pTypeLibImpl->TypeInfoCount);
3197 ptr = (char*)pLibBlk + len;
3199 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3203 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3205 w = *(WORD*)(ptr + 2);
3208 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3210 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3211 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3213 w = *(WORD*)(ptr + 4 + len);
3215 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3217 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3219 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3220 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3222 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3223 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3224 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3226 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3228 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3231 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3232 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3233 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3234 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3235 len += sizeof(SLTG_OtherTypeInfo);
3239 pAfterOTIBlks = ptr;
3241 /* Skip this WORD and get the next DWORD */
3242 len = *(DWORD*)(pAfterOTIBlks + 2);
3244 /* Now add this to pLibBLk look at what we're pointing at and
3245 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3246 dust and we should be pointing at the beginning of the name
3249 pNameTable = (char*)pLibBlk + len;
3251 switch(*(WORD*)pNameTable) {
3258 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3262 pNameTable += 0x216;
3266 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3268 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3271 /* Hopefully we now have enough ptrs set up to actually read in
3272 some TypeInfos. It's not clear which order to do them in, so
3273 I'll just follow the links along the BlkEntry chain and read
3274 them in in the order in which they're in the file */
3276 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3278 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3279 pBlkEntry[order].next != 0;
3280 order = pBlkEntry[order].next - 1, i++) {
3282 SLTG_TypeInfoHeader *pTIHeader;
3283 SLTG_TypeInfoTail *pTITail;
3285 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3286 pOtherTypeInfoBlks[i].index_name)) {
3287 FIXME("Index strings don't match\n");
3292 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3293 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3296 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3297 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3298 (*ppTypeInfoImpl)->index = i;
3299 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3300 pOtherTypeInfoBlks[i].name_offs +
3302 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3303 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3305 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3306 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3307 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3308 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3309 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3311 if((pTIHeader->typeflags1 & 7) != 2)
3312 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3313 if(pTIHeader->typeflags3 != 2)
3314 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3316 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3317 debugstr_w((*ppTypeInfoImpl)->Name),
3318 typekind_desc[pTIHeader->typekind],
3319 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3320 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3322 switch(pTIHeader->typekind) {
3324 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3328 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3331 case TKIND_INTERFACE:
3332 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3336 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3340 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3341 if (pTITail->tdescalias_vt)
3342 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3345 case TKIND_DISPATCH:
3346 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3350 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3356 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3357 but we've already set those */
3358 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3359 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3360 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3362 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3384 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3385 pBlk = (char*)pBlk + pBlkEntry[order].len;
3388 if(i != pTypeLibImpl->TypeInfoCount) {
3389 FIXME("Somehow processed %d TypeInfos\n", i);
3393 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3394 return (ITypeLib2*)pTypeLibImpl;
3397 /* ITypeLib::QueryInterface
3399 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3404 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3406 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3409 if(IsEqualIID(riid, &IID_IUnknown) ||
3410 IsEqualIID(riid,&IID_ITypeLib)||
3411 IsEqualIID(riid,&IID_ITypeLib2))
3418 ITypeLib2_AddRef(iface);
3419 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3422 TRACE("-- Interface: E_NOINTERFACE\n");
3423 return E_NOINTERFACE;
3428 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3430 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3431 ULONG ref = InterlockedIncrement(&This->ref);
3433 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3438 /* ITypeLib::Release
3440 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3442 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3443 ULONG ref = InterlockedDecrement(&This->ref);
3445 TRACE("(%p)->(%lu)\n",This, ref);
3449 /* remove cache entry */
3452 TRACE("removing from cache list\n");
3453 EnterCriticalSection(&cache_section);
3454 if (This->next) This->next->prev = This->prev;
3455 if (This->prev) This->prev->next = This->next;
3456 else tlb_cache_first = This->next;
3457 LeaveCriticalSection(&cache_section);
3458 HeapFree(GetProcessHeap(), 0, This->path);
3460 /* FIXME destroy child objects */
3461 TRACE(" destroying ITypeLib(%p)\n",This);
3465 SysFreeString(This->Name);
3469 if (This->DocString)
3471 SysFreeString(This->DocString);
3472 This->DocString = NULL;
3477 SysFreeString(This->HelpFile);
3478 This->HelpFile = NULL;
3481 if (This->HelpStringDll)
3483 SysFreeString(This->HelpStringDll);
3484 This->HelpStringDll = NULL;
3487 if (This->pTypeInfo) /* can be NULL */
3488 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3489 HeapFree(GetProcessHeap(),0,This);
3496 /* ITypeLib::GetTypeInfoCount
3498 * Returns the number of type descriptions in the type library
3500 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3502 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3503 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3504 return This->TypeInfoCount;
3507 /* ITypeLib::GetTypeInfo
3509 * retrieves the specified type description in the library.
3511 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3514 ITypeInfo **ppTInfo)
3518 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3519 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3521 TRACE("(%p)->(index=%d)\n", This, index);
3523 if (!ppTInfo) return E_INVALIDARG;
3525 /* search element n in list */
3526 for(i=0; i < index; i++)
3528 pTypeInfo = pTypeInfo->next;
3531 TRACE("-- element not found\n");
3532 return TYPE_E_ELEMENTNOTFOUND;
3536 *ppTInfo = (ITypeInfo *) pTypeInfo;
3538 ITypeInfo_AddRef(*ppTInfo);
3539 TRACE("-- found (%p)\n",*ppTInfo);
3544 /* ITypeLibs::GetTypeInfoType
3546 * Retrieves the type of a type description.
3548 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3553 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3555 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3557 TRACE("(%p) index %d\n", This, index);
3559 if(!pTKind) return E_INVALIDARG;
3561 /* search element n in list */
3562 for(i=0; i < index; i++)
3566 TRACE("-- element not found\n");
3567 return TYPE_E_ELEMENTNOTFOUND;
3569 pTInfo = pTInfo->next;
3572 *pTKind = pTInfo->TypeAttr.typekind;
3573 TRACE("-- found Type (%d)\n", *pTKind);
3577 /* ITypeLib::GetTypeInfoOfGuid
3579 * Retrieves the type description that corresponds to the specified GUID.
3582 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3585 ITypeInfo **ppTInfo)
3587 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3588 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3590 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3594 WARN("-- element not found\n");
3595 return TYPE_E_ELEMENTNOTFOUND;
3598 /* search linked list for guid */
3599 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3601 pTypeInfo = pTypeInfo->next;
3605 /* end of list reached */
3606 WARN("-- element not found\n");
3607 return TYPE_E_ELEMENTNOTFOUND;
3611 TRACE("-- found (%p, %s)\n",
3613 debugstr_w(pTypeInfo->Name));
3615 *ppTInfo = (ITypeInfo*)pTypeInfo;
3616 ITypeInfo_AddRef(*ppTInfo);
3620 /* ITypeLib::GetLibAttr
3622 * Retrieves the structure that contains the library's attributes.
3625 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3627 LPTLIBATTR *ppTLibAttr)
3629 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3630 TRACE("(%p)\n",This);
3631 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3632 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3636 /* ITypeLib::GetTypeComp
3638 * Enables a client compiler to bind to a library's types, variables,
3639 * constants, and global functions.
3642 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3644 ITypeComp **ppTComp)
3646 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3648 TRACE("(%p)->(%p)\n",This,ppTComp);
3649 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3650 ITypeComp_AddRef(*ppTComp);
3655 /* ITypeLib::GetDocumentation
3657 * Retrieves the library's documentation string, the complete Help file name
3658 * and path, and the context identifier for the library Help topic in the Help
3661 * On a successful return all non-null BSTR pointers will have been set,
3664 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3668 BSTR *pBstrDocString,
3669 DWORD *pdwHelpContext,
3670 BSTR *pBstrHelpFile)
3672 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3674 HRESULT result = E_INVALIDARG;
3679 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3681 pBstrName, pBstrDocString,
3682 pdwHelpContext, pBstrHelpFile);
3686 /* documentation for the typelib */
3691 if(!(*pBstrName = SysAllocString(This->Name)))
3699 if (This->DocString)
3701 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3704 else if (This->Name)
3706 if(!(*pBstrDocString = SysAllocString(This->Name)))
3710 *pBstrDocString = NULL;
3714 *pdwHelpContext = This->dwHelpContext;
3720 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3724 *pBstrHelpFile = NULL;
3731 /* for a typeinfo */
3732 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3734 if(SUCCEEDED(result))
3736 result = ITypeInfo_GetDocumentation(pTInfo,
3740 pdwHelpContext, pBstrHelpFile);
3742 ITypeInfo_Release(pTInfo);
3747 if (pBstrDocString) SysFreeString (*pBstrDocString);
3749 if (pBstrName) SysFreeString (*pBstrName);
3751 return STG_E_INSUFFICIENTMEMORY;
3756 * Indicates whether a passed-in string contains the name of a type or member
3757 * described in the library.
3760 static HRESULT WINAPI ITypeLib2_fnIsName(
3766 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3767 ITypeInfoImpl *pTInfo;
3768 TLBFuncDesc *pFInfo;
3771 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3773 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3777 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3778 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3779 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3780 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3781 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3782 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3783 goto ITypeLib2_fnIsName_exit;
3785 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3786 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3791 ITypeLib2_fnIsName_exit:
3792 TRACE("(%p)slow! search for %s: %s found!\n", This,
3793 debugstr_w(szNameBuf), *pfName?"NOT":"");
3798 /* ITypeLib::FindName
3800 * Finds occurrences of a type description in a type library. This may be used
3801 * to quickly verify that a name exists in a type library.
3804 static HRESULT WINAPI ITypeLib2_fnFindName(
3808 ITypeInfo **ppTInfo,
3812 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3813 ITypeInfoImpl *pTInfo;
3814 TLBFuncDesc *pFInfo;
3817 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3819 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3820 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3821 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3822 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3823 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3824 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3825 goto ITypeLib2_fnFindName_exit;
3828 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3829 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3831 ITypeLib2_fnFindName_exit:
3832 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3833 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3836 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3837 This, *pcFound, debugstr_w(szNameBuf), j);
3844 /* ITypeLib::ReleaseTLibAttr
3846 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3849 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3851 TLIBATTR *pTLibAttr)
3853 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3854 TRACE("freeing (%p)\n",This);
3855 HeapFree(GetProcessHeap(),0,pTLibAttr);
3859 /* ITypeLib2::GetCustData
3861 * gets the custom data
3863 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3868 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3869 TLBCustData *pCData;
3871 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3873 if( IsEqualIID(guid, &pCData->guid)) break;
3876 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3880 VariantInit( pVarVal);
3881 VariantCopy( pVarVal, &pCData->data);
3884 return E_INVALIDARG; /* FIXME: correct? */
3887 /* ITypeLib2::GetLibStatistics
3889 * Returns statistics about a type library that are required for efficient
3890 * sizing of hash tables.
3893 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3895 ULONG *pcUniqueNames,
3896 ULONG *pcchUniqueNames)
3898 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3900 FIXME("(%p): stub!\n", This);
3902 if(pcUniqueNames) *pcUniqueNames=1;
3903 if(pcchUniqueNames) *pcchUniqueNames=1;
3907 /* ITypeLib2::GetDocumentation2
3909 * Retrieves the library's documentation string, the complete Help file name
3910 * and path, the localization context to use, and the context ID for the
3911 * library Help topic in the Help file.
3914 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3918 BSTR *pbstrHelpString,
3919 DWORD *pdwHelpStringContext,
3920 BSTR *pbstrHelpStringDll)
3922 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3926 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3928 /* the help string should be obtained from the helpstringdll,
3929 * using the _DLLGetDocumentation function, based on the supplied
3930 * lcid. Nice to do sometime...
3934 /* documentation for the typelib */
3936 *pbstrHelpString=SysAllocString(This->DocString);
3937 if(pdwHelpStringContext)
3938 *pdwHelpStringContext=This->dwHelpContext;
3939 if(pbstrHelpStringDll)
3940 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3946 /* for a typeinfo */
3947 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3949 if(SUCCEEDED(result))
3951 ITypeInfo2 * pTInfo2;
3952 result = ITypeInfo_QueryInterface(pTInfo,
3954 (LPVOID*) &pTInfo2);
3956 if(SUCCEEDED(result))
3958 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3962 pdwHelpStringContext,
3963 pbstrHelpStringDll);
3965 ITypeInfo2_Release(pTInfo2);
3968 ITypeInfo_Release(pTInfo);
3974 /* ITypeLib2::GetAllCustData
3976 * Gets all custom data items for the library.
3979 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3981 CUSTDATA *pCustData)
3983 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3984 TLBCustData *pCData;
3986 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3987 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3988 if(pCustData->prgCustData ){
3989 pCustData->cCustData=This->ctCustData;
3990 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3991 pCustData->prgCustData[i].guid=pCData->guid;
3992 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3995 ERR(" OUT OF MEMORY!\n");
3996 return E_OUTOFMEMORY;
4001 static const ITypeLib2Vtbl tlbvt = {
4002 ITypeLib2_fnQueryInterface,
4004 ITypeLib2_fnRelease,
4005 ITypeLib2_fnGetTypeInfoCount,
4006 ITypeLib2_fnGetTypeInfo,
4007 ITypeLib2_fnGetTypeInfoType,
4008 ITypeLib2_fnGetTypeInfoOfGuid,
4009 ITypeLib2_fnGetLibAttr,
4010 ITypeLib2_fnGetTypeComp,
4011 ITypeLib2_fnGetDocumentation,
4013 ITypeLib2_fnFindName,
4014 ITypeLib2_fnReleaseTLibAttr,
4016 ITypeLib2_fnGetCustData,
4017 ITypeLib2_fnGetLibStatistics,
4018 ITypeLib2_fnGetDocumentation2,
4019 ITypeLib2_fnGetAllCustData
4023 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4025 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4027 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4030 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4032 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4034 return ITypeLib2_AddRef((ITypeLib2 *)This);
4037 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4039 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4041 return ITypeLib2_Release((ITypeLib2 *)This);
4044 static HRESULT WINAPI ITypeLibComp_fnBind(
4049 ITypeInfo ** ppTInfo,
4050 DESCKIND * pDescKind,
4053 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4054 ITypeInfoImpl *pTypeInfo;
4056 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4058 *pDescKind = DESCKIND_NONE;
4059 pBindPtr->lptcomp = NULL;
4062 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4064 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4066 /* FIXME: check wFlags here? */
4067 /* FIXME: we should use a hash table to look this info up using lHash
4068 * instead of an O(n) search */
4069 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4070 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4072 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4074 *pDescKind = DESCKIND_TYPECOMP;
4075 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4076 ITypeComp_AddRef(pBindPtr->lptcomp);
4077 TRACE("module or enum: %s\n", debugstr_w(szName));
4082 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4083 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4085 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4088 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4089 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4091 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4096 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4097 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4099 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4101 ITypeInfo *subtypeinfo;
4103 DESCKIND subdesckind;
4105 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4106 &subtypeinfo, &subdesckind, &subbindptr);
4107 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4109 TYPEDESC tdesc_appobject =
4112 (TYPEDESC *)pTypeInfo->hreftype
4116 const VARDESC vardesc_appobject =
4119 NULL, /* lpstrSchema */
4134 VAR_STATIC /* varkind */
4137 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4139 /* cleanup things filled in by Bind call so we can put our
4140 * application object data in there instead */
4141 switch (subdesckind)
4143 case DESCKIND_FUNCDESC:
4144 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4146 case DESCKIND_VARDESC:
4147 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4152 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4154 if (pTypeInfo->hreftype == -1)
4155 FIXME("no hreftype for interface %p\n", pTypeInfo);
4157 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4161 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4162 *ppTInfo = (ITypeInfo *)pTypeInfo;
4163 ITypeInfo_AddRef(*ppTInfo);
4169 TRACE("name not found %s\n", debugstr_w(szName));
4173 static HRESULT WINAPI ITypeLibComp_fnBindType(
4177 ITypeInfo ** ppTInfo,
4178 ITypeComp ** ppTComp)
4180 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4184 static const ITypeCompVtbl tlbtcvt =
4187 ITypeLibComp_fnQueryInterface,
4188 ITypeLibComp_fnAddRef,
4189 ITypeLibComp_fnRelease,
4191 ITypeLibComp_fnBind,
4192 ITypeLibComp_fnBindType
4195 /*================== ITypeInfo(2) Methods ===================================*/
4196 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4198 ITypeInfoImpl * pTypeInfoImpl;
4200 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4203 pTypeInfoImpl->lpVtbl = &tinfvt;
4204 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4205 pTypeInfoImpl->ref=1;
4206 pTypeInfoImpl->hreftype = -1;
4208 TRACE("(%p)\n", pTypeInfoImpl);
4209 return (ITypeInfo2*) pTypeInfoImpl;
4212 /* ITypeInfo::QueryInterface
4214 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4219 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4221 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4224 if(IsEqualIID(riid, &IID_IUnknown) ||
4225 IsEqualIID(riid,&IID_ITypeInfo)||
4226 IsEqualIID(riid,&IID_ITypeInfo2))
4230 ITypeInfo_AddRef(iface);
4231 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4234 TRACE("-- Interface: E_NOINTERFACE\n");
4235 return E_NOINTERFACE;
4238 /* ITypeInfo::AddRef
4240 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4242 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4243 ULONG ref = InterlockedIncrement(&This->ref);
4245 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4247 TRACE("(%p)->ref is %lu\n",This, ref);
4251 /* ITypeInfo::Release
4253 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4255 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4256 ULONG ref = InterlockedDecrement(&This->ref);
4258 TRACE("(%p)->(%lu)\n",This, ref);
4261 /* We don't release ITypeLib when ref=0 because
4262 it means that function is called by ITypeLib2_Release */
4263 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4265 static int once = 0;
4269 FIXME("destroy child objects\n");
4272 TRACE("destroying ITypeInfo(%p)\n",This);
4275 SysFreeString(This->Name);
4279 if (This->DocString)
4281 SysFreeString(This->DocString);
4282 This->DocString = 0;
4287 SysFreeString(This->DllName);
4293 ITypeInfo_Release((ITypeInfo*)This->next);
4296 HeapFree(GetProcessHeap(),0,This);
4302 /* ITypeInfo::GetTypeAttr
4304 * Retrieves a TYPEATTR structure that contains the attributes of the type
4308 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4309 LPTYPEATTR *ppTypeAttr)
4311 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4314 TRACE("(%p)\n",This);
4316 size = sizeof(**ppTypeAttr);
4317 if (This->TypeAttr.typekind == TKIND_ALIAS)
4318 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4320 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4322 return E_OUTOFMEMORY;
4324 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4326 if (This->TypeAttr.typekind == TKIND_ALIAS)
4327 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4328 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4330 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4331 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4333 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4334 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4339 /* ITypeInfo::GetTypeComp
4341 * Retrieves the ITypeComp interface for the type description, which enables a
4342 * client compiler to bind to the type description's members.
4345 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4346 ITypeComp * *ppTComp)
4348 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4350 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4352 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4353 ITypeComp_AddRef(*ppTComp);
4357 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4359 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4360 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4361 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4365 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4367 memcpy(dest, src, sizeof(ELEMDESC));
4368 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4369 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4371 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4372 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4373 *buffer += sizeof(PARAMDESCEX);
4374 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4375 VariantInit(&pparamdescex_dest->varDefaultValue);
4376 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4377 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4380 dest->u.paramdesc.pparamdescex = NULL;
4384 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4386 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4387 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4390 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4394 SIZE_T size = sizeof(*src);
4398 size += sizeof(*src->lprgscode) * src->cScodes;
4399 size += TLB_SizeElemDesc(&src->elemdescFunc);
4400 for (i = 0; i < src->cParams; i++)
4402 size += sizeof(ELEMDESC);
4403 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4406 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4407 if (!dest) return E_OUTOFMEMORY;
4409 memcpy(dest, src, sizeof(FUNCDESC));
4410 buffer = (char *)(dest + 1);
4412 dest->lprgscode = (SCODE *)buffer;
4413 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4414 buffer += sizeof(*src->lprgscode) * src->cScodes;
4416 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4419 SysFreeString((BSTR)dest);
4423 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4424 buffer += sizeof(ELEMDESC) * src->cParams;
4425 for (i = 0; i < src->cParams; i++)
4427 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4433 /* undo the above actions */
4434 for (i = i - 1; i >= 0; i--)
4435 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4436 TLB_FreeElemDesc(&dest->elemdescFunc);
4437 SysFreeString((BSTR)dest);
4441 /* special treatment for dispinterfaces: this makes functions appear
4442 * to return their [retval] value when it is really returning an
4444 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4446 if (dest->cParams &&
4447 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4449 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4450 if (elemdesc->tdesc.vt != VT_PTR)
4452 ERR("elemdesc should have started with VT_PTR instead of:\n");
4454 dump_ELEMDESC(elemdesc);
4455 return E_UNEXPECTED;
4458 /* copy last parameter to the return value. we are using a flat
4459 * buffer so there is no danger of leaking memory in
4461 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4463 /* remove the last parameter */
4467 /* otherwise this function is made to appear to have no return
4469 dest->elemdescFunc.tdesc.vt = VT_VOID;
4477 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4479 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4480 const TLBFuncDesc *pFDesc;
4483 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4488 *ppFuncDesc = &pFDesc->funcdesc;
4492 return E_INVALIDARG;
4495 /* ITypeInfo::GetFuncDesc
4497 * Retrieves the FUNCDESC structure that contains information about a
4498 * specified function.
4501 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4502 LPFUNCDESC *ppFuncDesc)
4504 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4505 const FUNCDESC *internal_funcdesc;
4508 TRACE("(%p) index %d\n", This, index);
4510 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4514 return TLB_AllocAndInitFuncDesc(
4517 This->TypeAttr.typekind == TKIND_DISPATCH);
4520 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4524 SIZE_T size = sizeof(*src);
4527 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4528 if (src->varkind == VAR_CONST)
4529 size += sizeof(VARIANT);
4530 size += TLB_SizeElemDesc(&src->elemdescVar);
4532 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4533 if (!dest) return E_OUTOFMEMORY;
4536 buffer = (char *)(dest + 1);
4537 if (src->lpstrSchema)
4540 dest->lpstrSchema = (LPOLESTR)buffer;
4541 len = strlenW(src->lpstrSchema);
4542 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4543 buffer += (len + 1) * sizeof(WCHAR);
4546 if (src->varkind == VAR_CONST)
4550 dest->u.lpvarValue = (VARIANT *)buffer;
4551 *dest->u.lpvarValue = *src->u.lpvarValue;
4552 buffer += sizeof(VARIANT);
4553 VariantInit(dest->u.lpvarValue);
4554 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4557 SysFreeString((BSTR)dest_ptr);
4561 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4564 if (src->varkind == VAR_CONST)
4565 VariantClear(dest->u.lpvarValue);
4566 SysFreeString((BSTR)dest);
4573 /* ITypeInfo::GetVarDesc
4575 * Retrieves a VARDESC structure that describes the specified variable.
4578 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4579 LPVARDESC *ppVarDesc)
4581 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4583 const TLBVarDesc *pVDesc;
4585 TRACE("(%p) index %d\n", This, index);
4587 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4591 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4593 return E_INVALIDARG;
4596 /* ITypeInfo_GetNames
4598 * Retrieves the variable with the specified member ID (or the name of the
4599 * property or method and its parameters) that correspond to the specified
4602 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4603 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4605 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4606 const TLBFuncDesc *pFDesc;
4607 const TLBVarDesc *pVDesc;
4609 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4610 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4613 /* function found, now return function and parameter names */
4614 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4617 *rgBstrNames=SysAllocString(pFDesc->Name);
4619 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4625 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4628 *rgBstrNames=SysAllocString(pVDesc->Name);
4633 if(This->TypeAttr.cImplTypes &&
4634 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4635 /* recursive search */
4638 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4640 if(SUCCEEDED(result))
4642 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4643 ITypeInfo_Release(pTInfo);
4646 WARN("Could not search inherited interface!\n");
4650 WARN("no names found\n");
4653 return TYPE_E_ELEMENTNOTFOUND;
4660 /* ITypeInfo::GetRefTypeOfImplType
4662 * If a type description describes a COM class, it retrieves the type
4663 * description of the implemented interface types. For an interface,
4664 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4668 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4673 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4676 const TLBImplType *pImpl = This->impltypelist;
4678 TRACE("(%p) index %d\n", This, index);
4679 if (TRACE_ON(ole)) dump_TypeInfo(This);
4683 /* only valid on dual interfaces;
4684 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4686 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4688 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4689 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4695 hr = TYPE_E_ELEMENTNOTFOUND;
4700 /* get element n from linked list */
4701 for(i=0; pImpl && i<index; i++)
4703 pImpl = pImpl->next;
4707 *pRefType = pImpl->hRef;
4709 hr = TYPE_E_ELEMENTNOTFOUND;
4715 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4717 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4723 /* ITypeInfo::GetImplTypeFlags
4725 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4726 * or base interface in a type description.
4728 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4729 UINT index, INT *pImplTypeFlags)
4731 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4735 TRACE("(%p) index %d\n", This, index);
4736 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4737 i++, pImpl=pImpl->next)
4739 if(i==index && pImpl){
4740 *pImplTypeFlags=pImpl->implflags;
4744 return TYPE_E_ELEMENTNOTFOUND;
4748 * Maps between member names and member IDs, and parameter names and
4751 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4752 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4754 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4755 const TLBFuncDesc *pFDesc;
4756 const TLBVarDesc *pVDesc;
4760 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4763 /* init out parameters in case of failure */
4764 for (i = 0; i < cNames; i++)
4765 pMemId[i] = MEMBERID_NIL;
4767 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4769 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4770 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4771 for(i=1; i < cNames; i++){
4772 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4773 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4775 if( j<pFDesc->funcdesc.cParams)
4778 ret=DISP_E_UNKNOWNNAME;
4780 TRACE("-- 0x%08lx\n", ret);
4784 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4785 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4786 if(cNames) *pMemId=pVDesc->vardesc.memid;
4790 /* not found, see if it can be found in an inherited interface */
4791 if(This->TypeAttr.cImplTypes) {
4792 /* recursive search */
4794 ret=ITypeInfo_GetRefTypeInfo(iface,
4795 This->impltypelist->hRef, &pTInfo);
4797 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4798 ITypeInfo_Release(pTInfo);
4801 WARN("Could not search inherited interface!\n");
4803 WARN("no names found\n");
4804 return DISP_E_UNKNOWNNAME;
4807 /* ITypeInfo::Invoke
4809 * Invokes a method, or accesses a property of an object, that implements the
4810 * interface described by the type description.
4813 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4816 if (TRACE_ON(ole)) {
4818 TRACE("Calling %p(",func);
4819 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4831 res = func(args[0]);
4834 res = func(args[0],args[1]);
4837 res = func(args[0],args[1],args[2]);
4840 res = func(args[0],args[1],args[2],args[3]);
4843 res = func(args[0],args[1],args[2],args[3],args[4]);
4846 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4849 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4852 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4855 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4858 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4861 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4864 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]);
4867 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]);
4870 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]);
4873 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]);
4876 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]);
4879 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]);
4882 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]);
4885 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]);
4888 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]);
4891 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]);
4894 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]);
4897 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]);
4900 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4906 FIXME("unsupported calling convention %d\n",callconv);
4910 TRACE("returns %08lx\n",res);
4914 extern int _argsize(DWORD vt);
4916 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4919 ITypeInfo *tinfo2 = NULL;
4920 TYPEATTR *tattr = NULL;
4922 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4925 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4927 tdesc->u.hreftype, hr);
4930 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4933 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4934 ITypeInfo_Release(tinfo2);
4938 switch (tattr->typekind)
4945 tdesc = &tattr->tdescAlias;
4946 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4949 case TKIND_INTERFACE:
4950 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4956 case TKIND_DISPATCH:
4961 FIXME("TKIND_RECORD unhandled.\n");
4966 FIXME("TKIND_RECORD unhandled.\n");
4971 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4975 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4976 ITypeInfo_Release(tinfo2);
4980 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4984 /* enforce only one level of pointer indirection */
4985 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
4987 tdesc = tdesc->u.lptdesc;
4989 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4990 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4991 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4992 if ((tdesc->vt == VT_USERDEFINED) ||
4993 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4995 VARTYPE vt_userdefined = 0;
4996 const TYPEDESC *tdesc_userdefined = tdesc;
4997 if (tdesc->vt == VT_PTR)
4999 vt_userdefined = VT_BYREF;
5000 tdesc_userdefined = tdesc->u.lptdesc;
5002 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5004 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5005 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5007 *vt |= vt_userdefined;
5019 case VT_USERDEFINED:
5020 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5027 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5028 hr = DISP_E_BADVARTYPE;
5032 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5041 /***********************************************************************
5042 * DispCallFunc (OLEAUT32.@)
5044 * Invokes a function of the specifed calling convention, passing the
5045 * specified arguments and returns the result.
5048 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5049 * oVft [I] The offset in the vtable. See notes.
5050 * cc [I] Calling convention of the function to call.
5051 * vtReturn [I] The return type of the function.
5052 * cActuals [I] Number of parameters.
5053 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5054 * prgpvarg [I] The arguments to pass.
5055 * pvargResult [O] The return value of the function. Can be NULL.
5059 * Failure: HRESULT code.
5062 * The HRESULT return value of this function is not affected by the return
5063 * value of the user supplied function, which is returned in pvargResult.
5065 * If pvInstance is NULL then a non-object function is to be called and oVft
5066 * is the address of the function to call.
5068 * The cc parameter can be one of the following values:
5081 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5082 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5084 int i, argsize, argspos;
5088 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5089 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5090 pvargResult, V_VT(pvargResult));
5094 argsize++; /* for This pointer */
5096 for (i=0;i<cActuals;i++)
5098 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5099 dump_Variant(prgpvarg[i]);
5100 argsize += _argsize(prgvt[i]);
5102 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5107 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5111 for (i=0;i<cActuals;i++)
5113 VARIANT *arg = prgpvarg[i];
5114 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5115 if (prgvt[i] == VT_VARIANT)
5116 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5118 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5119 argspos += _argsize(prgvt[i]);
5124 FARPROC *vtable = *(FARPROC**)pvInstance;
5125 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5128 /* if we aren't invoking an object then the function pointer is stored
5130 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5132 if (pvargResult && (vtReturn != VT_EMPTY))
5134 TRACE("Method returned 0x%08lx\n",hres);
5135 V_VT(pvargResult) = vtReturn;
5136 V_UI4(pvargResult) = hres;
5139 HeapFree(GetProcessHeap(),0,args);
5143 #define INVBUF_ELEMENT_SIZE \
5144 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5145 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5146 ((VARIANTARG *)(buffer))
5147 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5148 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5149 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5150 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5151 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5152 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5154 static HRESULT WINAPI ITypeInfo_fnInvoke(
5159 DISPPARAMS *pDispParams,
5160 VARIANT *pVarResult,
5161 EXCEPINFO *pExcepInfo,
5164 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5166 unsigned int var_index;
5169 const TLBFuncDesc *pFuncInfo;
5171 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5172 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5174 dump_DispParms(pDispParams);
5176 /* we do this instead of using GetFuncDesc since it will return a fake
5177 * FUNCDESC for dispinterfaces and we want the real function description */
5178 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5179 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5183 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5187 TRACE("invoking:\n");
5188 dump_TLBFuncDescOne(pFuncInfo);
5191 switch (func_desc->funckind) {
5192 case FUNC_PUREVIRTUAL:
5193 case FUNC_VIRTUAL: {
5194 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5196 VARIANT retval; /* pointer for storing byref retvals in */
5197 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5198 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5199 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5202 for (i = 0; i < func_desc->cParams; i++)
5204 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5205 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5210 TRACE("changing args\n");
5211 for (i = 0; i < func_desc->cParams; i++)
5213 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5215 if (wParamFlags & PARAMFLAG_FRETVAL)
5217 /* note: this check is placed so that if the caller passes
5218 * in a VARIANTARG for the retval we just ignore it, like
5220 if (i == func_desc->cParams - 1)
5223 arg = prgpvarg[i] = &rgvarg[i];
5224 memset(arg, 0, sizeof(*arg));
5225 V_VT(arg) = rgvt[i];
5226 memset(&retval, 0, sizeof(retval));
5227 V_BYREF(arg) = &retval;
5231 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5232 hres = E_UNEXPECTED;
5236 else if (i < pDispParams->cArgs)
5238 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5239 dump_Variant(src_arg);
5241 if (rgvt[i] == VT_VARIANT)
5242 VariantCopy(&rgvarg[i], src_arg);
5243 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5245 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5246 V_VT(&missing_arg[i]) = V_VT(src_arg);
5247 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5248 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5249 V_VT(&rgvarg[i]) = rgvt[i];
5253 /* FIXME: this doesn't work for VT_BYREF arguments if
5254 * they are not the same type as in the paramdesc */
5255 V_VT(&rgvarg[i]) = V_VT(src_arg);
5256 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5257 V_VT(&rgvarg[i]) = rgvt[i];
5262 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5263 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5264 debugstr_VT(src_arg), debugstr_VF(src_arg));
5267 prgpvarg[i] = &rgvarg[i];
5269 else if (wParamFlags & PARAMFLAG_FOPT)
5272 arg = prgpvarg[i] = &rgvarg[i];
5273 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5275 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5281 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5282 V_VT(arg) = VT_VARIANT | VT_BYREF;
5283 V_VARIANTREF(arg) = &missing_arg[i];
5284 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5285 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5290 hres = DISP_E_BADPARAMCOUNT;
5294 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5295 if (func_desc->cParamsOpt < 0)
5297 FIXME("Does not support safearray optional parameters\n");
5298 hres = DISP_E_BADPARAMCOUNT;
5299 goto func_fail; /* FIXME: we don't free changed types here */
5302 V_VT(&varresult) = 0;
5303 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5304 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5306 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5307 V_VT(&varresult), func_desc->cParams, rgvt,
5308 prgpvarg, &varresult);
5310 for (i = 0; i < func_desc->cParams; i++)
5312 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5313 if (wParamFlags & PARAMFLAG_FRETVAL)
5317 TRACE("[retval] value: ");
5318 dump_Variant(prgpvarg[i]);
5322 /* deref return value */
5323 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5325 /* free data stored in varresult. Note that
5326 * VariantClear doesn't do what we want because we are
5327 * working with byref types. */
5328 /* FIXME: clear safearrays, bstrs, records and
5329 * variants here too */
5330 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5331 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5333 if(*V_UNKNOWNREF(prgpvarg[i]))
5334 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5338 else if (i < pDispParams->cArgs)
5340 if (wParamFlags & PARAMFLAG_FOUT)
5342 hres = VariantChangeType(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i],
5344 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5347 ERR("failed to convert param %d to vt %d\n", i,
5348 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5352 VariantClear(&rgvarg[i]);
5354 else if (wParamFlags & PARAMFLAG_FOPT)
5356 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5357 VariantClear(&rgvarg[i]);
5361 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5363 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5364 hres = DISP_E_EXCEPTION;
5365 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5369 HeapFree(GetProcessHeap(), 0, buffer);
5372 case FUNC_DISPATCH: {
5375 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5376 if (SUCCEEDED(hres)) {
5377 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5378 hres = IDispatch_Invoke(
5379 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5380 pVarResult,pExcepInfo,pArgErr
5383 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5384 IDispatch_Release(disp);
5386 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5390 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5395 TRACE("-- 0x%08lx\n", hres);
5398 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5401 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5402 if(FAILED(hres)) return hres;
5404 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5405 dump_VARDESC(var_desc);
5406 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5410 /* not found, look for it in inherited interfaces */
5411 ITypeInfo2_GetTypeKind(iface, &type_kind);
5412 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5414 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5415 /* recursive search */
5417 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5418 if(SUCCEEDED(hres)){
5419 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5420 ITypeInfo_Release(pTInfo);
5423 WARN("Could not search inherited interface!\n");
5426 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5427 return DISP_E_MEMBERNOTFOUND;
5430 /* ITypeInfo::GetDocumentation
5432 * Retrieves the documentation string, the complete Help file name and path,
5433 * and the context ID for the Help topic for a specified type description.
5435 * (Can be tested by the Visual Basic Editor in Word for instance.)
5437 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5438 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5439 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5441 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5442 const TLBFuncDesc *pFDesc;
5443 const TLBVarDesc *pVDesc;
5444 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5445 " HelpContext(%p) HelpFile(%p)\n",
5446 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5447 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5449 *pBstrName=SysAllocString(This->Name);
5451 *pBstrDocString=SysAllocString(This->DocString);
5453 *pdwHelpContext=This->dwHelpContext;
5455 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5457 }else {/* for a member */
5458 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5459 if(pFDesc->funcdesc.memid==memid){
5461 *pBstrName = SysAllocString(pFDesc->Name);
5463 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5465 *pdwHelpContext=pFDesc->helpcontext;
5468 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5469 if(pVDesc->vardesc.memid==memid){
5471 *pBstrName = SysAllocString(pVDesc->Name);
5473 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5475 *pdwHelpContext=pVDesc->HelpContext;
5479 WARN("member %ld not found\n", memid);
5480 return TYPE_E_ELEMENTNOTFOUND;
5483 /* ITypeInfo::GetDllEntry
5485 * Retrieves a description or specification of an entry point for a function
5488 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5489 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5492 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5493 const TLBFuncDesc *pFDesc;
5495 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5497 if (pBstrDllName) *pBstrDllName = NULL;
5498 if (pBstrName) *pBstrName = NULL;
5499 if (pwOrdinal) *pwOrdinal = 0;
5501 if (This->TypeAttr.typekind != TKIND_MODULE)
5502 return TYPE_E_BADMODULEKIND;
5504 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5505 if(pFDesc->funcdesc.memid==memid){
5506 dump_TypeInfo(This);
5508 dump_TLBFuncDescOne(pFDesc);
5511 *pBstrDllName = SysAllocString(This->DllName);
5513 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5515 *pBstrName = SysAllocString(pFDesc->Entry);
5523 *pwOrdinal = (DWORD)pFDesc->Entry;
5526 return TYPE_E_ELEMENTNOTFOUND;
5529 /* ITypeInfo::GetRefTypeInfo
5531 * If a type description references other type descriptions, it retrieves
5532 * the referenced type descriptions.
5534 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5537 ITypeInfo **ppTInfo)
5539 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5540 HRESULT result = E_FAIL;
5542 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5544 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5545 ITypeInfo_AddRef(*ppTInfo);
5548 else if (hRefType == -1 &&
5549 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5550 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5552 /* when we meet a DUAL dispinterface, we must create the interface
5555 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5558 /* the interface version contains the same information as the dispinterface
5559 * copy the contents of the structs.
5561 *pTypeInfoImpl = *This;
5562 pTypeInfoImpl->ref = 1;
5564 /* change the type to interface */
5565 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5567 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5569 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5574 TLBRefType *pRefType;
5575 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5576 if(pRefType->reference == hRefType)
5580 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5581 if(pRefType && hRefType != -1) {
5582 ITypeLib *pTLib = NULL;
5584 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5586 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5588 if(pRefType->pImpTLInfo->pImpTypeLib) {
5589 TRACE("typeinfo in imported typelib that is already loaded\n");
5590 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5591 ITypeLib2_AddRef((ITypeLib*) pTLib);
5594 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5595 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5596 pRefType->pImpTLInfo->wVersionMajor,
5597 pRefType->pImpTLInfo->wVersionMinor,
5598 pRefType->pImpTLInfo->lcid,
5601 if(!SUCCEEDED(result)) {
5602 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5603 result=LoadTypeLib(libnam, &pTLib);
5604 SysFreeString(libnam);
5606 if(SUCCEEDED(result)) {
5607 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5608 ITypeLib2_AddRef(pTLib);
5612 if(SUCCEEDED(result)) {
5613 if(pRefType->index == TLB_REF_USE_GUID)
5614 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5618 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5622 ITypeLib2_Release(pTLib);
5626 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5627 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5631 /* ITypeInfo::AddressOfMember
5633 * Retrieves the addresses of static functions or variables, such as those
5636 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5637 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5639 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5645 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5647 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5651 module = LoadLibraryW(dll);
5654 ERR("couldn't load %s\n", debugstr_w(dll));
5656 if (entry) SysFreeString(entry);
5657 return STG_E_FILENOTFOUND;
5659 /* FIXME: store library somewhere where we can free it */
5664 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5665 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5666 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5668 *ppv = GetProcAddress(module, entryA);
5670 ERR("function not found %s\n", debugstr_a(entryA));
5672 HeapFree(GetProcessHeap(), 0, entryA);
5676 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5678 ERR("function not found %d\n", ordinal);
5682 if (entry) SysFreeString(entry);
5685 return TYPE_E_DLLFUNCTIONNOTFOUND;
5690 /* ITypeInfo::CreateInstance
5692 * Creates a new instance of a type that describes a component object class
5695 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5696 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5698 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5699 FIXME("(%p) stub!\n", This);
5703 /* ITypeInfo::GetMops
5705 * Retrieves marshalling information.
5707 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5710 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5711 FIXME("(%p) stub!\n", This);
5715 /* ITypeInfo::GetContainingTypeLib
5717 * Retrieves the containing type library and the index of the type description
5718 * within that type library.
5720 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5721 ITypeLib * *ppTLib, UINT *pIndex)
5723 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5725 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5727 *pIndex=This->index;
5728 TRACE("returning pIndex=%d\n", *pIndex);
5732 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5733 ITypeLib2_AddRef(*ppTLib);
5734 TRACE("returning ppTLib=%p\n", *ppTLib);
5740 /* ITypeInfo::ReleaseTypeAttr
5742 * Releases a TYPEATTR previously returned by GetTypeAttr.
5745 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5746 TYPEATTR* pTypeAttr)
5748 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5749 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5750 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5753 /* ITypeInfo::ReleaseFuncDesc
5755 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5757 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5759 FUNCDESC *pFuncDesc)
5761 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5764 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5766 for (i = 0; i < pFuncDesc->cParams; i++)
5767 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5768 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5770 SysFreeString((BSTR)pFuncDesc);
5773 /* ITypeInfo::ReleaseVarDesc
5775 * Releases a VARDESC previously returned by GetVarDesc.
5777 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5780 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5781 TRACE("(%p)->(%p)\n", This, pVarDesc);
5783 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5784 if (pVarDesc->varkind == VAR_CONST)
5785 VariantClear(pVarDesc->u.lpvarValue);
5786 SysFreeString((BSTR)pVarDesc);
5789 /* ITypeInfo2::GetTypeKind
5791 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5794 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5795 TYPEKIND *pTypeKind)
5797 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5798 *pTypeKind=This->TypeAttr.typekind;
5799 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5803 /* ITypeInfo2::GetTypeFlags
5805 * Returns the type flags without any allocations. This returns a DWORD type
5806 * flag, which expands the type flags without growing the TYPEATTR (type
5810 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5812 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5813 *pTypeFlags=This->TypeAttr.wTypeFlags;
5814 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5818 /* ITypeInfo2::GetFuncIndexOfMemId
5819 * Binds to a specific member based on a known DISPID, where the member name
5820 * is not known (for example, when binding to a default member).
5823 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5824 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5826 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5827 const TLBFuncDesc *pFuncInfo;
5831 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5832 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5838 result = TYPE_E_ELEMENTNOTFOUND;
5840 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5841 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5845 /* TypeInfo2::GetVarIndexOfMemId
5847 * Binds to a specific member based on a known DISPID, where the member name
5848 * is not known (for example, when binding to a default member).
5851 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5852 MEMBERID memid, UINT *pVarIndex)
5854 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5855 TLBVarDesc *pVarInfo;
5858 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5859 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5865 result = TYPE_E_ELEMENTNOTFOUND;
5867 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5868 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5872 /* ITypeInfo2::GetCustData
5874 * Gets the custom data
5876 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5881 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5882 TLBCustData *pCData;
5884 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5885 if( IsEqualIID(guid, &pCData->guid)) break;
5887 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5891 VariantInit( pVarVal);
5892 VariantCopy( pVarVal, &pCData->data);
5895 return E_INVALIDARG; /* FIXME: correct? */
5898 /* ITypeInfo2::GetFuncCustData
5900 * Gets the custom data
5902 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5908 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5909 TLBCustData *pCData=NULL;
5910 TLBFuncDesc * pFDesc;
5912 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5913 pFDesc=pFDesc->next);
5916 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5917 if( IsEqualIID(guid, &pCData->guid)) break;
5919 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5922 VariantInit( pVarVal);
5923 VariantCopy( pVarVal, &pCData->data);
5926 return E_INVALIDARG; /* FIXME: correct? */
5929 /* ITypeInfo2::GetParamCustData
5931 * Gets the custom data
5933 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5940 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5941 TLBCustData *pCData=NULL;
5942 TLBFuncDesc * pFDesc;
5945 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5947 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5948 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5949 pCData = pCData->next)
5950 if( IsEqualIID(guid, &pCData->guid)) break;
5952 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5956 VariantInit( pVarVal);
5957 VariantCopy( pVarVal, &pCData->data);
5960 return E_INVALIDARG; /* FIXME: correct? */
5963 /* ITypeInfo2::GetVarCustData
5965 * Gets the custom data
5967 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5973 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5974 TLBCustData *pCData=NULL;
5975 TLBVarDesc * pVDesc;
5978 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5982 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5984 if( IsEqualIID(guid, &pCData->guid)) break;
5988 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5992 VariantInit( pVarVal);
5993 VariantCopy( pVarVal, &pCData->data);
5996 return E_INVALIDARG; /* FIXME: correct? */
5999 /* ITypeInfo2::GetImplCustData
6001 * Gets the custom data
6003 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6009 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6010 TLBCustData *pCData=NULL;
6011 TLBImplType * pRDesc;
6014 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6018 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6020 if( IsEqualIID(guid, &pCData->guid)) break;
6024 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6028 VariantInit( pVarVal);
6029 VariantCopy( pVarVal, &pCData->data);
6032 return E_INVALIDARG; /* FIXME: correct? */
6035 /* ITypeInfo2::GetDocumentation2
6037 * Retrieves the documentation string, the complete Help file name and path,
6038 * the localization context to use, and the context ID for the library Help
6039 * topic in the Help file.
6042 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6046 BSTR *pbstrHelpString,
6047 DWORD *pdwHelpStringContext,
6048 BSTR *pbstrHelpStringDll)
6050 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6051 const TLBFuncDesc *pFDesc;
6052 const TLBVarDesc *pVDesc;
6053 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6054 "HelpStringContext(%p) HelpStringDll(%p)\n",
6055 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6056 pbstrHelpStringDll );
6057 /* the help string should be obtained from the helpstringdll,
6058 * using the _DLLGetDocumentation function, based on the supplied
6059 * lcid. Nice to do sometime...
6061 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6063 *pbstrHelpString=SysAllocString(This->Name);
6064 if(pdwHelpStringContext)
6065 *pdwHelpStringContext=This->dwHelpStringContext;
6066 if(pbstrHelpStringDll)
6067 *pbstrHelpStringDll=
6068 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6070 }else {/* for a member */
6071 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6072 if(pFDesc->funcdesc.memid==memid){
6074 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6075 if(pdwHelpStringContext)
6076 *pdwHelpStringContext=pFDesc->HelpStringContext;
6077 if(pbstrHelpStringDll)
6078 *pbstrHelpStringDll=
6079 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6082 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6083 if(pVDesc->vardesc.memid==memid){
6085 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6086 if(pdwHelpStringContext)
6087 *pdwHelpStringContext=pVDesc->HelpStringContext;
6088 if(pbstrHelpStringDll)
6089 *pbstrHelpStringDll=
6090 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6094 return TYPE_E_ELEMENTNOTFOUND;
6097 /* ITypeInfo2::GetAllCustData
6099 * Gets all custom data items for the Type info.
6102 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6104 CUSTDATA *pCustData)
6106 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6107 TLBCustData *pCData;
6110 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6112 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6113 if(pCustData->prgCustData ){
6114 pCustData->cCustData=This->ctCustData;
6115 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6116 pCustData->prgCustData[i].guid=pCData->guid;
6117 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6120 ERR(" OUT OF MEMORY!\n");
6121 return E_OUTOFMEMORY;
6126 /* ITypeInfo2::GetAllFuncCustData
6128 * Gets all custom data items for the specified Function
6131 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6134 CUSTDATA *pCustData)
6136 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6137 TLBCustData *pCData;
6138 TLBFuncDesc * pFDesc;
6140 TRACE("(%p) index %d\n", This, index);
6141 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6142 pFDesc=pFDesc->next)
6145 pCustData->prgCustData =
6146 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6147 if(pCustData->prgCustData ){
6148 pCustData->cCustData=pFDesc->ctCustData;
6149 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6150 pCData = pCData->next){
6151 pCustData->prgCustData[i].guid=pCData->guid;
6152 VariantCopy(& pCustData->prgCustData[i].varValue,
6156 ERR(" OUT OF MEMORY!\n");
6157 return E_OUTOFMEMORY;
6161 return TYPE_E_ELEMENTNOTFOUND;
6164 /* ITypeInfo2::GetAllParamCustData
6166 * Gets all custom data items for the Functions
6169 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6170 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6172 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6173 TLBCustData *pCData=NULL;
6174 TLBFuncDesc * pFDesc;
6176 TRACE("(%p) index %d\n", This, indexFunc);
6177 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6178 pFDesc=pFDesc->next)
6180 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6181 pCustData->prgCustData =
6182 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6183 sizeof(CUSTDATAITEM));
6184 if(pCustData->prgCustData ){
6185 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6186 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6187 pCData; i++, pCData = pCData->next){
6188 pCustData->prgCustData[i].guid=pCData->guid;
6189 VariantCopy(& pCustData->prgCustData[i].varValue,
6193 ERR(" OUT OF MEMORY!\n");
6194 return E_OUTOFMEMORY;
6198 return TYPE_E_ELEMENTNOTFOUND;
6201 /* ITypeInfo2::GetAllVarCustData
6203 * Gets all custom data items for the specified Variable
6206 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6207 UINT index, CUSTDATA *pCustData)
6209 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6210 TLBCustData *pCData;
6211 TLBVarDesc * pVDesc;
6213 TRACE("(%p) index %d\n", This, index);
6214 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6215 pVDesc=pVDesc->next)
6218 pCustData->prgCustData =
6219 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6220 if(pCustData->prgCustData ){
6221 pCustData->cCustData=pVDesc->ctCustData;
6222 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6223 pCData = pCData->next){
6224 pCustData->prgCustData[i].guid=pCData->guid;
6225 VariantCopy(& pCustData->prgCustData[i].varValue,
6229 ERR(" OUT OF MEMORY!\n");
6230 return E_OUTOFMEMORY;
6234 return TYPE_E_ELEMENTNOTFOUND;
6237 /* ITypeInfo2::GetAllImplCustData
6239 * Gets all custom data items for the specified implementation type
6242 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6245 CUSTDATA *pCustData)
6247 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6248 TLBCustData *pCData;
6249 TLBImplType * pRDesc;
6251 TRACE("(%p) index %d\n", This, index);
6252 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6253 pRDesc=pRDesc->next)
6256 pCustData->prgCustData =
6257 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6258 if(pCustData->prgCustData ){
6259 pCustData->cCustData=pRDesc->ctCustData;
6260 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6261 pCData = pCData->next){
6262 pCustData->prgCustData[i].guid=pCData->guid;
6263 VariantCopy(& pCustData->prgCustData[i].varValue,
6267 ERR(" OUT OF MEMORY!\n");
6268 return E_OUTOFMEMORY;
6272 return TYPE_E_ELEMENTNOTFOUND;
6275 static const ITypeInfo2Vtbl tinfvt =
6278 ITypeInfo_fnQueryInterface,
6280 ITypeInfo_fnRelease,
6282 ITypeInfo_fnGetTypeAttr,
6283 ITypeInfo_fnGetTypeComp,
6284 ITypeInfo_fnGetFuncDesc,
6285 ITypeInfo_fnGetVarDesc,
6286 ITypeInfo_fnGetNames,
6287 ITypeInfo_fnGetRefTypeOfImplType,
6288 ITypeInfo_fnGetImplTypeFlags,
6289 ITypeInfo_fnGetIDsOfNames,
6291 ITypeInfo_fnGetDocumentation,
6292 ITypeInfo_fnGetDllEntry,
6293 ITypeInfo_fnGetRefTypeInfo,
6294 ITypeInfo_fnAddressOfMember,
6295 ITypeInfo_fnCreateInstance,
6296 ITypeInfo_fnGetMops,
6297 ITypeInfo_fnGetContainingTypeLib,
6298 ITypeInfo_fnReleaseTypeAttr,
6299 ITypeInfo_fnReleaseFuncDesc,
6300 ITypeInfo_fnReleaseVarDesc,
6302 ITypeInfo2_fnGetTypeKind,
6303 ITypeInfo2_fnGetTypeFlags,
6304 ITypeInfo2_fnGetFuncIndexOfMemId,
6305 ITypeInfo2_fnGetVarIndexOfMemId,
6306 ITypeInfo2_fnGetCustData,
6307 ITypeInfo2_fnGetFuncCustData,
6308 ITypeInfo2_fnGetParamCustData,
6309 ITypeInfo2_fnGetVarCustData,
6310 ITypeInfo2_fnGetImplTypeCustData,
6311 ITypeInfo2_fnGetDocumentation2,
6312 ITypeInfo2_fnGetAllCustData,
6313 ITypeInfo2_fnGetAllFuncCustData,
6314 ITypeInfo2_fnGetAllParamCustData,
6315 ITypeInfo2_fnGetAllVarCustData,
6316 ITypeInfo2_fnGetAllImplTypeCustData,
6319 /******************************************************************************
6320 * CreateDispTypeInfo [OLEAUT32.31]
6322 * Build type information for an object so it can be called through an
6323 * IDispatch interface.
6326 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6327 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6330 * This call allows an objects methods to be accessed through IDispatch, by
6331 * building an ITypeInfo object that IDispatch can use to call through.
6333 HRESULT WINAPI CreateDispTypeInfo(
6334 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6335 LCID lcid, /* [I] Locale Id */
6336 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6338 ITypeInfoImpl *pTIClass, *pTIIface;
6339 ITypeLibImpl *pTypeLibImpl;
6341 TLBFuncDesc **ppFuncDesc;
6344 pTypeLibImpl = TypeLibImpl_Constructor();
6345 if (!pTypeLibImpl) return E_FAIL;
6347 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6348 pTIIface->pTypeLib = pTypeLibImpl;
6349 pTIIface->index = 0;
6350 pTIIface->Name = NULL;
6351 pTIIface->dwHelpContext = -1;
6352 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6353 pTIIface->TypeAttr.lcid = lcid;
6354 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6355 pTIIface->TypeAttr.wMajorVerNum = 0;
6356 pTIIface->TypeAttr.wMinorVerNum = 0;
6357 pTIIface->TypeAttr.cbAlignment = 2;
6358 pTIIface->TypeAttr.cbSizeInstance = -1;
6359 pTIIface->TypeAttr.cbSizeVft = -1;
6360 pTIIface->TypeAttr.cFuncs = 0;
6361 pTIIface->TypeAttr.cImplTypes = 0;
6362 pTIIface->TypeAttr.cVars = 0;
6363 pTIIface->TypeAttr.wTypeFlags = 0;
6365 ppFuncDesc = &pTIIface->funclist;
6366 for(func = 0; func < pidata->cMembers; func++) {
6367 METHODDATA *md = pidata->pmethdata + func;
6368 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6369 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6370 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6371 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6372 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6373 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6374 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6375 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6376 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6377 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6378 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6379 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6380 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6381 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6382 md->cArgs * sizeof(ELEMDESC));
6383 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6384 md->cArgs * sizeof(TLBParDesc));
6385 for(param = 0; param < md->cArgs; param++) {
6386 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6387 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6389 (*ppFuncDesc)->helpcontext = 0;
6390 (*ppFuncDesc)->HelpStringContext = 0;
6391 (*ppFuncDesc)->HelpString = NULL;
6392 (*ppFuncDesc)->Entry = NULL;
6393 (*ppFuncDesc)->ctCustData = 0;
6394 (*ppFuncDesc)->pCustData = NULL;
6395 (*ppFuncDesc)->next = NULL;
6396 ppFuncDesc = &(*ppFuncDesc)->next;
6399 dump_TypeInfo(pTIIface);
6401 pTypeLibImpl->pTypeInfo = pTIIface;
6402 pTypeLibImpl->TypeInfoCount++;
6404 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6405 pTIClass->pTypeLib = pTypeLibImpl;
6406 pTIClass->index = 1;
6407 pTIClass->Name = NULL;
6408 pTIClass->dwHelpContext = -1;
6409 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6410 pTIClass->TypeAttr.lcid = lcid;
6411 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6412 pTIClass->TypeAttr.wMajorVerNum = 0;
6413 pTIClass->TypeAttr.wMinorVerNum = 0;
6414 pTIClass->TypeAttr.cbAlignment = 2;
6415 pTIClass->TypeAttr.cbSizeInstance = -1;
6416 pTIClass->TypeAttr.cbSizeVft = -1;
6417 pTIClass->TypeAttr.cFuncs = 0;
6418 pTIClass->TypeAttr.cImplTypes = 1;
6419 pTIClass->TypeAttr.cVars = 0;
6420 pTIClass->TypeAttr.wTypeFlags = 0;
6422 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6423 pTIClass->impltypelist->hRef = 1;
6425 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6426 pTIClass->reflist->index = 0;
6427 pTIClass->reflist->reference = 1;
6428 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6430 dump_TypeInfo(pTIClass);
6432 pTIIface->next = pTIClass;
6433 pTypeLibImpl->TypeInfoCount++;
6435 *pptinfo = (ITypeInfo*)pTIClass;
6440 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6442 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6444 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6447 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6449 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6451 return ITypeInfo_AddRef((ITypeInfo *)This);
6454 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6456 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6458 return ITypeInfo_Release((ITypeInfo *)This);
6461 static HRESULT WINAPI ITypeComp_fnBind(
6466 ITypeInfo ** ppTInfo,
6467 DESCKIND * pDescKind,
6470 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6471 const TLBFuncDesc *pFDesc;
6472 const TLBVarDesc *pVDesc;
6474 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6476 *pDescKind = DESCKIND_NONE;
6477 pBindPtr->lpfuncdesc = NULL;
6480 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6481 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6482 if (!strcmpW(pFDesc->Name, szName)) {
6488 HRESULT hr = TLB_AllocAndInitFuncDesc(
6490 &pBindPtr->lpfuncdesc,
6491 This->TypeAttr.typekind == TKIND_DISPATCH);
6494 *pDescKind = DESCKIND_FUNCDESC;
6495 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6496 ITypeInfo_AddRef(*ppTInfo);
6499 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6500 if (!strcmpW(pVDesc->Name, szName)) {
6501 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6504 *pDescKind = DESCKIND_VARDESC;
6505 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6506 ITypeInfo_AddRef(*ppTInfo);
6511 /* FIXME: search each inherited interface, not just the first */
6512 if (This->TypeAttr.cImplTypes) {
6513 /* recursive search */
6517 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6520 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6521 ITypeInfo_Release(pTInfo);
6525 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6526 ITypeComp_Release(pTComp);
6529 WARN("Could not search inherited interface!\n");
6531 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6532 return DISP_E_MEMBERNOTFOUND;
6535 static HRESULT WINAPI ITypeComp_fnBindType(
6539 ITypeInfo ** ppTInfo,
6540 ITypeComp ** ppTComp)
6542 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6544 /* strange behaviour (does nothing) but like the
6547 if (!ppTInfo || !ppTComp)
6556 static const ITypeCompVtbl tcompvt =
6559 ITypeComp_fnQueryInterface,
6561 ITypeComp_fnRelease,
6564 ITypeComp_fnBindType