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 */
351 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
352 (szFile[0] && (szFile[1] == ':'))) break;
353 /* else fall-through */
355 case REGKIND_REGISTER:
356 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
358 IUnknown_Release(*pptLib);
366 TRACE(" returns %08lx\n",res);
370 /******************************************************************************
371 * LoadRegTypeLib [OLEAUT32.162]
373 * Loads a registered type library.
376 * rguid [I] GUID of the registered type library.
377 * wVerMajor [I] major version.
378 * wVerMinor [I] minor version.
379 * lcid [I] locale ID.
380 * ppTLib [O] pointer that receives an ITypeLib object on success.
384 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
387 HRESULT WINAPI LoadRegTypeLib(
399 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
403 res= LoadTypeLib(bstr, ppTLib);
407 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
413 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
414 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
415 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
416 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
417 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
418 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
420 /******************************************************************************
421 * RegisterTypeLib [OLEAUT32.163]
422 * Adds information about a type library to the System Registry
424 * Docs: ITypeLib FAR * ptlib
425 * Docs: OLECHAR FAR* szFullPath
426 * Docs: OLECHAR FAR* szHelpDir
432 HRESULT WINAPI RegisterTypeLib(
433 ITypeLib * ptlib, /* [in] Pointer to the library*/
434 OLECHAR * szFullPath, /* [in] full Path of the library*/
435 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
438 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
439 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
440 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
450 if (ptlib == NULL || szFullPath == NULL)
453 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
456 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
459 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
460 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
464 /* Set the human-readable name of the typelib */
465 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
467 if (RegSetValueExW(key, NULL, 0, REG_SZ,
468 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
476 /* Make up the name of the typelib path subkey */
477 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
479 /* Create the typelib path subkey */
480 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
481 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
483 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
484 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
492 /* Create the flags subkey */
493 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
494 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
496 /* FIXME: is %u correct? */
497 static const WCHAR formatW[] = {'%','u',0};
499 sprintfW(buf, formatW, attr->wLibFlags);
500 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
501 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
509 /* create the helpdir subkey */
510 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
511 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
513 BOOL freeHelpDir = FALSE;
516 /* if we created a new key, and helpDir was null, set the helpdir
517 to the directory which contains the typelib. However,
518 if we just opened an existing key, we leave the helpdir alone */
519 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
520 szHelpDir = SysAllocString(szFullPath);
521 pIndexStr = strrchrW(szHelpDir, '\\');
528 /* if we have an szHelpDir, set it! */
529 if (szHelpDir != NULL) {
530 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
531 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
537 if (freeHelpDir) SysFreeString(szHelpDir);
549 /* register OLE Automation-compatible interfaces for this typelib */
550 types = ITypeLib_GetTypeInfoCount(ptlib);
551 for (tidx=0; tidx<types; tidx++) {
552 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
553 LPOLESTR name = NULL;
554 ITypeInfo *tinfo = NULL;
556 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
559 case TKIND_INTERFACE:
560 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
561 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
565 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
566 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
570 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
575 TYPEATTR *tattr = NULL;
576 ITypeInfo_GetTypeAttr(tinfo, &tattr);
579 TRACE_(typelib)("guid=%s, flags=%04x (",
580 debugstr_guid(&tattr->guid),
583 if (TRACE_ON(typelib)) {
584 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
604 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
606 /* register interface<->typelib coupling */
607 get_interface_key( &tattr->guid, keyName );
608 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
609 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
612 RegSetValueExW(key, NULL, 0, REG_SZ,
613 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
615 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
616 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
617 RegSetValueExW(subKey, NULL, 0, REG_SZ,
618 (BYTE*)PSOA, sizeof PSOA);
622 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
623 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
624 RegSetValueExW(subKey, NULL, 0, REG_SZ,
625 (BYTE*)PSOA, sizeof PSOA);
629 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
630 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
633 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
634 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
636 StringFromGUID2(&attr->guid, buffer, 40);
637 RegSetValueExW(subKey, NULL, 0, REG_SZ,
638 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
639 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
640 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
641 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
649 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
652 ITypeInfo_Release(tinfo);
659 ITypeLib_ReleaseTLibAttr(ptlib, attr);
665 /******************************************************************************
666 * UnRegisterTypeLib [OLEAUT32.186]
667 * Removes information about a type library from the System Registry
674 HRESULT WINAPI UnRegisterTypeLib(
675 REFGUID libid, /* [in] Guid of the library */
676 WORD wVerMajor, /* [in] major version */
677 WORD wVerMinor, /* [in] minor version */
678 LCID lcid, /* [in] locale id */
681 BSTR tlibPath = NULL;
684 WCHAR subKeyName[50];
687 BOOL deleteOtherStuff;
690 TYPEATTR* typeAttr = NULL;
692 ITypeInfo* typeInfo = NULL;
693 ITypeLib* typeLib = NULL;
696 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
698 /* Create the path to the key */
699 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
701 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
703 TRACE("Unsupported syskind %i\n", syskind);
704 result = E_INVALIDARG;
708 /* get the path to the typelib on disk */
709 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
710 result = E_INVALIDARG;
714 /* Try and open the key to the type library. */
715 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
716 result = E_INVALIDARG;
720 /* Try and load the type library */
721 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
722 result = TYPE_E_INVALIDSTATE;
726 /* remove any types registered with this typelib */
727 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
728 for (i=0; i<numTypes; i++) {
729 /* get the kind of type */
730 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
734 /* skip non-interfaces, and get type info for the type */
735 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
738 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
741 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
745 /* the path to the type */
746 get_interface_key( &typeAttr->guid, subKeyName );
748 /* Delete its bits */
749 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
752 RegDeleteKeyW(subKey, ProxyStubClsidW);
753 RegDeleteKeyW(subKey, ProxyStubClsid32W);
754 RegDeleteKeyW(subKey, TypeLibW);
757 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
760 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
762 if (typeInfo) ITypeInfo_Release(typeInfo);
766 /* Now, delete the type library path subkey */
767 get_lcid_subkey( lcid, syskind, subKeyName );
768 RegDeleteKeyW(key, subKeyName);
769 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
770 RegDeleteKeyW(key, subKeyName);
772 /* check if there is anything besides the FLAGS/HELPDIR keys.
773 If there is, we don't delete them */
774 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
775 deleteOtherStuff = TRUE;
777 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
778 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
780 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
781 if (!strcmpW(subKeyName, FLAGSW)) continue;
782 if (!strcmpW(subKeyName, HELPDIRW)) continue;
783 deleteOtherStuff = FALSE;
787 /* only delete the other parts of the key if we're absolutely sure */
788 if (deleteOtherStuff) {
789 RegDeleteKeyW(key, FLAGSW);
790 RegDeleteKeyW(key, HELPDIRW);
794 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
795 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
796 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
800 if (tlibPath) SysFreeString(tlibPath);
801 if (typeLib) ITypeLib_Release(typeLib);
802 if (subKey) RegCloseKey(subKey);
803 if (key) RegCloseKey(key);
807 /*======================= ITypeLib implementation =======================*/
809 typedef struct tagTLBCustData
813 struct tagTLBCustData* next;
816 /* data structure for import typelibs */
817 typedef struct tagTLBImpLib
819 int offset; /* offset in the file (MSFT)
820 offset in nametable (SLTG)
821 just used to identify library while reading
823 GUID guid; /* libid */
824 BSTR name; /* name */
826 LCID lcid; /* lcid of imported typelib */
828 WORD wVersionMajor; /* major version number */
829 WORD wVersionMinor; /* minor version number */
831 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
832 NULL if not yet loaded */
833 struct tagTLBImpLib * next;
836 /* internal ITypeLib data */
837 typedef struct tagITypeLibImpl
839 const ITypeLib2Vtbl *lpVtbl;
840 const ITypeCompVtbl *lpVtblTypeComp;
842 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
844 /* strings can be stored in tlb as multibyte strings BUT they are *always*
845 * exported to the application as a UNICODE string.
851 unsigned long dwHelpContext;
852 int TypeInfoCount; /* nr of typeinfo's in librarry */
853 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
854 int ctCustData; /* number of items in cust data list */
855 TLBCustData * pCustData; /* linked list to cust data */
856 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
857 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
858 libary. Only used while read MSFT
861 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
862 struct tagITypeLibImpl *next, *prev;
867 static const ITypeLib2Vtbl tlbvt;
868 static const ITypeCompVtbl tlbtcvt;
870 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
872 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
875 /* ITypeLib methods */
876 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
877 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
879 /*======================= ITypeInfo implementation =======================*/
881 /* data for referenced types */
882 typedef struct tagTLBRefType
884 INT index; /* Type index for internal ref or for external ref
885 it the format is SLTG. -2 indicates to
888 GUID guid; /* guid of the referenced type */
889 /* if index == TLB_REF_USE_GUID */
891 HREFTYPE reference; /* The href of this ref */
892 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
893 TLB_REF_INTERNAL for internal refs
894 TLB_REF_NOT_FOUND for broken refs */
896 struct tagTLBRefType * next;
899 #define TLB_REF_USE_GUID -2
901 #define TLB_REF_INTERNAL (void*)-2
902 #define TLB_REF_NOT_FOUND (void*)-1
904 /* internal Parameter data */
905 typedef struct tagTLBParDesc
909 TLBCustData * pCustData; /* linked list to cust data */
912 /* internal Function data */
913 typedef struct tagTLBFuncDesc
915 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
916 BSTR Name; /* the name of this function */
917 TLBParDesc *pParamDesc; /* array with param names and custom data */
919 int HelpStringContext;
921 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
923 TLBCustData * pCustData; /* linked list to cust data; */
924 struct tagTLBFuncDesc * next;
927 /* internal Variable data */
928 typedef struct tagTLBVarDesc
930 VARDESC vardesc; /* lots of info on the variable and its attributes. */
931 BSTR Name; /* the name of this variable */
933 int HelpStringContext; /* FIXME: where? */
936 TLBCustData * pCustData;/* linked list to cust data; */
937 struct tagTLBVarDesc * next;
940 /* internal implemented interface data */
941 typedef struct tagTLBImplType
943 HREFTYPE hRef; /* hRef of interface */
944 int implflags; /* IMPLFLAG_*s */
946 TLBCustData * pCustData;/* linked list to custom data; */
947 struct tagTLBImplType *next;
950 /* internal TypeInfo data */
951 typedef struct tagITypeInfoImpl
953 const ITypeInfo2Vtbl *lpVtbl;
954 const ITypeCompVtbl *lpVtblTypeComp;
956 TYPEATTR TypeAttr ; /* _lots_ of type information. */
957 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
958 int index; /* index in this typelib; */
959 HREFTYPE hreftype; /* hreftype for app object binding */
960 /* type libs seem to store the doc strings in ascii
961 * so why should we do it in unicode?
966 unsigned long dwHelpContext;
967 unsigned long dwHelpStringContext;
970 TLBFuncDesc * funclist; /* linked list with function descriptions */
973 TLBVarDesc * varlist; /* linked list with variable descriptions */
975 /* Implemented Interfaces */
976 TLBImplType * impltypelist;
978 TLBRefType * reflist;
980 TLBCustData * pCustData; /* linked list to cust data; */
981 struct tagITypeInfoImpl * next;
984 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
986 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
989 static const ITypeInfo2Vtbl tinfvt;
990 static const ITypeCompVtbl tcompvt;
992 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
994 typedef struct tagTLBContext
996 unsigned int oStart; /* start of TLB in file */
997 unsigned int pos; /* current pos */
998 unsigned int length; /* total length */
999 void *mapping; /* memory mapping */
1000 MSFT_SegDir * pTblDir;
1001 ITypeLibImpl* pLibInfo;
1005 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1010 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1011 if (pTD->vt & VT_RESERVED)
1012 szVarType += strlen(strcpy(szVarType, "reserved | "));
1013 if (pTD->vt & VT_BYREF)
1014 szVarType += strlen(strcpy(szVarType, "ref to "));
1015 if (pTD->vt & VT_ARRAY)
1016 szVarType += strlen(strcpy(szVarType, "array of "));
1017 if (pTD->vt & VT_VECTOR)
1018 szVarType += strlen(strcpy(szVarType, "vector of "));
1019 switch(pTD->vt & VT_TYPEMASK) {
1020 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1021 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1022 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1023 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1024 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1025 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1026 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1027 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1028 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1029 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1030 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1031 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1032 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1033 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1034 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1035 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1036 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1037 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1038 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1039 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1040 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1041 pTD->u.hreftype); break;
1042 case VT_PTR: sprintf(szVarType, "ptr to ");
1043 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1045 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1046 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1048 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1049 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1050 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1053 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1057 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1059 USHORT flags = edesc->u.paramdesc.wParamFlags;
1060 dump_TypeDesc(&edesc->tdesc,buf);
1061 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1062 MESSAGE("\t\tu.paramdesc.wParamFlags");
1063 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1064 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1065 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1066 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1067 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1068 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1069 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1070 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1071 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1073 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1075 MESSAGE("memid is %08lx\n",funcdesc->memid);
1076 for (i=0;i<funcdesc->cParams;i++) {
1077 MESSAGE("Param %d:\n",i);
1078 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1080 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1081 switch (funcdesc->funckind) {
1082 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1083 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1084 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1085 case FUNC_STATIC: MESSAGE("static");break;
1086 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1087 default: MESSAGE("unknown");break;
1089 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1090 switch (funcdesc->invkind) {
1091 case INVOKE_FUNC: MESSAGE("func");break;
1092 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1093 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1094 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1096 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1097 switch (funcdesc->callconv) {
1098 case CC_CDECL: MESSAGE("cdecl");break;
1099 case CC_PASCAL: MESSAGE("pascal");break;
1100 case CC_STDCALL: MESSAGE("stdcall");break;
1101 case CC_SYSCALL: MESSAGE("syscall");break;
1104 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1105 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1106 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1108 MESSAGE("\telemdescFunc (return value type):\n");
1109 dump_ELEMDESC(&funcdesc->elemdescFunc);
1112 static const char * typekind_desc[] =
1125 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1128 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1129 for (i=0;i<pfd->funcdesc.cParams;i++)
1130 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1133 dump_FUNCDESC(&(pfd->funcdesc));
1135 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1136 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1138 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1142 dump_TLBFuncDescOne(pfd);
1146 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1150 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1155 static void dump_TLBImpLib(const TLBImpLib *import)
1157 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1158 debugstr_w(import->name));
1159 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1160 import->wVersionMinor, import->lcid, import->offset);
1163 static void dump_TLBRefType(const TLBRefType * prt)
1167 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1168 if(prt->index == -1)
1169 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1171 TRACE_(typelib)("type no: %d\n", prt->index);
1173 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1174 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1175 TRACE_(typelib)("in lib\n");
1176 dump_TLBImpLib(prt->pImpTLInfo);
1182 static void dump_TLBImplType(const TLBImplType * impl)
1186 "implementing/inheriting interface hRef = %lx implflags %x\n",
1187 impl->hRef, impl->implflags);
1192 void dump_Variant(const VARIANT * pvar)
1196 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1200 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1201 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1203 TRACE(",%p", V_BYREF(pvar));
1205 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1207 TRACE(",%p", V_ARRAY(pvar));
1209 else switch (V_TYPE(pvar))
1211 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1212 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1213 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1214 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1216 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1218 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1219 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1220 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1221 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1222 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1223 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1224 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1225 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1226 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1227 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1228 V_CY(pvar).s.Lo); break;
1230 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1231 TRACE(",<invalid>");
1233 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1234 st.wHour, st.wMinute, st.wSecond);
1238 case VT_USERDEFINED:
1240 case VT_NULL: break;
1241 default: TRACE(",?"); break;
1247 static void dump_DispParms(const DISPPARAMS * pdp)
1251 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1253 while (index < pdp->cArgs)
1255 dump_Variant( &pdp->rgvarg[index] );
1260 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1262 TRACE("%p ref=%lu\n", pty, pty->ref);
1263 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1264 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1265 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1266 TRACE("fct:%u var:%u impl:%u\n",
1267 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1268 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1269 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1270 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1272 dump_TLBFuncDesc(pty->funclist);
1273 dump_TLBVarDesc(pty->varlist);
1274 dump_TLBImplType(pty->impltypelist);
1277 static void dump_VARDESC(const VARDESC *v)
1279 MESSAGE("memid %ld\n",v->memid);
1280 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1281 MESSAGE("oInst %ld\n",v->u.oInst);
1282 dump_ELEMDESC(&(v->elemdescVar));
1283 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1284 MESSAGE("varkind %d\n",v->varkind);
1287 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1289 /* VT_LPWSTR is largest type that */
1290 /* may appear in type description*/
1291 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1292 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1293 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1294 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1295 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1296 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1300 static void TLB_abort(void)
1304 static void * TLB_Alloc(unsigned size)
1307 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1309 ERR("cannot allocate memory\n");
1314 static void TLB_Free(void * ptr)
1316 HeapFree(GetProcessHeap(), 0, ptr);
1319 /* returns the size required for a deep copy of a typedesc into a
1321 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1325 if (alloc_initial_space)
1326 size += sizeof(TYPEDESC);
1332 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1335 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1336 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1342 /* deep copy a typedesc into a flat buffer */
1343 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1348 buffer = (char *)buffer + sizeof(TYPEDESC);
1357 dest->u.lptdesc = buffer;
1358 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1361 dest->u.lpadesc = buffer;
1362 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1363 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1364 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1370 /**********************************************************************
1372 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1375 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1377 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1378 pcx->pos, count, pcx->oStart, pcx->length, where);
1380 if (where != DO_NOT_SEEK)
1382 where += pcx->oStart;
1383 if (where > pcx->length)
1386 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1391 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1392 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1397 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1402 ret = MSFT_Read(buffer, count, pcx, where);
1403 FromLEDWords(buffer, ret);
1408 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1413 ret = MSFT_Read(buffer, count, pcx, where);
1414 FromLEWords(buffer, ret);
1419 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1421 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1422 memset(pGuid,0, sizeof(GUID));
1425 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1426 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1427 pGuid->Data2 = FromLEWord(pGuid->Data2);
1428 pGuid->Data3 = FromLEWord(pGuid->Data3);
1429 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1432 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1434 MSFT_NameIntro niName;
1438 ERR_(typelib)("bad offset %d\n", offset);
1442 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1443 pcx->pTblDir->pNametab.offset+offset);
1445 return niName.hreftype;
1448 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1451 MSFT_NameIntro niName;
1453 WCHAR* pwstring = NULL;
1454 BSTR bstrName = NULL;
1458 ERR_(typelib)("bad offset %d\n", offset);
1461 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1462 pcx->pTblDir->pNametab.offset+offset);
1463 niName.namelen &= 0xFF; /* FIXME: correct ? */
1464 name=TLB_Alloc((niName.namelen & 0xff) +1);
1465 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1466 name[niName.namelen & 0xff]='\0';
1468 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1471 /* no invalid characters in string */
1474 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1476 /* don't check for invalid character since this has been done previously */
1477 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1479 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1480 lengthInChars = SysStringLen(bstrName);
1481 HeapFree(GetProcessHeap(), 0, pwstring);
1484 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1488 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1495 if(offset<0) return NULL;
1496 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1497 if(length <= 0) return 0;
1498 string=TLB_Alloc(length +1);
1499 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1500 string[length]='\0';
1502 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1503 string, -1, NULL, 0);
1505 /* no invalid characters in string */
1508 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1510 /* don't check for invalid character since this has been done previously */
1511 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1513 bstr = SysAllocStringLen(pwstring, lengthInChars);
1514 lengthInChars = SysStringLen(bstr);
1515 HeapFree(GetProcessHeap(), 0, pwstring);
1518 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1522 * read a value and fill a VARIANT structure
1524 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1528 TRACE_(typelib)("\n");
1530 if(offset <0) { /* data are packed in here */
1531 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1532 V_I4(pVar) = offset & 0x3ffffff;
1535 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1536 pcx->pTblDir->pCustData.offset + offset );
1537 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1538 switch (V_VT(pVar)){
1539 case VT_EMPTY: /* FIXME: is this right? */
1540 case VT_NULL: /* FIXME: is this right? */
1541 case VT_I2 : /* this should not happen */
1552 case VT_VOID : /* FIXME: is this right? */
1560 case VT_DECIMAL : /* FIXME: is this right? */
1563 /* pointer types with known behaviour */
1566 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1568 FIXME("BSTR length = %d?\n", size);
1570 ptr=TLB_Alloc(size);/* allocate temp buffer */
1571 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1572 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1573 /* FIXME: do we need a AtoW conversion here? */
1574 V_UNION(pVar, bstrVal[size])=L'\0';
1575 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1580 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1587 case VT_USERDEFINED :
1593 case VT_STREAMED_OBJECT :
1594 case VT_STORED_OBJECT :
1595 case VT_BLOB_OBJECT :
1600 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1604 if(size>0) /* (big|small) endian correct? */
1605 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1609 * create a linked list with custom data
1611 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1617 TRACE_(typelib)("\n");
1621 pNew=TLB_Alloc(sizeof(TLBCustData));
1622 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1623 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1624 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1625 /* add new custom data at head of the list */
1626 pNew->next=*ppCustData;
1628 offset = entry.next;
1633 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1637 pTd->vt=type & VT_TYPEMASK;
1639 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1641 if(pTd->vt == VT_USERDEFINED)
1642 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1644 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1648 MSFT_DoFuncs(TLBContext* pcx,
1653 TLBFuncDesc** pptfd)
1656 * member information is stored in a data structure at offset
1657 * indicated by the memoffset field of the typeinfo structure
1658 * There are several distinctive parts.
1659 * The first part starts with a field that holds the total length
1660 * of this (first) part excluding this field. Then follow the records,
1661 * for each member there is one record.
1663 * The first entry is always the length of the record (including this
1665 * The rest of the record depends on the type of the member. If there is
1666 * a field indicating the member type (function, variable, interface, etc)
1667 * I have not found it yet. At this time we depend on the information
1668 * in the type info and the usual order how things are stored.
1670 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1673 * Third is an equal sized array with file offsets to the name entry
1676 * The fourth and last (?) part is an array with offsets to the records
1677 * in the first part of this file segment.
1680 int infolen, nameoffset, reclength, nrattributes, i;
1681 int recoffset = offset + sizeof(INT);
1684 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1685 TLBFuncDesc *ptfd_prev = NULL;
1687 TRACE_(typelib)("\n");
1689 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1691 for ( i = 0; i < cFuncs ; i++ )
1693 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1695 /* name, eventually add to a hash table */
1696 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1697 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1699 /* nameoffset is sometimes -1 on the second half of a propget/propput
1700 * pair of functions */
1701 if ((nameoffset == -1) && (i > 0))
1702 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1704 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1706 /* read the function information record */
1707 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1711 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1713 /* do the attributes */
1714 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1717 if ( nrattributes > 0 )
1719 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1721 if ( nrattributes > 1 )
1723 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1724 pFuncRec->OptAttr[1]) ;
1726 if ( nrattributes > 2 )
1728 if ( pFuncRec->FKCCIC & 0x2000 )
1730 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1734 (*pptfd)->Entry = MSFT_ReadString(pcx,
1735 pFuncRec->OptAttr[2]);
1737 if( nrattributes > 5 )
1739 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1741 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1744 pFuncRec->OptAttr[6],
1745 &(*pptfd)->pCustData);
1752 /* fill the FuncDesc Structure */
1753 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1754 offset + infolen + ( i + 1) * sizeof(INT));
1756 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1757 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1758 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1759 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1760 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1761 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1762 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1766 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1769 /* do the parameters/arguments */
1770 if(pFuncRec->nrargs)
1773 MSFT_ParameterInfo paraminfo;
1775 (*pptfd)->funcdesc.lprgelemdescParam =
1776 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1778 (*pptfd)->pParamDesc =
1779 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1781 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1782 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1784 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1786 TYPEDESC *lpArgTypeDesc;
1787 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1794 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1797 if (paraminfo.oName == -1)
1798 /* this occurs for [propput] or [propget] methods, so
1799 * we should just set the name of the parameter to the
1800 * name of the method. */
1801 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1803 (*pptfd)->pParamDesc[j].Name =
1804 MSFT_ReadName( pcx, paraminfo.oName );
1805 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1807 lpArgTypeDesc = &elemdesc->tdesc;
1809 /* resolve referenced type if any */
1810 while ( lpArgTypeDesc != NULL )
1812 switch ( lpArgTypeDesc->vt )
1815 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1819 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1822 case VT_USERDEFINED:
1823 MSFT_DoRefType(pcx, pTI,
1824 lpArgTypeDesc->u.hreftype);
1826 lpArgTypeDesc = NULL;
1830 lpArgTypeDesc = NULL;
1835 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1836 (pFuncRec->FKCCIC & 0x1000) )
1838 INT* pInt = (INT *)((char *)pFuncRec +
1840 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1842 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1844 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1845 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1847 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1851 elemdesc->u.paramdesc.pparamdescex = NULL;
1853 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1856 pFuncRec->OptAttr[7+j],
1857 &(*pptfd)->pParamDesc[j].pCustData);
1860 /* SEEK value = jump to offset,
1861 * from there jump to the end of record,
1862 * go back by (j-1) arguments
1864 MSFT_ReadLEDWords( ¶minfo ,
1865 sizeof(MSFT_ParameterInfo), pcx,
1866 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1867 * sizeof(MSFT_ParameterInfo)));
1871 /* scode is not used: archaic win16 stuff FIXME: right? */
1872 (*pptfd)->funcdesc.cScodes = 0 ;
1873 (*pptfd)->funcdesc.lprgscode = NULL ;
1876 pptfd = & ((*pptfd)->next);
1877 recoffset += reclength;
1881 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1882 int cVars, int offset, TLBVarDesc ** pptvd)
1884 int infolen, nameoffset, reclength;
1886 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1890 TRACE_(typelib)("\n");
1892 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1893 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1894 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1895 recoffset += offset+sizeof(INT);
1896 for(i=0;i<cVars;i++){
1897 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1898 /* name, eventually add to a hash table */
1899 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1900 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1901 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1902 /* read the variable information record */
1903 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1905 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1907 if(reclength >(6*sizeof(INT)) )
1908 (*pptvd)->HelpContext=pVarRec->HelpContext;
1909 if(reclength >(7*sizeof(INT)) )
1910 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1911 if(reclength >(8*sizeof(INT)) )
1912 if(reclength >(9*sizeof(INT)) )
1913 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1914 /* fill the VarDesc Structure */
1915 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1916 offset + infolen + ( i + 1) * sizeof(INT));
1917 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1918 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1919 MSFT_GetTdesc(pcx, pVarRec->DataType,
1920 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1921 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1922 if(pVarRec->VarKind == VAR_CONST ){
1923 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1924 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1925 pVarRec->OffsValue, pcx);
1927 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1928 pptvd=&((*pptvd)->next);
1929 recoffset += reclength;
1932 /* fill in data for a hreftype (offset). When the referenced type is contained
1933 * in the typelib, it's just an (file) offset in the type info base dir.
1934 * If comes from import, it's an offset+1 in the ImpInfo table
1936 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1940 TLBRefType **ppRefType = &pTI->reflist;
1942 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1945 if((*ppRefType)->reference == offset)
1947 ppRefType = &(*ppRefType)->next;
1950 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1951 sizeof(**ppRefType));
1953 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1954 /* external typelib */
1955 MSFT_ImpInfo impinfo;
1956 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1958 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1960 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1961 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1962 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1963 if(pImpLib->offset==impinfo.oImpFile) break;
1964 pImpLib=pImpLib->next;
1967 (*ppRefType)->reference=offset;
1968 (*ppRefType)->pImpTLInfo = pImpLib;
1969 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1970 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1971 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
1972 (*ppRefType)->index = TLB_REF_USE_GUID;
1974 (*ppRefType)->index = impinfo.oGuid;
1976 ERR("Cannot find a reference\n");
1977 (*ppRefType)->reference=-1;
1978 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1981 /* in this typelib */
1982 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1983 (*ppRefType)->reference=offset;
1984 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1988 /* process Implemented Interfaces of a com class */
1989 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1993 MSFT_RefRecord refrec;
1994 TLBImplType **ppImpl = &pTI->impltypelist;
1996 TRACE_(typelib)("\n");
1998 for(i=0;i<count;i++){
1999 if(offset<0) break; /* paranoia */
2000 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2001 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2002 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2003 (*ppImpl)->hRef = refrec.reftype;
2004 (*ppImpl)->implflags=refrec.flags;
2005 (*ppImpl)->ctCustData=
2006 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2007 offset=refrec.onext;
2008 ppImpl=&((*ppImpl)->next);
2012 * process a typeinfo record
2014 static ITypeInfoImpl * MSFT_DoTypeInfo(
2018 ITypeLibImpl * pLibInfo)
2020 MSFT_TypeInfoBase tiBase;
2021 ITypeInfoImpl *ptiRet;
2023 TRACE_(typelib)("count=%u\n", count);
2025 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2026 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2027 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2029 /* this is where we are coming from */
2030 ptiRet->pTypeLib = pLibInfo;
2031 ptiRet->index=count;
2032 /* fill in the typeattr fields */
2033 WARN("Assign constructor/destructor memid\n");
2035 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2036 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2037 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2038 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2039 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2040 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2041 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2042 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2043 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2044 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2045 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2046 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2047 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2048 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2049 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2050 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2051 MSFT_GetTdesc(pcx, tiBase.datatype1,
2052 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2055 /* IDLDESC idldescType; *//* never saw this one != zero */
2057 /* name, eventually add to a hash table */
2058 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2059 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2060 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2062 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2063 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2064 ptiRet->dwHelpContext=tiBase.helpcontext;
2066 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2067 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2069 /* note: InfoType's Help file and HelpStringDll come from the containing
2070 * library. Further HelpString and Docstring appear to be the same thing :(
2073 if(ptiRet->TypeAttr.cFuncs >0 )
2074 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2075 ptiRet->TypeAttr.cVars,
2076 tiBase.memoffset, & ptiRet->funclist);
2078 if(ptiRet->TypeAttr.cVars >0 )
2079 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2080 ptiRet->TypeAttr.cVars,
2081 tiBase.memoffset, & ptiRet->varlist);
2082 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2083 switch(ptiRet->TypeAttr.typekind)
2086 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2089 case TKIND_DISPATCH:
2090 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2092 if (tiBase.datatype1 != -1)
2094 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2095 ptiRet->impltypelist->hRef = tiBase.datatype1;
2099 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2100 ptiRet->impltypelist->hRef = dispatch_href;
2104 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2105 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2106 ptiRet->impltypelist->hRef = tiBase.datatype1;
2111 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2113 TRACE_(typelib)("%s guid: %s kind:%s\n",
2114 debugstr_w(ptiRet->Name),
2115 debugstr_guid(&ptiRet->TypeAttr.guid),
2116 typekind_desc[ptiRet->TypeAttr.typekind]);
2121 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2122 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2123 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2126 static ITypeLibImpl *tlb_cache_first;
2127 static CRITICAL_SECTION cache_section;
2128 static CRITICAL_SECTION_DEBUG cache_section_debug =
2130 0, 0, &cache_section,
2131 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2132 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2134 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2137 /****************************************************************************
2140 * find the type of the typelib file and map the typelib resource into
2143 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2144 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2145 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2147 ITypeLibImpl *entry;
2148 int ret = TYPE_E_CANTLOADLIBRARY;
2154 lstrcpynW(pszPath, pszFileName, cchPath);
2156 /* first try loading as a dll and access the typelib as a resource */
2157 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2158 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2161 /* it may have been specified with resource index appended to the
2162 * path, so remove it and try again */
2163 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2164 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2166 index = atoiW(pIndexStr);
2167 pszPath[pIndexStr - pszFileName - 1] = '\0';
2169 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2170 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2174 /* get the path to the specified typelib file */
2177 /* otherwise, try loading as a regular file */
2178 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2179 return TYPE_E_CANTLOADLIBRARY;
2182 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2184 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2185 EnterCriticalSection(&cache_section);
2186 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2188 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2190 TRACE("cache hit\n");
2191 *ppTypeLib = (ITypeLib2*)entry;
2192 ITypeLib_AddRef(*ppTypeLib);
2193 LeaveCriticalSection(&cache_section);
2197 LeaveCriticalSection(&cache_section);
2199 /* now actually load and parse the typelib */
2202 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2203 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2206 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2209 LPVOID pBase = LockResource(hGlobal);
2210 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2214 /* try to load as incore resource */
2215 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2216 if (dwSignature == MSFT_SIGNATURE)
2217 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2218 else if (dwSignature == SLTG_SIGNATURE)
2219 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2221 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2223 FreeResource( hGlobal );
2226 FreeLibrary(hinstDLL);
2230 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2231 if (INVALID_HANDLE_VALUE != hFile)
2233 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2236 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2239 /* retrieve file size */
2240 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2241 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2243 if (dwSignature == MSFT_SIGNATURE)
2244 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2245 else if (dwSignature == SLTG_SIGNATURE)
2246 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2248 UnmapViewOfFile(pBase);
2250 CloseHandle(hMapping);
2257 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2259 TRACE("adding to cache\n");
2260 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2261 lstrcpyW(impl->path, pszPath);
2262 /* We should really canonicalise the path here. */
2263 impl->index = index;
2265 /* FIXME: check if it has added already in the meantime */
2266 EnterCriticalSection(&cache_section);
2267 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2269 tlb_cache_first = impl;
2270 LeaveCriticalSection(&cache_section);
2273 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2278 /*================== ITypeLib(2) Methods ===================================*/
2280 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2282 ITypeLibImpl* pTypeLibImpl;
2284 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2285 if (!pTypeLibImpl) return NULL;
2287 pTypeLibImpl->lpVtbl = &tlbvt;
2288 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2289 pTypeLibImpl->ref = 1;
2291 return pTypeLibImpl;
2294 /****************************************************************************
2295 * ITypeLib2_Constructor_MSFT
2297 * loading an MSFT typelib from an in-memory image
2299 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2303 MSFT_Header tlbHeader;
2304 MSFT_SegDir tlbSegDir;
2305 ITypeLibImpl * pTypeLibImpl;
2307 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2309 pTypeLibImpl = TypeLibImpl_Constructor();
2310 if (!pTypeLibImpl) return NULL;
2312 /* get pointer to beginning of typelib data */
2316 cx.pLibInfo = pTypeLibImpl;
2317 cx.length = dwTLBLength;
2320 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2321 TRACE_(typelib)("header:\n");
2322 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2323 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2324 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2327 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2329 /* there is a small amount of information here until the next important
2331 * the segment directory . Try to calculate the amount of data */
2332 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2334 /* now read the segment directory */
2335 TRACE("read segment directory (at %ld)\n",lPSegDir);
2336 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2337 cx.pTblDir = &tlbSegDir;
2339 /* just check two entries */
2340 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2342 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2343 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2347 /* now fill our internal data */
2348 /* TLIBATTR fields */
2349 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2351 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2352 /* Windows seems to have zero here, is this correct? */
2353 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2354 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2356 pTypeLibImpl->LibAttr.lcid = 0;
2358 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2359 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2360 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2361 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2363 /* name, eventually add to a hash table */
2364 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2367 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2368 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2370 if( tlbHeader.varflags & HELPDLLFLAG)
2373 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2374 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2377 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2380 if(tlbHeader.CustomDataOffset >= 0)
2382 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2385 /* fill in typedescriptions */
2386 if(tlbSegDir.pTypdescTab.length > 0)
2388 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2390 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2391 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2394 /* FIXME: add several sanity checks here */
2395 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2396 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2398 /* FIXME: check safearray */
2400 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2402 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2404 else if(td[0] == VT_CARRAY)
2406 /* array descr table here */
2407 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2409 else if(td[0] == VT_USERDEFINED)
2411 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2413 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2416 /* second time around to fill the array subscript info */
2419 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2420 if(tlbSegDir.pArrayDescriptions.offset>0)
2422 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2423 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2426 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2428 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2430 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2432 for(j = 0; j<td[2]; j++)
2434 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2435 sizeof(INT), &cx, DO_NOT_SEEK);
2436 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2437 sizeof(INT), &cx, DO_NOT_SEEK);
2442 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2443 ERR("didn't find array description data\n");
2448 /* imported type libs */
2449 if(tlbSegDir.pImpFiles.offset>0)
2451 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2452 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2455 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2460 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2461 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2462 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2464 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2465 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2466 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2467 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2470 name = TLB_Alloc(size+1);
2471 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2472 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2473 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2474 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2477 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2478 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2480 ppImpLib = &(*ppImpLib)->next;
2485 if(tlbHeader.nrtypeinfos >= 0 )
2487 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2488 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2491 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2493 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2495 ppTI = &((*ppTI)->next);
2496 (pTypeLibImpl->TypeInfoCount)++;
2500 TRACE("(%p)\n", pTypeLibImpl);
2501 return (ITypeLib2*) pTypeLibImpl;
2505 static BSTR TLB_MultiByteToBSTR(char *ptr)
2511 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2512 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2513 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2514 ret = SysAllocString(nameW);
2515 HeapFree(GetProcessHeap(), 0, nameW);
2519 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2525 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2526 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2530 guid->Data4[0] = s >> 8;
2531 guid->Data4[1] = s & 0xff;
2534 for(i = 0; i < 6; i++) {
2535 memcpy(b, str + 24 + 2 * i, 2);
2536 guid->Data4[i + 2] = strtol(b, NULL, 16);
2541 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2548 bytelen = *(WORD*)ptr;
2549 if(bytelen == 0xffff) return 2;
2550 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2551 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2552 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2553 *pBstr = SysAllocStringLen(nameW, len);
2554 HeapFree(GetProcessHeap(), 0, nameW);
2558 static WORD SLTG_ReadStringA(char *ptr, char **str)
2563 bytelen = *(WORD*)ptr;
2564 if(bytelen == 0xffff) return 2;
2565 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2566 memcpy(*str, ptr + 2, bytelen);
2567 (*str)[bytelen] = '\0';
2571 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2573 char *ptr = pLibBlk;
2576 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2577 FIXME("libblk magic = %04x\n", w);
2582 if((w = *(WORD*)ptr) != 0xffff) {
2583 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2588 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2590 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2592 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2595 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2598 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2599 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2601 pTypeLibImpl->LibAttr.lcid = 0;
2604 ptr += 4; /* skip res12 */
2606 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2609 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2612 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2615 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2616 ptr += sizeof(GUID);
2618 return ptr - (char*)pLibBlk;
2621 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2624 TYPEDESC *pTD = &pElem->tdesc;
2626 /* Handle [in/out] first */
2627 if((*pType & 0xc000) == 0xc000)
2628 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2629 else if(*pType & 0x8000)
2630 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2631 else if(*pType & 0x4000)
2632 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2634 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2637 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2640 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2643 if((*pType & 0xe00) == 0xe00) {
2645 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2647 pTD = pTD->u.lptdesc;
2649 switch(*pType & 0x7f) {
2652 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2654 pTD = pTD->u.lptdesc;
2657 case VT_USERDEFINED:
2658 pTD->vt = VT_USERDEFINED;
2659 pTD->u.hreftype = *(++pType) / 4;
2665 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2668 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2670 pTD->vt = VT_CARRAY;
2671 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2673 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2674 pTD->u.lpadesc->cDims = pSA->cDims;
2675 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2676 pSA->cDims * sizeof(SAFEARRAYBOUND));
2678 pTD = &pTD->u.lpadesc->tdescElem;
2684 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2688 pTD->vt = VT_SAFEARRAY;
2689 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2691 pTD = pTD->u.lptdesc;
2695 pTD->vt = *pType & 0x7f;
2705 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2710 TLBRefType **ppRefType;
2712 if(pRef->magic != SLTG_REF_MAGIC) {
2713 FIXME("Ref magic = %x\n", pRef->magic);
2716 name = ( (char*)(&pRef->names) + pRef->number);
2718 ppRefType = &pTI->reflist;
2719 for(ref = 0; ref < pRef->number >> 3; ref++) {
2721 unsigned int lib_offs, type_num;
2723 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2724 sizeof(**ppRefType));
2726 name += SLTG_ReadStringA(name, &refname);
2727 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2728 FIXME("Can't sscanf ref\n");
2729 if(lib_offs != 0xffff) {
2730 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2733 if((*import)->offset == lib_offs)
2735 import = &(*import)->next;
2738 char fname[MAX_PATH+1];
2741 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2743 (*import)->offset = lib_offs;
2744 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2746 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2747 &(*import)->wVersionMajor,
2748 &(*import)->wVersionMinor,
2749 &(*import)->lcid, fname) != 4) {
2750 FIXME("can't sscanf ref %s\n",
2751 pNameTable + lib_offs + 40);
2753 len = strlen(fname);
2754 if(fname[len-1] != '#')
2755 FIXME("fname = %s\n", fname);
2756 fname[len-1] = '\0';
2757 (*import)->name = TLB_MultiByteToBSTR(fname);
2759 (*ppRefType)->pImpTLInfo = *import;
2760 } else { /* internal ref */
2761 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2763 (*ppRefType)->reference = ref;
2764 (*ppRefType)->index = type_num;
2766 HeapFree(GetProcessHeap(), 0, refname);
2767 ppRefType = &(*ppRefType)->next;
2769 if((BYTE)*name != SLTG_REF_MAGIC)
2770 FIXME("End of ref block magic = %x\n", *name);
2771 dump_TLBRefType(pTI->reflist);
2774 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2777 SLTG_ImplInfo *info;
2778 TLBImplType **ppImplType = &pTI->impltypelist;
2779 /* I don't really get this structure, usually it's 0x16 bytes
2780 long, but iuser.tlb contains some that are 0x18 bytes long.
2781 That's ok because we can use the next ptr to jump to the next
2782 one. But how do we know the length of the last one? The WORD
2783 at offs 0x8 might be the clue. For now I'm just assuming that
2784 the last one is the regular 0x16 bytes. */
2786 info = (SLTG_ImplInfo*)pBlk;
2788 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2789 sizeof(**ppImplType));
2790 (*ppImplType)->hRef = info->ref;
2791 (*ppImplType)->implflags = info->impltypeflags;
2792 pTI->TypeAttr.cImplTypes++;
2793 ppImplType = &(*ppImplType)->next;
2795 if(info->next == 0xffff)
2798 FIXME("Interface inheriting more than one interface\n");
2799 info = (SLTG_ImplInfo*)(pBlk + info->next);
2801 info++; /* see comment at top of function */
2805 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2808 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2809 SLTG_MemberHeader *pMemHeader;
2810 char *pFirstItem, *pNextItem;
2812 if(pTIHeader->href_table != 0xffffffff) {
2813 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2818 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2820 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2822 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2823 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2826 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2830 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2833 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2834 SLTG_MemberHeader *pMemHeader;
2835 SLTG_Function *pFunc;
2836 char *pFirstItem, *pNextItem;
2837 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2840 if(pTIHeader->href_table != 0xffffffff) {
2841 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2845 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2847 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2849 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2850 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2853 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2854 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2859 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2860 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2861 FIXME("func magic = %02x\n", pFunc->magic);
2864 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2865 sizeof(**ppFuncDesc));
2866 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2868 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2869 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2870 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2871 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2872 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2873 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2875 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2876 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2878 if(pFunc->retnextopt & 0x80)
2879 pType = &pFunc->rettype;
2881 pType = (WORD*)(pFirstItem + pFunc->rettype);
2884 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2886 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2887 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2888 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2889 (*ppFuncDesc)->pParamDesc =
2890 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2891 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2893 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2895 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2896 char *paramName = pNameTable + *pArg;
2898 /* If arg type follows then paramName points to the 2nd
2899 letter of the name, else the next WORD is an offset to
2900 the arg type and paramName points to the first letter.
2901 So let's take one char off paramName and see if we're
2902 pointing at an alpha-numeric char. However if *pArg is
2903 0xffff or 0xfffe then the param has no name, the former
2904 meaning that the next WORD is the type, the latter
2905 meaning the the next WORD is an offset to the type. */
2910 else if(*pArg == 0xfffe) {
2914 else if(paramName[-1] && !isalnum(paramName[-1]))
2919 if(HaveOffs) { /* the next word is an offset to type */
2920 pType = (WORD*)(pFirstItem + *pArg);
2921 SLTG_DoType(pType, pFirstItem,
2922 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2927 pArg = SLTG_DoType(pArg, pFirstItem,
2928 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2931 /* Are we an optional param ? */
2932 if((*ppFuncDesc)->funcdesc.cParams - param <=
2933 (*ppFuncDesc)->funcdesc.cParamsOpt)
2934 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2937 (*ppFuncDesc)->pParamDesc[param].Name =
2938 TLB_MultiByteToBSTR(paramName);
2942 ppFuncDesc = &((*ppFuncDesc)->next);
2943 if(pFunc->next == 0xffff) break;
2945 pTI->TypeAttr.cFuncs = num;
2946 if (TRACE_ON(typelib))
2947 dump_TLBFuncDesc(pTI->funclist);
2948 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2951 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2954 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2955 SLTG_MemberHeader *pMemHeader;
2956 SLTG_RecordItem *pItem;
2958 TLBVarDesc **ppVarDesc = &pTI->varlist;
2963 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2965 pFirstItem = (char*)(pMemHeader + 1);
2966 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2967 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2968 if(pItem->magic != SLTG_RECORD_MAGIC) {
2969 FIXME("record magic = %02x\n", pItem->magic);
2972 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2973 sizeof(**ppVarDesc));
2974 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2975 (*ppVarDesc)->vardesc.memid = pItem->memid;
2976 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2977 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2979 if(pItem->typepos == 0x02)
2980 pType = &pItem->type;
2981 else if(pItem->typepos == 0x00)
2982 pType = (WORD*)(pFirstItem + pItem->type);
2984 FIXME("typepos = %02x\n", pItem->typepos);
2988 SLTG_DoType(pType, pFirstItem,
2989 &(*ppVarDesc)->vardesc.elemdescVar);
2991 /* FIXME("helpcontext, helpstring\n"); */
2993 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2995 ppVarDesc = &((*ppVarDesc)->next);
2996 if(pItem->next == 0xffff) break;
2998 pTI->TypeAttr.cVars = num;
2999 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3002 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3005 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3006 SLTG_MemberHeader *pMemHeader;
3007 SLTG_AliasItem *pItem;
3010 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3011 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3014 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3015 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3016 if (pItem->vt == 0xffff) {
3017 if (i<(pMemHeader->cbExtra/4-1))
3018 FIXME("Endmarker too early in process alias data!\n");
3022 FIXME("Chain extends over last entry?\n");
3025 if (pItem->vt == VT_USERDEFINED) {
3026 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3027 /* guessing here ... */
3028 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3029 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3032 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3033 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3037 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3040 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3043 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3044 SLTG_MemberHeader *pMemHeader;
3045 SLTG_AliasItem *pItem;
3047 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3048 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3049 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3050 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3051 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3054 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3057 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3058 SLTG_MemberHeader *pMemHeader;
3059 SLTG_EnumItem *pItem;
3061 TLBVarDesc **ppVarDesc = &pTI->varlist;
3064 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3066 pFirstItem = (char*)(pMemHeader + 1);
3067 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3068 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3069 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3070 FIXME("enumitem magic = %04x\n", pItem->magic);
3073 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3074 sizeof(**ppVarDesc));
3075 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3076 (*ppVarDesc)->vardesc.memid = pItem->memid;
3077 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3079 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3080 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3081 *(INT*)(pItem->value + pFirstItem);
3082 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3083 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3084 /* FIXME("helpcontext, helpstring\n"); */
3086 ppVarDesc = &((*ppVarDesc)->next);
3087 if(pItem->next == 0xffff) break;
3089 pTI->TypeAttr.cVars = num;
3090 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3093 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3094 managable copy of it into this */
3107 } SLTG_InternalOtherTypeInfo;
3109 /****************************************************************************
3110 * ITypeLib2_Constructor_SLTG
3112 * loading a SLTG typelib from an in-memory image
3114 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3116 ITypeLibImpl *pTypeLibImpl;
3117 SLTG_Header *pHeader;
3118 SLTG_BlkEntry *pBlkEntry;
3122 LPVOID pBlk, pFirstBlk;
3123 SLTG_LibBlk *pLibBlk;
3124 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3125 char *pAfterOTIBlks = NULL;
3126 char *pNameTable, *ptr;
3129 ITypeInfoImpl **ppTypeInfoImpl;
3131 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3134 pTypeLibImpl = TypeLibImpl_Constructor();
3135 if (!pTypeLibImpl) return NULL;
3139 TRACE_(typelib)("header:\n");
3140 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3141 pHeader->nrOfFileBlks );
3142 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3143 FIXME("Header type magic 0x%08lx not supported.\n",
3144 pHeader->SLTG_magic);
3148 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3149 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3151 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3152 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3154 /* Next we have a magic block */
3155 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3157 /* Let's see if we're still in sync */
3158 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3159 sizeof(SLTG_COMPOBJ_MAGIC))) {
3160 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3163 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3164 sizeof(SLTG_DIR_MAGIC))) {
3165 FIXME("dir magic = %s\n", pMagic->dir_magic);
3169 pIndex = (SLTG_Index*)(pMagic+1);
3171 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3173 pFirstBlk = (LPVOID)(pPad9 + 1);
3175 /* We'll set up a ptr to the main library block, which is the last one. */
3177 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3178 pBlkEntry[order].next != 0;
3179 order = pBlkEntry[order].next - 1, i++) {
3180 pBlk = (char*)pBlk + pBlkEntry[order].len;
3184 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3186 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3191 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3193 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3194 sizeof(*pOtherTypeInfoBlks) *
3195 pTypeLibImpl->TypeInfoCount);
3198 ptr = (char*)pLibBlk + len;
3200 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3204 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3206 w = *(WORD*)(ptr + 2);
3209 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3211 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3212 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3214 w = *(WORD*)(ptr + 4 + len);
3216 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3218 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3220 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3221 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3223 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3224 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3225 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3227 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3229 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3232 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3233 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3234 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3235 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3236 len += sizeof(SLTG_OtherTypeInfo);
3240 pAfterOTIBlks = ptr;
3242 /* Skip this WORD and get the next DWORD */
3243 len = *(DWORD*)(pAfterOTIBlks + 2);
3245 /* Now add this to pLibBLk look at what we're pointing at and
3246 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3247 dust and we should be pointing at the beginning of the name
3250 pNameTable = (char*)pLibBlk + len;
3252 switch(*(WORD*)pNameTable) {
3259 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3263 pNameTable += 0x216;
3267 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3269 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3272 /* Hopefully we now have enough ptrs set up to actually read in
3273 some TypeInfos. It's not clear which order to do them in, so
3274 I'll just follow the links along the BlkEntry chain and read
3275 them in in the order in which they're in the file */
3277 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3279 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3280 pBlkEntry[order].next != 0;
3281 order = pBlkEntry[order].next - 1, i++) {
3283 SLTG_TypeInfoHeader *pTIHeader;
3284 SLTG_TypeInfoTail *pTITail;
3286 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3287 pOtherTypeInfoBlks[i].index_name)) {
3288 FIXME("Index strings don't match\n");
3293 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3294 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3297 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3298 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3299 (*ppTypeInfoImpl)->index = i;
3300 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3301 pOtherTypeInfoBlks[i].name_offs +
3303 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3304 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3306 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3307 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3308 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3309 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3310 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3312 if((pTIHeader->typeflags1 & 7) != 2)
3313 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3314 if(pTIHeader->typeflags3 != 2)
3315 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3317 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3318 debugstr_w((*ppTypeInfoImpl)->Name),
3319 typekind_desc[pTIHeader->typekind],
3320 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3321 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3323 switch(pTIHeader->typekind) {
3325 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3329 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3332 case TKIND_INTERFACE:
3333 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3337 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3341 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3342 if (pTITail->tdescalias_vt)
3343 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3346 case TKIND_DISPATCH:
3347 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3351 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3357 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3358 but we've already set those */
3359 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3360 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3361 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3363 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3385 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3386 pBlk = (char*)pBlk + pBlkEntry[order].len;
3389 if(i != pTypeLibImpl->TypeInfoCount) {
3390 FIXME("Somehow processed %d TypeInfos\n", i);
3394 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3395 return (ITypeLib2*)pTypeLibImpl;
3398 /* ITypeLib::QueryInterface
3400 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3405 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3407 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3410 if(IsEqualIID(riid, &IID_IUnknown) ||
3411 IsEqualIID(riid,&IID_ITypeLib)||
3412 IsEqualIID(riid,&IID_ITypeLib2))
3419 ITypeLib2_AddRef(iface);
3420 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3423 TRACE("-- Interface: E_NOINTERFACE\n");
3424 return E_NOINTERFACE;
3429 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3431 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3432 ULONG ref = InterlockedIncrement(&This->ref);
3434 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3439 /* ITypeLib::Release
3441 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3443 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3444 ULONG ref = InterlockedDecrement(&This->ref);
3446 TRACE("(%p)->(%lu)\n",This, ref);
3450 /* remove cache entry */
3453 TRACE("removing from cache list\n");
3454 EnterCriticalSection(&cache_section);
3455 if (This->next) This->next->prev = This->prev;
3456 if (This->prev) This->prev->next = This->next;
3457 else tlb_cache_first = This->next;
3458 LeaveCriticalSection(&cache_section);
3459 HeapFree(GetProcessHeap(), 0, This->path);
3461 /* FIXME destroy child objects */
3462 TRACE(" destroying ITypeLib(%p)\n",This);
3466 SysFreeString(This->Name);
3470 if (This->DocString)
3472 SysFreeString(This->DocString);
3473 This->DocString = NULL;
3478 SysFreeString(This->HelpFile);
3479 This->HelpFile = NULL;
3482 if (This->HelpStringDll)
3484 SysFreeString(This->HelpStringDll);
3485 This->HelpStringDll = NULL;
3488 if (This->pTypeInfo) /* can be NULL */
3489 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3490 HeapFree(GetProcessHeap(),0,This);
3497 /* ITypeLib::GetTypeInfoCount
3499 * Returns the number of type descriptions in the type library
3501 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3503 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3504 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3505 return This->TypeInfoCount;
3508 /* ITypeLib::GetTypeInfo
3510 * retrieves the specified type description in the library.
3512 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3515 ITypeInfo **ppTInfo)
3519 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3520 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3522 TRACE("(%p)->(index=%d)\n", This, index);
3524 if (!ppTInfo) return E_INVALIDARG;
3526 /* search element n in list */
3527 for(i=0; i < index; i++)
3529 pTypeInfo = pTypeInfo->next;
3532 TRACE("-- element not found\n");
3533 return TYPE_E_ELEMENTNOTFOUND;
3537 *ppTInfo = (ITypeInfo *) pTypeInfo;
3539 ITypeInfo_AddRef(*ppTInfo);
3540 TRACE("-- found (%p)\n",*ppTInfo);
3545 /* ITypeLibs::GetTypeInfoType
3547 * Retrieves the type of a type description.
3549 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3554 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3556 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3558 TRACE("(%p) index %d\n", This, index);
3560 if(!pTKind) return E_INVALIDARG;
3562 /* search element n in list */
3563 for(i=0; i < index; i++)
3567 TRACE("-- element not found\n");
3568 return TYPE_E_ELEMENTNOTFOUND;
3570 pTInfo = pTInfo->next;
3573 *pTKind = pTInfo->TypeAttr.typekind;
3574 TRACE("-- found Type (%d)\n", *pTKind);
3578 /* ITypeLib::GetTypeInfoOfGuid
3580 * Retrieves the type description that corresponds to the specified GUID.
3583 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3586 ITypeInfo **ppTInfo)
3588 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3589 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3591 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3595 WARN("-- element not found\n");
3596 return TYPE_E_ELEMENTNOTFOUND;
3599 /* search linked list for guid */
3600 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3602 pTypeInfo = pTypeInfo->next;
3606 /* end of list reached */
3607 WARN("-- element not found\n");
3608 return TYPE_E_ELEMENTNOTFOUND;
3612 TRACE("-- found (%p, %s)\n",
3614 debugstr_w(pTypeInfo->Name));
3616 *ppTInfo = (ITypeInfo*)pTypeInfo;
3617 ITypeInfo_AddRef(*ppTInfo);
3621 /* ITypeLib::GetLibAttr
3623 * Retrieves the structure that contains the library's attributes.
3626 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3628 LPTLIBATTR *ppTLibAttr)
3630 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3631 TRACE("(%p)\n",This);
3632 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3633 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3637 /* ITypeLib::GetTypeComp
3639 * Enables a client compiler to bind to a library's types, variables,
3640 * constants, and global functions.
3643 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3645 ITypeComp **ppTComp)
3647 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3649 TRACE("(%p)->(%p)\n",This,ppTComp);
3650 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3651 ITypeComp_AddRef(*ppTComp);
3656 /* ITypeLib::GetDocumentation
3658 * Retrieves the library's documentation string, the complete Help file name
3659 * and path, and the context identifier for the library Help topic in the Help
3662 * On a successful return all non-null BSTR pointers will have been set,
3665 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3669 BSTR *pBstrDocString,
3670 DWORD *pdwHelpContext,
3671 BSTR *pBstrHelpFile)
3673 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3675 HRESULT result = E_INVALIDARG;
3680 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3682 pBstrName, pBstrDocString,
3683 pdwHelpContext, pBstrHelpFile);
3687 /* documentation for the typelib */
3692 if(!(*pBstrName = SysAllocString(This->Name)))
3700 if (This->DocString)
3702 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3705 else if (This->Name)
3707 if(!(*pBstrDocString = SysAllocString(This->Name)))
3711 *pBstrDocString = NULL;
3715 *pdwHelpContext = This->dwHelpContext;
3721 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3725 *pBstrHelpFile = NULL;
3732 /* for a typeinfo */
3733 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3735 if(SUCCEEDED(result))
3737 result = ITypeInfo_GetDocumentation(pTInfo,
3741 pdwHelpContext, pBstrHelpFile);
3743 ITypeInfo_Release(pTInfo);
3748 if (pBstrDocString) SysFreeString (*pBstrDocString);
3750 if (pBstrName) SysFreeString (*pBstrName);
3752 return STG_E_INSUFFICIENTMEMORY;
3757 * Indicates whether a passed-in string contains the name of a type or member
3758 * described in the library.
3761 static HRESULT WINAPI ITypeLib2_fnIsName(
3767 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3768 ITypeInfoImpl *pTInfo;
3769 TLBFuncDesc *pFInfo;
3772 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3774 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3778 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3779 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3780 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3781 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3782 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3783 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3784 goto ITypeLib2_fnIsName_exit;
3786 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3787 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3792 ITypeLib2_fnIsName_exit:
3793 TRACE("(%p)slow! search for %s: %s found!\n", This,
3794 debugstr_w(szNameBuf), *pfName?"NOT":"");
3799 /* ITypeLib::FindName
3801 * Finds occurrences of a type description in a type library. This may be used
3802 * to quickly verify that a name exists in a type library.
3805 static HRESULT WINAPI ITypeLib2_fnFindName(
3809 ITypeInfo **ppTInfo,
3813 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3814 ITypeInfoImpl *pTInfo;
3815 TLBFuncDesc *pFInfo;
3818 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3820 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3821 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3822 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3823 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3824 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3825 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3826 goto ITypeLib2_fnFindName_exit;
3829 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3830 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3832 ITypeLib2_fnFindName_exit:
3833 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3834 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3837 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3838 This, *pcFound, debugstr_w(szNameBuf), j);
3845 /* ITypeLib::ReleaseTLibAttr
3847 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3850 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3852 TLIBATTR *pTLibAttr)
3854 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3855 TRACE("freeing (%p)\n",This);
3856 HeapFree(GetProcessHeap(),0,pTLibAttr);
3860 /* ITypeLib2::GetCustData
3862 * gets the custom data
3864 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3869 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3870 TLBCustData *pCData;
3872 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3874 if( IsEqualIID(guid, &pCData->guid)) break;
3877 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3881 VariantInit( pVarVal);
3882 VariantCopy( pVarVal, &pCData->data);
3885 return E_INVALIDARG; /* FIXME: correct? */
3888 /* ITypeLib2::GetLibStatistics
3890 * Returns statistics about a type library that are required for efficient
3891 * sizing of hash tables.
3894 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3896 ULONG *pcUniqueNames,
3897 ULONG *pcchUniqueNames)
3899 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3901 FIXME("(%p): stub!\n", This);
3903 if(pcUniqueNames) *pcUniqueNames=1;
3904 if(pcchUniqueNames) *pcchUniqueNames=1;
3908 /* ITypeLib2::GetDocumentation2
3910 * Retrieves the library's documentation string, the complete Help file name
3911 * and path, the localization context to use, and the context ID for the
3912 * library Help topic in the Help file.
3915 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3919 BSTR *pbstrHelpString,
3920 DWORD *pdwHelpStringContext,
3921 BSTR *pbstrHelpStringDll)
3923 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3927 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3929 /* the help string should be obtained from the helpstringdll,
3930 * using the _DLLGetDocumentation function, based on the supplied
3931 * lcid. Nice to do sometime...
3935 /* documentation for the typelib */
3937 *pbstrHelpString=SysAllocString(This->DocString);
3938 if(pdwHelpStringContext)
3939 *pdwHelpStringContext=This->dwHelpContext;
3940 if(pbstrHelpStringDll)
3941 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3947 /* for a typeinfo */
3948 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3950 if(SUCCEEDED(result))
3952 ITypeInfo2 * pTInfo2;
3953 result = ITypeInfo_QueryInterface(pTInfo,
3955 (LPVOID*) &pTInfo2);
3957 if(SUCCEEDED(result))
3959 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3963 pdwHelpStringContext,
3964 pbstrHelpStringDll);
3966 ITypeInfo2_Release(pTInfo2);
3969 ITypeInfo_Release(pTInfo);
3975 /* ITypeLib2::GetAllCustData
3977 * Gets all custom data items for the library.
3980 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3982 CUSTDATA *pCustData)
3984 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3985 TLBCustData *pCData;
3987 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3988 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3989 if(pCustData->prgCustData ){
3990 pCustData->cCustData=This->ctCustData;
3991 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3992 pCustData->prgCustData[i].guid=pCData->guid;
3993 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3996 ERR(" OUT OF MEMORY!\n");
3997 return E_OUTOFMEMORY;
4002 static const ITypeLib2Vtbl tlbvt = {
4003 ITypeLib2_fnQueryInterface,
4005 ITypeLib2_fnRelease,
4006 ITypeLib2_fnGetTypeInfoCount,
4007 ITypeLib2_fnGetTypeInfo,
4008 ITypeLib2_fnGetTypeInfoType,
4009 ITypeLib2_fnGetTypeInfoOfGuid,
4010 ITypeLib2_fnGetLibAttr,
4011 ITypeLib2_fnGetTypeComp,
4012 ITypeLib2_fnGetDocumentation,
4014 ITypeLib2_fnFindName,
4015 ITypeLib2_fnReleaseTLibAttr,
4017 ITypeLib2_fnGetCustData,
4018 ITypeLib2_fnGetLibStatistics,
4019 ITypeLib2_fnGetDocumentation2,
4020 ITypeLib2_fnGetAllCustData
4024 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4026 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4028 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4031 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4033 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4035 return ITypeLib2_AddRef((ITypeLib2 *)This);
4038 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4040 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4042 return ITypeLib2_Release((ITypeLib2 *)This);
4045 static HRESULT WINAPI ITypeLibComp_fnBind(
4050 ITypeInfo ** ppTInfo,
4051 DESCKIND * pDescKind,
4054 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4055 ITypeInfoImpl *pTypeInfo;
4057 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4059 *pDescKind = DESCKIND_NONE;
4060 pBindPtr->lptcomp = NULL;
4063 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4065 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4067 /* FIXME: check wFlags here? */
4068 /* FIXME: we should use a hash table to look this info up using lHash
4069 * instead of an O(n) search */
4070 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4071 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4073 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4075 *pDescKind = DESCKIND_TYPECOMP;
4076 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4077 ITypeComp_AddRef(pBindPtr->lptcomp);
4078 TRACE("module or enum: %s\n", debugstr_w(szName));
4083 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4084 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4086 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4089 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4090 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4092 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4097 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4098 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4100 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4102 ITypeInfo *subtypeinfo;
4104 DESCKIND subdesckind;
4106 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4107 &subtypeinfo, &subdesckind, &subbindptr);
4108 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4110 TYPEDESC tdesc_appobject =
4113 (TYPEDESC *)pTypeInfo->hreftype
4117 const VARDESC vardesc_appobject =
4120 NULL, /* lpstrSchema */
4135 VAR_STATIC /* varkind */
4138 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4140 /* cleanup things filled in by Bind call so we can put our
4141 * application object data in there instead */
4142 switch (subdesckind)
4144 case DESCKIND_FUNCDESC:
4145 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4147 case DESCKIND_VARDESC:
4148 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4153 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4155 if (pTypeInfo->hreftype == -1)
4156 FIXME("no hreftype for interface %p\n", pTypeInfo);
4158 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4162 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4163 *ppTInfo = (ITypeInfo *)pTypeInfo;
4164 ITypeInfo_AddRef(*ppTInfo);
4170 TRACE("name not found %s\n", debugstr_w(szName));
4174 static HRESULT WINAPI ITypeLibComp_fnBindType(
4178 ITypeInfo ** ppTInfo,
4179 ITypeComp ** ppTComp)
4181 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4185 static const ITypeCompVtbl tlbtcvt =
4188 ITypeLibComp_fnQueryInterface,
4189 ITypeLibComp_fnAddRef,
4190 ITypeLibComp_fnRelease,
4192 ITypeLibComp_fnBind,
4193 ITypeLibComp_fnBindType
4196 /*================== ITypeInfo(2) Methods ===================================*/
4197 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4199 ITypeInfoImpl * pTypeInfoImpl;
4201 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4204 pTypeInfoImpl->lpVtbl = &tinfvt;
4205 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4206 pTypeInfoImpl->ref=1;
4207 pTypeInfoImpl->hreftype = -1;
4209 TRACE("(%p)\n", pTypeInfoImpl);
4210 return (ITypeInfo2*) pTypeInfoImpl;
4213 /* ITypeInfo::QueryInterface
4215 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4220 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4222 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4225 if(IsEqualIID(riid, &IID_IUnknown) ||
4226 IsEqualIID(riid,&IID_ITypeInfo)||
4227 IsEqualIID(riid,&IID_ITypeInfo2))
4231 ITypeInfo_AddRef(iface);
4232 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4235 TRACE("-- Interface: E_NOINTERFACE\n");
4236 return E_NOINTERFACE;
4239 /* ITypeInfo::AddRef
4241 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4243 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4244 ULONG ref = InterlockedIncrement(&This->ref);
4246 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4248 TRACE("(%p)->ref is %lu\n",This, ref);
4252 /* ITypeInfo::Release
4254 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4256 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4257 ULONG ref = InterlockedDecrement(&This->ref);
4259 TRACE("(%p)->(%lu)\n",This, ref);
4262 /* We don't release ITypeLib when ref=0 because
4263 it means that function is called by ITypeLib2_Release */
4264 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4266 static int once = 0;
4270 FIXME("destroy child objects\n");
4273 TRACE("destroying ITypeInfo(%p)\n",This);
4276 SysFreeString(This->Name);
4280 if (This->DocString)
4282 SysFreeString(This->DocString);
4283 This->DocString = 0;
4288 SysFreeString(This->DllName);
4294 ITypeInfo_Release((ITypeInfo*)This->next);
4297 HeapFree(GetProcessHeap(),0,This);
4303 /* ITypeInfo::GetTypeAttr
4305 * Retrieves a TYPEATTR structure that contains the attributes of the type
4309 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4310 LPTYPEATTR *ppTypeAttr)
4312 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4315 TRACE("(%p)\n",This);
4317 size = sizeof(**ppTypeAttr);
4318 if (This->TypeAttr.typekind == TKIND_ALIAS)
4319 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4321 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4323 return E_OUTOFMEMORY;
4325 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4327 if (This->TypeAttr.typekind == TKIND_ALIAS)
4328 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4329 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4331 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4332 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4334 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4335 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4340 /* ITypeInfo::GetTypeComp
4342 * Retrieves the ITypeComp interface for the type description, which enables a
4343 * client compiler to bind to the type description's members.
4346 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4347 ITypeComp * *ppTComp)
4349 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4351 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4353 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4354 ITypeComp_AddRef(*ppTComp);
4358 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4360 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4361 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4362 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4366 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4368 memcpy(dest, src, sizeof(ELEMDESC));
4369 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4370 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4372 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4373 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4374 *buffer += sizeof(PARAMDESCEX);
4375 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4376 VariantInit(&pparamdescex_dest->varDefaultValue);
4377 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4378 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4381 dest->u.paramdesc.pparamdescex = NULL;
4385 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4387 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4388 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4391 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4395 SIZE_T size = sizeof(*src);
4399 size += sizeof(*src->lprgscode) * src->cScodes;
4400 size += TLB_SizeElemDesc(&src->elemdescFunc);
4401 for (i = 0; i < src->cParams; i++)
4403 size += sizeof(ELEMDESC);
4404 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4407 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4408 if (!dest) return E_OUTOFMEMORY;
4410 memcpy(dest, src, sizeof(FUNCDESC));
4411 buffer = (char *)(dest + 1);
4413 dest->lprgscode = (SCODE *)buffer;
4414 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4415 buffer += sizeof(*src->lprgscode) * src->cScodes;
4417 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4420 SysFreeString((BSTR)dest);
4424 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4425 buffer += sizeof(ELEMDESC) * src->cParams;
4426 for (i = 0; i < src->cParams; i++)
4428 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4434 /* undo the above actions */
4435 for (i = i - 1; i >= 0; i--)
4436 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4437 TLB_FreeElemDesc(&dest->elemdescFunc);
4438 SysFreeString((BSTR)dest);
4442 /* special treatment for dispinterfaces: this makes functions appear
4443 * to return their [retval] value when it is really returning an
4445 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4447 if (dest->cParams &&
4448 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4450 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4451 if (elemdesc->tdesc.vt != VT_PTR)
4453 ERR("elemdesc should have started with VT_PTR instead of:\n");
4455 dump_ELEMDESC(elemdesc);
4456 return E_UNEXPECTED;
4459 /* copy last parameter to the return value. we are using a flat
4460 * buffer so there is no danger of leaking memory in
4462 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4464 /* remove the last parameter */
4468 /* otherwise this function is made to appear to have no return
4470 dest->elemdescFunc.tdesc.vt = VT_VOID;
4478 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4480 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4481 const TLBFuncDesc *pFDesc;
4484 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4489 *ppFuncDesc = &pFDesc->funcdesc;
4493 return E_INVALIDARG;
4496 /* ITypeInfo::GetFuncDesc
4498 * Retrieves the FUNCDESC structure that contains information about a
4499 * specified function.
4502 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4503 LPFUNCDESC *ppFuncDesc)
4505 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4506 const FUNCDESC *internal_funcdesc;
4509 TRACE("(%p) index %d\n", This, index);
4511 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4515 return TLB_AllocAndInitFuncDesc(
4518 This->TypeAttr.typekind == TKIND_DISPATCH);
4521 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4525 SIZE_T size = sizeof(*src);
4528 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4529 if (src->varkind == VAR_CONST)
4530 size += sizeof(VARIANT);
4531 size += TLB_SizeElemDesc(&src->elemdescVar);
4533 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4534 if (!dest) return E_OUTOFMEMORY;
4537 buffer = (char *)(dest + 1);
4538 if (src->lpstrSchema)
4541 dest->lpstrSchema = (LPOLESTR)buffer;
4542 len = strlenW(src->lpstrSchema);
4543 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4544 buffer += (len + 1) * sizeof(WCHAR);
4547 if (src->varkind == VAR_CONST)
4551 dest->u.lpvarValue = (VARIANT *)buffer;
4552 *dest->u.lpvarValue = *src->u.lpvarValue;
4553 buffer += sizeof(VARIANT);
4554 VariantInit(dest->u.lpvarValue);
4555 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4558 SysFreeString((BSTR)dest_ptr);
4562 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4565 if (src->varkind == VAR_CONST)
4566 VariantClear(dest->u.lpvarValue);
4567 SysFreeString((BSTR)dest);
4574 /* ITypeInfo::GetVarDesc
4576 * Retrieves a VARDESC structure that describes the specified variable.
4579 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4580 LPVARDESC *ppVarDesc)
4582 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4584 const TLBVarDesc *pVDesc;
4586 TRACE("(%p) index %d\n", This, index);
4588 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4592 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4594 return E_INVALIDARG;
4597 /* ITypeInfo_GetNames
4599 * Retrieves the variable with the specified member ID (or the name of the
4600 * property or method and its parameters) that correspond to the specified
4603 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4604 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4606 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4607 const TLBFuncDesc *pFDesc;
4608 const TLBVarDesc *pVDesc;
4610 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4611 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4614 /* function found, now return function and parameter names */
4615 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4618 *rgBstrNames=SysAllocString(pFDesc->Name);
4620 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4626 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4629 *rgBstrNames=SysAllocString(pVDesc->Name);
4634 if(This->TypeAttr.cImplTypes &&
4635 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4636 /* recursive search */
4639 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4641 if(SUCCEEDED(result))
4643 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4644 ITypeInfo_Release(pTInfo);
4647 WARN("Could not search inherited interface!\n");
4651 WARN("no names found\n");
4654 return TYPE_E_ELEMENTNOTFOUND;
4661 /* ITypeInfo::GetRefTypeOfImplType
4663 * If a type description describes a COM class, it retrieves the type
4664 * description of the implemented interface types. For an interface,
4665 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4669 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4674 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4677 const TLBImplType *pImpl = This->impltypelist;
4679 TRACE("(%p) index %d\n", This, index);
4680 if (TRACE_ON(ole)) dump_TypeInfo(This);
4684 /* only valid on dual interfaces;
4685 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4687 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4689 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4690 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4696 hr = TYPE_E_ELEMENTNOTFOUND;
4701 /* get element n from linked list */
4702 for(i=0; pImpl && i<index; i++)
4704 pImpl = pImpl->next;
4708 *pRefType = pImpl->hRef;
4710 hr = TYPE_E_ELEMENTNOTFOUND;
4716 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4718 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4724 /* ITypeInfo::GetImplTypeFlags
4726 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4727 * or base interface in a type description.
4729 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4730 UINT index, INT *pImplTypeFlags)
4732 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4736 TRACE("(%p) index %d\n", This, index);
4737 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4738 i++, pImpl=pImpl->next)
4740 if(i==index && pImpl){
4741 *pImplTypeFlags=pImpl->implflags;
4745 return TYPE_E_ELEMENTNOTFOUND;
4749 * Maps between member names and member IDs, and parameter names and
4752 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4753 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4755 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4756 const TLBFuncDesc *pFDesc;
4757 const TLBVarDesc *pVDesc;
4761 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4764 /* init out parameters in case of failure */
4765 for (i = 0; i < cNames; i++)
4766 pMemId[i] = MEMBERID_NIL;
4768 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4770 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4771 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4772 for(i=1; i < cNames; i++){
4773 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4774 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4776 if( j<pFDesc->funcdesc.cParams)
4779 ret=DISP_E_UNKNOWNNAME;
4781 TRACE("-- 0x%08lx\n", ret);
4785 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4786 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4787 if(cNames) *pMemId=pVDesc->vardesc.memid;
4791 /* not found, see if it can be found in an inherited interface */
4792 if(This->TypeAttr.cImplTypes) {
4793 /* recursive search */
4795 ret=ITypeInfo_GetRefTypeInfo(iface,
4796 This->impltypelist->hRef, &pTInfo);
4798 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4799 ITypeInfo_Release(pTInfo);
4802 WARN("Could not search inherited interface!\n");
4804 WARN("no names found\n");
4805 return DISP_E_UNKNOWNNAME;
4808 /* ITypeInfo::Invoke
4810 * Invokes a method, or accesses a property of an object, that implements the
4811 * interface described by the type description.
4814 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4817 if (TRACE_ON(ole)) {
4819 TRACE("Calling %p(",func);
4820 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4832 res = func(args[0]);
4835 res = func(args[0],args[1]);
4838 res = func(args[0],args[1],args[2]);
4841 res = func(args[0],args[1],args[2],args[3]);
4844 res = func(args[0],args[1],args[2],args[3],args[4]);
4847 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4850 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4853 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4856 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4859 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4862 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4865 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]);
4868 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]);
4871 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]);
4874 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]);
4877 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]);
4880 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]);
4883 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]);
4886 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]);
4889 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]);
4892 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]);
4895 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]);
4898 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]);
4901 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4907 FIXME("unsupported calling convention %d\n",callconv);
4911 TRACE("returns %08lx\n",res);
4915 extern int _argsize(DWORD vt);
4917 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4920 ITypeInfo *tinfo2 = NULL;
4921 TYPEATTR *tattr = NULL;
4923 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4926 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4928 tdesc->u.hreftype, hr);
4931 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4934 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4935 ITypeInfo_Release(tinfo2);
4939 switch (tattr->typekind)
4946 tdesc = &tattr->tdescAlias;
4947 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4950 case TKIND_INTERFACE:
4951 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4957 case TKIND_DISPATCH:
4962 FIXME("TKIND_RECORD unhandled.\n");
4967 FIXME("TKIND_RECORD unhandled.\n");
4972 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4976 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4977 ITypeInfo_Release(tinfo2);
4981 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4985 /* enforce only one level of pointer indirection */
4986 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
4988 tdesc = tdesc->u.lptdesc;
4990 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4991 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4992 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4993 if ((tdesc->vt == VT_USERDEFINED) ||
4994 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4996 VARTYPE vt_userdefined = 0;
4997 const TYPEDESC *tdesc_userdefined = tdesc;
4998 if (tdesc->vt == VT_PTR)
5000 vt_userdefined = VT_BYREF;
5001 tdesc_userdefined = tdesc->u.lptdesc;
5003 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5005 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5006 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5008 *vt |= vt_userdefined;
5020 case VT_USERDEFINED:
5021 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5028 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5029 hr = DISP_E_BADVARTYPE;
5033 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5042 /***********************************************************************
5043 * DispCallFunc (OLEAUT32.@)
5045 * Invokes a function of the specifed calling convention, passing the
5046 * specified arguments and returns the result.
5049 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5050 * oVft [I] The offset in the vtable. See notes.
5051 * cc [I] Calling convention of the function to call.
5052 * vtReturn [I] The return type of the function.
5053 * cActuals [I] Number of parameters.
5054 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5055 * prgpvarg [I] The arguments to pass.
5056 * pvargResult [O] The return value of the function. Can be NULL.
5060 * Failure: HRESULT code.
5063 * The HRESULT return value of this function is not affected by the return
5064 * value of the user supplied function, which is returned in pvargResult.
5066 * If pvInstance is NULL then a non-object function is to be called and oVft
5067 * is the address of the function to call.
5069 * The cc parameter can be one of the following values:
5082 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5083 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5085 int i, argsize, argspos;
5089 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5090 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5091 pvargResult, V_VT(pvargResult));
5095 argsize++; /* for This pointer */
5097 for (i=0;i<cActuals;i++)
5099 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5100 dump_Variant(prgpvarg[i]);
5101 argsize += _argsize(prgvt[i]);
5103 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5108 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5112 for (i=0;i<cActuals;i++)
5114 VARIANT *arg = prgpvarg[i];
5115 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5116 if (prgvt[i] == VT_VARIANT)
5117 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5119 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5120 argspos += _argsize(prgvt[i]);
5125 FARPROC *vtable = *(FARPROC**)pvInstance;
5126 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5129 /* if we aren't invoking an object then the function pointer is stored
5131 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5133 if (pvargResult && (vtReturn != VT_EMPTY))
5135 TRACE("Method returned 0x%08lx\n",hres);
5136 V_VT(pvargResult) = vtReturn;
5137 V_UI4(pvargResult) = hres;
5140 HeapFree(GetProcessHeap(),0,args);
5144 #define INVBUF_ELEMENT_SIZE \
5145 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5146 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5147 ((VARIANTARG *)(buffer))
5148 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5149 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5150 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5151 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5152 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5153 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5155 static HRESULT WINAPI ITypeInfo_fnInvoke(
5160 DISPPARAMS *pDispParams,
5161 VARIANT *pVarResult,
5162 EXCEPINFO *pExcepInfo,
5165 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5167 unsigned int var_index;
5170 const TLBFuncDesc *pFuncInfo;
5172 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5173 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5175 dump_DispParms(pDispParams);
5177 /* we do this instead of using GetFuncDesc since it will return a fake
5178 * FUNCDESC for dispinterfaces and we want the real function description */
5179 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5180 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5184 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5188 TRACE("invoking:\n");
5189 dump_TLBFuncDescOne(pFuncInfo);
5192 switch (func_desc->funckind) {
5193 case FUNC_PUREVIRTUAL:
5194 case FUNC_VIRTUAL: {
5195 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5197 VARIANT retval; /* pointer for storing byref retvals in */
5198 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5199 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5200 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5203 for (i = 0; i < func_desc->cParams; i++)
5205 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5206 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5211 TRACE("changing args\n");
5212 for (i = 0; i < func_desc->cParams; i++)
5214 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5216 if (wParamFlags & PARAMFLAG_FRETVAL)
5218 /* note: this check is placed so that if the caller passes
5219 * in a VARIANTARG for the retval we just ignore it, like
5221 if (i == func_desc->cParams - 1)
5224 arg = prgpvarg[i] = &rgvarg[i];
5225 memset(arg, 0, sizeof(*arg));
5226 V_VT(arg) = rgvt[i];
5227 memset(&retval, 0, sizeof(retval));
5228 V_BYREF(arg) = &retval;
5232 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5233 hres = E_UNEXPECTED;
5237 else if (i < pDispParams->cArgs)
5239 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5240 dump_Variant(src_arg);
5242 if (rgvt[i] == VT_VARIANT)
5243 VariantCopy(&rgvarg[i], src_arg);
5244 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5246 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5247 V_VT(&missing_arg[i]) = V_VT(src_arg);
5248 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5249 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5250 V_VT(&rgvarg[i]) = rgvt[i];
5254 /* FIXME: this doesn't work for VT_BYREF arguments if
5255 * they are not the same type as in the paramdesc */
5256 V_VT(&rgvarg[i]) = V_VT(src_arg);
5257 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5258 V_VT(&rgvarg[i]) = rgvt[i];
5263 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5264 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5265 debugstr_VT(src_arg), debugstr_VF(src_arg));
5268 prgpvarg[i] = &rgvarg[i];
5270 else if (wParamFlags & PARAMFLAG_FOPT)
5273 arg = prgpvarg[i] = &rgvarg[i];
5274 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5276 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5282 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5283 V_VT(arg) = VT_VARIANT | VT_BYREF;
5284 V_VARIANTREF(arg) = &missing_arg[i];
5285 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5286 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5291 hres = DISP_E_BADPARAMCOUNT;
5295 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5296 if (func_desc->cParamsOpt < 0)
5298 FIXME("Does not support safearray optional parameters\n");
5299 hres = DISP_E_BADPARAMCOUNT;
5300 goto func_fail; /* FIXME: we don't free changed types here */
5303 V_VT(&varresult) = 0;
5304 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5305 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5307 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5308 V_VT(&varresult), func_desc->cParams, rgvt,
5309 prgpvarg, &varresult);
5311 for (i = 0; i < func_desc->cParams; i++)
5313 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5314 if (wParamFlags & PARAMFLAG_FRETVAL)
5318 TRACE("[retval] value: ");
5319 dump_Variant(prgpvarg[i]);
5323 /* deref return value */
5324 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5326 /* free data stored in varresult. Note that
5327 * VariantClear doesn't do what we want because we are
5328 * working with byref types. */
5329 /* FIXME: clear safearrays, bstrs, records and
5330 * variants here too */
5331 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5332 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5334 if(*V_UNKNOWNREF(prgpvarg[i]))
5335 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5339 else if (i < pDispParams->cArgs)
5341 if (wParamFlags & PARAMFLAG_FOUT)
5343 hres = VariantChangeType(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i],
5345 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5348 ERR("failed to convert param %d to vt %d\n", i,
5349 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5353 VariantClear(&rgvarg[i]);
5355 else if (wParamFlags & PARAMFLAG_FOPT)
5357 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5358 VariantClear(&rgvarg[i]);
5362 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5364 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5365 hres = DISP_E_EXCEPTION;
5366 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5370 HeapFree(GetProcessHeap(), 0, buffer);
5373 case FUNC_DISPATCH: {
5376 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5377 if (SUCCEEDED(hres)) {
5378 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5379 hres = IDispatch_Invoke(
5380 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5381 pVarResult,pExcepInfo,pArgErr
5384 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5385 IDispatch_Release(disp);
5387 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5391 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5396 TRACE("-- 0x%08lx\n", hres);
5399 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5402 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5403 if(FAILED(hres)) return hres;
5405 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5406 dump_VARDESC(var_desc);
5407 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5411 /* not found, look for it in inherited interfaces */
5412 ITypeInfo2_GetTypeKind(iface, &type_kind);
5413 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5415 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5416 /* recursive search */
5418 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5419 if(SUCCEEDED(hres)){
5420 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5421 ITypeInfo_Release(pTInfo);
5424 WARN("Could not search inherited interface!\n");
5427 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5428 return DISP_E_MEMBERNOTFOUND;
5431 /* ITypeInfo::GetDocumentation
5433 * Retrieves the documentation string, the complete Help file name and path,
5434 * and the context ID for the Help topic for a specified type description.
5436 * (Can be tested by the Visual Basic Editor in Word for instance.)
5438 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5439 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5440 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5442 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5443 const TLBFuncDesc *pFDesc;
5444 const TLBVarDesc *pVDesc;
5445 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5446 " HelpContext(%p) HelpFile(%p)\n",
5447 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5448 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5450 *pBstrName=SysAllocString(This->Name);
5452 *pBstrDocString=SysAllocString(This->DocString);
5454 *pdwHelpContext=This->dwHelpContext;
5456 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5458 }else {/* for a member */
5459 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5460 if(pFDesc->funcdesc.memid==memid){
5462 *pBstrName = SysAllocString(pFDesc->Name);
5464 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5466 *pdwHelpContext=pFDesc->helpcontext;
5469 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5470 if(pVDesc->vardesc.memid==memid){
5472 *pBstrName = SysAllocString(pVDesc->Name);
5474 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5476 *pdwHelpContext=pVDesc->HelpContext;
5480 WARN("member %ld not found\n", memid);
5481 return TYPE_E_ELEMENTNOTFOUND;
5484 /* ITypeInfo::GetDllEntry
5486 * Retrieves a description or specification of an entry point for a function
5489 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5490 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5493 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5494 const TLBFuncDesc *pFDesc;
5496 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5498 if (pBstrDllName) *pBstrDllName = NULL;
5499 if (pBstrName) *pBstrName = NULL;
5500 if (pwOrdinal) *pwOrdinal = 0;
5502 if (This->TypeAttr.typekind != TKIND_MODULE)
5503 return TYPE_E_BADMODULEKIND;
5505 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5506 if(pFDesc->funcdesc.memid==memid){
5507 dump_TypeInfo(This);
5509 dump_TLBFuncDescOne(pFDesc);
5512 *pBstrDllName = SysAllocString(This->DllName);
5514 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5516 *pBstrName = SysAllocString(pFDesc->Entry);
5524 *pwOrdinal = (DWORD)pFDesc->Entry;
5527 return TYPE_E_ELEMENTNOTFOUND;
5530 /* ITypeInfo::GetRefTypeInfo
5532 * If a type description references other type descriptions, it retrieves
5533 * the referenced type descriptions.
5535 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5538 ITypeInfo **ppTInfo)
5540 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5541 HRESULT result = E_FAIL;
5543 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5545 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5546 ITypeInfo_AddRef(*ppTInfo);
5549 else if (hRefType == -1 &&
5550 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5551 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5553 /* when we meet a DUAL dispinterface, we must create the interface
5556 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5559 /* the interface version contains the same information as the dispinterface
5560 * copy the contents of the structs.
5562 *pTypeInfoImpl = *This;
5563 pTypeInfoImpl->ref = 1;
5565 /* change the type to interface */
5566 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5568 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5570 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5575 TLBRefType *pRefType;
5576 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5577 if(pRefType->reference == hRefType)
5581 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5582 if(pRefType && hRefType != -1) {
5583 ITypeLib *pTLib = NULL;
5585 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5587 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5589 if(pRefType->pImpTLInfo->pImpTypeLib) {
5590 TRACE("typeinfo in imported typelib that is already loaded\n");
5591 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5592 ITypeLib2_AddRef((ITypeLib*) pTLib);
5595 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5596 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5597 pRefType->pImpTLInfo->wVersionMajor,
5598 pRefType->pImpTLInfo->wVersionMinor,
5599 pRefType->pImpTLInfo->lcid,
5602 if(!SUCCEEDED(result)) {
5603 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5604 result=LoadTypeLib(libnam, &pTLib);
5605 SysFreeString(libnam);
5607 if(SUCCEEDED(result)) {
5608 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5609 ITypeLib2_AddRef(pTLib);
5613 if(SUCCEEDED(result)) {
5614 if(pRefType->index == TLB_REF_USE_GUID)
5615 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5619 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5623 ITypeLib2_Release(pTLib);
5627 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5628 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5632 /* ITypeInfo::AddressOfMember
5634 * Retrieves the addresses of static functions or variables, such as those
5637 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5638 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5640 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5646 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5648 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5652 module = LoadLibraryW(dll);
5655 ERR("couldn't load %s\n", debugstr_w(dll));
5657 if (entry) SysFreeString(entry);
5658 return STG_E_FILENOTFOUND;
5660 /* FIXME: store library somewhere where we can free it */
5665 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5666 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5667 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5669 *ppv = GetProcAddress(module, entryA);
5671 ERR("function not found %s\n", debugstr_a(entryA));
5673 HeapFree(GetProcessHeap(), 0, entryA);
5677 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5679 ERR("function not found %d\n", ordinal);
5683 if (entry) SysFreeString(entry);
5686 return TYPE_E_DLLFUNCTIONNOTFOUND;
5691 /* ITypeInfo::CreateInstance
5693 * Creates a new instance of a type that describes a component object class
5696 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5697 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5699 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5700 FIXME("(%p) stub!\n", This);
5704 /* ITypeInfo::GetMops
5706 * Retrieves marshalling information.
5708 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5711 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5712 FIXME("(%p) stub!\n", This);
5716 /* ITypeInfo::GetContainingTypeLib
5718 * Retrieves the containing type library and the index of the type description
5719 * within that type library.
5721 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5722 ITypeLib * *ppTLib, UINT *pIndex)
5724 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5726 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5728 *pIndex=This->index;
5729 TRACE("returning pIndex=%d\n", *pIndex);
5733 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5734 ITypeLib2_AddRef(*ppTLib);
5735 TRACE("returning ppTLib=%p\n", *ppTLib);
5741 /* ITypeInfo::ReleaseTypeAttr
5743 * Releases a TYPEATTR previously returned by GetTypeAttr.
5746 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5747 TYPEATTR* pTypeAttr)
5749 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5750 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5751 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5754 /* ITypeInfo::ReleaseFuncDesc
5756 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5758 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5760 FUNCDESC *pFuncDesc)
5762 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5765 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5767 for (i = 0; i < pFuncDesc->cParams; i++)
5768 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5769 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5771 SysFreeString((BSTR)pFuncDesc);
5774 /* ITypeInfo::ReleaseVarDesc
5776 * Releases a VARDESC previously returned by GetVarDesc.
5778 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5781 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5782 TRACE("(%p)->(%p)\n", This, pVarDesc);
5784 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5785 if (pVarDesc->varkind == VAR_CONST)
5786 VariantClear(pVarDesc->u.lpvarValue);
5787 SysFreeString((BSTR)pVarDesc);
5790 /* ITypeInfo2::GetTypeKind
5792 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5795 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5796 TYPEKIND *pTypeKind)
5798 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5799 *pTypeKind=This->TypeAttr.typekind;
5800 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5804 /* ITypeInfo2::GetTypeFlags
5806 * Returns the type flags without any allocations. This returns a DWORD type
5807 * flag, which expands the type flags without growing the TYPEATTR (type
5811 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5813 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5814 *pTypeFlags=This->TypeAttr.wTypeFlags;
5815 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5819 /* ITypeInfo2::GetFuncIndexOfMemId
5820 * Binds to a specific member based on a known DISPID, where the member name
5821 * is not known (for example, when binding to a default member).
5824 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5825 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5827 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5828 const TLBFuncDesc *pFuncInfo;
5832 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5833 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5839 result = TYPE_E_ELEMENTNOTFOUND;
5841 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5842 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5846 /* TypeInfo2::GetVarIndexOfMemId
5848 * Binds to a specific member based on a known DISPID, where the member name
5849 * is not known (for example, when binding to a default member).
5852 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5853 MEMBERID memid, UINT *pVarIndex)
5855 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5856 TLBVarDesc *pVarInfo;
5859 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5860 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5866 result = TYPE_E_ELEMENTNOTFOUND;
5868 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5869 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5873 /* ITypeInfo2::GetCustData
5875 * Gets the custom data
5877 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5882 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5883 TLBCustData *pCData;
5885 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5886 if( IsEqualIID(guid, &pCData->guid)) break;
5888 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5892 VariantInit( pVarVal);
5893 VariantCopy( pVarVal, &pCData->data);
5896 return E_INVALIDARG; /* FIXME: correct? */
5899 /* ITypeInfo2::GetFuncCustData
5901 * Gets the custom data
5903 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5909 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5910 TLBCustData *pCData=NULL;
5911 TLBFuncDesc * pFDesc;
5913 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5914 pFDesc=pFDesc->next);
5917 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5918 if( IsEqualIID(guid, &pCData->guid)) break;
5920 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5923 VariantInit( pVarVal);
5924 VariantCopy( pVarVal, &pCData->data);
5927 return E_INVALIDARG; /* FIXME: correct? */
5930 /* ITypeInfo2::GetParamCustData
5932 * Gets the custom data
5934 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5941 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5942 TLBCustData *pCData=NULL;
5943 TLBFuncDesc * pFDesc;
5946 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5948 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5949 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5950 pCData = pCData->next)
5951 if( IsEqualIID(guid, &pCData->guid)) break;
5953 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5957 VariantInit( pVarVal);
5958 VariantCopy( pVarVal, &pCData->data);
5961 return E_INVALIDARG; /* FIXME: correct? */
5964 /* ITypeInfo2::GetVarCustData
5966 * Gets the custom data
5968 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5974 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5975 TLBCustData *pCData=NULL;
5976 TLBVarDesc * pVDesc;
5979 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5983 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5985 if( IsEqualIID(guid, &pCData->guid)) break;
5989 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5993 VariantInit( pVarVal);
5994 VariantCopy( pVarVal, &pCData->data);
5997 return E_INVALIDARG; /* FIXME: correct? */
6000 /* ITypeInfo2::GetImplCustData
6002 * Gets the custom data
6004 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6010 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6011 TLBCustData *pCData=NULL;
6012 TLBImplType * pRDesc;
6015 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6019 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6021 if( IsEqualIID(guid, &pCData->guid)) break;
6025 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6029 VariantInit( pVarVal);
6030 VariantCopy( pVarVal, &pCData->data);
6033 return E_INVALIDARG; /* FIXME: correct? */
6036 /* ITypeInfo2::GetDocumentation2
6038 * Retrieves the documentation string, the complete Help file name and path,
6039 * the localization context to use, and the context ID for the library Help
6040 * topic in the Help file.
6043 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6047 BSTR *pbstrHelpString,
6048 DWORD *pdwHelpStringContext,
6049 BSTR *pbstrHelpStringDll)
6051 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6052 const TLBFuncDesc *pFDesc;
6053 const TLBVarDesc *pVDesc;
6054 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6055 "HelpStringContext(%p) HelpStringDll(%p)\n",
6056 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6057 pbstrHelpStringDll );
6058 /* the help string should be obtained from the helpstringdll,
6059 * using the _DLLGetDocumentation function, based on the supplied
6060 * lcid. Nice to do sometime...
6062 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6064 *pbstrHelpString=SysAllocString(This->Name);
6065 if(pdwHelpStringContext)
6066 *pdwHelpStringContext=This->dwHelpStringContext;
6067 if(pbstrHelpStringDll)
6068 *pbstrHelpStringDll=
6069 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6071 }else {/* for a member */
6072 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6073 if(pFDesc->funcdesc.memid==memid){
6075 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6076 if(pdwHelpStringContext)
6077 *pdwHelpStringContext=pFDesc->HelpStringContext;
6078 if(pbstrHelpStringDll)
6079 *pbstrHelpStringDll=
6080 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6083 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6084 if(pVDesc->vardesc.memid==memid){
6086 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6087 if(pdwHelpStringContext)
6088 *pdwHelpStringContext=pVDesc->HelpStringContext;
6089 if(pbstrHelpStringDll)
6090 *pbstrHelpStringDll=
6091 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6095 return TYPE_E_ELEMENTNOTFOUND;
6098 /* ITypeInfo2::GetAllCustData
6100 * Gets all custom data items for the Type info.
6103 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6105 CUSTDATA *pCustData)
6107 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6108 TLBCustData *pCData;
6111 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6113 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6114 if(pCustData->prgCustData ){
6115 pCustData->cCustData=This->ctCustData;
6116 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6117 pCustData->prgCustData[i].guid=pCData->guid;
6118 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6121 ERR(" OUT OF MEMORY!\n");
6122 return E_OUTOFMEMORY;
6127 /* ITypeInfo2::GetAllFuncCustData
6129 * Gets all custom data items for the specified Function
6132 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6135 CUSTDATA *pCustData)
6137 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6138 TLBCustData *pCData;
6139 TLBFuncDesc * pFDesc;
6141 TRACE("(%p) index %d\n", This, index);
6142 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6143 pFDesc=pFDesc->next)
6146 pCustData->prgCustData =
6147 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6148 if(pCustData->prgCustData ){
6149 pCustData->cCustData=pFDesc->ctCustData;
6150 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6151 pCData = pCData->next){
6152 pCustData->prgCustData[i].guid=pCData->guid;
6153 VariantCopy(& pCustData->prgCustData[i].varValue,
6157 ERR(" OUT OF MEMORY!\n");
6158 return E_OUTOFMEMORY;
6162 return TYPE_E_ELEMENTNOTFOUND;
6165 /* ITypeInfo2::GetAllParamCustData
6167 * Gets all custom data items for the Functions
6170 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6171 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6173 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6174 TLBCustData *pCData=NULL;
6175 TLBFuncDesc * pFDesc;
6177 TRACE("(%p) index %d\n", This, indexFunc);
6178 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6179 pFDesc=pFDesc->next)
6181 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6182 pCustData->prgCustData =
6183 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6184 sizeof(CUSTDATAITEM));
6185 if(pCustData->prgCustData ){
6186 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6187 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6188 pCData; i++, pCData = pCData->next){
6189 pCustData->prgCustData[i].guid=pCData->guid;
6190 VariantCopy(& pCustData->prgCustData[i].varValue,
6194 ERR(" OUT OF MEMORY!\n");
6195 return E_OUTOFMEMORY;
6199 return TYPE_E_ELEMENTNOTFOUND;
6202 /* ITypeInfo2::GetAllVarCustData
6204 * Gets all custom data items for the specified Variable
6207 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6208 UINT index, CUSTDATA *pCustData)
6210 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6211 TLBCustData *pCData;
6212 TLBVarDesc * pVDesc;
6214 TRACE("(%p) index %d\n", This, index);
6215 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6216 pVDesc=pVDesc->next)
6219 pCustData->prgCustData =
6220 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6221 if(pCustData->prgCustData ){
6222 pCustData->cCustData=pVDesc->ctCustData;
6223 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6224 pCData = pCData->next){
6225 pCustData->prgCustData[i].guid=pCData->guid;
6226 VariantCopy(& pCustData->prgCustData[i].varValue,
6230 ERR(" OUT OF MEMORY!\n");
6231 return E_OUTOFMEMORY;
6235 return TYPE_E_ELEMENTNOTFOUND;
6238 /* ITypeInfo2::GetAllImplCustData
6240 * Gets all custom data items for the specified implementation type
6243 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6246 CUSTDATA *pCustData)
6248 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6249 TLBCustData *pCData;
6250 TLBImplType * pRDesc;
6252 TRACE("(%p) index %d\n", This, index);
6253 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6254 pRDesc=pRDesc->next)
6257 pCustData->prgCustData =
6258 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6259 if(pCustData->prgCustData ){
6260 pCustData->cCustData=pRDesc->ctCustData;
6261 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6262 pCData = pCData->next){
6263 pCustData->prgCustData[i].guid=pCData->guid;
6264 VariantCopy(& pCustData->prgCustData[i].varValue,
6268 ERR(" OUT OF MEMORY!\n");
6269 return E_OUTOFMEMORY;
6273 return TYPE_E_ELEMENTNOTFOUND;
6276 static const ITypeInfo2Vtbl tinfvt =
6279 ITypeInfo_fnQueryInterface,
6281 ITypeInfo_fnRelease,
6283 ITypeInfo_fnGetTypeAttr,
6284 ITypeInfo_fnGetTypeComp,
6285 ITypeInfo_fnGetFuncDesc,
6286 ITypeInfo_fnGetVarDesc,
6287 ITypeInfo_fnGetNames,
6288 ITypeInfo_fnGetRefTypeOfImplType,
6289 ITypeInfo_fnGetImplTypeFlags,
6290 ITypeInfo_fnGetIDsOfNames,
6292 ITypeInfo_fnGetDocumentation,
6293 ITypeInfo_fnGetDllEntry,
6294 ITypeInfo_fnGetRefTypeInfo,
6295 ITypeInfo_fnAddressOfMember,
6296 ITypeInfo_fnCreateInstance,
6297 ITypeInfo_fnGetMops,
6298 ITypeInfo_fnGetContainingTypeLib,
6299 ITypeInfo_fnReleaseTypeAttr,
6300 ITypeInfo_fnReleaseFuncDesc,
6301 ITypeInfo_fnReleaseVarDesc,
6303 ITypeInfo2_fnGetTypeKind,
6304 ITypeInfo2_fnGetTypeFlags,
6305 ITypeInfo2_fnGetFuncIndexOfMemId,
6306 ITypeInfo2_fnGetVarIndexOfMemId,
6307 ITypeInfo2_fnGetCustData,
6308 ITypeInfo2_fnGetFuncCustData,
6309 ITypeInfo2_fnGetParamCustData,
6310 ITypeInfo2_fnGetVarCustData,
6311 ITypeInfo2_fnGetImplTypeCustData,
6312 ITypeInfo2_fnGetDocumentation2,
6313 ITypeInfo2_fnGetAllCustData,
6314 ITypeInfo2_fnGetAllFuncCustData,
6315 ITypeInfo2_fnGetAllParamCustData,
6316 ITypeInfo2_fnGetAllVarCustData,
6317 ITypeInfo2_fnGetAllImplTypeCustData,
6320 /******************************************************************************
6321 * CreateDispTypeInfo [OLEAUT32.31]
6323 * Build type information for an object so it can be called through an
6324 * IDispatch interface.
6327 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6328 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6331 * This call allows an objects methods to be accessed through IDispatch, by
6332 * building an ITypeInfo object that IDispatch can use to call through.
6334 HRESULT WINAPI CreateDispTypeInfo(
6335 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6336 LCID lcid, /* [I] Locale Id */
6337 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6339 ITypeInfoImpl *pTIClass, *pTIIface;
6340 ITypeLibImpl *pTypeLibImpl;
6342 TLBFuncDesc **ppFuncDesc;
6345 pTypeLibImpl = TypeLibImpl_Constructor();
6346 if (!pTypeLibImpl) return E_FAIL;
6348 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6349 pTIIface->pTypeLib = pTypeLibImpl;
6350 pTIIface->index = 0;
6351 pTIIface->Name = NULL;
6352 pTIIface->dwHelpContext = -1;
6353 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6354 pTIIface->TypeAttr.lcid = lcid;
6355 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6356 pTIIface->TypeAttr.wMajorVerNum = 0;
6357 pTIIface->TypeAttr.wMinorVerNum = 0;
6358 pTIIface->TypeAttr.cbAlignment = 2;
6359 pTIIface->TypeAttr.cbSizeInstance = -1;
6360 pTIIface->TypeAttr.cbSizeVft = -1;
6361 pTIIface->TypeAttr.cFuncs = 0;
6362 pTIIface->TypeAttr.cImplTypes = 0;
6363 pTIIface->TypeAttr.cVars = 0;
6364 pTIIface->TypeAttr.wTypeFlags = 0;
6366 ppFuncDesc = &pTIIface->funclist;
6367 for(func = 0; func < pidata->cMembers; func++) {
6368 METHODDATA *md = pidata->pmethdata + func;
6369 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6370 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6371 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6372 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6373 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6374 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6375 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6376 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6377 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6378 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6379 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6380 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6381 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6382 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6383 md->cArgs * sizeof(ELEMDESC));
6384 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6385 md->cArgs * sizeof(TLBParDesc));
6386 for(param = 0; param < md->cArgs; param++) {
6387 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6388 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6390 (*ppFuncDesc)->helpcontext = 0;
6391 (*ppFuncDesc)->HelpStringContext = 0;
6392 (*ppFuncDesc)->HelpString = NULL;
6393 (*ppFuncDesc)->Entry = NULL;
6394 (*ppFuncDesc)->ctCustData = 0;
6395 (*ppFuncDesc)->pCustData = NULL;
6396 (*ppFuncDesc)->next = NULL;
6397 ppFuncDesc = &(*ppFuncDesc)->next;
6400 dump_TypeInfo(pTIIface);
6402 pTypeLibImpl->pTypeInfo = pTIIface;
6403 pTypeLibImpl->TypeInfoCount++;
6405 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6406 pTIClass->pTypeLib = pTypeLibImpl;
6407 pTIClass->index = 1;
6408 pTIClass->Name = NULL;
6409 pTIClass->dwHelpContext = -1;
6410 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6411 pTIClass->TypeAttr.lcid = lcid;
6412 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6413 pTIClass->TypeAttr.wMajorVerNum = 0;
6414 pTIClass->TypeAttr.wMinorVerNum = 0;
6415 pTIClass->TypeAttr.cbAlignment = 2;
6416 pTIClass->TypeAttr.cbSizeInstance = -1;
6417 pTIClass->TypeAttr.cbSizeVft = -1;
6418 pTIClass->TypeAttr.cFuncs = 0;
6419 pTIClass->TypeAttr.cImplTypes = 1;
6420 pTIClass->TypeAttr.cVars = 0;
6421 pTIClass->TypeAttr.wTypeFlags = 0;
6423 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6424 pTIClass->impltypelist->hRef = 1;
6426 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6427 pTIClass->reflist->index = 0;
6428 pTIClass->reflist->reference = 1;
6429 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6431 dump_TypeInfo(pTIClass);
6433 pTIIface->next = pTIClass;
6434 pTypeLibImpl->TypeInfoCount++;
6436 *pptinfo = (ITypeInfo*)pTIClass;
6441 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6443 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6445 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6448 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6450 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6452 return ITypeInfo_AddRef((ITypeInfo *)This);
6455 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6457 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6459 return ITypeInfo_Release((ITypeInfo *)This);
6462 static HRESULT WINAPI ITypeComp_fnBind(
6467 ITypeInfo ** ppTInfo,
6468 DESCKIND * pDescKind,
6471 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6472 const TLBFuncDesc *pFDesc;
6473 const TLBVarDesc *pVDesc;
6475 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6477 *pDescKind = DESCKIND_NONE;
6478 pBindPtr->lpfuncdesc = NULL;
6481 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6482 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6483 if (!strcmpW(pFDesc->Name, szName)) {
6489 HRESULT hr = TLB_AllocAndInitFuncDesc(
6491 &pBindPtr->lpfuncdesc,
6492 This->TypeAttr.typekind == TKIND_DISPATCH);
6495 *pDescKind = DESCKIND_FUNCDESC;
6496 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6497 ITypeInfo_AddRef(*ppTInfo);
6500 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6501 if (!strcmpW(pVDesc->Name, szName)) {
6502 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6505 *pDescKind = DESCKIND_VARDESC;
6506 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6507 ITypeInfo_AddRef(*ppTInfo);
6512 /* FIXME: search each inherited interface, not just the first */
6513 if (This->TypeAttr.cImplTypes) {
6514 /* recursive search */
6518 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6521 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6522 ITypeInfo_Release(pTInfo);
6526 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6527 ITypeComp_Release(pTComp);
6530 WARN("Could not search inherited interface!\n");
6532 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6533 return DISP_E_MEMBERNOTFOUND;
6536 static HRESULT WINAPI ITypeComp_fnBindType(
6540 ITypeInfo ** ppTInfo,
6541 ITypeComp ** ppTComp)
6543 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6545 /* strange behaviour (does nothing) but like the
6548 if (!ppTInfo || !ppTComp)
6557 static const ITypeCompVtbl tcompvt =
6560 ITypeComp_fnQueryInterface,
6562 ITypeComp_fnRelease,
6565 ITypeComp_fnBindType