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(
395 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
399 res= LoadTypeLib(bstr, ppTLib);
403 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
409 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
410 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
411 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
412 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
413 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
414 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
416 /******************************************************************************
417 * RegisterTypeLib [OLEAUT32.163]
418 * Adds information about a type library to the System Registry
420 * Docs: ITypeLib FAR * ptlib
421 * Docs: OLECHAR FAR* szFullPath
422 * Docs: OLECHAR FAR* szHelpDir
428 HRESULT WINAPI RegisterTypeLib(
429 ITypeLib * ptlib, /* [in] Pointer to the library*/
430 OLECHAR * szFullPath, /* [in] full Path of the library*/
431 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
434 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
435 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
436 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
446 if (ptlib == NULL || szFullPath == NULL)
449 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
452 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
455 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
456 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
460 /* Set the human-readable name of the typelib */
461 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
463 if (RegSetValueExW(key, NULL, 0, REG_SZ,
464 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
472 /* Make up the name of the typelib path subkey */
473 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
475 /* Create the typelib path subkey */
476 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
477 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
479 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
480 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
488 /* Create the flags subkey */
489 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
490 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
492 /* FIXME: is %u correct? */
493 static const WCHAR formatW[] = {'%','u',0};
495 sprintfW(buf, formatW, attr->wLibFlags);
496 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
497 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
505 /* create the helpdir subkey */
506 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
507 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
509 BOOL freeHelpDir = FALSE;
512 /* if we created a new key, and helpDir was null, set the helpdir
513 to the directory which contains the typelib. However,
514 if we just opened an existing key, we leave the helpdir alone */
515 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
516 szHelpDir = SysAllocString(szFullPath);
517 pIndexStr = strrchrW(szHelpDir, '\\');
524 /* if we have an szHelpDir, set it! */
525 if (szHelpDir != NULL) {
526 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
527 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
533 if (freeHelpDir) SysFreeString(szHelpDir);
545 /* register OLE Automation-compatible interfaces for this typelib */
546 types = ITypeLib_GetTypeInfoCount(ptlib);
547 for (tidx=0; tidx<types; tidx++) {
548 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
549 LPOLESTR name = NULL;
550 ITypeInfo *tinfo = NULL;
552 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
555 case TKIND_INTERFACE:
556 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
557 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
561 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
562 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
566 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
571 TYPEATTR *tattr = NULL;
572 ITypeInfo_GetTypeAttr(tinfo, &tattr);
575 TRACE_(typelib)("guid=%s, flags=%04x (",
576 debugstr_guid(&tattr->guid),
579 if (TRACE_ON(typelib)) {
580 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
600 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
602 /* register interface<->typelib coupling */
603 get_interface_key( &tattr->guid, keyName );
604 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
605 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
608 RegSetValueExW(key, NULL, 0, REG_SZ,
609 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
611 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
612 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
613 RegSetValueExW(subKey, NULL, 0, REG_SZ,
614 (BYTE*)PSOA, sizeof PSOA);
618 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
619 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
620 RegSetValueExW(subKey, NULL, 0, REG_SZ,
621 (BYTE*)PSOA, sizeof PSOA);
625 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
626 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
629 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
630 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
632 StringFromGUID2(&attr->guid, buffer, 40);
633 RegSetValueExW(subKey, NULL, 0, REG_SZ,
634 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
635 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
636 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
637 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
645 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
648 ITypeInfo_Release(tinfo);
655 ITypeLib_ReleaseTLibAttr(ptlib, attr);
661 /******************************************************************************
662 * UnRegisterTypeLib [OLEAUT32.186]
663 * Removes information about a type library from the System Registry
670 HRESULT WINAPI UnRegisterTypeLib(
671 REFGUID libid, /* [in] Guid of the library */
672 WORD wVerMajor, /* [in] major version */
673 WORD wVerMinor, /* [in] minor version */
674 LCID lcid, /* [in] locale id */
677 BSTR tlibPath = NULL;
680 WCHAR subKeyName[50];
683 BOOL deleteOtherStuff;
686 TYPEATTR* typeAttr = NULL;
688 ITypeInfo* typeInfo = NULL;
689 ITypeLib* typeLib = NULL;
692 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
694 /* Create the path to the key */
695 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
697 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
699 TRACE("Unsupported syskind %i\n", syskind);
700 result = E_INVALIDARG;
704 /* get the path to the typelib on disk */
705 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
706 result = E_INVALIDARG;
710 /* Try and open the key to the type library. */
711 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
712 result = E_INVALIDARG;
716 /* Try and load the type library */
717 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
718 result = TYPE_E_INVALIDSTATE;
722 /* remove any types registered with this typelib */
723 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
724 for (i=0; i<numTypes; i++) {
725 /* get the kind of type */
726 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
730 /* skip non-interfaces, and get type info for the type */
731 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
734 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
737 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
741 /* the path to the type */
742 get_interface_key( &typeAttr->guid, subKeyName );
744 /* Delete its bits */
745 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
748 RegDeleteKeyW(subKey, ProxyStubClsidW);
749 RegDeleteKeyW(subKey, ProxyStubClsid32W);
750 RegDeleteKeyW(subKey, TypeLibW);
753 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
756 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
758 if (typeInfo) ITypeInfo_Release(typeInfo);
762 /* Now, delete the type library path subkey */
763 get_lcid_subkey( lcid, syskind, subKeyName );
764 RegDeleteKeyW(key, subKeyName);
765 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
766 RegDeleteKeyW(key, subKeyName);
768 /* check if there is anything besides the FLAGS/HELPDIR keys.
769 If there is, we don't delete them */
770 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
771 deleteOtherStuff = TRUE;
773 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
774 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
776 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
777 if (!strcmpW(subKeyName, FLAGSW)) continue;
778 if (!strcmpW(subKeyName, HELPDIRW)) continue;
779 deleteOtherStuff = FALSE;
783 /* only delete the other parts of the key if we're absolutely sure */
784 if (deleteOtherStuff) {
785 RegDeleteKeyW(key, FLAGSW);
786 RegDeleteKeyW(key, HELPDIRW);
790 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
791 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
792 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
796 if (tlibPath) SysFreeString(tlibPath);
797 if (typeLib) ITypeLib_Release(typeLib);
798 if (subKey) RegCloseKey(subKey);
799 if (key) RegCloseKey(key);
803 /*======================= ITypeLib implementation =======================*/
805 typedef struct tagTLBCustData
809 struct tagTLBCustData* next;
812 /* data structure for import typelibs */
813 typedef struct tagTLBImpLib
815 int offset; /* offset in the file (MSFT)
816 offset in nametable (SLTG)
817 just used to identify library while reading
819 GUID guid; /* libid */
820 BSTR name; /* name */
822 LCID lcid; /* lcid of imported typelib */
824 WORD wVersionMajor; /* major version number */
825 WORD wVersionMinor; /* minor version number */
827 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
828 NULL if not yet loaded */
829 struct tagTLBImpLib * next;
832 /* internal ITypeLib data */
833 typedef struct tagITypeLibImpl
835 const ITypeLib2Vtbl *lpVtbl;
836 const ITypeCompVtbl *lpVtblTypeComp;
838 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
840 /* strings can be stored in tlb as multibyte strings BUT they are *always*
841 * exported to the application as a UNICODE string.
847 unsigned long dwHelpContext;
848 int TypeInfoCount; /* nr of typeinfo's in librarry */
849 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
850 int ctCustData; /* number of items in cust data list */
851 TLBCustData * pCustData; /* linked list to cust data */
852 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
853 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
854 libary. Only used while read MSFT
857 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
858 struct tagITypeLibImpl *next, *prev;
863 static const ITypeLib2Vtbl tlbvt;
864 static const ITypeCompVtbl tlbtcvt;
866 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
868 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
871 /* ITypeLib methods */
872 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
873 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
875 /*======================= ITypeInfo implementation =======================*/
877 /* data for referenced types */
878 typedef struct tagTLBRefType
880 INT index; /* Type index for internal ref or for external ref
881 it the format is SLTG. -2 indicates to
884 GUID guid; /* guid of the referenced type */
885 /* if index == TLB_REF_USE_GUID */
887 HREFTYPE reference; /* The href of this ref */
888 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
889 TLB_REF_INTERNAL for internal refs
890 TLB_REF_NOT_FOUND for broken refs */
892 struct tagTLBRefType * next;
895 #define TLB_REF_USE_GUID -2
897 #define TLB_REF_INTERNAL (void*)-2
898 #define TLB_REF_NOT_FOUND (void*)-1
900 /* internal Parameter data */
901 typedef struct tagTLBParDesc
905 TLBCustData * pCustData; /* linked list to cust data */
908 /* internal Function data */
909 typedef struct tagTLBFuncDesc
911 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
912 BSTR Name; /* the name of this function */
913 TLBParDesc *pParamDesc; /* array with param names and custom data */
915 int HelpStringContext;
917 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
919 TLBCustData * pCustData; /* linked list to cust data; */
920 struct tagTLBFuncDesc * next;
923 /* internal Variable data */
924 typedef struct tagTLBVarDesc
926 VARDESC vardesc; /* lots of info on the variable and its attributes. */
927 BSTR Name; /* the name of this variable */
929 int HelpStringContext; /* FIXME: where? */
932 TLBCustData * pCustData;/* linked list to cust data; */
933 struct tagTLBVarDesc * next;
936 /* internal implemented interface data */
937 typedef struct tagTLBImplType
939 HREFTYPE hRef; /* hRef of interface */
940 int implflags; /* IMPLFLAG_*s */
942 TLBCustData * pCustData;/* linked list to custom data; */
943 struct tagTLBImplType *next;
946 /* internal TypeInfo data */
947 typedef struct tagITypeInfoImpl
949 const ITypeInfo2Vtbl *lpVtbl;
950 const ITypeCompVtbl *lpVtblTypeComp;
952 TYPEATTR TypeAttr ; /* _lots_ of type information. */
953 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
954 int index; /* index in this typelib; */
955 HREFTYPE hreftype; /* hreftype for app object binding */
956 /* type libs seem to store the doc strings in ascii
957 * so why should we do it in unicode?
962 unsigned long dwHelpContext;
963 unsigned long dwHelpStringContext;
966 TLBFuncDesc * funclist; /* linked list with function descriptions */
969 TLBVarDesc * varlist; /* linked list with variable descriptions */
971 /* Implemented Interfaces */
972 TLBImplType * impltypelist;
974 TLBRefType * reflist;
976 TLBCustData * pCustData; /* linked list to cust data; */
977 struct tagITypeInfoImpl * next;
980 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
982 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
985 static const ITypeInfo2Vtbl tinfvt;
986 static const ITypeCompVtbl tcompvt;
988 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
990 typedef struct tagTLBContext
992 unsigned int oStart; /* start of TLB in file */
993 unsigned int pos; /* current pos */
994 unsigned int length; /* total length */
995 void *mapping; /* memory mapping */
996 MSFT_SegDir * pTblDir;
997 ITypeLibImpl* pLibInfo;
1001 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1006 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1007 if (pTD->vt & VT_RESERVED)
1008 szVarType += strlen(strcpy(szVarType, "reserved | "));
1009 if (pTD->vt & VT_BYREF)
1010 szVarType += strlen(strcpy(szVarType, "ref to "));
1011 if (pTD->vt & VT_ARRAY)
1012 szVarType += strlen(strcpy(szVarType, "array of "));
1013 if (pTD->vt & VT_VECTOR)
1014 szVarType += strlen(strcpy(szVarType, "vector of "));
1015 switch(pTD->vt & VT_TYPEMASK) {
1016 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1017 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1018 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1019 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1020 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1021 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1022 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1023 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1024 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1025 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1026 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1027 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1028 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1029 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1030 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1031 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1032 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1033 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1034 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1035 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1036 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1037 pTD->u.hreftype); break;
1038 case VT_PTR: sprintf(szVarType, "ptr to ");
1039 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1041 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1042 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1044 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1045 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1046 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1049 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1053 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1055 USHORT flags = edesc->u.paramdesc.wParamFlags;
1056 dump_TypeDesc(&edesc->tdesc,buf);
1057 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1058 MESSAGE("\t\tu.paramdesc.wParamFlags");
1059 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1060 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1061 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1062 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1063 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1064 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1065 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1066 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1067 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1069 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1071 MESSAGE("memid is %08lx\n",funcdesc->memid);
1072 for (i=0;i<funcdesc->cParams;i++) {
1073 MESSAGE("Param %d:\n",i);
1074 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1076 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1077 switch (funcdesc->funckind) {
1078 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1079 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1080 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1081 case FUNC_STATIC: MESSAGE("static");break;
1082 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1083 default: MESSAGE("unknown");break;
1085 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1086 switch (funcdesc->invkind) {
1087 case INVOKE_FUNC: MESSAGE("func");break;
1088 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1089 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1090 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1092 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1093 switch (funcdesc->callconv) {
1094 case CC_CDECL: MESSAGE("cdecl");break;
1095 case CC_PASCAL: MESSAGE("pascal");break;
1096 case CC_STDCALL: MESSAGE("stdcall");break;
1097 case CC_SYSCALL: MESSAGE("syscall");break;
1100 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1101 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1102 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1104 MESSAGE("\telemdescFunc (return value type):\n");
1105 dump_ELEMDESC(&funcdesc->elemdescFunc);
1108 static const char * typekind_desc[] =
1121 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1124 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1125 for (i=0;i<pfd->funcdesc.cParams;i++)
1126 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1129 dump_FUNCDESC(&(pfd->funcdesc));
1131 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1132 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1134 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1138 dump_TLBFuncDescOne(pfd);
1142 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1146 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1151 static void dump_TLBImpLib(const TLBImpLib *import)
1153 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1154 debugstr_w(import->name));
1155 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1156 import->wVersionMinor, import->lcid, import->offset);
1159 static void dump_TLBRefType(const TLBRefType * prt)
1163 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1164 if(prt->index == -1)
1165 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1167 TRACE_(typelib)("type no: %d\n", prt->index);
1169 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1170 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1171 TRACE_(typelib)("in lib\n");
1172 dump_TLBImpLib(prt->pImpTLInfo);
1178 static void dump_TLBImplType(const TLBImplType * impl)
1182 "implementing/inheriting interface hRef = %lx implflags %x\n",
1183 impl->hRef, impl->implflags);
1188 void dump_Variant(const VARIANT * pvar)
1192 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1196 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1197 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1199 TRACE(",%p", V_BYREF(pvar));
1201 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1203 TRACE(",%p", V_ARRAY(pvar));
1205 else switch (V_TYPE(pvar))
1207 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1208 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1209 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1210 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1212 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1214 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1215 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1216 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1217 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1218 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1219 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1220 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1221 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1222 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1223 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1224 V_CY(pvar).s.Lo); break;
1226 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1227 TRACE(",<invalid>");
1229 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1230 st.wHour, st.wMinute, st.wSecond);
1234 case VT_USERDEFINED:
1236 case VT_NULL: break;
1237 default: TRACE(",?"); break;
1243 static void dump_DispParms(const DISPPARAMS * pdp)
1247 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1249 while (index < pdp->cArgs)
1251 dump_Variant( &pdp->rgvarg[index] );
1256 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1258 TRACE("%p ref=%lu\n", pty, pty->ref);
1259 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1260 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1261 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1262 TRACE("fct:%u var:%u impl:%u\n",
1263 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1264 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1265 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1266 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1268 dump_TLBFuncDesc(pty->funclist);
1269 dump_TLBVarDesc(pty->varlist);
1270 dump_TLBImplType(pty->impltypelist);
1273 static void dump_VARDESC(const VARDESC *v)
1275 MESSAGE("memid %ld\n",v->memid);
1276 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1277 MESSAGE("oInst %ld\n",v->u.oInst);
1278 dump_ELEMDESC(&(v->elemdescVar));
1279 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1280 MESSAGE("varkind %d\n",v->varkind);
1283 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1285 /* VT_LPWSTR is largest type that */
1286 /* may appear in type description*/
1287 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1288 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1289 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1290 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1291 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1292 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1296 static void TLB_abort(void)
1300 static void * TLB_Alloc(unsigned size)
1303 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1305 ERR("cannot allocate memory\n");
1310 static void TLB_Free(void * ptr)
1312 HeapFree(GetProcessHeap(), 0, ptr);
1315 /* returns the size required for a deep copy of a typedesc into a
1317 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1321 if (alloc_initial_space)
1322 size += sizeof(TYPEDESC);
1328 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1331 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1332 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1338 /* deep copy a typedesc into a flat buffer */
1339 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1344 buffer = (char *)buffer + sizeof(TYPEDESC);
1353 dest->u.lptdesc = buffer;
1354 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1357 dest->u.lpadesc = buffer;
1358 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1359 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1360 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1366 /**********************************************************************
1368 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1371 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1373 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1374 pcx->pos, count, pcx->oStart, pcx->length, where);
1376 if (where != DO_NOT_SEEK)
1378 where += pcx->oStart;
1379 if (where > pcx->length)
1382 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1387 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1388 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1393 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1398 ret = MSFT_Read(buffer, count, pcx, where);
1399 FromLEDWords(buffer, ret);
1404 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1409 ret = MSFT_Read(buffer, count, pcx, where);
1410 FromLEWords(buffer, ret);
1415 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1417 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1418 memset(pGuid,0, sizeof(GUID));
1421 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1422 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1423 pGuid->Data2 = FromLEWord(pGuid->Data2);
1424 pGuid->Data3 = FromLEWord(pGuid->Data3);
1425 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1428 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1430 MSFT_NameIntro niName;
1434 ERR_(typelib)("bad offset %d\n", offset);
1438 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1439 pcx->pTblDir->pNametab.offset+offset);
1441 return niName.hreftype;
1444 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1447 MSFT_NameIntro niName;
1449 WCHAR* pwstring = NULL;
1450 BSTR bstrName = NULL;
1454 ERR_(typelib)("bad offset %d\n", offset);
1457 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1458 pcx->pTblDir->pNametab.offset+offset);
1459 niName.namelen &= 0xFF; /* FIXME: correct ? */
1460 name=TLB_Alloc((niName.namelen & 0xff) +1);
1461 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1462 name[niName.namelen & 0xff]='\0';
1464 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1467 /* no invalid characters in string */
1470 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1472 /* don't check for invalid character since this has been done previously */
1473 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1475 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1476 lengthInChars = SysStringLen(bstrName);
1477 HeapFree(GetProcessHeap(), 0, pwstring);
1480 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1484 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1491 if(offset<0) return NULL;
1492 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1493 if(length <= 0) return 0;
1494 string=TLB_Alloc(length +1);
1495 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1496 string[length]='\0';
1498 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1499 string, -1, NULL, 0);
1501 /* no invalid characters in string */
1504 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1506 /* don't check for invalid character since this has been done previously */
1507 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1509 bstr = SysAllocStringLen(pwstring, lengthInChars);
1510 lengthInChars = SysStringLen(bstr);
1511 HeapFree(GetProcessHeap(), 0, pwstring);
1514 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1518 * read a value and fill a VARIANT structure
1520 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1524 TRACE_(typelib)("\n");
1526 if(offset <0) { /* data are packed in here */
1527 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1528 V_I4(pVar) = offset & 0x3ffffff;
1531 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1532 pcx->pTblDir->pCustData.offset + offset );
1533 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1534 switch (V_VT(pVar)){
1535 case VT_EMPTY: /* FIXME: is this right? */
1536 case VT_NULL: /* FIXME: is this right? */
1537 case VT_I2 : /* this should not happen */
1548 case VT_VOID : /* FIXME: is this right? */
1556 case VT_DECIMAL : /* FIXME: is this right? */
1559 /* pointer types with known behaviour */
1562 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1564 FIXME("BSTR length = %d?\n", size);
1566 ptr=TLB_Alloc(size);/* allocate temp buffer */
1567 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1568 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1569 /* FIXME: do we need a AtoW conversion here? */
1570 V_UNION(pVar, bstrVal[size])=L'\0';
1571 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1576 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1583 case VT_USERDEFINED :
1589 case VT_STREAMED_OBJECT :
1590 case VT_STORED_OBJECT :
1591 case VT_BLOB_OBJECT :
1596 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1600 if(size>0) /* (big|small) endian correct? */
1601 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1605 * create a linked list with custom data
1607 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1613 TRACE_(typelib)("\n");
1617 pNew=TLB_Alloc(sizeof(TLBCustData));
1618 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1619 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1620 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1621 /* add new custom data at head of the list */
1622 pNew->next=*ppCustData;
1624 offset = entry.next;
1629 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1633 pTd->vt=type & VT_TYPEMASK;
1635 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1637 if(pTd->vt == VT_USERDEFINED)
1638 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1640 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1644 MSFT_DoFuncs(TLBContext* pcx,
1649 TLBFuncDesc** pptfd)
1652 * member information is stored in a data structure at offset
1653 * indicated by the memoffset field of the typeinfo structure
1654 * There are several distinctive parts.
1655 * The first part starts with a field that holds the total length
1656 * of this (first) part excluding this field. Then follow the records,
1657 * for each member there is one record.
1659 * The first entry is always the length of the record (including this
1661 * The rest of the record depends on the type of the member. If there is
1662 * a field indicating the member type (function, variable, interface, etc)
1663 * I have not found it yet. At this time we depend on the information
1664 * in the type info and the usual order how things are stored.
1666 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1669 * Third is an equal sized array with file offsets to the name entry
1672 * The fourth and last (?) part is an array with offsets to the records
1673 * in the first part of this file segment.
1676 int infolen, nameoffset, reclength, nrattributes, i;
1677 int recoffset = offset + sizeof(INT);
1680 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1681 TLBFuncDesc *ptfd_prev = NULL;
1683 TRACE_(typelib)("\n");
1685 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1687 for ( i = 0; i < cFuncs ; i++ )
1689 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1691 /* name, eventually add to a hash table */
1692 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1693 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1695 /* nameoffset is sometimes -1 on the second half of a propget/propput
1696 * pair of functions */
1697 if ((nameoffset == -1) && (i > 0))
1698 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1700 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1702 /* read the function information record */
1703 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1707 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1709 /* do the attributes */
1710 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1713 if ( nrattributes > 0 )
1715 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1717 if ( nrattributes > 1 )
1719 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1720 pFuncRec->OptAttr[1]) ;
1722 if ( nrattributes > 2 )
1724 if ( pFuncRec->FKCCIC & 0x2000 )
1726 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1730 (*pptfd)->Entry = MSFT_ReadString(pcx,
1731 pFuncRec->OptAttr[2]);
1733 if( nrattributes > 5 )
1735 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1737 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1740 pFuncRec->OptAttr[6],
1741 &(*pptfd)->pCustData);
1748 /* fill the FuncDesc Structure */
1749 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1750 offset + infolen + ( i + 1) * sizeof(INT));
1752 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1753 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1754 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1755 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1756 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1757 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1758 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1762 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1765 /* do the parameters/arguments */
1766 if(pFuncRec->nrargs)
1769 MSFT_ParameterInfo paraminfo;
1771 (*pptfd)->funcdesc.lprgelemdescParam =
1772 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1774 (*pptfd)->pParamDesc =
1775 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1777 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1778 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1780 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1782 TYPEDESC *lpArgTypeDesc;
1783 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1790 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1793 if (paraminfo.oName == -1)
1794 /* this occurs for [propput] or [propget] methods, so
1795 * we should just set the name of the parameter to the
1796 * name of the method. */
1797 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1799 (*pptfd)->pParamDesc[j].Name =
1800 MSFT_ReadName( pcx, paraminfo.oName );
1801 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1803 lpArgTypeDesc = &elemdesc->tdesc;
1805 /* resolve referenced type if any */
1806 while ( lpArgTypeDesc != NULL )
1808 switch ( lpArgTypeDesc->vt )
1811 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1815 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1818 case VT_USERDEFINED:
1819 MSFT_DoRefType(pcx, pTI,
1820 lpArgTypeDesc->u.hreftype);
1822 lpArgTypeDesc = NULL;
1826 lpArgTypeDesc = NULL;
1831 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1832 (pFuncRec->FKCCIC & 0x1000) )
1834 INT* pInt = (INT *)((char *)pFuncRec +
1836 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1838 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1840 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1841 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1843 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1847 elemdesc->u.paramdesc.pparamdescex = NULL;
1849 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1852 pFuncRec->OptAttr[7+j],
1853 &(*pptfd)->pParamDesc[j].pCustData);
1856 /* SEEK value = jump to offset,
1857 * from there jump to the end of record,
1858 * go back by (j-1) arguments
1860 MSFT_ReadLEDWords( ¶minfo ,
1861 sizeof(MSFT_ParameterInfo), pcx,
1862 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1863 * sizeof(MSFT_ParameterInfo)));
1867 /* scode is not used: archaic win16 stuff FIXME: right? */
1868 (*pptfd)->funcdesc.cScodes = 0 ;
1869 (*pptfd)->funcdesc.lprgscode = NULL ;
1872 pptfd = & ((*pptfd)->next);
1873 recoffset += reclength;
1877 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1878 int cVars, int offset, TLBVarDesc ** pptvd)
1880 int infolen, nameoffset, reclength;
1882 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1886 TRACE_(typelib)("\n");
1888 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1889 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1890 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1891 recoffset += offset+sizeof(INT);
1892 for(i=0;i<cVars;i++){
1893 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1894 /* name, eventually add to a hash table */
1895 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1896 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1897 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1898 /* read the variable information record */
1899 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1901 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1903 if(reclength >(6*sizeof(INT)) )
1904 (*pptvd)->HelpContext=pVarRec->HelpContext;
1905 if(reclength >(7*sizeof(INT)) )
1906 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1907 if(reclength >(8*sizeof(INT)) )
1908 if(reclength >(9*sizeof(INT)) )
1909 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1910 /* fill the VarDesc Structure */
1911 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1912 offset + infolen + ( i + 1) * sizeof(INT));
1913 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1914 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1915 MSFT_GetTdesc(pcx, pVarRec->DataType,
1916 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1917 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1918 if(pVarRec->VarKind == VAR_CONST ){
1919 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1920 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1921 pVarRec->OffsValue, pcx);
1923 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1924 pptvd=&((*pptvd)->next);
1925 recoffset += reclength;
1928 /* fill in data for a hreftype (offset). When the referenced type is contained
1929 * in the typelib, it's just an (file) offset in the type info base dir.
1930 * If comes from import, it's an offset+1 in the ImpInfo table
1932 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1936 TLBRefType **ppRefType = &pTI->reflist;
1938 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1941 if((*ppRefType)->reference == offset)
1943 ppRefType = &(*ppRefType)->next;
1946 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1947 sizeof(**ppRefType));
1949 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1950 /* external typelib */
1951 MSFT_ImpInfo impinfo;
1952 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1954 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1956 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1957 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1958 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1959 if(pImpLib->offset==impinfo.oImpFile) break;
1960 pImpLib=pImpLib->next;
1963 (*ppRefType)->reference=offset;
1964 (*ppRefType)->pImpTLInfo = pImpLib;
1965 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1966 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1967 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
1968 (*ppRefType)->index = TLB_REF_USE_GUID;
1970 (*ppRefType)->index = impinfo.oGuid;
1972 ERR("Cannot find a reference\n");
1973 (*ppRefType)->reference=-1;
1974 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1977 /* in this typelib */
1978 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1979 (*ppRefType)->reference=offset;
1980 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1984 /* process Implemented Interfaces of a com class */
1985 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1989 MSFT_RefRecord refrec;
1990 TLBImplType **ppImpl = &pTI->impltypelist;
1992 TRACE_(typelib)("\n");
1994 for(i=0;i<count;i++){
1995 if(offset<0) break; /* paranoia */
1996 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
1997 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
1998 MSFT_DoRefType(pcx, pTI, refrec.reftype);
1999 (*ppImpl)->hRef = refrec.reftype;
2000 (*ppImpl)->implflags=refrec.flags;
2001 (*ppImpl)->ctCustData=
2002 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2003 offset=refrec.onext;
2004 ppImpl=&((*ppImpl)->next);
2008 * process a typeinfo record
2010 static ITypeInfoImpl * MSFT_DoTypeInfo(
2014 ITypeLibImpl * pLibInfo)
2016 MSFT_TypeInfoBase tiBase;
2017 ITypeInfoImpl *ptiRet;
2019 TRACE_(typelib)("count=%u\n", count);
2021 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2022 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2023 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2025 /* this is where we are coming from */
2026 ptiRet->pTypeLib = pLibInfo;
2027 ptiRet->index=count;
2028 /* fill in the typeattr fields */
2029 WARN("Assign constructor/destructor memid\n");
2031 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2032 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2033 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2034 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2035 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2036 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2037 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2038 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2039 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2040 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2041 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2042 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2043 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2044 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2045 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2046 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2047 MSFT_GetTdesc(pcx, tiBase.datatype1,
2048 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2051 /* IDLDESC idldescType; *//* never saw this one != zero */
2053 /* name, eventually add to a hash table */
2054 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2055 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2056 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2058 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2059 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2060 ptiRet->dwHelpContext=tiBase.helpcontext;
2062 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2063 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2065 /* note: InfoType's Help file and HelpStringDll come from the containing
2066 * library. Further HelpString and Docstring appear to be the same thing :(
2069 if(ptiRet->TypeAttr.cFuncs >0 )
2070 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2071 ptiRet->TypeAttr.cVars,
2072 tiBase.memoffset, & ptiRet->funclist);
2074 if(ptiRet->TypeAttr.cVars >0 )
2075 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2076 ptiRet->TypeAttr.cVars,
2077 tiBase.memoffset, & ptiRet->varlist);
2078 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2079 switch(ptiRet->TypeAttr.typekind)
2082 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2085 case TKIND_DISPATCH:
2086 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2088 if (tiBase.datatype1 != -1)
2090 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2091 ptiRet->impltypelist->hRef = tiBase.datatype1;
2095 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2096 ptiRet->impltypelist->hRef = dispatch_href;
2100 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2101 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2102 ptiRet->impltypelist->hRef = tiBase.datatype1;
2107 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2109 TRACE_(typelib)("%s guid: %s kind:%s\n",
2110 debugstr_w(ptiRet->Name),
2111 debugstr_guid(&ptiRet->TypeAttr.guid),
2112 typekind_desc[ptiRet->TypeAttr.typekind]);
2117 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2118 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2119 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2122 static ITypeLibImpl *tlb_cache_first;
2123 static CRITICAL_SECTION cache_section;
2124 static CRITICAL_SECTION_DEBUG cache_section_debug =
2126 0, 0, &cache_section,
2127 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2128 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2130 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2133 /****************************************************************************
2136 * find the type of the typelib file and map the typelib resource into
2139 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2140 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2141 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2143 ITypeLibImpl *entry;
2144 int ret = TYPE_E_CANTLOADLIBRARY;
2150 lstrcpynW(pszPath, pszFileName, cchPath);
2152 /* first try loading as a dll and access the typelib as a resource */
2153 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2154 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2157 /* it may have been specified with resource index appended to the
2158 * path, so remove it and try again */
2159 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2160 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2162 index = atoiW(pIndexStr);
2163 pszPath[pIndexStr - pszFileName - 1] = '\0';
2165 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2166 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2170 /* get the path to the specified typelib file */
2173 /* otherwise, try loading as a regular file */
2174 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2175 return TYPE_E_CANTLOADLIBRARY;
2178 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2180 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2181 EnterCriticalSection(&cache_section);
2182 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2184 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2186 TRACE("cache hit\n");
2187 *ppTypeLib = (ITypeLib2*)entry;
2188 ITypeLib_AddRef(*ppTypeLib);
2189 LeaveCriticalSection(&cache_section);
2193 LeaveCriticalSection(&cache_section);
2195 /* now actually load and parse the typelib */
2198 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2199 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2202 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2205 LPVOID pBase = LockResource(hGlobal);
2206 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2210 /* try to load as incore resource */
2211 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2212 if (dwSignature == MSFT_SIGNATURE)
2213 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2214 else if (dwSignature == SLTG_SIGNATURE)
2215 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2217 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2219 FreeResource( hGlobal );
2222 FreeLibrary(hinstDLL);
2226 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2227 if (INVALID_HANDLE_VALUE != hFile)
2229 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2232 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2235 /* retrieve file size */
2236 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2237 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2239 if (dwSignature == MSFT_SIGNATURE)
2240 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2241 else if (dwSignature == SLTG_SIGNATURE)
2242 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2244 UnmapViewOfFile(pBase);
2246 CloseHandle(hMapping);
2253 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2255 TRACE("adding to cache\n");
2256 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2257 lstrcpyW(impl->path, pszPath);
2258 /* We should really canonicalise the path here. */
2259 impl->index = index;
2261 /* FIXME: check if it has added already in the meantime */
2262 EnterCriticalSection(&cache_section);
2263 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2265 tlb_cache_first = impl;
2266 LeaveCriticalSection(&cache_section);
2269 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2274 /*================== ITypeLib(2) Methods ===================================*/
2276 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2278 ITypeLibImpl* pTypeLibImpl;
2280 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2281 if (!pTypeLibImpl) return NULL;
2283 pTypeLibImpl->lpVtbl = &tlbvt;
2284 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2285 pTypeLibImpl->ref = 1;
2287 return pTypeLibImpl;
2290 /****************************************************************************
2291 * ITypeLib2_Constructor_MSFT
2293 * loading an MSFT typelib from an in-memory image
2295 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2299 MSFT_Header tlbHeader;
2300 MSFT_SegDir tlbSegDir;
2301 ITypeLibImpl * pTypeLibImpl;
2303 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2305 pTypeLibImpl = TypeLibImpl_Constructor();
2306 if (!pTypeLibImpl) return NULL;
2308 /* get pointer to beginning of typelib data */
2312 cx.pLibInfo = pTypeLibImpl;
2313 cx.length = dwTLBLength;
2316 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2317 TRACE_(typelib)("header:\n");
2318 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2319 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2320 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2323 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2325 /* there is a small amount of information here until the next important
2327 * the segment directory . Try to calculate the amount of data */
2328 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2330 /* now read the segment directory */
2331 TRACE("read segment directory (at %ld)\n",lPSegDir);
2332 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2333 cx.pTblDir = &tlbSegDir;
2335 /* just check two entries */
2336 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2338 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2339 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2343 /* now fill our internal data */
2344 /* TLIBATTR fields */
2345 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2347 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2348 /* Windows seems to have zero here, is this correct? */
2349 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2350 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2352 pTypeLibImpl->LibAttr.lcid = 0;
2354 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2355 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2356 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2357 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2359 /* name, eventually add to a hash table */
2360 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2363 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2364 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2366 if( tlbHeader.varflags & HELPDLLFLAG)
2369 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2370 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2373 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2376 if(tlbHeader.CustomDataOffset >= 0)
2378 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2381 /* fill in typedescriptions */
2382 if(tlbSegDir.pTypdescTab.length > 0)
2384 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2386 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2387 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2390 /* FIXME: add several sanity checks here */
2391 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2392 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2394 /* FIXME: check safearray */
2396 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2398 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2400 else if(td[0] == VT_CARRAY)
2402 /* array descr table here */
2403 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2405 else if(td[0] == VT_USERDEFINED)
2407 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2409 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2412 /* second time around to fill the array subscript info */
2415 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2416 if(tlbSegDir.pArrayDescriptions.offset>0)
2418 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2419 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2422 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2424 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2426 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2428 for(j = 0; j<td[2]; j++)
2430 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2431 sizeof(INT), &cx, DO_NOT_SEEK);
2432 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2433 sizeof(INT), &cx, DO_NOT_SEEK);
2438 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2439 ERR("didn't find array description data\n");
2444 /* imported type libs */
2445 if(tlbSegDir.pImpFiles.offset>0)
2447 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2448 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2451 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2456 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2457 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2458 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2460 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2461 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2462 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2463 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2466 name = TLB_Alloc(size+1);
2467 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2468 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2469 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2470 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2473 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2474 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2476 ppImpLib = &(*ppImpLib)->next;
2481 if(tlbHeader.nrtypeinfos >= 0 )
2483 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2484 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2487 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2489 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2491 ppTI = &((*ppTI)->next);
2492 (pTypeLibImpl->TypeInfoCount)++;
2496 TRACE("(%p)\n", pTypeLibImpl);
2497 return (ITypeLib2*) pTypeLibImpl;
2501 static BSTR TLB_MultiByteToBSTR(char *ptr)
2507 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2508 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2509 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2510 ret = SysAllocString(nameW);
2511 HeapFree(GetProcessHeap(), 0, nameW);
2515 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2521 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2522 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2526 guid->Data4[0] = s >> 8;
2527 guid->Data4[1] = s & 0xff;
2530 for(i = 0; i < 6; i++) {
2531 memcpy(b, str + 24 + 2 * i, 2);
2532 guid->Data4[i + 2] = strtol(b, NULL, 16);
2537 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2544 bytelen = *(WORD*)ptr;
2545 if(bytelen == 0xffff) return 2;
2546 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2547 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2548 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2549 *pBstr = SysAllocStringLen(nameW, len);
2550 HeapFree(GetProcessHeap(), 0, nameW);
2554 static WORD SLTG_ReadStringA(char *ptr, char **str)
2559 bytelen = *(WORD*)ptr;
2560 if(bytelen == 0xffff) return 2;
2561 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2562 memcpy(*str, ptr + 2, bytelen);
2563 (*str)[bytelen] = '\0';
2567 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2569 char *ptr = pLibBlk;
2572 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2573 FIXME("libblk magic = %04x\n", w);
2578 if((w = *(WORD*)ptr) != 0xffff) {
2579 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2584 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2586 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2588 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2591 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2594 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2595 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2597 pTypeLibImpl->LibAttr.lcid = 0;
2600 ptr += 4; /* skip res12 */
2602 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2605 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2608 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2611 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2612 ptr += sizeof(GUID);
2614 return ptr - (char*)pLibBlk;
2617 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2620 TYPEDESC *pTD = &pElem->tdesc;
2622 /* Handle [in/out] first */
2623 if((*pType & 0xc000) == 0xc000)
2624 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2625 else if(*pType & 0x8000)
2626 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2627 else if(*pType & 0x4000)
2628 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2630 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2633 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2636 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2639 if((*pType & 0xe00) == 0xe00) {
2641 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2643 pTD = pTD->u.lptdesc;
2645 switch(*pType & 0x7f) {
2648 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2650 pTD = pTD->u.lptdesc;
2653 case VT_USERDEFINED:
2654 pTD->vt = VT_USERDEFINED;
2655 pTD->u.hreftype = *(++pType) / 4;
2661 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2664 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2666 pTD->vt = VT_CARRAY;
2667 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2669 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2670 pTD->u.lpadesc->cDims = pSA->cDims;
2671 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2672 pSA->cDims * sizeof(SAFEARRAYBOUND));
2674 pTD = &pTD->u.lpadesc->tdescElem;
2680 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2684 pTD->vt = VT_SAFEARRAY;
2685 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2687 pTD = pTD->u.lptdesc;
2691 pTD->vt = *pType & 0x7f;
2701 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2706 TLBRefType **ppRefType;
2708 if(pRef->magic != SLTG_REF_MAGIC) {
2709 FIXME("Ref magic = %x\n", pRef->magic);
2712 name = ( (char*)(&pRef->names) + pRef->number);
2714 ppRefType = &pTI->reflist;
2715 for(ref = 0; ref < pRef->number >> 3; ref++) {
2717 unsigned int lib_offs, type_num;
2719 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2720 sizeof(**ppRefType));
2722 name += SLTG_ReadStringA(name, &refname);
2723 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2724 FIXME("Can't sscanf ref\n");
2725 if(lib_offs != 0xffff) {
2726 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2729 if((*import)->offset == lib_offs)
2731 import = &(*import)->next;
2734 char fname[MAX_PATH+1];
2737 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2739 (*import)->offset = lib_offs;
2740 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2742 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2743 &(*import)->wVersionMajor,
2744 &(*import)->wVersionMinor,
2745 &(*import)->lcid, fname) != 4) {
2746 FIXME("can't sscanf ref %s\n",
2747 pNameTable + lib_offs + 40);
2749 len = strlen(fname);
2750 if(fname[len-1] != '#')
2751 FIXME("fname = %s\n", fname);
2752 fname[len-1] = '\0';
2753 (*import)->name = TLB_MultiByteToBSTR(fname);
2755 (*ppRefType)->pImpTLInfo = *import;
2756 } else { /* internal ref */
2757 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2759 (*ppRefType)->reference = ref;
2760 (*ppRefType)->index = type_num;
2762 HeapFree(GetProcessHeap(), 0, refname);
2763 ppRefType = &(*ppRefType)->next;
2765 if((BYTE)*name != SLTG_REF_MAGIC)
2766 FIXME("End of ref block magic = %x\n", *name);
2767 dump_TLBRefType(pTI->reflist);
2770 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2773 SLTG_ImplInfo *info;
2774 TLBImplType **ppImplType = &pTI->impltypelist;
2775 /* I don't really get this structure, usually it's 0x16 bytes
2776 long, but iuser.tlb contains some that are 0x18 bytes long.
2777 That's ok because we can use the next ptr to jump to the next
2778 one. But how do we know the length of the last one? The WORD
2779 at offs 0x8 might be the clue. For now I'm just assuming that
2780 the last one is the regular 0x16 bytes. */
2782 info = (SLTG_ImplInfo*)pBlk;
2784 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2785 sizeof(**ppImplType));
2786 (*ppImplType)->hRef = info->ref;
2787 (*ppImplType)->implflags = info->impltypeflags;
2788 pTI->TypeAttr.cImplTypes++;
2789 ppImplType = &(*ppImplType)->next;
2791 if(info->next == 0xffff)
2794 FIXME("Interface inheriting more than one interface\n");
2795 info = (SLTG_ImplInfo*)(pBlk + info->next);
2797 info++; /* see comment at top of function */
2801 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2804 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2805 SLTG_MemberHeader *pMemHeader;
2806 char *pFirstItem, *pNextItem;
2808 if(pTIHeader->href_table != 0xffffffff) {
2809 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2814 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2816 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2818 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2819 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2822 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2826 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2829 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2830 SLTG_MemberHeader *pMemHeader;
2831 SLTG_Function *pFunc;
2832 char *pFirstItem, *pNextItem;
2833 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2836 if(pTIHeader->href_table != 0xffffffff) {
2837 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2841 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2843 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2845 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2846 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2849 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2850 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2855 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2856 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2857 FIXME("func magic = %02x\n", pFunc->magic);
2860 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2861 sizeof(**ppFuncDesc));
2862 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2864 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2865 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2866 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2867 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2868 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2869 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2871 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2872 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2874 if(pFunc->retnextopt & 0x80)
2875 pType = &pFunc->rettype;
2877 pType = (WORD*)(pFirstItem + pFunc->rettype);
2880 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2882 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2883 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2884 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2885 (*ppFuncDesc)->pParamDesc =
2886 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2887 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2889 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2891 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2892 char *paramName = pNameTable + *pArg;
2894 /* If arg type follows then paramName points to the 2nd
2895 letter of the name, else the next WORD is an offset to
2896 the arg type and paramName points to the first letter.
2897 So let's take one char off paramName and see if we're
2898 pointing at an alpha-numeric char. However if *pArg is
2899 0xffff or 0xfffe then the param has no name, the former
2900 meaning that the next WORD is the type, the latter
2901 meaning the the next WORD is an offset to the type. */
2906 else if(*pArg == 0xfffe) {
2910 else if(paramName[-1] && !isalnum(paramName[-1]))
2915 if(HaveOffs) { /* the next word is an offset to type */
2916 pType = (WORD*)(pFirstItem + *pArg);
2917 SLTG_DoType(pType, pFirstItem,
2918 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2923 pArg = SLTG_DoType(pArg, pFirstItem,
2924 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2927 /* Are we an optional param ? */
2928 if((*ppFuncDesc)->funcdesc.cParams - param <=
2929 (*ppFuncDesc)->funcdesc.cParamsOpt)
2930 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2933 (*ppFuncDesc)->pParamDesc[param].Name =
2934 TLB_MultiByteToBSTR(paramName);
2938 ppFuncDesc = &((*ppFuncDesc)->next);
2939 if(pFunc->next == 0xffff) break;
2941 pTI->TypeAttr.cFuncs = num;
2942 if (TRACE_ON(typelib))
2943 dump_TLBFuncDesc(pTI->funclist);
2944 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2947 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2950 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2951 SLTG_MemberHeader *pMemHeader;
2952 SLTG_RecordItem *pItem;
2954 TLBVarDesc **ppVarDesc = &pTI->varlist;
2959 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2961 pFirstItem = (char*)(pMemHeader + 1);
2962 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2963 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2964 if(pItem->magic != SLTG_RECORD_MAGIC) {
2965 FIXME("record magic = %02x\n", pItem->magic);
2968 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2969 sizeof(**ppVarDesc));
2970 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2971 (*ppVarDesc)->vardesc.memid = pItem->memid;
2972 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2973 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2975 if(pItem->typepos == 0x02)
2976 pType = &pItem->type;
2977 else if(pItem->typepos == 0x00)
2978 pType = (WORD*)(pFirstItem + pItem->type);
2980 FIXME("typepos = %02x\n", pItem->typepos);
2984 SLTG_DoType(pType, pFirstItem,
2985 &(*ppVarDesc)->vardesc.elemdescVar);
2987 /* FIXME("helpcontext, helpstring\n"); */
2989 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2991 ppVarDesc = &((*ppVarDesc)->next);
2992 if(pItem->next == 0xffff) break;
2994 pTI->TypeAttr.cVars = num;
2995 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2998 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3001 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3002 SLTG_MemberHeader *pMemHeader;
3003 SLTG_AliasItem *pItem;
3006 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3007 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3010 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3011 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3012 if (pItem->vt == 0xffff) {
3013 if (i<(pMemHeader->cbExtra/4-1))
3014 FIXME("Endmarker too early in process alias data!\n");
3018 FIXME("Chain extends over last entry?\n");
3021 if (pItem->vt == VT_USERDEFINED) {
3022 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3023 /* guessing here ... */
3024 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3025 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3028 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3029 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3033 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3036 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3039 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3040 SLTG_MemberHeader *pMemHeader;
3041 SLTG_AliasItem *pItem;
3043 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3044 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3045 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3046 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3047 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3050 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3053 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3054 SLTG_MemberHeader *pMemHeader;
3055 SLTG_EnumItem *pItem;
3057 TLBVarDesc **ppVarDesc = &pTI->varlist;
3060 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3062 pFirstItem = (char*)(pMemHeader + 1);
3063 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3064 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3065 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3066 FIXME("enumitem magic = %04x\n", pItem->magic);
3069 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3070 sizeof(**ppVarDesc));
3071 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3072 (*ppVarDesc)->vardesc.memid = pItem->memid;
3073 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3075 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3076 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3077 *(INT*)(pItem->value + pFirstItem);
3078 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3079 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3080 /* FIXME("helpcontext, helpstring\n"); */
3082 ppVarDesc = &((*ppVarDesc)->next);
3083 if(pItem->next == 0xffff) break;
3085 pTI->TypeAttr.cVars = num;
3086 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3089 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3090 managable copy of it into this */
3103 } SLTG_InternalOtherTypeInfo;
3105 /****************************************************************************
3106 * ITypeLib2_Constructor_SLTG
3108 * loading a SLTG typelib from an in-memory image
3110 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3112 ITypeLibImpl *pTypeLibImpl;
3113 SLTG_Header *pHeader;
3114 SLTG_BlkEntry *pBlkEntry;
3118 LPVOID pBlk, pFirstBlk;
3119 SLTG_LibBlk *pLibBlk;
3120 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3121 char *pAfterOTIBlks = NULL;
3122 char *pNameTable, *ptr;
3125 ITypeInfoImpl **ppTypeInfoImpl;
3127 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3130 pTypeLibImpl = TypeLibImpl_Constructor();
3131 if (!pTypeLibImpl) return NULL;
3135 TRACE_(typelib)("header:\n");
3136 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3137 pHeader->nrOfFileBlks );
3138 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3139 FIXME("Header type magic 0x%08lx not supported.\n",
3140 pHeader->SLTG_magic);
3144 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3145 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3147 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3148 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3150 /* Next we have a magic block */
3151 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3153 /* Let's see if we're still in sync */
3154 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3155 sizeof(SLTG_COMPOBJ_MAGIC))) {
3156 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3159 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3160 sizeof(SLTG_DIR_MAGIC))) {
3161 FIXME("dir magic = %s\n", pMagic->dir_magic);
3165 pIndex = (SLTG_Index*)(pMagic+1);
3167 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3169 pFirstBlk = (LPVOID)(pPad9 + 1);
3171 /* We'll set up a ptr to the main library block, which is the last one. */
3173 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3174 pBlkEntry[order].next != 0;
3175 order = pBlkEntry[order].next - 1, i++) {
3176 pBlk = (char*)pBlk + pBlkEntry[order].len;
3180 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3182 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3187 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3189 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3190 sizeof(*pOtherTypeInfoBlks) *
3191 pTypeLibImpl->TypeInfoCount);
3194 ptr = (char*)pLibBlk + len;
3196 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3200 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3202 w = *(WORD*)(ptr + 2);
3205 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3207 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3208 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3210 w = *(WORD*)(ptr + 4 + len);
3212 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3214 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3216 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3217 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3219 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3220 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3221 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3223 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3225 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3228 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3229 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3230 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3231 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3232 len += sizeof(SLTG_OtherTypeInfo);
3236 pAfterOTIBlks = ptr;
3238 /* Skip this WORD and get the next DWORD */
3239 len = *(DWORD*)(pAfterOTIBlks + 2);
3241 /* Now add this to pLibBLk look at what we're pointing at and
3242 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3243 dust and we should be pointing at the beginning of the name
3246 pNameTable = (char*)pLibBlk + len;
3248 switch(*(WORD*)pNameTable) {
3255 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3259 pNameTable += 0x216;
3263 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3265 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3268 /* Hopefully we now have enough ptrs set up to actually read in
3269 some TypeInfos. It's not clear which order to do them in, so
3270 I'll just follow the links along the BlkEntry chain and read
3271 them in in the order in which they're in the file */
3273 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3275 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3276 pBlkEntry[order].next != 0;
3277 order = pBlkEntry[order].next - 1, i++) {
3279 SLTG_TypeInfoHeader *pTIHeader;
3280 SLTG_TypeInfoTail *pTITail;
3282 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3283 pOtherTypeInfoBlks[i].index_name)) {
3284 FIXME("Index strings don't match\n");
3289 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3290 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3293 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3294 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3295 (*ppTypeInfoImpl)->index = i;
3296 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3297 pOtherTypeInfoBlks[i].name_offs +
3299 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3300 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3302 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3303 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3304 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3305 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3306 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3308 if((pTIHeader->typeflags1 & 7) != 2)
3309 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3310 if(pTIHeader->typeflags3 != 2)
3311 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3313 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3314 debugstr_w((*ppTypeInfoImpl)->Name),
3315 typekind_desc[pTIHeader->typekind],
3316 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3317 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3319 switch(pTIHeader->typekind) {
3321 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3325 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3328 case TKIND_INTERFACE:
3329 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3333 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3337 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3338 if (pTITail->tdescalias_vt)
3339 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3342 case TKIND_DISPATCH:
3343 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3347 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3353 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3354 but we've already set those */
3355 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3356 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3357 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3359 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3381 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3382 pBlk = (char*)pBlk + pBlkEntry[order].len;
3385 if(i != pTypeLibImpl->TypeInfoCount) {
3386 FIXME("Somehow processed %d TypeInfos\n", i);
3390 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3391 return (ITypeLib2*)pTypeLibImpl;
3394 /* ITypeLib::QueryInterface
3396 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3401 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3403 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3406 if(IsEqualIID(riid, &IID_IUnknown) ||
3407 IsEqualIID(riid,&IID_ITypeLib)||
3408 IsEqualIID(riid,&IID_ITypeLib2))
3415 ITypeLib2_AddRef(iface);
3416 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3419 TRACE("-- Interface: E_NOINTERFACE\n");
3420 return E_NOINTERFACE;
3425 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3427 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3428 ULONG ref = InterlockedIncrement(&This->ref);
3430 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3435 /* ITypeLib::Release
3437 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3439 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3440 ULONG ref = InterlockedDecrement(&This->ref);
3442 TRACE("(%p)->(%lu)\n",This, ref);
3446 /* remove cache entry */
3449 TRACE("removing from cache list\n");
3450 EnterCriticalSection(&cache_section);
3451 if (This->next) This->next->prev = This->prev;
3452 if (This->prev) This->prev->next = This->next;
3453 else tlb_cache_first = This->next;
3454 LeaveCriticalSection(&cache_section);
3455 HeapFree(GetProcessHeap(), 0, This->path);
3457 /* FIXME destroy child objects */
3458 TRACE(" destroying ITypeLib(%p)\n",This);
3462 SysFreeString(This->Name);
3466 if (This->DocString)
3468 SysFreeString(This->DocString);
3469 This->DocString = NULL;
3474 SysFreeString(This->HelpFile);
3475 This->HelpFile = NULL;
3478 if (This->HelpStringDll)
3480 SysFreeString(This->HelpStringDll);
3481 This->HelpStringDll = NULL;
3484 if (This->pTypeInfo) /* can be NULL */
3485 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3486 HeapFree(GetProcessHeap(),0,This);
3493 /* ITypeLib::GetTypeInfoCount
3495 * Returns the number of type descriptions in the type library
3497 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3499 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3500 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3501 return This->TypeInfoCount;
3504 /* ITypeLib::GetTypeInfo
3506 * retrieves the specified type description in the library.
3508 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3511 ITypeInfo **ppTInfo)
3515 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3516 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3518 TRACE("(%p)->(index=%d)\n", This, index);
3520 if (!ppTInfo) return E_INVALIDARG;
3522 /* search element n in list */
3523 for(i=0; i < index; i++)
3525 pTypeInfo = pTypeInfo->next;
3528 TRACE("-- element not found\n");
3529 return TYPE_E_ELEMENTNOTFOUND;
3533 *ppTInfo = (ITypeInfo *) pTypeInfo;
3535 ITypeInfo_AddRef(*ppTInfo);
3536 TRACE("-- found (%p)\n",*ppTInfo);
3541 /* ITypeLibs::GetTypeInfoType
3543 * Retrieves the type of a type description.
3545 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3550 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3552 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3554 TRACE("(%p) index %d\n", This, index);
3556 if(!pTKind) return E_INVALIDARG;
3558 /* search element n in list */
3559 for(i=0; i < index; i++)
3563 TRACE("-- element not found\n");
3564 return TYPE_E_ELEMENTNOTFOUND;
3566 pTInfo = pTInfo->next;
3569 *pTKind = pTInfo->TypeAttr.typekind;
3570 TRACE("-- found Type (%d)\n", *pTKind);
3574 /* ITypeLib::GetTypeInfoOfGuid
3576 * Retrieves the type description that corresponds to the specified GUID.
3579 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3582 ITypeInfo **ppTInfo)
3584 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3585 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3587 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3591 WARN("-- element not found\n");
3592 return TYPE_E_ELEMENTNOTFOUND;
3595 /* search linked list for guid */
3596 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3598 pTypeInfo = pTypeInfo->next;
3602 /* end of list reached */
3603 WARN("-- element not found\n");
3604 return TYPE_E_ELEMENTNOTFOUND;
3608 TRACE("-- found (%p, %s)\n",
3610 debugstr_w(pTypeInfo->Name));
3612 *ppTInfo = (ITypeInfo*)pTypeInfo;
3613 ITypeInfo_AddRef(*ppTInfo);
3617 /* ITypeLib::GetLibAttr
3619 * Retrieves the structure that contains the library's attributes.
3622 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3624 LPTLIBATTR *ppTLibAttr)
3626 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3627 TRACE("(%p)\n",This);
3628 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3629 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3633 /* ITypeLib::GetTypeComp
3635 * Enables a client compiler to bind to a library's types, variables,
3636 * constants, and global functions.
3639 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3641 ITypeComp **ppTComp)
3643 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3645 TRACE("(%p)->(%p)\n",This,ppTComp);
3646 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3647 ITypeComp_AddRef(*ppTComp);
3652 /* ITypeLib::GetDocumentation
3654 * Retrieves the library's documentation string, the complete Help file name
3655 * and path, and the context identifier for the library Help topic in the Help
3658 * On a successful return all non-null BSTR pointers will have been set,
3661 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3665 BSTR *pBstrDocString,
3666 DWORD *pdwHelpContext,
3667 BSTR *pBstrHelpFile)
3669 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3671 HRESULT result = E_INVALIDARG;
3676 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3678 pBstrName, pBstrDocString,
3679 pdwHelpContext, pBstrHelpFile);
3683 /* documentation for the typelib */
3688 if(!(*pBstrName = SysAllocString(This->Name)))
3696 if (This->DocString)
3698 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3701 else if (This->Name)
3703 if(!(*pBstrDocString = SysAllocString(This->Name)))
3707 *pBstrDocString = NULL;
3711 *pdwHelpContext = This->dwHelpContext;
3717 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3721 *pBstrHelpFile = NULL;
3728 /* for a typeinfo */
3729 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3731 if(SUCCEEDED(result))
3733 result = ITypeInfo_GetDocumentation(pTInfo,
3737 pdwHelpContext, pBstrHelpFile);
3739 ITypeInfo_Release(pTInfo);
3744 if (pBstrDocString) SysFreeString (*pBstrDocString);
3746 if (pBstrName) SysFreeString (*pBstrName);
3748 return STG_E_INSUFFICIENTMEMORY;
3753 * Indicates whether a passed-in string contains the name of a type or member
3754 * described in the library.
3757 static HRESULT WINAPI ITypeLib2_fnIsName(
3763 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3764 ITypeInfoImpl *pTInfo;
3765 TLBFuncDesc *pFInfo;
3768 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3770 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3774 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3775 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3776 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3777 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3778 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3779 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3780 goto ITypeLib2_fnIsName_exit;
3782 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3783 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3788 ITypeLib2_fnIsName_exit:
3789 TRACE("(%p)slow! search for %s: %s found!\n", This,
3790 debugstr_w(szNameBuf), *pfName?"NOT":"");
3795 /* ITypeLib::FindName
3797 * Finds occurrences of a type description in a type library. This may be used
3798 * to quickly verify that a name exists in a type library.
3801 static HRESULT WINAPI ITypeLib2_fnFindName(
3805 ITypeInfo **ppTInfo,
3809 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3810 ITypeInfoImpl *pTInfo;
3811 TLBFuncDesc *pFInfo;
3814 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3816 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3817 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3818 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3819 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3820 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3821 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3822 goto ITypeLib2_fnFindName_exit;
3825 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3826 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3828 ITypeLib2_fnFindName_exit:
3829 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3830 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3833 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3834 This, *pcFound, debugstr_w(szNameBuf), j);
3841 /* ITypeLib::ReleaseTLibAttr
3843 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3846 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3848 TLIBATTR *pTLibAttr)
3850 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3851 TRACE("freeing (%p)\n",This);
3852 HeapFree(GetProcessHeap(),0,pTLibAttr);
3856 /* ITypeLib2::GetCustData
3858 * gets the custom data
3860 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3865 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3866 TLBCustData *pCData;
3868 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3870 if( IsEqualIID(guid, &pCData->guid)) break;
3873 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3877 VariantInit( pVarVal);
3878 VariantCopy( pVarVal, &pCData->data);
3881 return E_INVALIDARG; /* FIXME: correct? */
3884 /* ITypeLib2::GetLibStatistics
3886 * Returns statistics about a type library that are required for efficient
3887 * sizing of hash tables.
3890 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3892 ULONG *pcUniqueNames,
3893 ULONG *pcchUniqueNames)
3895 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3897 FIXME("(%p): stub!\n", This);
3899 if(pcUniqueNames) *pcUniqueNames=1;
3900 if(pcchUniqueNames) *pcchUniqueNames=1;
3904 /* ITypeLib2::GetDocumentation2
3906 * Retrieves the library's documentation string, the complete Help file name
3907 * and path, the localization context to use, and the context ID for the
3908 * library Help topic in the Help file.
3911 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3915 BSTR *pbstrHelpString,
3916 DWORD *pdwHelpStringContext,
3917 BSTR *pbstrHelpStringDll)
3919 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3923 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3925 /* the help string should be obtained from the helpstringdll,
3926 * using the _DLLGetDocumentation function, based on the supplied
3927 * lcid. Nice to do sometime...
3931 /* documentation for the typelib */
3933 *pbstrHelpString=SysAllocString(This->DocString);
3934 if(pdwHelpStringContext)
3935 *pdwHelpStringContext=This->dwHelpContext;
3936 if(pbstrHelpStringDll)
3937 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3943 /* for a typeinfo */
3944 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3946 if(SUCCEEDED(result))
3948 ITypeInfo2 * pTInfo2;
3949 result = ITypeInfo_QueryInterface(pTInfo,
3951 (LPVOID*) &pTInfo2);
3953 if(SUCCEEDED(result))
3955 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3959 pdwHelpStringContext,
3960 pbstrHelpStringDll);
3962 ITypeInfo2_Release(pTInfo2);
3965 ITypeInfo_Release(pTInfo);
3971 /* ITypeLib2::GetAllCustData
3973 * Gets all custom data items for the library.
3976 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3978 CUSTDATA *pCustData)
3980 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3981 TLBCustData *pCData;
3983 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3984 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3985 if(pCustData->prgCustData ){
3986 pCustData->cCustData=This->ctCustData;
3987 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3988 pCustData->prgCustData[i].guid=pCData->guid;
3989 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3992 ERR(" OUT OF MEMORY!\n");
3993 return E_OUTOFMEMORY;
3998 static const ITypeLib2Vtbl tlbvt = {
3999 ITypeLib2_fnQueryInterface,
4001 ITypeLib2_fnRelease,
4002 ITypeLib2_fnGetTypeInfoCount,
4003 ITypeLib2_fnGetTypeInfo,
4004 ITypeLib2_fnGetTypeInfoType,
4005 ITypeLib2_fnGetTypeInfoOfGuid,
4006 ITypeLib2_fnGetLibAttr,
4007 ITypeLib2_fnGetTypeComp,
4008 ITypeLib2_fnGetDocumentation,
4010 ITypeLib2_fnFindName,
4011 ITypeLib2_fnReleaseTLibAttr,
4013 ITypeLib2_fnGetCustData,
4014 ITypeLib2_fnGetLibStatistics,
4015 ITypeLib2_fnGetDocumentation2,
4016 ITypeLib2_fnGetAllCustData
4020 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4022 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4024 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4027 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4029 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4031 return ITypeLib2_AddRef((ITypeLib2 *)This);
4034 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4036 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4038 return ITypeLib2_Release((ITypeLib2 *)This);
4041 static HRESULT WINAPI ITypeLibComp_fnBind(
4046 ITypeInfo ** ppTInfo,
4047 DESCKIND * pDescKind,
4050 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4051 ITypeInfoImpl *pTypeInfo;
4053 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4055 *pDescKind = DESCKIND_NONE;
4056 pBindPtr->lptcomp = NULL;
4059 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4061 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4063 /* FIXME: check wFlags here? */
4064 /* FIXME: we should use a hash table to look this info up using lHash
4065 * instead of an O(n) search */
4066 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4067 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4069 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4071 *pDescKind = DESCKIND_TYPECOMP;
4072 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4073 ITypeComp_AddRef(pBindPtr->lptcomp);
4074 TRACE("module or enum: %s\n", debugstr_w(szName));
4079 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4080 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4082 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4085 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4086 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4088 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4093 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4094 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4096 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4098 ITypeInfo *subtypeinfo;
4100 DESCKIND subdesckind;
4102 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4103 &subtypeinfo, &subdesckind, &subbindptr);
4104 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4106 TYPEDESC tdesc_appobject =
4109 (TYPEDESC *)pTypeInfo->hreftype
4113 const VARDESC vardesc_appobject =
4116 NULL, /* lpstrSchema */
4131 VAR_STATIC /* varkind */
4134 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4136 /* cleanup things filled in by Bind call so we can put our
4137 * application object data in there instead */
4138 switch (subdesckind)
4140 case DESCKIND_FUNCDESC:
4141 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4143 case DESCKIND_VARDESC:
4144 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4149 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4151 if (pTypeInfo->hreftype == -1)
4152 FIXME("no hreftype for interface %p\n", pTypeInfo);
4154 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4158 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4159 *ppTInfo = (ITypeInfo *)pTypeInfo;
4160 ITypeInfo_AddRef(*ppTInfo);
4166 TRACE("name not found %s\n", debugstr_w(szName));
4170 static HRESULT WINAPI ITypeLibComp_fnBindType(
4174 ITypeInfo ** ppTInfo,
4175 ITypeComp ** ppTComp)
4177 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4181 static const ITypeCompVtbl tlbtcvt =
4184 ITypeLibComp_fnQueryInterface,
4185 ITypeLibComp_fnAddRef,
4186 ITypeLibComp_fnRelease,
4188 ITypeLibComp_fnBind,
4189 ITypeLibComp_fnBindType
4192 /*================== ITypeInfo(2) Methods ===================================*/
4193 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4195 ITypeInfoImpl * pTypeInfoImpl;
4197 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4200 pTypeInfoImpl->lpVtbl = &tinfvt;
4201 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4202 pTypeInfoImpl->ref=1;
4203 pTypeInfoImpl->hreftype = -1;
4205 TRACE("(%p)\n", pTypeInfoImpl);
4206 return (ITypeInfo2*) pTypeInfoImpl;
4209 /* ITypeInfo::QueryInterface
4211 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4216 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4218 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4221 if(IsEqualIID(riid, &IID_IUnknown) ||
4222 IsEqualIID(riid,&IID_ITypeInfo)||
4223 IsEqualIID(riid,&IID_ITypeInfo2))
4227 ITypeInfo_AddRef(iface);
4228 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4231 TRACE("-- Interface: E_NOINTERFACE\n");
4232 return E_NOINTERFACE;
4235 /* ITypeInfo::AddRef
4237 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4239 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4240 ULONG ref = InterlockedIncrement(&This->ref);
4242 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4244 TRACE("(%p)->ref is %lu\n",This, ref);
4248 /* ITypeInfo::Release
4250 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4252 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4253 ULONG ref = InterlockedDecrement(&This->ref);
4255 TRACE("(%p)->(%lu)\n",This, ref);
4258 /* We don't release ITypeLib when ref=0 because
4259 it means that function is called by ITypeLib2_Release */
4260 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4262 static int once = 0;
4266 FIXME("destroy child objects\n");
4269 TRACE("destroying ITypeInfo(%p)\n",This);
4272 SysFreeString(This->Name);
4276 if (This->DocString)
4278 SysFreeString(This->DocString);
4279 This->DocString = 0;
4284 SysFreeString(This->DllName);
4290 ITypeInfo_Release((ITypeInfo*)This->next);
4293 HeapFree(GetProcessHeap(),0,This);
4299 /* ITypeInfo::GetTypeAttr
4301 * Retrieves a TYPEATTR structure that contains the attributes of the type
4305 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4306 LPTYPEATTR *ppTypeAttr)
4308 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4311 TRACE("(%p)\n",This);
4313 size = sizeof(**ppTypeAttr);
4314 if (This->TypeAttr.typekind == TKIND_ALIAS)
4315 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4317 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4319 return E_OUTOFMEMORY;
4321 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4323 if (This->TypeAttr.typekind == TKIND_ALIAS)
4324 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4325 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4327 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4328 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4330 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4331 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4336 /* ITypeInfo::GetTypeComp
4338 * Retrieves the ITypeComp interface for the type description, which enables a
4339 * client compiler to bind to the type description's members.
4342 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4343 ITypeComp * *ppTComp)
4345 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4347 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4349 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4350 ITypeComp_AddRef(*ppTComp);
4354 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4356 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4357 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4358 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4362 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4364 memcpy(dest, src, sizeof(ELEMDESC));
4365 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4366 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4368 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4369 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4370 *buffer += sizeof(PARAMDESCEX);
4371 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4372 VariantInit(&pparamdescex_dest->varDefaultValue);
4373 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4374 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4377 dest->u.paramdesc.pparamdescex = NULL;
4381 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4383 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4384 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4387 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4391 SIZE_T size = sizeof(*src);
4395 size += sizeof(*src->lprgscode) * src->cScodes;
4396 size += TLB_SizeElemDesc(&src->elemdescFunc);
4397 for (i = 0; i < src->cParams; i++)
4399 size += sizeof(ELEMDESC);
4400 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4403 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4404 if (!dest) return E_OUTOFMEMORY;
4406 memcpy(dest, src, sizeof(FUNCDESC));
4407 buffer = (char *)(dest + 1);
4409 dest->lprgscode = (SCODE *)buffer;
4410 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4411 buffer += sizeof(*src->lprgscode) * src->cScodes;
4413 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4416 SysFreeString((BSTR)dest);
4420 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4421 buffer += sizeof(ELEMDESC) * src->cParams;
4422 for (i = 0; i < src->cParams; i++)
4424 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4430 /* undo the above actions */
4431 for (i = i - 1; i >= 0; i--)
4432 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4433 TLB_FreeElemDesc(&dest->elemdescFunc);
4434 SysFreeString((BSTR)dest);
4438 /* special treatment for dispinterfaces: this makes functions appear
4439 * to return their [retval] value when it is really returning an
4441 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4443 if (dest->cParams &&
4444 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4446 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4447 if (elemdesc->tdesc.vt != VT_PTR)
4449 ERR("elemdesc should have started with VT_PTR instead of:\n");
4451 dump_ELEMDESC(elemdesc);
4452 return E_UNEXPECTED;
4455 /* copy last parameter to the return value. we are using a flat
4456 * buffer so there is no danger of leaking memory in
4458 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4460 /* remove the last parameter */
4464 /* otherwise this function is made to appear to have no return
4466 dest->elemdescFunc.tdesc.vt = VT_VOID;
4474 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4476 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4477 const TLBFuncDesc *pFDesc;
4480 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4485 *ppFuncDesc = &pFDesc->funcdesc;
4489 return E_INVALIDARG;
4492 /* ITypeInfo::GetFuncDesc
4494 * Retrieves the FUNCDESC structure that contains information about a
4495 * specified function.
4498 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4499 LPFUNCDESC *ppFuncDesc)
4501 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4502 const FUNCDESC *internal_funcdesc;
4505 TRACE("(%p) index %d\n", This, index);
4507 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4511 return TLB_AllocAndInitFuncDesc(
4514 This->TypeAttr.typekind == TKIND_DISPATCH);
4517 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4521 SIZE_T size = sizeof(*src);
4524 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4525 if (src->varkind == VAR_CONST)
4526 size += sizeof(VARIANT);
4527 size += TLB_SizeElemDesc(&src->elemdescVar);
4529 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4530 if (!dest) return E_OUTOFMEMORY;
4533 buffer = (char *)(dest + 1);
4534 if (src->lpstrSchema)
4537 dest->lpstrSchema = (LPOLESTR)buffer;
4538 len = strlenW(src->lpstrSchema);
4539 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4540 buffer += (len + 1) * sizeof(WCHAR);
4543 if (src->varkind == VAR_CONST)
4547 dest->u.lpvarValue = (VARIANT *)buffer;
4548 *dest->u.lpvarValue = *src->u.lpvarValue;
4549 buffer += sizeof(VARIANT);
4550 VariantInit(dest->u.lpvarValue);
4551 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4554 SysFreeString((BSTR)dest_ptr);
4558 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4561 if (src->varkind == VAR_CONST)
4562 VariantClear(dest->u.lpvarValue);
4563 SysFreeString((BSTR)dest);
4570 /* ITypeInfo::GetVarDesc
4572 * Retrieves a VARDESC structure that describes the specified variable.
4575 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4576 LPVARDESC *ppVarDesc)
4578 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4580 const TLBVarDesc *pVDesc;
4582 TRACE("(%p) index %d\n", This, index);
4584 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4588 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4590 return E_INVALIDARG;
4593 /* ITypeInfo_GetNames
4595 * Retrieves the variable with the specified member ID (or the name of the
4596 * property or method and its parameters) that correspond to the specified
4599 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4600 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4602 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4603 const TLBFuncDesc *pFDesc;
4604 const TLBVarDesc *pVDesc;
4606 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4607 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4610 /* function found, now return function and parameter names */
4611 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4614 *rgBstrNames=SysAllocString(pFDesc->Name);
4616 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4622 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4625 *rgBstrNames=SysAllocString(pVDesc->Name);
4630 if(This->TypeAttr.cImplTypes &&
4631 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4632 /* recursive search */
4635 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4637 if(SUCCEEDED(result))
4639 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4640 ITypeInfo_Release(pTInfo);
4643 WARN("Could not search inherited interface!\n");
4647 WARN("no names found\n");
4650 return TYPE_E_ELEMENTNOTFOUND;
4657 /* ITypeInfo::GetRefTypeOfImplType
4659 * If a type description describes a COM class, it retrieves the type
4660 * description of the implemented interface types. For an interface,
4661 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4665 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4670 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4673 const TLBImplType *pImpl = This->impltypelist;
4675 TRACE("(%p) index %d\n", This, index);
4676 if (TRACE_ON(ole)) dump_TypeInfo(This);
4680 /* only valid on dual interfaces;
4681 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4683 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4685 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4686 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4692 hr = TYPE_E_ELEMENTNOTFOUND;
4697 /* get element n from linked list */
4698 for(i=0; pImpl && i<index; i++)
4700 pImpl = pImpl->next;
4704 *pRefType = pImpl->hRef;
4706 hr = TYPE_E_ELEMENTNOTFOUND;
4712 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4714 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4720 /* ITypeInfo::GetImplTypeFlags
4722 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4723 * or base interface in a type description.
4725 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4726 UINT index, INT *pImplTypeFlags)
4728 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4732 TRACE("(%p) index %d\n", This, index);
4733 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4734 i++, pImpl=pImpl->next)
4736 if(i==index && pImpl){
4737 *pImplTypeFlags=pImpl->implflags;
4741 return TYPE_E_ELEMENTNOTFOUND;
4745 * Maps between member names and member IDs, and parameter names and
4748 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4749 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4751 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4752 const TLBFuncDesc *pFDesc;
4753 const TLBVarDesc *pVDesc;
4757 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4760 /* init out parameters in case of failure */
4761 for (i = 0; i < cNames; i++)
4762 pMemId[i] = MEMBERID_NIL;
4764 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4766 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4767 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4768 for(i=1; i < cNames; i++){
4769 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4770 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4772 if( j<pFDesc->funcdesc.cParams)
4775 ret=DISP_E_UNKNOWNNAME;
4777 TRACE("-- 0x%08lx\n", ret);
4781 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4782 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4783 if(cNames) *pMemId=pVDesc->vardesc.memid;
4787 /* not found, see if it can be found in an inherited interface */
4788 if(This->TypeAttr.cImplTypes) {
4789 /* recursive search */
4791 ret=ITypeInfo_GetRefTypeInfo(iface,
4792 This->impltypelist->hRef, &pTInfo);
4794 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4795 ITypeInfo_Release(pTInfo);
4798 WARN("Could not search inherited interface!\n");
4800 WARN("no names found\n");
4801 return DISP_E_UNKNOWNNAME;
4804 /* ITypeInfo::Invoke
4806 * Invokes a method, or accesses a property of an object, that implements the
4807 * interface described by the type description.
4810 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4813 if (TRACE_ON(ole)) {
4815 TRACE("Calling %p(",func);
4816 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4828 res = func(args[0]);
4831 res = func(args[0],args[1]);
4834 res = func(args[0],args[1],args[2]);
4837 res = func(args[0],args[1],args[2],args[3]);
4840 res = func(args[0],args[1],args[2],args[3],args[4]);
4843 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4846 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4849 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4852 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4855 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4858 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4861 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
4864 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
4867 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
4870 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
4873 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
4876 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
4879 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
4882 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
4885 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
4888 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
4891 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
4894 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
4897 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4903 FIXME("unsupported calling convention %d\n",callconv);
4907 TRACE("returns %08lx\n",res);
4911 extern int _argsize(DWORD vt);
4913 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4916 ITypeInfo *tinfo2 = NULL;
4917 TYPEATTR *tattr = NULL;
4919 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4922 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4924 tdesc->u.hreftype, hr);
4927 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4930 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4931 ITypeInfo_Release(tinfo2);
4935 switch (tattr->typekind)
4942 tdesc = &tattr->tdescAlias;
4943 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4946 case TKIND_INTERFACE:
4947 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4953 case TKIND_DISPATCH:
4958 FIXME("TKIND_RECORD unhandled.\n");
4963 FIXME("TKIND_RECORD unhandled.\n");
4968 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4972 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4973 ITypeInfo_Release(tinfo2);
4977 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4981 /* enforce only one level of pointer indirection */
4982 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
4984 tdesc = tdesc->u.lptdesc;
4986 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4987 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4988 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4989 if ((tdesc->vt == VT_USERDEFINED) ||
4990 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4992 VARTYPE vt_userdefined = 0;
4993 const TYPEDESC *tdesc_userdefined = tdesc;
4994 if (tdesc->vt == VT_PTR)
4996 vt_userdefined = VT_BYREF;
4997 tdesc_userdefined = tdesc->u.lptdesc;
4999 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5001 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5002 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5004 *vt |= vt_userdefined;
5016 case VT_USERDEFINED:
5017 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5024 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5025 hr = DISP_E_BADVARTYPE;
5029 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5038 /***********************************************************************
5039 * DispCallFunc (OLEAUT32.@)
5041 * Invokes a function of the specifed calling convention, passing the
5042 * specified arguments and returns the result.
5045 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5046 * oVft [I] The offset in the vtable. See notes.
5047 * cc [I] Calling convention of the function to call.
5048 * vtReturn [I] The return type of the function.
5049 * cActuals [I] Number of parameters.
5050 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5051 * prgpvarg [I] The arguments to pass.
5052 * pvargResult [O] The return value of the function. Can be NULL.
5056 * Failure: HRESULT code.
5059 * The HRESULT return value of this function is not affected by the return
5060 * value of the user supplied function, which is returned in pvargResult.
5062 * If pvInstance is NULL then a non-object function is to be called and oVft
5063 * is the address of the function to call.
5065 * The cc parameter can be one of the following values:
5078 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5079 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5081 int i, argsize, argspos;
5085 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5086 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5087 pvargResult, V_VT(pvargResult));
5091 argsize++; /* for This pointer */
5093 for (i=0;i<cActuals;i++)
5095 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5096 dump_Variant(prgpvarg[i]);
5097 argsize += _argsize(prgvt[i]);
5099 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5104 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5108 for (i=0;i<cActuals;i++)
5110 VARIANT *arg = prgpvarg[i];
5111 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5112 if (prgvt[i] == VT_VARIANT)
5113 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5115 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5116 argspos += _argsize(prgvt[i]);
5121 FARPROC *vtable = *(FARPROC**)pvInstance;
5122 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5125 /* if we aren't invoking an object then the function pointer is stored
5127 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5129 if (pvargResult && (vtReturn != VT_EMPTY))
5131 TRACE("Method returned 0x%08lx\n",hres);
5132 V_VT(pvargResult) = vtReturn;
5133 V_UI4(pvargResult) = hres;
5136 HeapFree(GetProcessHeap(),0,args);
5140 #define INVBUF_ELEMENT_SIZE \
5141 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5142 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5143 ((VARIANTARG *)(buffer))
5144 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5145 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5146 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5147 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5148 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5149 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5151 static HRESULT WINAPI ITypeInfo_fnInvoke(
5156 DISPPARAMS *pDispParams,
5157 VARIANT *pVarResult,
5158 EXCEPINFO *pExcepInfo,
5161 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5163 unsigned int var_index;
5166 const TLBFuncDesc *pFuncInfo;
5168 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5169 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5171 dump_DispParms(pDispParams);
5173 /* we do this instead of using GetFuncDesc since it will return a fake
5174 * FUNCDESC for dispinterfaces and we want the real function description */
5175 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5176 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5180 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5184 TRACE("invoking:\n");
5185 dump_TLBFuncDescOne(pFuncInfo);
5188 switch (func_desc->funckind) {
5189 case FUNC_PUREVIRTUAL:
5190 case FUNC_VIRTUAL: {
5191 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5193 VARIANT retval; /* pointer for storing byref retvals in */
5194 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5195 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5196 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5199 for (i = 0; i < func_desc->cParams; i++)
5201 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5202 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5207 TRACE("changing args\n");
5208 for (i = 0; i < func_desc->cParams; i++)
5210 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5212 if (wParamFlags & PARAMFLAG_FRETVAL)
5214 /* note: this check is placed so that if the caller passes
5215 * in a VARIANTARG for the retval we just ignore it, like
5217 if (i == func_desc->cParams - 1)
5220 arg = prgpvarg[i] = &rgvarg[i];
5221 memset(arg, 0, sizeof(*arg));
5222 V_VT(arg) = rgvt[i];
5223 memset(&retval, 0, sizeof(retval));
5224 V_BYREF(arg) = &retval;
5228 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5229 hres = E_UNEXPECTED;
5233 else if (i < pDispParams->cArgs)
5235 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5236 dump_Variant(src_arg);
5238 if (rgvt[i] == VT_VARIANT)
5239 VariantCopy(&rgvarg[i], src_arg);
5240 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5242 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5243 V_VT(&missing_arg[i]) = V_VT(src_arg);
5244 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5245 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5246 V_VT(&rgvarg[i]) = rgvt[i];
5250 /* FIXME: this doesn't work for VT_BYREF arguments if
5251 * they are not the same type as in the paramdesc */
5252 V_VT(&rgvarg[i]) = V_VT(src_arg);
5253 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5254 V_VT(&rgvarg[i]) = rgvt[i];
5259 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5260 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5261 debugstr_VT(src_arg), debugstr_VF(src_arg));
5264 prgpvarg[i] = &rgvarg[i];
5266 else if (wParamFlags & PARAMFLAG_FOPT)
5269 arg = prgpvarg[i] = &rgvarg[i];
5270 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5272 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5278 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5279 V_VT(arg) = VT_VARIANT | VT_BYREF;
5280 V_VARIANTREF(arg) = &missing_arg[i];
5281 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5282 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5287 hres = DISP_E_BADPARAMCOUNT;
5291 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5292 if (func_desc->cParamsOpt < 0)
5294 FIXME("Does not support safearray optional parameters\n");
5295 hres = DISP_E_BADPARAMCOUNT;
5296 goto func_fail; /* FIXME: we don't free changed types here */
5299 V_VT(&varresult) = 0;
5300 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5301 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5303 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5304 V_VT(&varresult), func_desc->cParams, rgvt,
5305 prgpvarg, &varresult);
5307 for (i = 0; i < func_desc->cParams; i++)
5309 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5310 if (wParamFlags & PARAMFLAG_FRETVAL)
5314 TRACE("[retval] value: ");
5315 dump_Variant(prgpvarg[i]);
5319 /* deref return value */
5320 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5322 /* free data stored in varresult. Note that
5323 * VariantClear doesn't do what we want because we are
5324 * working with byref types. */
5325 /* FIXME: clear safearrays, bstrs, records and
5326 * variants here too */
5327 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5328 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5330 if(*V_UNKNOWNREF(prgpvarg[i]))
5331 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5335 else if (i < pDispParams->cArgs)
5337 if (wParamFlags & PARAMFLAG_FOUT)
5339 hres = VariantChangeType(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i],
5341 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5344 ERR("failed to convert param %d to vt %d\n", i,
5345 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5349 VariantClear(&rgvarg[i]);
5351 else if (wParamFlags & PARAMFLAG_FOPT)
5353 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5354 VariantClear(&rgvarg[i]);
5358 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5360 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5361 hres = DISP_E_EXCEPTION;
5362 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5366 HeapFree(GetProcessHeap(), 0, buffer);
5369 case FUNC_DISPATCH: {
5372 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5373 if (SUCCEEDED(hres)) {
5374 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5375 hres = IDispatch_Invoke(
5376 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5377 pVarResult,pExcepInfo,pArgErr
5380 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5381 IDispatch_Release(disp);
5383 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5387 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5392 TRACE("-- 0x%08lx\n", hres);
5395 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5398 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5399 if(FAILED(hres)) return hres;
5401 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5402 dump_VARDESC(var_desc);
5403 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5407 /* not found, look for it in inherited interfaces */
5408 ITypeInfo2_GetTypeKind(iface, &type_kind);
5409 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5411 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5412 /* recursive search */
5414 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5415 if(SUCCEEDED(hres)){
5416 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5417 ITypeInfo_Release(pTInfo);
5420 WARN("Could not search inherited interface!\n");
5423 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5424 return DISP_E_MEMBERNOTFOUND;
5427 /* ITypeInfo::GetDocumentation
5429 * Retrieves the documentation string, the complete Help file name and path,
5430 * and the context ID for the Help topic for a specified type description.
5432 * (Can be tested by the Visual Basic Editor in Word for instance.)
5434 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5435 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5436 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5438 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5439 const TLBFuncDesc *pFDesc;
5440 const TLBVarDesc *pVDesc;
5441 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5442 " HelpContext(%p) HelpFile(%p)\n",
5443 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5444 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5446 *pBstrName=SysAllocString(This->Name);
5448 *pBstrDocString=SysAllocString(This->DocString);
5450 *pdwHelpContext=This->dwHelpContext;
5452 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5454 }else {/* for a member */
5455 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5456 if(pFDesc->funcdesc.memid==memid){
5458 *pBstrName = SysAllocString(pFDesc->Name);
5460 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5462 *pdwHelpContext=pFDesc->helpcontext;
5465 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5466 if(pVDesc->vardesc.memid==memid){
5468 *pBstrName = SysAllocString(pVDesc->Name);
5470 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5472 *pdwHelpContext=pVDesc->HelpContext;
5476 WARN("member %ld not found\n", memid);
5477 return TYPE_E_ELEMENTNOTFOUND;
5480 /* ITypeInfo::GetDllEntry
5482 * Retrieves a description or specification of an entry point for a function
5485 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5486 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5489 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5490 const TLBFuncDesc *pFDesc;
5492 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5494 if (pBstrDllName) *pBstrDllName = NULL;
5495 if (pBstrName) *pBstrName = NULL;
5496 if (pwOrdinal) *pwOrdinal = 0;
5498 if (This->TypeAttr.typekind != TKIND_MODULE)
5499 return TYPE_E_BADMODULEKIND;
5501 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5502 if(pFDesc->funcdesc.memid==memid){
5503 dump_TypeInfo(This);
5505 dump_TLBFuncDescOne(pFDesc);
5508 *pBstrDllName = SysAllocString(This->DllName);
5510 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5512 *pBstrName = SysAllocString(pFDesc->Entry);
5520 *pwOrdinal = (DWORD)pFDesc->Entry;
5523 return TYPE_E_ELEMENTNOTFOUND;
5526 /* ITypeInfo::GetRefTypeInfo
5528 * If a type description references other type descriptions, it retrieves
5529 * the referenced type descriptions.
5531 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5534 ITypeInfo **ppTInfo)
5536 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5537 HRESULT result = E_FAIL;
5539 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5541 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5542 ITypeInfo_AddRef(*ppTInfo);
5545 else if (hRefType == -1 &&
5546 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5547 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5549 /* when we meet a DUAL dispinterface, we must create the interface
5552 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5555 /* the interface version contains the same information as the dispinterface
5556 * copy the contents of the structs.
5558 *pTypeInfoImpl = *This;
5559 pTypeInfoImpl->ref = 1;
5561 /* change the type to interface */
5562 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5564 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5566 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5571 TLBRefType *pRefType;
5572 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5573 if(pRefType->reference == hRefType)
5577 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5578 if(pRefType && hRefType != -1) {
5579 ITypeLib *pTLib = NULL;
5581 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5583 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5585 if(pRefType->pImpTLInfo->pImpTypeLib) {
5586 TRACE("typeinfo in imported typelib that is already loaded\n");
5587 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5588 ITypeLib2_AddRef((ITypeLib*) pTLib);
5591 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5592 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5593 pRefType->pImpTLInfo->wVersionMajor,
5594 pRefType->pImpTLInfo->wVersionMinor,
5595 pRefType->pImpTLInfo->lcid,
5598 if(!SUCCEEDED(result)) {
5599 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5600 result=LoadTypeLib(libnam, &pTLib);
5601 SysFreeString(libnam);
5603 if(SUCCEEDED(result)) {
5604 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5605 ITypeLib2_AddRef(pTLib);
5609 if(SUCCEEDED(result)) {
5610 if(pRefType->index == TLB_REF_USE_GUID)
5611 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5615 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5619 ITypeLib2_Release(pTLib);
5623 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5624 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5628 /* ITypeInfo::AddressOfMember
5630 * Retrieves the addresses of static functions or variables, such as those
5633 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5634 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5636 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5642 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5644 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5648 module = LoadLibraryW(dll);
5651 ERR("couldn't load %s\n", debugstr_w(dll));
5653 if (entry) SysFreeString(entry);
5654 return STG_E_FILENOTFOUND;
5656 /* FIXME: store library somewhere where we can free it */
5661 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5662 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5663 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5665 *ppv = GetProcAddress(module, entryA);
5667 ERR("function not found %s\n", debugstr_a(entryA));
5669 HeapFree(GetProcessHeap(), 0, entryA);
5673 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5675 ERR("function not found %d\n", ordinal);
5679 if (entry) SysFreeString(entry);
5682 return TYPE_E_DLLFUNCTIONNOTFOUND;
5687 /* ITypeInfo::CreateInstance
5689 * Creates a new instance of a type that describes a component object class
5692 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5693 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5695 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5696 FIXME("(%p) stub!\n", This);
5700 /* ITypeInfo::GetMops
5702 * Retrieves marshalling information.
5704 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5707 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5708 FIXME("(%p) stub!\n", This);
5712 /* ITypeInfo::GetContainingTypeLib
5714 * Retrieves the containing type library and the index of the type description
5715 * within that type library.
5717 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5718 ITypeLib * *ppTLib, UINT *pIndex)
5720 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5722 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5724 *pIndex=This->index;
5725 TRACE("returning pIndex=%d\n", *pIndex);
5729 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5730 ITypeLib2_AddRef(*ppTLib);
5731 TRACE("returning ppTLib=%p\n", *ppTLib);
5737 /* ITypeInfo::ReleaseTypeAttr
5739 * Releases a TYPEATTR previously returned by GetTypeAttr.
5742 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5743 TYPEATTR* pTypeAttr)
5745 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5746 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5747 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5750 /* ITypeInfo::ReleaseFuncDesc
5752 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5754 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5756 FUNCDESC *pFuncDesc)
5758 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5761 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5763 for (i = 0; i < pFuncDesc->cParams; i++)
5764 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5765 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5767 SysFreeString((BSTR)pFuncDesc);
5770 /* ITypeInfo::ReleaseVarDesc
5772 * Releases a VARDESC previously returned by GetVarDesc.
5774 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5777 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5778 TRACE("(%p)->(%p)\n", This, pVarDesc);
5780 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5781 if (pVarDesc->varkind == VAR_CONST)
5782 VariantClear(pVarDesc->u.lpvarValue);
5783 SysFreeString((BSTR)pVarDesc);
5786 /* ITypeInfo2::GetTypeKind
5788 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5791 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5792 TYPEKIND *pTypeKind)
5794 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5795 *pTypeKind=This->TypeAttr.typekind;
5796 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5800 /* ITypeInfo2::GetTypeFlags
5802 * Returns the type flags without any allocations. This returns a DWORD type
5803 * flag, which expands the type flags without growing the TYPEATTR (type
5807 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5809 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5810 *pTypeFlags=This->TypeAttr.wTypeFlags;
5811 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5815 /* ITypeInfo2::GetFuncIndexOfMemId
5816 * Binds to a specific member based on a known DISPID, where the member name
5817 * is not known (for example, when binding to a default member).
5820 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5821 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5823 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5824 const TLBFuncDesc *pFuncInfo;
5828 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5829 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5835 result = TYPE_E_ELEMENTNOTFOUND;
5837 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5838 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5842 /* TypeInfo2::GetVarIndexOfMemId
5844 * Binds to a specific member based on a known DISPID, where the member name
5845 * is not known (for example, when binding to a default member).
5848 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5849 MEMBERID memid, UINT *pVarIndex)
5851 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5852 TLBVarDesc *pVarInfo;
5855 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5856 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5862 result = TYPE_E_ELEMENTNOTFOUND;
5864 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5865 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5869 /* ITypeInfo2::GetCustData
5871 * Gets the custom data
5873 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5878 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5879 TLBCustData *pCData;
5881 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5882 if( IsEqualIID(guid, &pCData->guid)) break;
5884 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5888 VariantInit( pVarVal);
5889 VariantCopy( pVarVal, &pCData->data);
5892 return E_INVALIDARG; /* FIXME: correct? */
5895 /* ITypeInfo2::GetFuncCustData
5897 * Gets the custom data
5899 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5905 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5906 TLBCustData *pCData=NULL;
5907 TLBFuncDesc * pFDesc;
5909 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5910 pFDesc=pFDesc->next);
5913 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5914 if( IsEqualIID(guid, &pCData->guid)) break;
5916 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5919 VariantInit( pVarVal);
5920 VariantCopy( pVarVal, &pCData->data);
5923 return E_INVALIDARG; /* FIXME: correct? */
5926 /* ITypeInfo2::GetParamCustData
5928 * Gets the custom data
5930 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5937 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5938 TLBCustData *pCData=NULL;
5939 TLBFuncDesc * pFDesc;
5942 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5944 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5945 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5946 pCData = pCData->next)
5947 if( IsEqualIID(guid, &pCData->guid)) break;
5949 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5953 VariantInit( pVarVal);
5954 VariantCopy( pVarVal, &pCData->data);
5957 return E_INVALIDARG; /* FIXME: correct? */
5960 /* ITypeInfo2::GetVarCustData
5962 * Gets the custom data
5964 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5970 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5971 TLBCustData *pCData=NULL;
5972 TLBVarDesc * pVDesc;
5975 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5979 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5981 if( IsEqualIID(guid, &pCData->guid)) break;
5985 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5989 VariantInit( pVarVal);
5990 VariantCopy( pVarVal, &pCData->data);
5993 return E_INVALIDARG; /* FIXME: correct? */
5996 /* ITypeInfo2::GetImplCustData
5998 * Gets the custom data
6000 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6006 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6007 TLBCustData *pCData=NULL;
6008 TLBImplType * pRDesc;
6011 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6015 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6017 if( IsEqualIID(guid, &pCData->guid)) break;
6021 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6025 VariantInit( pVarVal);
6026 VariantCopy( pVarVal, &pCData->data);
6029 return E_INVALIDARG; /* FIXME: correct? */
6032 /* ITypeInfo2::GetDocumentation2
6034 * Retrieves the documentation string, the complete Help file name and path,
6035 * the localization context to use, and the context ID for the library Help
6036 * topic in the Help file.
6039 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6043 BSTR *pbstrHelpString,
6044 DWORD *pdwHelpStringContext,
6045 BSTR *pbstrHelpStringDll)
6047 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6048 const TLBFuncDesc *pFDesc;
6049 const TLBVarDesc *pVDesc;
6050 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6051 "HelpStringContext(%p) HelpStringDll(%p)\n",
6052 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6053 pbstrHelpStringDll );
6054 /* the help string should be obtained from the helpstringdll,
6055 * using the _DLLGetDocumentation function, based on the supplied
6056 * lcid. Nice to do sometime...
6058 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6060 *pbstrHelpString=SysAllocString(This->Name);
6061 if(pdwHelpStringContext)
6062 *pdwHelpStringContext=This->dwHelpStringContext;
6063 if(pbstrHelpStringDll)
6064 *pbstrHelpStringDll=
6065 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6067 }else {/* for a member */
6068 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6069 if(pFDesc->funcdesc.memid==memid){
6071 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6072 if(pdwHelpStringContext)
6073 *pdwHelpStringContext=pFDesc->HelpStringContext;
6074 if(pbstrHelpStringDll)
6075 *pbstrHelpStringDll=
6076 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6079 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6080 if(pVDesc->vardesc.memid==memid){
6082 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6083 if(pdwHelpStringContext)
6084 *pdwHelpStringContext=pVDesc->HelpStringContext;
6085 if(pbstrHelpStringDll)
6086 *pbstrHelpStringDll=
6087 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6091 return TYPE_E_ELEMENTNOTFOUND;
6094 /* ITypeInfo2::GetAllCustData
6096 * Gets all custom data items for the Type info.
6099 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6101 CUSTDATA *pCustData)
6103 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6104 TLBCustData *pCData;
6107 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6109 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6110 if(pCustData->prgCustData ){
6111 pCustData->cCustData=This->ctCustData;
6112 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6113 pCustData->prgCustData[i].guid=pCData->guid;
6114 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6117 ERR(" OUT OF MEMORY!\n");
6118 return E_OUTOFMEMORY;
6123 /* ITypeInfo2::GetAllFuncCustData
6125 * Gets all custom data items for the specified Function
6128 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6131 CUSTDATA *pCustData)
6133 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6134 TLBCustData *pCData;
6135 TLBFuncDesc * pFDesc;
6137 TRACE("(%p) index %d\n", This, index);
6138 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6139 pFDesc=pFDesc->next)
6142 pCustData->prgCustData =
6143 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6144 if(pCustData->prgCustData ){
6145 pCustData->cCustData=pFDesc->ctCustData;
6146 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6147 pCData = pCData->next){
6148 pCustData->prgCustData[i].guid=pCData->guid;
6149 VariantCopy(& pCustData->prgCustData[i].varValue,
6153 ERR(" OUT OF MEMORY!\n");
6154 return E_OUTOFMEMORY;
6158 return TYPE_E_ELEMENTNOTFOUND;
6161 /* ITypeInfo2::GetAllParamCustData
6163 * Gets all custom data items for the Functions
6166 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6167 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6169 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6170 TLBCustData *pCData=NULL;
6171 TLBFuncDesc * pFDesc;
6173 TRACE("(%p) index %d\n", This, indexFunc);
6174 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6175 pFDesc=pFDesc->next)
6177 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6178 pCustData->prgCustData =
6179 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6180 sizeof(CUSTDATAITEM));
6181 if(pCustData->prgCustData ){
6182 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6183 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6184 pCData; i++, pCData = pCData->next){
6185 pCustData->prgCustData[i].guid=pCData->guid;
6186 VariantCopy(& pCustData->prgCustData[i].varValue,
6190 ERR(" OUT OF MEMORY!\n");
6191 return E_OUTOFMEMORY;
6195 return TYPE_E_ELEMENTNOTFOUND;
6198 /* ITypeInfo2::GetAllVarCustData
6200 * Gets all custom data items for the specified Variable
6203 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6204 UINT index, CUSTDATA *pCustData)
6206 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6207 TLBCustData *pCData;
6208 TLBVarDesc * pVDesc;
6210 TRACE("(%p) index %d\n", This, index);
6211 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6212 pVDesc=pVDesc->next)
6215 pCustData->prgCustData =
6216 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6217 if(pCustData->prgCustData ){
6218 pCustData->cCustData=pVDesc->ctCustData;
6219 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6220 pCData = pCData->next){
6221 pCustData->prgCustData[i].guid=pCData->guid;
6222 VariantCopy(& pCustData->prgCustData[i].varValue,
6226 ERR(" OUT OF MEMORY!\n");
6227 return E_OUTOFMEMORY;
6231 return TYPE_E_ELEMENTNOTFOUND;
6234 /* ITypeInfo2::GetAllImplCustData
6236 * Gets all custom data items for the specified implementation type
6239 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6242 CUSTDATA *pCustData)
6244 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6245 TLBCustData *pCData;
6246 TLBImplType * pRDesc;
6248 TRACE("(%p) index %d\n", This, index);
6249 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6250 pRDesc=pRDesc->next)
6253 pCustData->prgCustData =
6254 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6255 if(pCustData->prgCustData ){
6256 pCustData->cCustData=pRDesc->ctCustData;
6257 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6258 pCData = pCData->next){
6259 pCustData->prgCustData[i].guid=pCData->guid;
6260 VariantCopy(& pCustData->prgCustData[i].varValue,
6264 ERR(" OUT OF MEMORY!\n");
6265 return E_OUTOFMEMORY;
6269 return TYPE_E_ELEMENTNOTFOUND;
6272 static const ITypeInfo2Vtbl tinfvt =
6275 ITypeInfo_fnQueryInterface,
6277 ITypeInfo_fnRelease,
6279 ITypeInfo_fnGetTypeAttr,
6280 ITypeInfo_fnGetTypeComp,
6281 ITypeInfo_fnGetFuncDesc,
6282 ITypeInfo_fnGetVarDesc,
6283 ITypeInfo_fnGetNames,
6284 ITypeInfo_fnGetRefTypeOfImplType,
6285 ITypeInfo_fnGetImplTypeFlags,
6286 ITypeInfo_fnGetIDsOfNames,
6288 ITypeInfo_fnGetDocumentation,
6289 ITypeInfo_fnGetDllEntry,
6290 ITypeInfo_fnGetRefTypeInfo,
6291 ITypeInfo_fnAddressOfMember,
6292 ITypeInfo_fnCreateInstance,
6293 ITypeInfo_fnGetMops,
6294 ITypeInfo_fnGetContainingTypeLib,
6295 ITypeInfo_fnReleaseTypeAttr,
6296 ITypeInfo_fnReleaseFuncDesc,
6297 ITypeInfo_fnReleaseVarDesc,
6299 ITypeInfo2_fnGetTypeKind,
6300 ITypeInfo2_fnGetTypeFlags,
6301 ITypeInfo2_fnGetFuncIndexOfMemId,
6302 ITypeInfo2_fnGetVarIndexOfMemId,
6303 ITypeInfo2_fnGetCustData,
6304 ITypeInfo2_fnGetFuncCustData,
6305 ITypeInfo2_fnGetParamCustData,
6306 ITypeInfo2_fnGetVarCustData,
6307 ITypeInfo2_fnGetImplTypeCustData,
6308 ITypeInfo2_fnGetDocumentation2,
6309 ITypeInfo2_fnGetAllCustData,
6310 ITypeInfo2_fnGetAllFuncCustData,
6311 ITypeInfo2_fnGetAllParamCustData,
6312 ITypeInfo2_fnGetAllVarCustData,
6313 ITypeInfo2_fnGetAllImplTypeCustData,
6316 /******************************************************************************
6317 * CreateDispTypeInfo [OLEAUT32.31]
6319 * Build type information for an object so it can be called through an
6320 * IDispatch interface.
6323 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6324 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6327 * This call allows an objects methods to be accessed through IDispatch, by
6328 * building an ITypeInfo object that IDispatch can use to call through.
6330 HRESULT WINAPI CreateDispTypeInfo(
6331 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6332 LCID lcid, /* [I] Locale Id */
6333 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6335 ITypeInfoImpl *pTIClass, *pTIIface;
6336 ITypeLibImpl *pTypeLibImpl;
6338 TLBFuncDesc **ppFuncDesc;
6341 pTypeLibImpl = TypeLibImpl_Constructor();
6342 if (!pTypeLibImpl) return E_FAIL;
6344 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6345 pTIIface->pTypeLib = pTypeLibImpl;
6346 pTIIface->index = 0;
6347 pTIIface->Name = NULL;
6348 pTIIface->dwHelpContext = -1;
6349 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6350 pTIIface->TypeAttr.lcid = lcid;
6351 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6352 pTIIface->TypeAttr.wMajorVerNum = 0;
6353 pTIIface->TypeAttr.wMinorVerNum = 0;
6354 pTIIface->TypeAttr.cbAlignment = 2;
6355 pTIIface->TypeAttr.cbSizeInstance = -1;
6356 pTIIface->TypeAttr.cbSizeVft = -1;
6357 pTIIface->TypeAttr.cFuncs = 0;
6358 pTIIface->TypeAttr.cImplTypes = 0;
6359 pTIIface->TypeAttr.cVars = 0;
6360 pTIIface->TypeAttr.wTypeFlags = 0;
6362 ppFuncDesc = &pTIIface->funclist;
6363 for(func = 0; func < pidata->cMembers; func++) {
6364 METHODDATA *md = pidata->pmethdata + func;
6365 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6366 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6367 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6368 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6369 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6370 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6371 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6372 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6373 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6374 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6375 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6376 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6377 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6378 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6379 md->cArgs * sizeof(ELEMDESC));
6380 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6381 md->cArgs * sizeof(TLBParDesc));
6382 for(param = 0; param < md->cArgs; param++) {
6383 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6384 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6386 (*ppFuncDesc)->helpcontext = 0;
6387 (*ppFuncDesc)->HelpStringContext = 0;
6388 (*ppFuncDesc)->HelpString = NULL;
6389 (*ppFuncDesc)->Entry = NULL;
6390 (*ppFuncDesc)->ctCustData = 0;
6391 (*ppFuncDesc)->pCustData = NULL;
6392 (*ppFuncDesc)->next = NULL;
6393 ppFuncDesc = &(*ppFuncDesc)->next;
6396 dump_TypeInfo(pTIIface);
6398 pTypeLibImpl->pTypeInfo = pTIIface;
6399 pTypeLibImpl->TypeInfoCount++;
6401 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6402 pTIClass->pTypeLib = pTypeLibImpl;
6403 pTIClass->index = 1;
6404 pTIClass->Name = NULL;
6405 pTIClass->dwHelpContext = -1;
6406 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6407 pTIClass->TypeAttr.lcid = lcid;
6408 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6409 pTIClass->TypeAttr.wMajorVerNum = 0;
6410 pTIClass->TypeAttr.wMinorVerNum = 0;
6411 pTIClass->TypeAttr.cbAlignment = 2;
6412 pTIClass->TypeAttr.cbSizeInstance = -1;
6413 pTIClass->TypeAttr.cbSizeVft = -1;
6414 pTIClass->TypeAttr.cFuncs = 0;
6415 pTIClass->TypeAttr.cImplTypes = 1;
6416 pTIClass->TypeAttr.cVars = 0;
6417 pTIClass->TypeAttr.wTypeFlags = 0;
6419 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6420 pTIClass->impltypelist->hRef = 1;
6422 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6423 pTIClass->reflist->index = 0;
6424 pTIClass->reflist->reference = 1;
6425 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6427 dump_TypeInfo(pTIClass);
6429 pTIIface->next = pTIClass;
6430 pTypeLibImpl->TypeInfoCount++;
6432 *pptinfo = (ITypeInfo*)pTIClass;
6437 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6439 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6441 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6444 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6446 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6448 return ITypeInfo_AddRef((ITypeInfo *)This);
6451 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6453 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6455 return ITypeInfo_Release((ITypeInfo *)This);
6458 static HRESULT WINAPI ITypeComp_fnBind(
6463 ITypeInfo ** ppTInfo,
6464 DESCKIND * pDescKind,
6467 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6468 const TLBFuncDesc *pFDesc;
6469 const TLBVarDesc *pVDesc;
6471 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6473 *pDescKind = DESCKIND_NONE;
6474 pBindPtr->lpfuncdesc = NULL;
6477 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6478 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6479 if (!strcmpW(pFDesc->Name, szName)) {
6485 HRESULT hr = TLB_AllocAndInitFuncDesc(
6487 &pBindPtr->lpfuncdesc,
6488 This->TypeAttr.typekind == TKIND_DISPATCH);
6491 *pDescKind = DESCKIND_FUNCDESC;
6492 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6493 ITypeInfo_AddRef(*ppTInfo);
6496 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6497 if (!strcmpW(pVDesc->Name, szName)) {
6498 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6501 *pDescKind = DESCKIND_VARDESC;
6502 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6503 ITypeInfo_AddRef(*ppTInfo);
6508 /* FIXME: search each inherited interface, not just the first */
6509 if (This->TypeAttr.cImplTypes) {
6510 /* recursive search */
6514 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6517 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6518 ITypeInfo_Release(pTInfo);
6522 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6523 ITypeComp_Release(pTComp);
6526 WARN("Could not search inherited interface!\n");
6528 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6529 return DISP_E_MEMBERNOTFOUND;
6532 static HRESULT WINAPI ITypeComp_fnBindType(
6536 ITypeInfo ** ppTInfo,
6537 ITypeComp ** ppTComp)
6539 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6541 /* strange behaviour (does nothing) but like the
6544 if (!ppTInfo || !ppTComp)
6553 static const ITypeCompVtbl tcompvt =
6556 ITypeComp_fnQueryInterface,
6558 ITypeComp_fnRelease,
6561 ITypeComp_fnBindType