4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
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 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
86 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
88 /****************************************************************************
91 * Takes p_iVal (which is in little endian) and returns it
92 * in the host machine's byte order.
94 #ifdef WORDS_BIGENDIAN
95 static WORD FromLEWord(WORD p_iVal)
97 return (((p_iVal & 0x00FF) << 8) |
98 ((p_iVal & 0xFF00) >> 8));
102 static DWORD FromLEDWord(DWORD p_iVal)
104 return (((p_iVal & 0x000000FF) << 24) |
105 ((p_iVal & 0x0000FF00) << 8) |
106 ((p_iVal & 0x00FF0000) >> 8) |
107 ((p_iVal & 0xFF000000) >> 24));
110 #define FromLEWord(X) (X)
111 #define FromLEDWord(X) (X)
115 /****************************************************************************
118 * Fix byte order in any structure if necessary
120 #ifdef WORDS_BIGENDIAN
121 static void FromLEWords(void *p_Val, int p_iSize)
125 p_iSize /= sizeof(WORD);
128 *Val = FromLEWord(*Val);
135 static void FromLEDWords(void *p_Val, int p_iSize)
139 p_iSize /= sizeof(DWORD);
142 *Val = FromLEDWord(*Val);
148 #define FromLEWords(X,Y) /*nothing*/
149 #define FromLEDWords(X,Y) /*nothing*/
152 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
153 /* buffer must be at least 60 characters long */
154 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
156 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
157 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
159 memcpy( buffer, TypelibW, sizeof(TypelibW) );
160 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
161 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
165 /* get the path of an interface key, in the form "Interface\\<guid>" */
166 /* buffer must be at least 50 characters long */
167 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
169 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
171 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
172 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
176 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
177 /* buffer must be at least 16 characters long */
178 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
180 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
181 static const WCHAR win16W[] = {'w','i','n','1','6',0};
182 static const WCHAR win32W[] = {'w','i','n','3','2',0};
184 sprintfW( buffer, LcidFormatW, lcid );
187 case SYS_WIN16: strcatW( buffer, win16W ); break;
188 case SYS_WIN32: strcatW( buffer, win32W ); break;
190 TRACE("Typelib is for unsupported syskind %i\n", syskind);
196 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
199 /****************************************************************************
200 * QueryPathOfRegTypeLib [OLEAUT32.164]
202 * Gets the path to a registered type library.
205 * guid [I] referenced guid
206 * wMaj [I] major version
207 * wMin [I] minor version
209 * path [O] path of typelib
213 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
214 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
217 HRESULT WINAPI QueryPathOfRegTypeLib(
224 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
228 WCHAR Path[MAX_PATH];
231 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
233 get_typelib_key( guid, wMaj, wMin, buffer );
235 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
236 if (res == ERROR_FILE_NOT_FOUND)
238 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
239 return TYPE_E_LIBNOTREGISTERED;
241 else if (res != ERROR_SUCCESS)
243 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
244 return TYPE_E_REGISTRYACCESS;
249 LONG dwPathLen = sizeof(Path);
251 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
253 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
257 else if (myLCID == lcid)
259 /* try with sub-langid */
260 myLCID = SUBLANGID(lcid);
262 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
264 /* try with system langid */
274 *path = SysAllocString( Path );
279 TRACE_(typelib)("-- 0x%08lx\n", hr);
283 /******************************************************************************
284 * CreateTypeLib [OLEAUT32.160] creates a typelib
290 HRESULT WINAPI CreateTypeLib(
291 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
293 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
297 /******************************************************************************
298 * LoadTypeLib [OLEAUT32.161]
300 * Loads a type library
303 * szFile [I] Name of file to load from.
304 * pptLib [O] Pointer that receives ITypeLib object on success.
311 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
313 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
315 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
316 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
319 /******************************************************************************
320 * LoadTypeLibEx [OLEAUT32.183]
322 * Loads and optionally registers a type library
328 HRESULT WINAPI LoadTypeLibEx(
329 LPCOLESTR szFile, /* [in] Name of file to load from */
330 REGKIND regkind, /* [in] Specify kind of registration */
331 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
333 WCHAR szPath[MAX_PATH+1];
336 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
340 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
345 case REGKIND_DEFAULT:
346 /* don't register typelibs supplied with full path. Experimentation confirms the following */
347 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
348 (szFile[0] && (szFile[1] == ':'))) break;
349 /* else fall-through */
351 case REGKIND_REGISTER:
352 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
354 IUnknown_Release(*pptLib);
362 TRACE(" returns %08lx\n",res);
366 /******************************************************************************
367 * LoadRegTypeLib [OLEAUT32.162]
369 * Loads a registered type library.
372 * rguid [I] GUID of the registered type library.
373 * wVerMajor [I] major version.
374 * wVerMinor [I] minor version.
375 * lcid [I] locale ID.
376 * ppTLib [O] pointer that receives an ITypeLib object on success.
380 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
383 HRESULT WINAPI LoadRegTypeLib(
395 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);
1643 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1645 /* resolve referenced type if any */
1648 switch (lpTypeDesc->vt)
1651 lpTypeDesc = lpTypeDesc->u.lptdesc;
1655 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1658 case VT_USERDEFINED:
1659 MSFT_DoRefType(pcx, pTI,
1660 lpTypeDesc->u.hreftype);
1672 MSFT_DoFuncs(TLBContext* pcx,
1677 TLBFuncDesc** pptfd)
1680 * member information is stored in a data structure at offset
1681 * indicated by the memoffset field of the typeinfo structure
1682 * There are several distinctive parts.
1683 * The first part starts with a field that holds the total length
1684 * of this (first) part excluding this field. Then follow the records,
1685 * for each member there is one record.
1687 * The first entry is always the length of the record (including this
1689 * The rest of the record depends on the type of the member. If there is
1690 * a field indicating the member type (function, variable, interface, etc)
1691 * I have not found it yet. At this time we depend on the information
1692 * in the type info and the usual order how things are stored.
1694 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1697 * Third is an equal sized array with file offsets to the name entry
1700 * The fourth and last (?) part is an array with offsets to the records
1701 * in the first part of this file segment.
1704 int infolen, nameoffset, reclength, nrattributes, i;
1705 int recoffset = offset + sizeof(INT);
1708 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1709 TLBFuncDesc *ptfd_prev = NULL;
1711 TRACE_(typelib)("\n");
1713 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1715 for ( i = 0; i < cFuncs ; i++ )
1717 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1719 /* name, eventually add to a hash table */
1720 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1721 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1723 /* nameoffset is sometimes -1 on the second half of a propget/propput
1724 * pair of functions */
1725 if ((nameoffset == -1) && (i > 0))
1726 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1728 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1730 /* read the function information record */
1731 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1735 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1737 /* do the attributes */
1738 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1741 if ( nrattributes > 0 )
1743 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1745 if ( nrattributes > 1 )
1747 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1748 pFuncRec->OptAttr[1]) ;
1750 if ( nrattributes > 2 )
1752 if ( pFuncRec->FKCCIC & 0x2000 )
1754 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1758 (*pptfd)->Entry = MSFT_ReadString(pcx,
1759 pFuncRec->OptAttr[2]);
1761 if( nrattributes > 5 )
1763 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1765 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1768 pFuncRec->OptAttr[6],
1769 &(*pptfd)->pCustData);
1776 /* fill the FuncDesc Structure */
1777 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1778 offset + infolen + ( i + 1) * sizeof(INT));
1780 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1781 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1782 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1783 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1784 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1785 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1786 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1790 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1792 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1794 /* do the parameters/arguments */
1795 if(pFuncRec->nrargs)
1798 MSFT_ParameterInfo paraminfo;
1800 (*pptfd)->funcdesc.lprgelemdescParam =
1801 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1803 (*pptfd)->pParamDesc =
1804 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1806 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1807 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1809 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1811 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1818 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1821 if (paraminfo.oName == -1)
1822 /* this occurs for [propput] or [propget] methods, so
1823 * we should just set the name of the parameter to the
1824 * name of the method. */
1825 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1827 (*pptfd)->pParamDesc[j].Name =
1828 MSFT_ReadName( pcx, paraminfo.oName );
1829 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1831 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1834 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1835 (pFuncRec->FKCCIC & 0x1000) )
1837 INT* pInt = (INT *)((char *)pFuncRec +
1839 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1841 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1843 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1844 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1846 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1850 elemdesc->u.paramdesc.pparamdescex = NULL;
1852 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1855 pFuncRec->OptAttr[7+j],
1856 &(*pptfd)->pParamDesc[j].pCustData);
1859 /* SEEK value = jump to offset,
1860 * from there jump to the end of record,
1861 * go back by (j-1) arguments
1863 MSFT_ReadLEDWords( ¶minfo ,
1864 sizeof(MSFT_ParameterInfo), pcx,
1865 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1866 * sizeof(MSFT_ParameterInfo)));
1870 /* scode is not used: archaic win16 stuff FIXME: right? */
1871 (*pptfd)->funcdesc.cScodes = 0 ;
1872 (*pptfd)->funcdesc.lprgscode = NULL ;
1875 pptfd = & ((*pptfd)->next);
1876 recoffset += reclength;
1880 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1881 int cVars, int offset, TLBVarDesc ** pptvd)
1883 int infolen, nameoffset, reclength;
1885 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1889 TRACE_(typelib)("\n");
1891 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1892 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1893 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1894 recoffset += offset+sizeof(INT);
1895 for(i=0;i<cVars;i++){
1896 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1897 /* name, eventually add to a hash table */
1898 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1899 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1900 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1901 /* read the variable information record */
1902 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1904 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1906 if(reclength >(6*sizeof(INT)) )
1907 (*pptvd)->HelpContext=pVarRec->HelpContext;
1908 if(reclength >(7*sizeof(INT)) )
1909 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1910 if(reclength >(8*sizeof(INT)) )
1911 if(reclength >(9*sizeof(INT)) )
1912 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1913 /* fill the VarDesc Structure */
1914 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1915 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1916 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1917 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1918 MSFT_GetTdesc(pcx, pVarRec->DataType,
1919 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1920 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1921 if(pVarRec->VarKind == VAR_CONST ){
1922 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1923 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1924 pVarRec->OffsValue, pcx);
1926 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1927 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1928 pptvd=&((*pptvd)->next);
1929 recoffset += reclength;
1932 /* fill in data for a hreftype (offset). When the referenced type is contained
1933 * in the typelib, it's just an (file) offset in the type info base dir.
1934 * If comes from import, it's an offset+1 in the ImpInfo table
1936 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1940 TLBRefType **ppRefType = &pTI->reflist;
1942 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1945 if((*ppRefType)->reference == offset)
1947 ppRefType = &(*ppRefType)->next;
1950 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1951 sizeof(**ppRefType));
1953 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1954 /* external typelib */
1955 MSFT_ImpInfo impinfo;
1956 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1958 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1960 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1961 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1962 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1963 if(pImpLib->offset==impinfo.oImpFile) break;
1964 pImpLib=pImpLib->next;
1967 (*ppRefType)->reference=offset;
1968 (*ppRefType)->pImpTLInfo = pImpLib;
1969 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1970 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1971 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
1972 (*ppRefType)->index = TLB_REF_USE_GUID;
1974 (*ppRefType)->index = impinfo.oGuid;
1976 ERR("Cannot find a reference\n");
1977 (*ppRefType)->reference=-1;
1978 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1981 /* in this typelib */
1982 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1983 (*ppRefType)->reference=offset;
1984 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1988 /* process Implemented Interfaces of a com class */
1989 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1993 MSFT_RefRecord refrec;
1994 TLBImplType **ppImpl = &pTI->impltypelist;
1996 TRACE_(typelib)("\n");
1998 for(i=0;i<count;i++){
1999 if(offset<0) break; /* paranoia */
2000 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2001 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2002 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2003 (*ppImpl)->hRef = refrec.reftype;
2004 (*ppImpl)->implflags=refrec.flags;
2005 (*ppImpl)->ctCustData=
2006 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2007 offset=refrec.onext;
2008 ppImpl=&((*ppImpl)->next);
2012 * process a typeinfo record
2014 static ITypeInfoImpl * MSFT_DoTypeInfo(
2018 ITypeLibImpl * pLibInfo)
2020 MSFT_TypeInfoBase tiBase;
2021 ITypeInfoImpl *ptiRet;
2023 TRACE_(typelib)("count=%u\n", count);
2025 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2026 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2027 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2029 /* this is where we are coming from */
2030 ptiRet->pTypeLib = pLibInfo;
2031 ptiRet->index=count;
2032 /* fill in the typeattr fields */
2033 WARN("Assign constructor/destructor memid\n");
2035 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2036 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2037 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2038 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2039 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2040 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2041 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2042 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2043 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2044 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2045 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2046 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2047 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2048 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2049 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2050 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2051 MSFT_GetTdesc(pcx, tiBase.datatype1,
2052 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2055 /* IDLDESC idldescType; *//* never saw this one != zero */
2057 /* name, eventually add to a hash table */
2058 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2059 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2060 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2062 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2063 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2064 ptiRet->dwHelpContext=tiBase.helpcontext;
2066 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2067 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2069 /* note: InfoType's Help file and HelpStringDll come from the containing
2070 * library. Further HelpString and Docstring appear to be the same thing :(
2073 if(ptiRet->TypeAttr.cFuncs >0 )
2074 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2075 ptiRet->TypeAttr.cVars,
2076 tiBase.memoffset, & ptiRet->funclist);
2078 if(ptiRet->TypeAttr.cVars >0 )
2079 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2080 ptiRet->TypeAttr.cVars,
2081 tiBase.memoffset, & ptiRet->varlist);
2082 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2083 switch(ptiRet->TypeAttr.typekind)
2086 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2089 case TKIND_DISPATCH:
2090 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2092 if (tiBase.datatype1 != -1)
2094 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2095 ptiRet->impltypelist->hRef = tiBase.datatype1;
2099 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2100 ptiRet->impltypelist->hRef = dispatch_href;
2104 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2105 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2106 ptiRet->impltypelist->hRef = tiBase.datatype1;
2111 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2113 TRACE_(typelib)("%s guid: %s kind:%s\n",
2114 debugstr_w(ptiRet->Name),
2115 debugstr_guid(&ptiRet->TypeAttr.guid),
2116 typekind_desc[ptiRet->TypeAttr.typekind]);
2121 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2122 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2123 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2126 static ITypeLibImpl *tlb_cache_first;
2127 static CRITICAL_SECTION cache_section;
2128 static CRITICAL_SECTION_DEBUG cache_section_debug =
2130 0, 0, &cache_section,
2131 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2132 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2134 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2137 /****************************************************************************
2140 * find the type of the typelib file and map the typelib resource into
2143 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2144 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2145 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2147 ITypeLibImpl *entry;
2148 int ret = TYPE_E_CANTLOADLIBRARY;
2154 lstrcpynW(pszPath, pszFileName, cchPath);
2156 /* first try loading as a dll and access the typelib as a resource */
2157 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2158 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2161 /* it may have been specified with resource index appended to the
2162 * path, so remove it and try again */
2163 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2164 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2166 index = atoiW(pIndexStr);
2167 pszPath[pIndexStr - pszFileName - 1] = '\0';
2169 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2170 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2174 /* get the path to the specified typelib file */
2177 /* otherwise, try loading as a regular file */
2178 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2179 return TYPE_E_CANTLOADLIBRARY;
2182 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2184 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2185 EnterCriticalSection(&cache_section);
2186 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2188 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2190 TRACE("cache hit\n");
2191 *ppTypeLib = (ITypeLib2*)entry;
2192 ITypeLib_AddRef(*ppTypeLib);
2193 LeaveCriticalSection(&cache_section);
2197 LeaveCriticalSection(&cache_section);
2199 /* now actually load and parse the typelib */
2202 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2203 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2206 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2209 LPVOID pBase = LockResource(hGlobal);
2210 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2214 /* try to load as incore resource */
2215 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2216 if (dwSignature == MSFT_SIGNATURE)
2217 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2218 else if (dwSignature == SLTG_SIGNATURE)
2219 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2221 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2223 FreeResource( hGlobal );
2226 FreeLibrary(hinstDLL);
2230 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2231 if (INVALID_HANDLE_VALUE != hFile)
2233 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2236 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2239 /* retrieve file size */
2240 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2241 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2243 if (dwSignature == MSFT_SIGNATURE)
2244 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2245 else if (dwSignature == SLTG_SIGNATURE)
2246 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2248 UnmapViewOfFile(pBase);
2250 CloseHandle(hMapping);
2257 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2259 TRACE("adding to cache\n");
2260 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2261 lstrcpyW(impl->path, pszPath);
2262 /* We should really canonicalise the path here. */
2263 impl->index = index;
2265 /* FIXME: check if it has added already in the meantime */
2266 EnterCriticalSection(&cache_section);
2267 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2269 tlb_cache_first = impl;
2270 LeaveCriticalSection(&cache_section);
2273 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2278 /*================== ITypeLib(2) Methods ===================================*/
2280 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2282 ITypeLibImpl* pTypeLibImpl;
2284 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2285 if (!pTypeLibImpl) return NULL;
2287 pTypeLibImpl->lpVtbl = &tlbvt;
2288 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2289 pTypeLibImpl->ref = 1;
2291 return pTypeLibImpl;
2294 /****************************************************************************
2295 * ITypeLib2_Constructor_MSFT
2297 * loading an MSFT typelib from an in-memory image
2299 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2303 MSFT_Header tlbHeader;
2304 MSFT_SegDir tlbSegDir;
2305 ITypeLibImpl * pTypeLibImpl;
2307 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2309 pTypeLibImpl = TypeLibImpl_Constructor();
2310 if (!pTypeLibImpl) return NULL;
2312 /* get pointer to beginning of typelib data */
2316 cx.pLibInfo = pTypeLibImpl;
2317 cx.length = dwTLBLength;
2320 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2321 TRACE_(typelib)("header:\n");
2322 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2323 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2324 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2327 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2329 /* there is a small amount of information here until the next important
2331 * the segment directory . Try to calculate the amount of data */
2332 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2334 /* now read the segment directory */
2335 TRACE("read segment directory (at %ld)\n",lPSegDir);
2336 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2337 cx.pTblDir = &tlbSegDir;
2339 /* just check two entries */
2340 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2342 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2343 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2347 /* now fill our internal data */
2348 /* TLIBATTR fields */
2349 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2351 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2352 /* Windows seems to have zero here, is this correct? */
2353 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2354 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2356 pTypeLibImpl->LibAttr.lcid = 0;
2358 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2359 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2360 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2361 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2363 /* name, eventually add to a hash table */
2364 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2367 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2368 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2370 if( tlbHeader.varflags & HELPDLLFLAG)
2373 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2374 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2377 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2380 if(tlbHeader.CustomDataOffset >= 0)
2382 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2385 /* fill in typedescriptions */
2386 if(tlbSegDir.pTypdescTab.length > 0)
2388 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2390 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2391 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2394 /* FIXME: add several sanity checks here */
2395 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2396 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2398 /* FIXME: check safearray */
2400 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2402 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2404 else if(td[0] == VT_CARRAY)
2406 /* array descr table here */
2407 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2409 else if(td[0] == VT_USERDEFINED)
2411 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2413 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2416 /* second time around to fill the array subscript info */
2419 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2420 if(tlbSegDir.pArrayDescriptions.offset>0)
2422 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2423 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2426 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2428 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2430 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2432 for(j = 0; j<td[2]; j++)
2434 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2435 sizeof(INT), &cx, DO_NOT_SEEK);
2436 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2437 sizeof(INT), &cx, DO_NOT_SEEK);
2442 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2443 ERR("didn't find array description data\n");
2448 /* imported type libs */
2449 if(tlbSegDir.pImpFiles.offset>0)
2451 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2452 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2455 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2460 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2461 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2462 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2464 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2465 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2466 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2467 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2470 name = TLB_Alloc(size+1);
2471 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2472 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2473 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2474 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2477 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2478 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2480 ppImpLib = &(*ppImpLib)->next;
2485 if(tlbHeader.nrtypeinfos >= 0 )
2487 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2488 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2491 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2493 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2495 ppTI = &((*ppTI)->next);
2496 (pTypeLibImpl->TypeInfoCount)++;
2500 TRACE("(%p)\n", pTypeLibImpl);
2501 return (ITypeLib2*) pTypeLibImpl;
2505 static BSTR TLB_MultiByteToBSTR(char *ptr)
2511 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2512 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2513 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2514 ret = SysAllocString(nameW);
2515 HeapFree(GetProcessHeap(), 0, nameW);
2519 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2525 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2526 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2530 guid->Data4[0] = s >> 8;
2531 guid->Data4[1] = s & 0xff;
2534 for(i = 0; i < 6; i++) {
2535 memcpy(b, str + 24 + 2 * i, 2);
2536 guid->Data4[i + 2] = strtol(b, NULL, 16);
2541 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2548 bytelen = *(WORD*)ptr;
2549 if(bytelen == 0xffff) return 2;
2550 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2551 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2552 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2553 *pBstr = SysAllocStringLen(nameW, len);
2554 HeapFree(GetProcessHeap(), 0, nameW);
2558 static WORD SLTG_ReadStringA(char *ptr, char **str)
2563 bytelen = *(WORD*)ptr;
2564 if(bytelen == 0xffff) return 2;
2565 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2566 memcpy(*str, ptr + 2, bytelen);
2567 (*str)[bytelen] = '\0';
2571 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2573 char *ptr = pLibBlk;
2576 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2577 FIXME("libblk magic = %04x\n", w);
2582 if((w = *(WORD*)ptr) != 0xffff) {
2583 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2588 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2590 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2592 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2595 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2598 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2599 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2601 pTypeLibImpl->LibAttr.lcid = 0;
2604 ptr += 4; /* skip res12 */
2606 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2609 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2612 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2615 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2616 ptr += sizeof(GUID);
2618 return ptr - (char*)pLibBlk;
2621 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2624 TYPEDESC *pTD = &pElem->tdesc;
2626 /* Handle [in/out] first */
2627 if((*pType & 0xc000) == 0xc000)
2628 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2629 else if(*pType & 0x8000)
2630 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2631 else if(*pType & 0x4000)
2632 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2634 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2637 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2640 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2643 if((*pType & 0xe00) == 0xe00) {
2645 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2647 pTD = pTD->u.lptdesc;
2649 switch(*pType & 0x7f) {
2652 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2654 pTD = pTD->u.lptdesc;
2657 case VT_USERDEFINED:
2658 pTD->vt = VT_USERDEFINED;
2659 pTD->u.hreftype = *(++pType) / 4;
2665 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2668 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2670 pTD->vt = VT_CARRAY;
2671 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2673 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2674 pTD->u.lpadesc->cDims = pSA->cDims;
2675 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2676 pSA->cDims * sizeof(SAFEARRAYBOUND));
2678 pTD = &pTD->u.lpadesc->tdescElem;
2684 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2688 pTD->vt = VT_SAFEARRAY;
2689 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2691 pTD = pTD->u.lptdesc;
2695 pTD->vt = *pType & 0x7f;
2705 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2710 TLBRefType **ppRefType;
2712 if(pRef->magic != SLTG_REF_MAGIC) {
2713 FIXME("Ref magic = %x\n", pRef->magic);
2716 name = ( (char*)(&pRef->names) + pRef->number);
2718 ppRefType = &pTI->reflist;
2719 for(ref = 0; ref < pRef->number >> 3; ref++) {
2721 unsigned int lib_offs, type_num;
2723 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2724 sizeof(**ppRefType));
2726 name += SLTG_ReadStringA(name, &refname);
2727 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2728 FIXME("Can't sscanf ref\n");
2729 if(lib_offs != 0xffff) {
2730 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2733 if((*import)->offset == lib_offs)
2735 import = &(*import)->next;
2738 char fname[MAX_PATH+1];
2741 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2743 (*import)->offset = lib_offs;
2744 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2746 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2747 &(*import)->wVersionMajor,
2748 &(*import)->wVersionMinor,
2749 &(*import)->lcid, fname) != 4) {
2750 FIXME("can't sscanf ref %s\n",
2751 pNameTable + lib_offs + 40);
2753 len = strlen(fname);
2754 if(fname[len-1] != '#')
2755 FIXME("fname = %s\n", fname);
2756 fname[len-1] = '\0';
2757 (*import)->name = TLB_MultiByteToBSTR(fname);
2759 (*ppRefType)->pImpTLInfo = *import;
2760 } else { /* internal ref */
2761 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2763 (*ppRefType)->reference = ref;
2764 (*ppRefType)->index = type_num;
2766 HeapFree(GetProcessHeap(), 0, refname);
2767 ppRefType = &(*ppRefType)->next;
2769 if((BYTE)*name != SLTG_REF_MAGIC)
2770 FIXME("End of ref block magic = %x\n", *name);
2771 dump_TLBRefType(pTI->reflist);
2774 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2777 SLTG_ImplInfo *info;
2778 TLBImplType **ppImplType = &pTI->impltypelist;
2779 /* I don't really get this structure, usually it's 0x16 bytes
2780 long, but iuser.tlb contains some that are 0x18 bytes long.
2781 That's ok because we can use the next ptr to jump to the next
2782 one. But how do we know the length of the last one? The WORD
2783 at offs 0x8 might be the clue. For now I'm just assuming that
2784 the last one is the regular 0x16 bytes. */
2786 info = (SLTG_ImplInfo*)pBlk;
2788 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2789 sizeof(**ppImplType));
2790 (*ppImplType)->hRef = info->ref;
2791 (*ppImplType)->implflags = info->impltypeflags;
2792 pTI->TypeAttr.cImplTypes++;
2793 ppImplType = &(*ppImplType)->next;
2795 if(info->next == 0xffff)
2798 FIXME("Interface inheriting more than one interface\n");
2799 info = (SLTG_ImplInfo*)(pBlk + info->next);
2801 info++; /* see comment at top of function */
2805 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2808 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2809 SLTG_MemberHeader *pMemHeader;
2810 char *pFirstItem, *pNextItem;
2812 if(pTIHeader->href_table != 0xffffffff) {
2813 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2818 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2820 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2822 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2823 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2826 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2830 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2833 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2834 SLTG_MemberHeader *pMemHeader;
2835 SLTG_Function *pFunc;
2836 char *pFirstItem, *pNextItem;
2837 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2840 if(pTIHeader->href_table != 0xffffffff) {
2841 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2845 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2847 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2849 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2850 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2853 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2854 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2859 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2860 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2861 FIXME("func magic = %02x\n", pFunc->magic);
2864 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2865 sizeof(**ppFuncDesc));
2866 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2868 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2869 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2870 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2871 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2872 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2873 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2875 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2876 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2878 if(pFunc->retnextopt & 0x80)
2879 pType = &pFunc->rettype;
2881 pType = (WORD*)(pFirstItem + pFunc->rettype);
2884 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2886 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2887 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2888 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2889 (*ppFuncDesc)->pParamDesc =
2890 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2891 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2893 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2895 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2896 char *paramName = pNameTable + *pArg;
2898 /* If arg type follows then paramName points to the 2nd
2899 letter of the name, else the next WORD is an offset to
2900 the arg type and paramName points to the first letter.
2901 So let's take one char off paramName and see if we're
2902 pointing at an alpha-numeric char. However if *pArg is
2903 0xffff or 0xfffe then the param has no name, the former
2904 meaning that the next WORD is the type, the latter
2905 meaning the the next WORD is an offset to the type. */
2910 else if(*pArg == 0xfffe) {
2914 else if(paramName[-1] && !isalnum(paramName[-1]))
2919 if(HaveOffs) { /* the next word is an offset to type */
2920 pType = (WORD*)(pFirstItem + *pArg);
2921 SLTG_DoType(pType, pFirstItem,
2922 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2927 pArg = SLTG_DoType(pArg, pFirstItem,
2928 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2931 /* Are we an optional param ? */
2932 if((*ppFuncDesc)->funcdesc.cParams - param <=
2933 (*ppFuncDesc)->funcdesc.cParamsOpt)
2934 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2937 (*ppFuncDesc)->pParamDesc[param].Name =
2938 TLB_MultiByteToBSTR(paramName);
2942 ppFuncDesc = &((*ppFuncDesc)->next);
2943 if(pFunc->next == 0xffff) break;
2945 pTI->TypeAttr.cFuncs = num;
2946 if (TRACE_ON(typelib))
2947 dump_TLBFuncDesc(pTI->funclist);
2948 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2951 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2954 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2955 SLTG_MemberHeader *pMemHeader;
2956 SLTG_RecordItem *pItem;
2958 TLBVarDesc **ppVarDesc = &pTI->varlist;
2963 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2965 pFirstItem = (char*)(pMemHeader + 1);
2966 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2967 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2968 if(pItem->magic != SLTG_RECORD_MAGIC) {
2969 FIXME("record magic = %02x\n", pItem->magic);
2972 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2973 sizeof(**ppVarDesc));
2974 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2975 (*ppVarDesc)->vardesc.memid = pItem->memid;
2976 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2977 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2979 if(pItem->typepos == 0x02)
2980 pType = &pItem->type;
2981 else if(pItem->typepos == 0x00)
2982 pType = (WORD*)(pFirstItem + pItem->type);
2984 FIXME("typepos = %02x\n", pItem->typepos);
2988 SLTG_DoType(pType, pFirstItem,
2989 &(*ppVarDesc)->vardesc.elemdescVar);
2991 /* FIXME("helpcontext, helpstring\n"); */
2993 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2995 ppVarDesc = &((*ppVarDesc)->next);
2996 if(pItem->next == 0xffff) break;
2998 pTI->TypeAttr.cVars = num;
2999 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3002 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3005 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3006 SLTG_MemberHeader *pMemHeader;
3007 SLTG_AliasItem *pItem;
3010 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3011 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3014 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3015 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3016 if (pItem->vt == 0xffff) {
3017 if (i<(pMemHeader->cbExtra/4-1))
3018 FIXME("Endmarker too early in process alias data!\n");
3022 FIXME("Chain extends over last entry?\n");
3025 if (pItem->vt == VT_USERDEFINED) {
3026 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3027 /* guessing here ... */
3028 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3029 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3032 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3033 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3037 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3040 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3043 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3044 SLTG_MemberHeader *pMemHeader;
3045 SLTG_AliasItem *pItem;
3047 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3048 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3049 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3050 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3051 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3054 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3057 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3058 SLTG_MemberHeader *pMemHeader;
3059 SLTG_EnumItem *pItem;
3061 TLBVarDesc **ppVarDesc = &pTI->varlist;
3064 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3066 pFirstItem = (char*)(pMemHeader + 1);
3067 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3068 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3069 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3070 FIXME("enumitem magic = %04x\n", pItem->magic);
3073 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3074 sizeof(**ppVarDesc));
3075 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3076 (*ppVarDesc)->vardesc.memid = pItem->memid;
3077 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3079 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3080 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3081 *(INT*)(pItem->value + pFirstItem);
3082 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3083 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3084 /* FIXME("helpcontext, helpstring\n"); */
3086 ppVarDesc = &((*ppVarDesc)->next);
3087 if(pItem->next == 0xffff) break;
3089 pTI->TypeAttr.cVars = num;
3090 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3093 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3094 managable copy of it into this */
3107 } SLTG_InternalOtherTypeInfo;
3109 /****************************************************************************
3110 * ITypeLib2_Constructor_SLTG
3112 * loading a SLTG typelib from an in-memory image
3114 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3116 ITypeLibImpl *pTypeLibImpl;
3117 SLTG_Header *pHeader;
3118 SLTG_BlkEntry *pBlkEntry;
3122 LPVOID pBlk, pFirstBlk;
3123 SLTG_LibBlk *pLibBlk;
3124 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3125 char *pAfterOTIBlks = NULL;
3126 char *pNameTable, *ptr;
3129 ITypeInfoImpl **ppTypeInfoImpl;
3131 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3134 pTypeLibImpl = TypeLibImpl_Constructor();
3135 if (!pTypeLibImpl) return NULL;
3139 TRACE_(typelib)("header:\n");
3140 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3141 pHeader->nrOfFileBlks );
3142 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3143 FIXME("Header type magic 0x%08lx not supported.\n",
3144 pHeader->SLTG_magic);
3148 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3149 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3151 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3152 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3154 /* Next we have a magic block */
3155 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3157 /* Let's see if we're still in sync */
3158 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3159 sizeof(SLTG_COMPOBJ_MAGIC))) {
3160 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3163 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3164 sizeof(SLTG_DIR_MAGIC))) {
3165 FIXME("dir magic = %s\n", pMagic->dir_magic);
3169 pIndex = (SLTG_Index*)(pMagic+1);
3171 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3173 pFirstBlk = (LPVOID)(pPad9 + 1);
3175 /* We'll set up a ptr to the main library block, which is the last one. */
3177 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3178 pBlkEntry[order].next != 0;
3179 order = pBlkEntry[order].next - 1, i++) {
3180 pBlk = (char*)pBlk + pBlkEntry[order].len;
3184 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3186 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3191 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3193 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3194 sizeof(*pOtherTypeInfoBlks) *
3195 pTypeLibImpl->TypeInfoCount);
3198 ptr = (char*)pLibBlk + len;
3200 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3204 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3206 w = *(WORD*)(ptr + 2);
3209 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3211 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3212 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3214 w = *(WORD*)(ptr + 4 + len);
3216 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3218 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3220 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3221 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3223 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3224 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3225 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3227 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3229 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3232 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3233 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3234 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3235 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3236 len += sizeof(SLTG_OtherTypeInfo);
3240 pAfterOTIBlks = ptr;
3242 /* Skip this WORD and get the next DWORD */
3243 len = *(DWORD*)(pAfterOTIBlks + 2);
3245 /* Now add this to pLibBLk look at what we're pointing at and
3246 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3247 dust and we should be pointing at the beginning of the name
3250 pNameTable = (char*)pLibBlk + len;
3252 switch(*(WORD*)pNameTable) {
3259 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3263 pNameTable += 0x216;
3267 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3269 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3272 /* Hopefully we now have enough ptrs set up to actually read in
3273 some TypeInfos. It's not clear which order to do them in, so
3274 I'll just follow the links along the BlkEntry chain and read
3275 them in in the order in which they're in the file */
3277 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3279 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3280 pBlkEntry[order].next != 0;
3281 order = pBlkEntry[order].next - 1, i++) {
3283 SLTG_TypeInfoHeader *pTIHeader;
3284 SLTG_TypeInfoTail *pTITail;
3286 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3287 pOtherTypeInfoBlks[i].index_name)) {
3288 FIXME("Index strings don't match\n");
3293 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3294 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3297 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3298 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3299 (*ppTypeInfoImpl)->index = i;
3300 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3301 pOtherTypeInfoBlks[i].name_offs +
3303 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3304 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3306 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3307 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3308 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3309 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3310 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3312 if((pTIHeader->typeflags1 & 7) != 2)
3313 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3314 if(pTIHeader->typeflags3 != 2)
3315 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3317 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3318 debugstr_w((*ppTypeInfoImpl)->Name),
3319 typekind_desc[pTIHeader->typekind],
3320 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3321 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3323 switch(pTIHeader->typekind) {
3325 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3329 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3332 case TKIND_INTERFACE:
3333 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3337 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3341 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3342 if (pTITail->tdescalias_vt)
3343 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3346 case TKIND_DISPATCH:
3347 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3351 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3357 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3358 but we've already set those */
3359 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3360 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3361 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3363 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3385 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3386 pBlk = (char*)pBlk + pBlkEntry[order].len;
3389 if(i != pTypeLibImpl->TypeInfoCount) {
3390 FIXME("Somehow processed %d TypeInfos\n", i);
3394 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3395 return (ITypeLib2*)pTypeLibImpl;
3398 /* ITypeLib::QueryInterface
3400 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3405 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3407 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3410 if(IsEqualIID(riid, &IID_IUnknown) ||
3411 IsEqualIID(riid,&IID_ITypeLib)||
3412 IsEqualIID(riid,&IID_ITypeLib2))
3419 ITypeLib2_AddRef(iface);
3420 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3423 TRACE("-- Interface: E_NOINTERFACE\n");
3424 return E_NOINTERFACE;
3429 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3431 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3432 ULONG ref = InterlockedIncrement(&This->ref);
3434 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3439 /* ITypeLib::Release
3441 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3443 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3444 ULONG ref = InterlockedDecrement(&This->ref);
3446 TRACE("(%p)->(%lu)\n",This, ref);
3450 /* remove cache entry */
3453 TRACE("removing from cache list\n");
3454 EnterCriticalSection(&cache_section);
3455 if (This->next) This->next->prev = This->prev;
3456 if (This->prev) This->prev->next = This->next;
3457 else tlb_cache_first = This->next;
3458 LeaveCriticalSection(&cache_section);
3459 HeapFree(GetProcessHeap(), 0, This->path);
3461 /* FIXME destroy child objects */
3462 TRACE(" destroying ITypeLib(%p)\n",This);
3466 SysFreeString(This->Name);
3470 if (This->DocString)
3472 SysFreeString(This->DocString);
3473 This->DocString = NULL;
3478 SysFreeString(This->HelpFile);
3479 This->HelpFile = NULL;
3482 if (This->HelpStringDll)
3484 SysFreeString(This->HelpStringDll);
3485 This->HelpStringDll = NULL;
3488 if (This->pTypeInfo) /* can be NULL */
3489 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3490 HeapFree(GetProcessHeap(),0,This);
3497 /* ITypeLib::GetTypeInfoCount
3499 * Returns the number of type descriptions in the type library
3501 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3503 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3504 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3505 return This->TypeInfoCount;
3508 /* ITypeLib::GetTypeInfo
3510 * retrieves the specified type description in the library.
3512 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3515 ITypeInfo **ppTInfo)
3519 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3520 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3522 TRACE("(%p)->(index=%d)\n", This, index);
3524 if (!ppTInfo) return E_INVALIDARG;
3526 /* search element n in list */
3527 for(i=0; i < index; i++)
3529 pTypeInfo = pTypeInfo->next;
3532 TRACE("-- element not found\n");
3533 return TYPE_E_ELEMENTNOTFOUND;
3537 *ppTInfo = (ITypeInfo *) pTypeInfo;
3539 ITypeInfo_AddRef(*ppTInfo);
3540 TRACE("-- found (%p)\n",*ppTInfo);
3545 /* ITypeLibs::GetTypeInfoType
3547 * Retrieves the type of a type description.
3549 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3554 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3556 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3558 TRACE("(%p) index %d\n", This, index);
3560 if(!pTKind) return E_INVALIDARG;
3562 /* search element n in list */
3563 for(i=0; i < index; i++)
3567 TRACE("-- element not found\n");
3568 return TYPE_E_ELEMENTNOTFOUND;
3570 pTInfo = pTInfo->next;
3573 *pTKind = pTInfo->TypeAttr.typekind;
3574 TRACE("-- found Type (%d)\n", *pTKind);
3578 /* ITypeLib::GetTypeInfoOfGuid
3580 * Retrieves the type description that corresponds to the specified GUID.
3583 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3586 ITypeInfo **ppTInfo)
3588 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3589 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3591 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3595 WARN("-- element not found\n");
3596 return TYPE_E_ELEMENTNOTFOUND;
3599 /* search linked list for guid */
3600 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3602 pTypeInfo = pTypeInfo->next;
3606 /* end of list reached */
3607 WARN("-- element not found\n");
3608 return TYPE_E_ELEMENTNOTFOUND;
3612 TRACE("-- found (%p, %s)\n",
3614 debugstr_w(pTypeInfo->Name));
3616 *ppTInfo = (ITypeInfo*)pTypeInfo;
3617 ITypeInfo_AddRef(*ppTInfo);
3621 /* ITypeLib::GetLibAttr
3623 * Retrieves the structure that contains the library's attributes.
3626 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3628 LPTLIBATTR *ppTLibAttr)
3630 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3631 TRACE("(%p)\n",This);
3632 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3633 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3637 /* ITypeLib::GetTypeComp
3639 * Enables a client compiler to bind to a library's types, variables,
3640 * constants, and global functions.
3643 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3645 ITypeComp **ppTComp)
3647 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3649 TRACE("(%p)->(%p)\n",This,ppTComp);
3650 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3651 ITypeComp_AddRef(*ppTComp);
3656 /* ITypeLib::GetDocumentation
3658 * Retrieves the library's documentation string, the complete Help file name
3659 * and path, and the context identifier for the library Help topic in the Help
3662 * On a successful return all non-null BSTR pointers will have been set,
3665 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3669 BSTR *pBstrDocString,
3670 DWORD *pdwHelpContext,
3671 BSTR *pBstrHelpFile)
3673 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3675 HRESULT result = E_INVALIDARG;
3680 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3682 pBstrName, pBstrDocString,
3683 pdwHelpContext, pBstrHelpFile);
3687 /* documentation for the typelib */
3692 if(!(*pBstrName = SysAllocString(This->Name)))
3700 if (This->DocString)
3702 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3705 else if (This->Name)
3707 if(!(*pBstrDocString = SysAllocString(This->Name)))
3711 *pBstrDocString = NULL;
3715 *pdwHelpContext = This->dwHelpContext;
3721 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3725 *pBstrHelpFile = NULL;
3732 /* for a typeinfo */
3733 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3735 if(SUCCEEDED(result))
3737 result = ITypeInfo_GetDocumentation(pTInfo,
3741 pdwHelpContext, pBstrHelpFile);
3743 ITypeInfo_Release(pTInfo);
3748 if (pBstrDocString) SysFreeString (*pBstrDocString);
3750 if (pBstrName) SysFreeString (*pBstrName);
3752 return STG_E_INSUFFICIENTMEMORY;
3757 * Indicates whether a passed-in string contains the name of a type or member
3758 * described in the library.
3761 static HRESULT WINAPI ITypeLib2_fnIsName(
3767 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3768 ITypeInfoImpl *pTInfo;
3769 TLBFuncDesc *pFInfo;
3772 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3774 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3778 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3779 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3780 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3781 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3782 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3783 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3784 goto ITypeLib2_fnIsName_exit;
3786 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3787 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3792 ITypeLib2_fnIsName_exit:
3793 TRACE("(%p)slow! search for %s: %s found!\n", This,
3794 debugstr_w(szNameBuf), *pfName?"NOT":"");
3799 /* ITypeLib::FindName
3801 * Finds occurrences of a type description in a type library. This may be used
3802 * to quickly verify that a name exists in a type library.
3805 static HRESULT WINAPI ITypeLib2_fnFindName(
3809 ITypeInfo **ppTInfo,
3813 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3814 ITypeInfoImpl *pTInfo;
3815 TLBFuncDesc *pFInfo;
3818 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3820 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3821 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3822 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3823 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3824 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3825 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3826 goto ITypeLib2_fnFindName_exit;
3829 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3830 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3832 ITypeLib2_fnFindName_exit:
3833 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3834 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3837 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3838 This, *pcFound, debugstr_w(szNameBuf), j);
3845 /* ITypeLib::ReleaseTLibAttr
3847 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3850 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3852 TLIBATTR *pTLibAttr)
3854 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3855 TRACE("freeing (%p)\n",This);
3856 HeapFree(GetProcessHeap(),0,pTLibAttr);
3860 /* ITypeLib2::GetCustData
3862 * gets the custom data
3864 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3869 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3870 TLBCustData *pCData;
3872 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3874 if( IsEqualIID(guid, &pCData->guid)) break;
3877 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3881 VariantInit( pVarVal);
3882 VariantCopy( pVarVal, &pCData->data);
3885 return E_INVALIDARG; /* FIXME: correct? */
3888 /* ITypeLib2::GetLibStatistics
3890 * Returns statistics about a type library that are required for efficient
3891 * sizing of hash tables.
3894 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3896 ULONG *pcUniqueNames,
3897 ULONG *pcchUniqueNames)
3899 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3901 FIXME("(%p): stub!\n", This);
3903 if(pcUniqueNames) *pcUniqueNames=1;
3904 if(pcchUniqueNames) *pcchUniqueNames=1;
3908 /* ITypeLib2::GetDocumentation2
3910 * Retrieves the library's documentation string, the complete Help file name
3911 * and path, the localization context to use, and the context ID for the
3912 * library Help topic in the Help file.
3915 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3919 BSTR *pbstrHelpString,
3920 DWORD *pdwHelpStringContext,
3921 BSTR *pbstrHelpStringDll)
3923 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3927 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3929 /* the help string should be obtained from the helpstringdll,
3930 * using the _DLLGetDocumentation function, based on the supplied
3931 * lcid. Nice to do sometime...
3935 /* documentation for the typelib */
3937 *pbstrHelpString=SysAllocString(This->DocString);
3938 if(pdwHelpStringContext)
3939 *pdwHelpStringContext=This->dwHelpContext;
3940 if(pbstrHelpStringDll)
3941 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3947 /* for a typeinfo */
3948 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3950 if(SUCCEEDED(result))
3952 ITypeInfo2 * pTInfo2;
3953 result = ITypeInfo_QueryInterface(pTInfo,
3955 (LPVOID*) &pTInfo2);
3957 if(SUCCEEDED(result))
3959 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3963 pdwHelpStringContext,
3964 pbstrHelpStringDll);
3966 ITypeInfo2_Release(pTInfo2);
3969 ITypeInfo_Release(pTInfo);
3975 /* ITypeLib2::GetAllCustData
3977 * Gets all custom data items for the library.
3980 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3982 CUSTDATA *pCustData)
3984 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3985 TLBCustData *pCData;
3987 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3988 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3989 if(pCustData->prgCustData ){
3990 pCustData->cCustData=This->ctCustData;
3991 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3992 pCustData->prgCustData[i].guid=pCData->guid;
3993 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3996 ERR(" OUT OF MEMORY!\n");
3997 return E_OUTOFMEMORY;
4002 static const ITypeLib2Vtbl tlbvt = {
4003 ITypeLib2_fnQueryInterface,
4005 ITypeLib2_fnRelease,
4006 ITypeLib2_fnGetTypeInfoCount,
4007 ITypeLib2_fnGetTypeInfo,
4008 ITypeLib2_fnGetTypeInfoType,
4009 ITypeLib2_fnGetTypeInfoOfGuid,
4010 ITypeLib2_fnGetLibAttr,
4011 ITypeLib2_fnGetTypeComp,
4012 ITypeLib2_fnGetDocumentation,
4014 ITypeLib2_fnFindName,
4015 ITypeLib2_fnReleaseTLibAttr,
4017 ITypeLib2_fnGetCustData,
4018 ITypeLib2_fnGetLibStatistics,
4019 ITypeLib2_fnGetDocumentation2,
4020 ITypeLib2_fnGetAllCustData
4024 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4026 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4028 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4031 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4033 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4035 return ITypeLib2_AddRef((ITypeLib2 *)This);
4038 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4040 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4042 return ITypeLib2_Release((ITypeLib2 *)This);
4045 static HRESULT WINAPI ITypeLibComp_fnBind(
4050 ITypeInfo ** ppTInfo,
4051 DESCKIND * pDescKind,
4054 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4055 ITypeInfoImpl *pTypeInfo;
4057 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4059 *pDescKind = DESCKIND_NONE;
4060 pBindPtr->lptcomp = NULL;
4063 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4065 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4067 /* FIXME: check wFlags here? */
4068 /* FIXME: we should use a hash table to look this info up using lHash
4069 * instead of an O(n) search */
4070 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4071 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4073 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4075 *pDescKind = DESCKIND_TYPECOMP;
4076 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4077 ITypeComp_AddRef(pBindPtr->lptcomp);
4078 TRACE("module or enum: %s\n", debugstr_w(szName));
4083 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4084 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4086 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4089 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4090 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4092 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4097 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4098 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4100 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4102 ITypeInfo *subtypeinfo;
4104 DESCKIND subdesckind;
4106 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4107 &subtypeinfo, &subdesckind, &subbindptr);
4108 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4110 TYPEDESC tdesc_appobject =
4113 (TYPEDESC *)pTypeInfo->hreftype
4117 const VARDESC vardesc_appobject =
4120 NULL, /* lpstrSchema */
4135 VAR_STATIC /* varkind */
4138 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4140 /* cleanup things filled in by Bind call so we can put our
4141 * application object data in there instead */
4142 switch (subdesckind)
4144 case DESCKIND_FUNCDESC:
4145 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4147 case DESCKIND_VARDESC:
4148 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4153 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4155 if (pTypeInfo->hreftype == -1)
4156 FIXME("no hreftype for interface %p\n", pTypeInfo);
4158 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4162 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4163 *ppTInfo = (ITypeInfo *)pTypeInfo;
4164 ITypeInfo_AddRef(*ppTInfo);
4170 TRACE("name not found %s\n", debugstr_w(szName));
4174 static HRESULT WINAPI ITypeLibComp_fnBindType(
4178 ITypeInfo ** ppTInfo,
4179 ITypeComp ** ppTComp)
4181 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4185 static const ITypeCompVtbl tlbtcvt =
4188 ITypeLibComp_fnQueryInterface,
4189 ITypeLibComp_fnAddRef,
4190 ITypeLibComp_fnRelease,
4192 ITypeLibComp_fnBind,
4193 ITypeLibComp_fnBindType
4196 /*================== ITypeInfo(2) Methods ===================================*/
4197 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4199 ITypeInfoImpl * pTypeInfoImpl;
4201 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4204 pTypeInfoImpl->lpVtbl = &tinfvt;
4205 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4206 pTypeInfoImpl->ref=1;
4207 pTypeInfoImpl->hreftype = -1;
4209 TRACE("(%p)\n", pTypeInfoImpl);
4210 return (ITypeInfo2*) pTypeInfoImpl;
4213 /* ITypeInfo::QueryInterface
4215 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4220 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4222 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4225 if(IsEqualIID(riid, &IID_IUnknown) ||
4226 IsEqualIID(riid,&IID_ITypeInfo)||
4227 IsEqualIID(riid,&IID_ITypeInfo2))
4231 ITypeInfo_AddRef(iface);
4232 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4235 TRACE("-- Interface: E_NOINTERFACE\n");
4236 return E_NOINTERFACE;
4239 /* ITypeInfo::AddRef
4241 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4243 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4244 ULONG ref = InterlockedIncrement(&This->ref);
4246 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4248 TRACE("(%p)->ref is %lu\n",This, ref);
4252 /* ITypeInfo::Release
4254 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4256 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4257 ULONG ref = InterlockedDecrement(&This->ref);
4259 TRACE("(%p)->(%lu)\n",This, ref);
4262 /* We don't release ITypeLib when ref=0 because
4263 it means that function is called by ITypeLib2_Release */
4264 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4266 static int once = 0;
4270 FIXME("destroy child objects\n");
4273 TRACE("destroying ITypeInfo(%p)\n",This);
4276 SysFreeString(This->Name);
4280 if (This->DocString)
4282 SysFreeString(This->DocString);
4283 This->DocString = 0;
4288 SysFreeString(This->DllName);
4294 ITypeInfo_Release((ITypeInfo*)This->next);
4297 HeapFree(GetProcessHeap(),0,This);
4303 /* ITypeInfo::GetTypeAttr
4305 * Retrieves a TYPEATTR structure that contains the attributes of the type
4309 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4310 LPTYPEATTR *ppTypeAttr)
4312 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4315 TRACE("(%p)\n",This);
4317 size = sizeof(**ppTypeAttr);
4318 if (This->TypeAttr.typekind == TKIND_ALIAS)
4319 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4321 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4323 return E_OUTOFMEMORY;
4325 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4327 if (This->TypeAttr.typekind == TKIND_ALIAS)
4328 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4329 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4331 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4332 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4334 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4335 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4340 /* ITypeInfo::GetTypeComp
4342 * Retrieves the ITypeComp interface for the type description, which enables a
4343 * client compiler to bind to the type description's members.
4346 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4347 ITypeComp * *ppTComp)
4349 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4351 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4353 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4354 ITypeComp_AddRef(*ppTComp);
4358 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4360 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4361 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4362 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4366 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4368 memcpy(dest, src, sizeof(ELEMDESC));
4369 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4370 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4372 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4373 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4374 *buffer += sizeof(PARAMDESCEX);
4375 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4376 VariantInit(&pparamdescex_dest->varDefaultValue);
4377 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4378 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4381 dest->u.paramdesc.pparamdescex = NULL;
4385 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4387 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4388 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4391 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4395 SIZE_T size = sizeof(*src);
4399 size += sizeof(*src->lprgscode) * src->cScodes;
4400 size += TLB_SizeElemDesc(&src->elemdescFunc);
4401 for (i = 0; i < src->cParams; i++)
4403 size += sizeof(ELEMDESC);
4404 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4407 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4408 if (!dest) return E_OUTOFMEMORY;
4410 memcpy(dest, src, sizeof(FUNCDESC));
4411 buffer = (char *)(dest + 1);
4413 dest->lprgscode = (SCODE *)buffer;
4414 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4415 buffer += sizeof(*src->lprgscode) * src->cScodes;
4417 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4420 SysFreeString((BSTR)dest);
4424 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4425 buffer += sizeof(ELEMDESC) * src->cParams;
4426 for (i = 0; i < src->cParams; i++)
4428 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4434 /* undo the above actions */
4435 for (i = i - 1; i >= 0; i--)
4436 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4437 TLB_FreeElemDesc(&dest->elemdescFunc);
4438 SysFreeString((BSTR)dest);
4442 /* special treatment for dispinterfaces: this makes functions appear
4443 * to return their [retval] value when it is really returning an
4445 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4447 if (dest->cParams &&
4448 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4450 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4451 if (elemdesc->tdesc.vt != VT_PTR)
4453 ERR("elemdesc should have started with VT_PTR instead of:\n");
4455 dump_ELEMDESC(elemdesc);
4456 return E_UNEXPECTED;
4459 /* copy last parameter to the return value. we are using a flat
4460 * buffer so there is no danger of leaking memory in
4462 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4464 /* remove the last parameter */
4468 /* otherwise this function is made to appear to have no return
4470 dest->elemdescFunc.tdesc.vt = VT_VOID;
4478 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4480 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4481 const TLBFuncDesc *pFDesc;
4484 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4489 *ppFuncDesc = &pFDesc->funcdesc;
4493 return E_INVALIDARG;
4496 /* ITypeInfo::GetFuncDesc
4498 * Retrieves the FUNCDESC structure that contains information about a
4499 * specified function.
4502 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4503 LPFUNCDESC *ppFuncDesc)
4505 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4506 const FUNCDESC *internal_funcdesc;
4509 TRACE("(%p) index %d\n", This, index);
4511 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4515 return TLB_AllocAndInitFuncDesc(
4518 This->TypeAttr.typekind == TKIND_DISPATCH);
4521 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4525 SIZE_T size = sizeof(*src);
4528 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4529 if (src->varkind == VAR_CONST)
4530 size += sizeof(VARIANT);
4531 size += TLB_SizeElemDesc(&src->elemdescVar);
4533 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4534 if (!dest) return E_OUTOFMEMORY;
4537 buffer = (char *)(dest + 1);
4538 if (src->lpstrSchema)
4541 dest->lpstrSchema = (LPOLESTR)buffer;
4542 len = strlenW(src->lpstrSchema);
4543 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4544 buffer += (len + 1) * sizeof(WCHAR);
4547 if (src->varkind == VAR_CONST)
4551 dest->u.lpvarValue = (VARIANT *)buffer;
4552 *dest->u.lpvarValue = *src->u.lpvarValue;
4553 buffer += sizeof(VARIANT);
4554 VariantInit(dest->u.lpvarValue);
4555 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4558 SysFreeString((BSTR)dest_ptr);
4562 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4565 if (src->varkind == VAR_CONST)
4566 VariantClear(dest->u.lpvarValue);
4567 SysFreeString((BSTR)dest);
4574 /* ITypeInfo::GetVarDesc
4576 * Retrieves a VARDESC structure that describes the specified variable.
4579 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4580 LPVARDESC *ppVarDesc)
4582 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4584 const TLBVarDesc *pVDesc;
4586 TRACE("(%p) index %d\n", This, index);
4588 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4592 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4594 return E_INVALIDARG;
4597 /* ITypeInfo_GetNames
4599 * Retrieves the variable with the specified member ID (or the name of the
4600 * property or method and its parameters) that correspond to the specified
4603 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4604 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4606 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4607 const TLBFuncDesc *pFDesc;
4608 const TLBVarDesc *pVDesc;
4610 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4611 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4614 /* function found, now return function and parameter names */
4615 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4618 *rgBstrNames=SysAllocString(pFDesc->Name);
4620 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4626 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4629 *rgBstrNames=SysAllocString(pVDesc->Name);
4634 if(This->TypeAttr.cImplTypes &&
4635 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4636 /* recursive search */
4639 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4641 if(SUCCEEDED(result))
4643 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4644 ITypeInfo_Release(pTInfo);
4647 WARN("Could not search inherited interface!\n");
4651 WARN("no names found\n");
4654 return TYPE_E_ELEMENTNOTFOUND;
4661 /* ITypeInfo::GetRefTypeOfImplType
4663 * If a type description describes a COM class, it retrieves the type
4664 * description of the implemented interface types. For an interface,
4665 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4669 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4674 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4677 const TLBImplType *pImpl = This->impltypelist;
4679 TRACE("(%p) index %d\n", This, index);
4680 if (TRACE_ON(ole)) dump_TypeInfo(This);
4684 /* only valid on dual interfaces;
4685 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4687 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4689 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4690 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4696 hr = TYPE_E_ELEMENTNOTFOUND;
4701 /* get element n from linked list */
4702 for(i=0; pImpl && i<index; i++)
4704 pImpl = pImpl->next;
4708 *pRefType = pImpl->hRef;
4710 hr = TYPE_E_ELEMENTNOTFOUND;
4716 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4718 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4724 /* ITypeInfo::GetImplTypeFlags
4726 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4727 * or base interface in a type description.
4729 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4730 UINT index, INT *pImplTypeFlags)
4732 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4736 TRACE("(%p) index %d\n", This, index);
4737 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4738 i++, pImpl=pImpl->next)
4740 if(i==index && pImpl){
4741 *pImplTypeFlags=pImpl->implflags;
4745 return TYPE_E_ELEMENTNOTFOUND;
4749 * Maps between member names and member IDs, and parameter names and
4752 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4753 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4755 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4756 const TLBFuncDesc *pFDesc;
4757 const TLBVarDesc *pVDesc;
4761 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4764 /* init out parameters in case of failure */
4765 for (i = 0; i < cNames; i++)
4766 pMemId[i] = MEMBERID_NIL;
4768 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4770 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4771 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4772 for(i=1; i < cNames; i++){
4773 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4774 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4776 if( j<pFDesc->funcdesc.cParams)
4779 ret=DISP_E_UNKNOWNNAME;
4781 TRACE("-- 0x%08lx\n", ret);
4785 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4786 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4787 if(cNames) *pMemId=pVDesc->vardesc.memid;
4791 /* not found, see if it can be found in an inherited interface */
4792 if(This->TypeAttr.cImplTypes) {
4793 /* recursive search */
4795 ret=ITypeInfo_GetRefTypeInfo(iface,
4796 This->impltypelist->hRef, &pTInfo);
4798 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4799 ITypeInfo_Release(pTInfo);
4802 WARN("Could not search inherited interface!\n");
4804 WARN("no names found\n");
4805 return DISP_E_UNKNOWNNAME;
4808 /* ITypeInfo::Invoke
4810 * Invokes a method, or accesses a property of an object, that implements the
4811 * interface described by the type description.
4814 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4817 if (TRACE_ON(ole)) {
4819 TRACE("Calling %p(",func);
4820 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4832 res = func(args[0]);
4835 res = func(args[0],args[1]);
4838 res = func(args[0],args[1],args[2]);
4841 res = func(args[0],args[1],args[2],args[3]);
4844 res = func(args[0],args[1],args[2],args[3],args[4]);
4847 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4850 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4853 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4856 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4859 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4862 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4865 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
4868 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
4871 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
4874 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
4877 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
4880 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
4883 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
4886 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
4889 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
4892 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
4895 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
4898 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
4901 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4907 FIXME("unsupported calling convention %d\n",callconv);
4911 TRACE("returns %08lx\n",res);
4915 extern int _argsize(DWORD vt);
4917 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4920 ITypeInfo *tinfo2 = NULL;
4921 TYPEATTR *tattr = NULL;
4923 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4926 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4928 tdesc->u.hreftype, hr);
4931 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4934 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4935 ITypeInfo_Release(tinfo2);
4939 switch (tattr->typekind)
4946 tdesc = &tattr->tdescAlias;
4947 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4950 case TKIND_INTERFACE:
4951 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4957 case TKIND_DISPATCH:
4962 FIXME("TKIND_RECORD unhandled.\n");
4967 FIXME("TKIND_RECORD unhandled.\n");
4972 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4976 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4977 ITypeInfo_Release(tinfo2);
4981 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4985 /* enforce only one level of pointer indirection */
4986 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
4988 tdesc = tdesc->u.lptdesc;
4990 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4991 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4992 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4993 if ((tdesc->vt == VT_USERDEFINED) ||
4994 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4996 VARTYPE vt_userdefined = 0;
4997 const TYPEDESC *tdesc_userdefined = tdesc;
4998 if (tdesc->vt == VT_PTR)
5000 vt_userdefined = VT_BYREF;
5001 tdesc_userdefined = tdesc->u.lptdesc;
5003 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5005 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5006 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5008 *vt |= vt_userdefined;
5020 case VT_USERDEFINED:
5021 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5028 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5029 hr = DISP_E_BADVARTYPE;
5033 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5042 /***********************************************************************
5043 * DispCallFunc (OLEAUT32.@)
5045 * Invokes a function of the specifed calling convention, passing the
5046 * specified arguments and returns the result.
5049 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5050 * oVft [I] The offset in the vtable. See notes.
5051 * cc [I] Calling convention of the function to call.
5052 * vtReturn [I] The return type of the function.
5053 * cActuals [I] Number of parameters.
5054 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5055 * prgpvarg [I] The arguments to pass.
5056 * pvargResult [O] The return value of the function. Can be NULL.
5060 * Failure: HRESULT code.
5063 * The HRESULT return value of this function is not affected by the return
5064 * value of the user supplied function, which is returned in pvargResult.
5066 * If pvInstance is NULL then a non-object function is to be called and oVft
5067 * is the address of the function to call.
5069 * The cc parameter can be one of the following values:
5082 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5083 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5085 int i, argsize, argspos;
5089 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5090 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5091 pvargResult, V_VT(pvargResult));
5095 argsize++; /* for This pointer */
5097 for (i=0;i<cActuals;i++)
5099 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5100 dump_Variant(prgpvarg[i]);
5101 argsize += _argsize(prgvt[i]);
5103 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5108 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5112 for (i=0;i<cActuals;i++)
5114 VARIANT *arg = prgpvarg[i];
5115 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5116 if (prgvt[i] == VT_VARIANT)
5117 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5119 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5120 argspos += _argsize(prgvt[i]);
5125 FARPROC *vtable = *(FARPROC**)pvInstance;
5126 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5129 /* if we aren't invoking an object then the function pointer is stored
5131 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5133 if (pvargResult && (vtReturn != VT_EMPTY))
5135 TRACE("Method returned 0x%08lx\n",hres);
5136 V_VT(pvargResult) = vtReturn;
5137 V_UI4(pvargResult) = hres;
5140 HeapFree(GetProcessHeap(),0,args);
5144 #define INVBUF_ELEMENT_SIZE \
5145 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5146 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5147 ((VARIANTARG *)(buffer))
5148 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5149 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5150 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5151 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5152 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5153 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5155 static HRESULT WINAPI ITypeInfo_fnInvoke(
5160 DISPPARAMS *pDispParams,
5161 VARIANT *pVarResult,
5162 EXCEPINFO *pExcepInfo,
5165 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5167 unsigned int var_index;
5170 const TLBFuncDesc *pFuncInfo;
5172 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5173 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5175 dump_DispParms(pDispParams);
5177 /* we do this instead of using GetFuncDesc since it will return a fake
5178 * FUNCDESC for dispinterfaces and we want the real function description */
5179 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5180 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5184 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5188 TRACE("invoking:\n");
5189 dump_TLBFuncDescOne(pFuncInfo);
5192 switch (func_desc->funckind) {
5193 case FUNC_PUREVIRTUAL:
5194 case FUNC_VIRTUAL: {
5195 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5197 VARIANT retval; /* pointer for storing byref retvals in */
5198 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5199 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5200 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5203 for (i = 0; i < func_desc->cParams; i++)
5205 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5206 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5211 TRACE("changing args\n");
5212 for (i = 0; i < func_desc->cParams; i++)
5214 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5216 if (wParamFlags & PARAMFLAG_FRETVAL)
5218 /* note: this check is placed so that if the caller passes
5219 * in a VARIANTARG for the retval we just ignore it, like
5221 if (i == func_desc->cParams - 1)
5224 arg = prgpvarg[i] = &rgvarg[i];
5225 memset(arg, 0, sizeof(*arg));
5226 V_VT(arg) = rgvt[i];
5227 memset(&retval, 0, sizeof(retval));
5228 V_BYREF(arg) = &retval;
5232 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5233 hres = E_UNEXPECTED;
5237 else if (i < pDispParams->cArgs)
5239 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5240 dump_Variant(src_arg);
5242 if (rgvt[i] == VT_VARIANT)
5243 hres = VariantCopy(&rgvarg[i], src_arg);
5244 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5246 if (rgvt[i] == V_VT(src_arg))
5247 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5250 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5251 hres = VariantCopy(&missing_arg[i], src_arg);
5252 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5254 V_VT(&rgvarg[i]) = rgvt[i];
5256 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5258 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5259 V_VT(&missing_arg[i]) = V_VT(src_arg);
5260 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5261 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5262 V_VT(&rgvarg[i]) = rgvt[i];
5264 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5266 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5267 V_VT(&rgvarg[i]) = rgvt[i];
5271 /* FIXME: this doesn't work for VT_BYREF arguments if
5272 * they are not the same type as in the paramdesc */
5273 V_VT(&rgvarg[i]) = V_VT(src_arg);
5274 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5275 V_VT(&rgvarg[i]) = rgvt[i];
5280 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5281 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5282 debugstr_VT(src_arg), debugstr_VF(src_arg));
5285 prgpvarg[i] = &rgvarg[i];
5287 else if (wParamFlags & PARAMFLAG_FOPT)
5290 arg = prgpvarg[i] = &rgvarg[i];
5291 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5293 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5299 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5300 V_VT(arg) = VT_VARIANT | VT_BYREF;
5301 V_VARIANTREF(arg) = &missing_arg[i];
5302 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5303 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5308 hres = DISP_E_BADPARAMCOUNT;
5312 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5313 if (func_desc->cParamsOpt < 0)
5315 FIXME("Does not support safearray optional parameters\n");
5316 hres = DISP_E_BADPARAMCOUNT;
5317 goto func_fail; /* FIXME: we don't free changed types here */
5320 V_VT(&varresult) = 0;
5321 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5322 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5324 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5325 V_VT(&varresult), func_desc->cParams, rgvt,
5326 prgpvarg, &varresult);
5328 for (i = 0; i < func_desc->cParams; i++)
5330 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5331 if (wParamFlags & PARAMFLAG_FRETVAL)
5335 TRACE("[retval] value: ");
5336 dump_Variant(prgpvarg[i]);
5340 /* deref return value */
5341 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5343 /* free data stored in varresult. Note that
5344 * VariantClear doesn't do what we want because we are
5345 * working with byref types. */
5346 /* FIXME: clear safearrays, bstrs, records and
5347 * variants here too */
5348 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5349 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5351 if(*V_UNKNOWNREF(prgpvarg[i]))
5352 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5356 else if (i < pDispParams->cArgs)
5358 if (wParamFlags & PARAMFLAG_FOUT)
5360 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5362 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5363 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5367 ERR("failed to convert param %d to vt %d\n", i,
5368 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5372 VariantClear(&rgvarg[i]);
5374 else if (wParamFlags & PARAMFLAG_FOPT)
5376 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5377 VariantClear(&rgvarg[i]);
5381 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5383 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5384 hres = DISP_E_EXCEPTION;
5385 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5389 HeapFree(GetProcessHeap(), 0, buffer);
5392 case FUNC_DISPATCH: {
5395 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5396 if (SUCCEEDED(hres)) {
5397 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5398 hres = IDispatch_Invoke(
5399 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5400 pVarResult,pExcepInfo,pArgErr
5403 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5404 IDispatch_Release(disp);
5406 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5410 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5415 TRACE("-- 0x%08lx\n", hres);
5418 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5421 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5422 if(FAILED(hres)) return hres;
5424 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5425 dump_VARDESC(var_desc);
5426 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5430 /* not found, look for it in inherited interfaces */
5431 ITypeInfo2_GetTypeKind(iface, &type_kind);
5432 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5434 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5435 /* recursive search */
5437 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5438 if(SUCCEEDED(hres)){
5439 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5440 ITypeInfo_Release(pTInfo);
5443 WARN("Could not search inherited interface!\n");
5446 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5447 return DISP_E_MEMBERNOTFOUND;
5450 /* ITypeInfo::GetDocumentation
5452 * Retrieves the documentation string, the complete Help file name and path,
5453 * and the context ID for the Help topic for a specified type description.
5455 * (Can be tested by the Visual Basic Editor in Word for instance.)
5457 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5458 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5459 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5461 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5462 const TLBFuncDesc *pFDesc;
5463 const TLBVarDesc *pVDesc;
5464 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5465 " HelpContext(%p) HelpFile(%p)\n",
5466 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5467 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5469 *pBstrName=SysAllocString(This->Name);
5471 *pBstrDocString=SysAllocString(This->DocString);
5473 *pdwHelpContext=This->dwHelpContext;
5475 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5477 }else {/* for a member */
5478 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5479 if(pFDesc->funcdesc.memid==memid){
5481 *pBstrName = SysAllocString(pFDesc->Name);
5483 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5485 *pdwHelpContext=pFDesc->helpcontext;
5488 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5489 if(pVDesc->vardesc.memid==memid){
5491 *pBstrName = SysAllocString(pVDesc->Name);
5493 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5495 *pdwHelpContext=pVDesc->HelpContext;
5499 WARN("member %ld not found\n", memid);
5500 return TYPE_E_ELEMENTNOTFOUND;
5503 /* ITypeInfo::GetDllEntry
5505 * Retrieves a description or specification of an entry point for a function
5508 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5509 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5512 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5513 const TLBFuncDesc *pFDesc;
5515 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5517 if (pBstrDllName) *pBstrDllName = NULL;
5518 if (pBstrName) *pBstrName = NULL;
5519 if (pwOrdinal) *pwOrdinal = 0;
5521 if (This->TypeAttr.typekind != TKIND_MODULE)
5522 return TYPE_E_BADMODULEKIND;
5524 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5525 if(pFDesc->funcdesc.memid==memid){
5526 dump_TypeInfo(This);
5528 dump_TLBFuncDescOne(pFDesc);
5531 *pBstrDllName = SysAllocString(This->DllName);
5533 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5535 *pBstrName = SysAllocString(pFDesc->Entry);
5543 *pwOrdinal = (DWORD)pFDesc->Entry;
5546 return TYPE_E_ELEMENTNOTFOUND;
5549 /* ITypeInfo::GetRefTypeInfo
5551 * If a type description references other type descriptions, it retrieves
5552 * the referenced type descriptions.
5554 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5557 ITypeInfo **ppTInfo)
5559 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5560 HRESULT result = E_FAIL;
5562 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5564 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5565 ITypeInfo_AddRef(*ppTInfo);
5568 else if (hRefType == -1 &&
5569 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5570 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5572 /* when we meet a DUAL dispinterface, we must create the interface
5575 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5578 /* the interface version contains the same information as the dispinterface
5579 * copy the contents of the structs.
5581 *pTypeInfoImpl = *This;
5582 pTypeInfoImpl->ref = 1;
5584 /* change the type to interface */
5585 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5587 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5589 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5594 TLBRefType *pRefType;
5595 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5596 if(pRefType->reference == hRefType)
5600 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5601 if(pRefType && hRefType != -1) {
5602 ITypeLib *pTLib = NULL;
5604 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5606 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5608 if(pRefType->pImpTLInfo->pImpTypeLib) {
5609 TRACE("typeinfo in imported typelib that is already loaded\n");
5610 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5611 ITypeLib2_AddRef((ITypeLib*) pTLib);
5614 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5615 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5616 pRefType->pImpTLInfo->wVersionMajor,
5617 pRefType->pImpTLInfo->wVersionMinor,
5618 pRefType->pImpTLInfo->lcid,
5621 if(!SUCCEEDED(result)) {
5622 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5623 result=LoadTypeLib(libnam, &pTLib);
5624 SysFreeString(libnam);
5626 if(SUCCEEDED(result)) {
5627 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5628 ITypeLib2_AddRef(pTLib);
5632 if(SUCCEEDED(result)) {
5633 if(pRefType->index == TLB_REF_USE_GUID)
5634 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5638 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5642 ITypeLib2_Release(pTLib);
5646 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5647 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5651 /* ITypeInfo::AddressOfMember
5653 * Retrieves the addresses of static functions or variables, such as those
5656 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5657 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5659 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5665 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5667 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5671 module = LoadLibraryW(dll);
5674 ERR("couldn't load %s\n", debugstr_w(dll));
5676 if (entry) SysFreeString(entry);
5677 return STG_E_FILENOTFOUND;
5679 /* FIXME: store library somewhere where we can free it */
5684 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5685 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5686 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5688 *ppv = GetProcAddress(module, entryA);
5690 ERR("function not found %s\n", debugstr_a(entryA));
5692 HeapFree(GetProcessHeap(), 0, entryA);
5696 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5698 ERR("function not found %d\n", ordinal);
5702 if (entry) SysFreeString(entry);
5705 return TYPE_E_DLLFUNCTIONNOTFOUND;
5710 /* ITypeInfo::CreateInstance
5712 * Creates a new instance of a type that describes a component object class
5715 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5716 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5718 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5719 FIXME("(%p) stub!\n", This);
5723 /* ITypeInfo::GetMops
5725 * Retrieves marshalling information.
5727 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5730 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5731 FIXME("(%p) stub!\n", This);
5735 /* ITypeInfo::GetContainingTypeLib
5737 * Retrieves the containing type library and the index of the type description
5738 * within that type library.
5740 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5741 ITypeLib * *ppTLib, UINT *pIndex)
5743 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5745 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5747 *pIndex=This->index;
5748 TRACE("returning pIndex=%d\n", *pIndex);
5752 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5753 ITypeLib2_AddRef(*ppTLib);
5754 TRACE("returning ppTLib=%p\n", *ppTLib);
5760 /* ITypeInfo::ReleaseTypeAttr
5762 * Releases a TYPEATTR previously returned by GetTypeAttr.
5765 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5766 TYPEATTR* pTypeAttr)
5768 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5769 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5770 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5773 /* ITypeInfo::ReleaseFuncDesc
5775 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5777 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5779 FUNCDESC *pFuncDesc)
5781 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5784 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5786 for (i = 0; i < pFuncDesc->cParams; i++)
5787 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5788 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5790 SysFreeString((BSTR)pFuncDesc);
5793 /* ITypeInfo::ReleaseVarDesc
5795 * Releases a VARDESC previously returned by GetVarDesc.
5797 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5800 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5801 TRACE("(%p)->(%p)\n", This, pVarDesc);
5803 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5804 if (pVarDesc->varkind == VAR_CONST)
5805 VariantClear(pVarDesc->u.lpvarValue);
5806 SysFreeString((BSTR)pVarDesc);
5809 /* ITypeInfo2::GetTypeKind
5811 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5814 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5815 TYPEKIND *pTypeKind)
5817 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5818 *pTypeKind=This->TypeAttr.typekind;
5819 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5823 /* ITypeInfo2::GetTypeFlags
5825 * Returns the type flags without any allocations. This returns a DWORD type
5826 * flag, which expands the type flags without growing the TYPEATTR (type
5830 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5832 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5833 *pTypeFlags=This->TypeAttr.wTypeFlags;
5834 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5838 /* ITypeInfo2::GetFuncIndexOfMemId
5839 * Binds to a specific member based on a known DISPID, where the member name
5840 * is not known (for example, when binding to a default member).
5843 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5844 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5846 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5847 const TLBFuncDesc *pFuncInfo;
5851 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5852 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5858 result = TYPE_E_ELEMENTNOTFOUND;
5860 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5861 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5865 /* TypeInfo2::GetVarIndexOfMemId
5867 * Binds to a specific member based on a known DISPID, where the member name
5868 * is not known (for example, when binding to a default member).
5871 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5872 MEMBERID memid, UINT *pVarIndex)
5874 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5875 TLBVarDesc *pVarInfo;
5878 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5879 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5885 result = TYPE_E_ELEMENTNOTFOUND;
5887 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5888 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5892 /* ITypeInfo2::GetCustData
5894 * Gets the custom data
5896 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5901 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5902 TLBCustData *pCData;
5904 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5905 if( IsEqualIID(guid, &pCData->guid)) break;
5907 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5911 VariantInit( pVarVal);
5912 VariantCopy( pVarVal, &pCData->data);
5915 return E_INVALIDARG; /* FIXME: correct? */
5918 /* ITypeInfo2::GetFuncCustData
5920 * Gets the custom data
5922 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5928 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5929 TLBCustData *pCData=NULL;
5930 TLBFuncDesc * pFDesc;
5932 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5933 pFDesc=pFDesc->next);
5936 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5937 if( IsEqualIID(guid, &pCData->guid)) break;
5939 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5942 VariantInit( pVarVal);
5943 VariantCopy( pVarVal, &pCData->data);
5946 return E_INVALIDARG; /* FIXME: correct? */
5949 /* ITypeInfo2::GetParamCustData
5951 * Gets the custom data
5953 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5960 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5961 TLBCustData *pCData=NULL;
5962 TLBFuncDesc * pFDesc;
5965 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5967 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5968 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5969 pCData = pCData->next)
5970 if( IsEqualIID(guid, &pCData->guid)) break;
5972 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5976 VariantInit( pVarVal);
5977 VariantCopy( pVarVal, &pCData->data);
5980 return E_INVALIDARG; /* FIXME: correct? */
5983 /* ITypeInfo2::GetVarCustData
5985 * Gets the custom data
5987 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5993 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5994 TLBCustData *pCData=NULL;
5995 TLBVarDesc * pVDesc;
5998 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6002 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6004 if( IsEqualIID(guid, &pCData->guid)) break;
6008 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6012 VariantInit( pVarVal);
6013 VariantCopy( pVarVal, &pCData->data);
6016 return E_INVALIDARG; /* FIXME: correct? */
6019 /* ITypeInfo2::GetImplCustData
6021 * Gets the custom data
6023 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6029 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6030 TLBCustData *pCData=NULL;
6031 TLBImplType * pRDesc;
6034 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6038 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6040 if( IsEqualIID(guid, &pCData->guid)) break;
6044 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6048 VariantInit( pVarVal);
6049 VariantCopy( pVarVal, &pCData->data);
6052 return E_INVALIDARG; /* FIXME: correct? */
6055 /* ITypeInfo2::GetDocumentation2
6057 * Retrieves the documentation string, the complete Help file name and path,
6058 * the localization context to use, and the context ID for the library Help
6059 * topic in the Help file.
6062 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6066 BSTR *pbstrHelpString,
6067 DWORD *pdwHelpStringContext,
6068 BSTR *pbstrHelpStringDll)
6070 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6071 const TLBFuncDesc *pFDesc;
6072 const TLBVarDesc *pVDesc;
6073 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6074 "HelpStringContext(%p) HelpStringDll(%p)\n",
6075 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6076 pbstrHelpStringDll );
6077 /* the help string should be obtained from the helpstringdll,
6078 * using the _DLLGetDocumentation function, based on the supplied
6079 * lcid. Nice to do sometime...
6081 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6083 *pbstrHelpString=SysAllocString(This->Name);
6084 if(pdwHelpStringContext)
6085 *pdwHelpStringContext=This->dwHelpStringContext;
6086 if(pbstrHelpStringDll)
6087 *pbstrHelpStringDll=
6088 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6090 }else {/* for a member */
6091 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6092 if(pFDesc->funcdesc.memid==memid){
6094 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6095 if(pdwHelpStringContext)
6096 *pdwHelpStringContext=pFDesc->HelpStringContext;
6097 if(pbstrHelpStringDll)
6098 *pbstrHelpStringDll=
6099 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6102 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6103 if(pVDesc->vardesc.memid==memid){
6105 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6106 if(pdwHelpStringContext)
6107 *pdwHelpStringContext=pVDesc->HelpStringContext;
6108 if(pbstrHelpStringDll)
6109 *pbstrHelpStringDll=
6110 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6114 return TYPE_E_ELEMENTNOTFOUND;
6117 /* ITypeInfo2::GetAllCustData
6119 * Gets all custom data items for the Type info.
6122 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6124 CUSTDATA *pCustData)
6126 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6127 TLBCustData *pCData;
6130 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6132 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6133 if(pCustData->prgCustData ){
6134 pCustData->cCustData=This->ctCustData;
6135 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6136 pCustData->prgCustData[i].guid=pCData->guid;
6137 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6140 ERR(" OUT OF MEMORY!\n");
6141 return E_OUTOFMEMORY;
6146 /* ITypeInfo2::GetAllFuncCustData
6148 * Gets all custom data items for the specified Function
6151 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6154 CUSTDATA *pCustData)
6156 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6157 TLBCustData *pCData;
6158 TLBFuncDesc * pFDesc;
6160 TRACE("(%p) index %d\n", This, index);
6161 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6162 pFDesc=pFDesc->next)
6165 pCustData->prgCustData =
6166 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6167 if(pCustData->prgCustData ){
6168 pCustData->cCustData=pFDesc->ctCustData;
6169 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6170 pCData = pCData->next){
6171 pCustData->prgCustData[i].guid=pCData->guid;
6172 VariantCopy(& pCustData->prgCustData[i].varValue,
6176 ERR(" OUT OF MEMORY!\n");
6177 return E_OUTOFMEMORY;
6181 return TYPE_E_ELEMENTNOTFOUND;
6184 /* ITypeInfo2::GetAllParamCustData
6186 * Gets all custom data items for the Functions
6189 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6190 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6192 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6193 TLBCustData *pCData=NULL;
6194 TLBFuncDesc * pFDesc;
6196 TRACE("(%p) index %d\n", This, indexFunc);
6197 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6198 pFDesc=pFDesc->next)
6200 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6201 pCustData->prgCustData =
6202 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6203 sizeof(CUSTDATAITEM));
6204 if(pCustData->prgCustData ){
6205 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6206 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6207 pCData; i++, pCData = pCData->next){
6208 pCustData->prgCustData[i].guid=pCData->guid;
6209 VariantCopy(& pCustData->prgCustData[i].varValue,
6213 ERR(" OUT OF MEMORY!\n");
6214 return E_OUTOFMEMORY;
6218 return TYPE_E_ELEMENTNOTFOUND;
6221 /* ITypeInfo2::GetAllVarCustData
6223 * Gets all custom data items for the specified Variable
6226 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6227 UINT index, CUSTDATA *pCustData)
6229 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6230 TLBCustData *pCData;
6231 TLBVarDesc * pVDesc;
6233 TRACE("(%p) index %d\n", This, index);
6234 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6235 pVDesc=pVDesc->next)
6238 pCustData->prgCustData =
6239 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6240 if(pCustData->prgCustData ){
6241 pCustData->cCustData=pVDesc->ctCustData;
6242 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6243 pCData = pCData->next){
6244 pCustData->prgCustData[i].guid=pCData->guid;
6245 VariantCopy(& pCustData->prgCustData[i].varValue,
6249 ERR(" OUT OF MEMORY!\n");
6250 return E_OUTOFMEMORY;
6254 return TYPE_E_ELEMENTNOTFOUND;
6257 /* ITypeInfo2::GetAllImplCustData
6259 * Gets all custom data items for the specified implementation type
6262 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6265 CUSTDATA *pCustData)
6267 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6268 TLBCustData *pCData;
6269 TLBImplType * pRDesc;
6271 TRACE("(%p) index %d\n", This, index);
6272 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6273 pRDesc=pRDesc->next)
6276 pCustData->prgCustData =
6277 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6278 if(pCustData->prgCustData ){
6279 pCustData->cCustData=pRDesc->ctCustData;
6280 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6281 pCData = pCData->next){
6282 pCustData->prgCustData[i].guid=pCData->guid;
6283 VariantCopy(& pCustData->prgCustData[i].varValue,
6287 ERR(" OUT OF MEMORY!\n");
6288 return E_OUTOFMEMORY;
6292 return TYPE_E_ELEMENTNOTFOUND;
6295 static const ITypeInfo2Vtbl tinfvt =
6298 ITypeInfo_fnQueryInterface,
6300 ITypeInfo_fnRelease,
6302 ITypeInfo_fnGetTypeAttr,
6303 ITypeInfo_fnGetTypeComp,
6304 ITypeInfo_fnGetFuncDesc,
6305 ITypeInfo_fnGetVarDesc,
6306 ITypeInfo_fnGetNames,
6307 ITypeInfo_fnGetRefTypeOfImplType,
6308 ITypeInfo_fnGetImplTypeFlags,
6309 ITypeInfo_fnGetIDsOfNames,
6311 ITypeInfo_fnGetDocumentation,
6312 ITypeInfo_fnGetDllEntry,
6313 ITypeInfo_fnGetRefTypeInfo,
6314 ITypeInfo_fnAddressOfMember,
6315 ITypeInfo_fnCreateInstance,
6316 ITypeInfo_fnGetMops,
6317 ITypeInfo_fnGetContainingTypeLib,
6318 ITypeInfo_fnReleaseTypeAttr,
6319 ITypeInfo_fnReleaseFuncDesc,
6320 ITypeInfo_fnReleaseVarDesc,
6322 ITypeInfo2_fnGetTypeKind,
6323 ITypeInfo2_fnGetTypeFlags,
6324 ITypeInfo2_fnGetFuncIndexOfMemId,
6325 ITypeInfo2_fnGetVarIndexOfMemId,
6326 ITypeInfo2_fnGetCustData,
6327 ITypeInfo2_fnGetFuncCustData,
6328 ITypeInfo2_fnGetParamCustData,
6329 ITypeInfo2_fnGetVarCustData,
6330 ITypeInfo2_fnGetImplTypeCustData,
6331 ITypeInfo2_fnGetDocumentation2,
6332 ITypeInfo2_fnGetAllCustData,
6333 ITypeInfo2_fnGetAllFuncCustData,
6334 ITypeInfo2_fnGetAllParamCustData,
6335 ITypeInfo2_fnGetAllVarCustData,
6336 ITypeInfo2_fnGetAllImplTypeCustData,
6339 /******************************************************************************
6340 * CreateDispTypeInfo [OLEAUT32.31]
6342 * Build type information for an object so it can be called through an
6343 * IDispatch interface.
6346 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6347 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6350 * This call allows an objects methods to be accessed through IDispatch, by
6351 * building an ITypeInfo object that IDispatch can use to call through.
6353 HRESULT WINAPI CreateDispTypeInfo(
6354 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6355 LCID lcid, /* [I] Locale Id */
6356 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6358 ITypeInfoImpl *pTIClass, *pTIIface;
6359 ITypeLibImpl *pTypeLibImpl;
6361 TLBFuncDesc **ppFuncDesc;
6364 pTypeLibImpl = TypeLibImpl_Constructor();
6365 if (!pTypeLibImpl) return E_FAIL;
6367 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6368 pTIIface->pTypeLib = pTypeLibImpl;
6369 pTIIface->index = 0;
6370 pTIIface->Name = NULL;
6371 pTIIface->dwHelpContext = -1;
6372 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6373 pTIIface->TypeAttr.lcid = lcid;
6374 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6375 pTIIface->TypeAttr.wMajorVerNum = 0;
6376 pTIIface->TypeAttr.wMinorVerNum = 0;
6377 pTIIface->TypeAttr.cbAlignment = 2;
6378 pTIIface->TypeAttr.cbSizeInstance = -1;
6379 pTIIface->TypeAttr.cbSizeVft = -1;
6380 pTIIface->TypeAttr.cFuncs = 0;
6381 pTIIface->TypeAttr.cImplTypes = 0;
6382 pTIIface->TypeAttr.cVars = 0;
6383 pTIIface->TypeAttr.wTypeFlags = 0;
6385 ppFuncDesc = &pTIIface->funclist;
6386 for(func = 0; func < pidata->cMembers; func++) {
6387 METHODDATA *md = pidata->pmethdata + func;
6388 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6389 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6390 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6391 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6392 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6393 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6394 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6395 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6396 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6397 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6398 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6399 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6400 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6401 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6402 md->cArgs * sizeof(ELEMDESC));
6403 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6404 md->cArgs * sizeof(TLBParDesc));
6405 for(param = 0; param < md->cArgs; param++) {
6406 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6407 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6409 (*ppFuncDesc)->helpcontext = 0;
6410 (*ppFuncDesc)->HelpStringContext = 0;
6411 (*ppFuncDesc)->HelpString = NULL;
6412 (*ppFuncDesc)->Entry = NULL;
6413 (*ppFuncDesc)->ctCustData = 0;
6414 (*ppFuncDesc)->pCustData = NULL;
6415 (*ppFuncDesc)->next = NULL;
6416 ppFuncDesc = &(*ppFuncDesc)->next;
6419 dump_TypeInfo(pTIIface);
6421 pTypeLibImpl->pTypeInfo = pTIIface;
6422 pTypeLibImpl->TypeInfoCount++;
6424 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6425 pTIClass->pTypeLib = pTypeLibImpl;
6426 pTIClass->index = 1;
6427 pTIClass->Name = NULL;
6428 pTIClass->dwHelpContext = -1;
6429 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6430 pTIClass->TypeAttr.lcid = lcid;
6431 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6432 pTIClass->TypeAttr.wMajorVerNum = 0;
6433 pTIClass->TypeAttr.wMinorVerNum = 0;
6434 pTIClass->TypeAttr.cbAlignment = 2;
6435 pTIClass->TypeAttr.cbSizeInstance = -1;
6436 pTIClass->TypeAttr.cbSizeVft = -1;
6437 pTIClass->TypeAttr.cFuncs = 0;
6438 pTIClass->TypeAttr.cImplTypes = 1;
6439 pTIClass->TypeAttr.cVars = 0;
6440 pTIClass->TypeAttr.wTypeFlags = 0;
6442 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6443 pTIClass->impltypelist->hRef = 1;
6445 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6446 pTIClass->reflist->index = 0;
6447 pTIClass->reflist->reference = 1;
6448 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6450 dump_TypeInfo(pTIClass);
6452 pTIIface->next = pTIClass;
6453 pTypeLibImpl->TypeInfoCount++;
6455 *pptinfo = (ITypeInfo*)pTIClass;
6460 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6462 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6464 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6467 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6469 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6471 return ITypeInfo_AddRef((ITypeInfo *)This);
6474 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6476 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6478 return ITypeInfo_Release((ITypeInfo *)This);
6481 static HRESULT WINAPI ITypeComp_fnBind(
6486 ITypeInfo ** ppTInfo,
6487 DESCKIND * pDescKind,
6490 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6491 const TLBFuncDesc *pFDesc;
6492 const TLBVarDesc *pVDesc;
6494 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6496 *pDescKind = DESCKIND_NONE;
6497 pBindPtr->lpfuncdesc = NULL;
6500 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6501 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6502 if (!strcmpW(pFDesc->Name, szName)) {
6508 HRESULT hr = TLB_AllocAndInitFuncDesc(
6510 &pBindPtr->lpfuncdesc,
6511 This->TypeAttr.typekind == TKIND_DISPATCH);
6514 *pDescKind = DESCKIND_FUNCDESC;
6515 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6516 ITypeInfo_AddRef(*ppTInfo);
6519 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6520 if (!strcmpW(pVDesc->Name, szName)) {
6521 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6524 *pDescKind = DESCKIND_VARDESC;
6525 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6526 ITypeInfo_AddRef(*ppTInfo);
6531 /* FIXME: search each inherited interface, not just the first */
6532 if (This->TypeAttr.cImplTypes) {
6533 /* recursive search */
6537 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6540 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6541 ITypeInfo_Release(pTInfo);
6545 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6546 ITypeComp_Release(pTComp);
6549 WARN("Could not search inherited interface!\n");
6551 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6552 return DISP_E_MEMBERNOTFOUND;
6555 static HRESULT WINAPI ITypeComp_fnBindType(
6559 ITypeInfo ** ppTInfo,
6560 ITypeComp ** ppTComp)
6562 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6564 /* strange behaviour (does nothing) but like the
6567 if (!ppTInfo || !ppTComp)
6576 static const ITypeCompVtbl tcompvt =
6579 ITypeComp_fnQueryInterface,
6581 ITypeComp_fnRelease,
6584 ITypeComp_fnBindType