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)
1370 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1375 static inline void MSFT_Seek(TLBContext *pcx, long where)
1377 if (where != DO_NOT_SEEK)
1379 where += pcx->oStart;
1380 if (where > pcx->length)
1383 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1391 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1393 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1394 pcx->pos, count, pcx->oStart, pcx->length, where);
1396 MSFT_Seek(pcx, where);
1397 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1398 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1403 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1408 ret = MSFT_Read(buffer, count, pcx, where);
1409 FromLEDWords(buffer, ret);
1414 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1419 ret = MSFT_Read(buffer, count, pcx, where);
1420 FromLEWords(buffer, ret);
1425 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1427 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1428 memset(pGuid,0, sizeof(GUID));
1431 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1432 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1433 pGuid->Data2 = FromLEWord(pGuid->Data2);
1434 pGuid->Data3 = FromLEWord(pGuid->Data3);
1435 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1438 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1440 MSFT_NameIntro niName;
1444 ERR_(typelib)("bad offset %d\n", offset);
1448 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1449 pcx->pTblDir->pNametab.offset+offset);
1451 return niName.hreftype;
1454 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1457 MSFT_NameIntro niName;
1459 WCHAR* pwstring = NULL;
1460 BSTR bstrName = NULL;
1464 ERR_(typelib)("bad offset %d\n", offset);
1467 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1468 pcx->pTblDir->pNametab.offset+offset);
1469 niName.namelen &= 0xFF; /* FIXME: correct ? */
1470 name=TLB_Alloc((niName.namelen & 0xff) +1);
1471 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1472 name[niName.namelen & 0xff]='\0';
1474 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1477 /* no invalid characters in string */
1480 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1482 /* don't check for invalid character since this has been done previously */
1483 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1485 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1486 lengthInChars = SysStringLen(bstrName);
1487 HeapFree(GetProcessHeap(), 0, pwstring);
1490 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1494 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1501 if(offset<0) return NULL;
1502 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1503 if(length <= 0) return 0;
1504 string=TLB_Alloc(length +1);
1505 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1506 string[length]='\0';
1508 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1509 string, -1, NULL, 0);
1511 /* no invalid characters in string */
1514 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1516 /* don't check for invalid character since this has been done previously */
1517 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1519 bstr = SysAllocStringLen(pwstring, lengthInChars);
1520 lengthInChars = SysStringLen(bstr);
1521 HeapFree(GetProcessHeap(), 0, pwstring);
1524 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1528 * read a value and fill a VARIANT structure
1530 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1534 TRACE_(typelib)("\n");
1536 if(offset <0) { /* data are packed in here */
1537 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1538 V_I4(pVar) = offset & 0x3ffffff;
1541 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1542 pcx->pTblDir->pCustData.offset + offset );
1543 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1544 switch (V_VT(pVar)){
1545 case VT_EMPTY: /* FIXME: is this right? */
1546 case VT_NULL: /* FIXME: is this right? */
1547 case VT_I2 : /* this should not happen */
1558 case VT_VOID : /* FIXME: is this right? */
1566 case VT_DECIMAL : /* FIXME: is this right? */
1569 /* pointer types with known behaviour */
1572 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1575 DWORD origPos = MSFT_Tell(pcx), nullPos;
1578 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1580 nullPos = MSFT_Tell(pcx);
1581 size = nullPos - origPos;
1582 MSFT_Seek(pcx, origPos);
1584 ptr=TLB_Alloc(size);/* allocate temp buffer */
1585 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1586 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1587 /* FIXME: do we need a AtoW conversion here? */
1588 V_UNION(pVar, bstrVal[size])=L'\0';
1589 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1593 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1600 case VT_USERDEFINED :
1606 case VT_STREAMED_OBJECT :
1607 case VT_STORED_OBJECT :
1608 case VT_BLOB_OBJECT :
1613 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1617 if(size>0) /* (big|small) endian correct? */
1618 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1622 * create a linked list with custom data
1624 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1630 TRACE_(typelib)("\n");
1634 pNew=TLB_Alloc(sizeof(TLBCustData));
1635 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1636 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1637 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1638 /* add new custom data at head of the list */
1639 pNew->next=*ppCustData;
1641 offset = entry.next;
1646 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1650 pTd->vt=type & VT_TYPEMASK;
1652 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1654 if(pTd->vt == VT_USERDEFINED)
1655 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1657 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1660 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1662 /* resolve referenced type if any */
1665 switch (lpTypeDesc->vt)
1668 lpTypeDesc = lpTypeDesc->u.lptdesc;
1672 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1675 case VT_USERDEFINED:
1676 MSFT_DoRefType(pcx, pTI,
1677 lpTypeDesc->u.hreftype);
1689 MSFT_DoFuncs(TLBContext* pcx,
1694 TLBFuncDesc** pptfd)
1697 * member information is stored in a data structure at offset
1698 * indicated by the memoffset field of the typeinfo structure
1699 * There are several distinctive parts.
1700 * The first part starts with a field that holds the total length
1701 * of this (first) part excluding this field. Then follow the records,
1702 * for each member there is one record.
1704 * The first entry is always the length of the record (including this
1706 * The rest of the record depends on the type of the member. If there is
1707 * a field indicating the member type (function, variable, interface, etc)
1708 * I have not found it yet. At this time we depend on the information
1709 * in the type info and the usual order how things are stored.
1711 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1714 * Third is an equal sized array with file offsets to the name entry
1717 * The fourth and last (?) part is an array with offsets to the records
1718 * in the first part of this file segment.
1721 int infolen, nameoffset, reclength, nrattributes, i;
1722 int recoffset = offset + sizeof(INT);
1725 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1726 TLBFuncDesc *ptfd_prev = NULL;
1728 TRACE_(typelib)("\n");
1730 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1732 for ( i = 0; i < cFuncs ; i++ )
1734 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1736 /* name, eventually add to a hash table */
1737 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1738 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1740 /* nameoffset is sometimes -1 on the second half of a propget/propput
1741 * pair of functions */
1742 if ((nameoffset == -1) && (i > 0))
1743 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1745 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1747 /* read the function information record */
1748 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1752 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1754 /* do the attributes */
1755 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1758 if ( nrattributes > 0 )
1760 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1762 if ( nrattributes > 1 )
1764 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1765 pFuncRec->OptAttr[1]) ;
1767 if ( nrattributes > 2 )
1769 if ( pFuncRec->FKCCIC & 0x2000 )
1771 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1775 (*pptfd)->Entry = MSFT_ReadString(pcx,
1776 pFuncRec->OptAttr[2]);
1778 if( nrattributes > 5 )
1780 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1782 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1785 pFuncRec->OptAttr[6],
1786 &(*pptfd)->pCustData);
1793 /* fill the FuncDesc Structure */
1794 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1795 offset + infolen + ( i + 1) * sizeof(INT));
1797 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1798 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1799 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1800 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1801 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1802 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1803 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1807 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1809 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1811 /* do the parameters/arguments */
1812 if(pFuncRec->nrargs)
1815 MSFT_ParameterInfo paraminfo;
1817 (*pptfd)->funcdesc.lprgelemdescParam =
1818 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1820 (*pptfd)->pParamDesc =
1821 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1823 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1824 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1826 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1828 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1835 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1838 if (paraminfo.oName == -1)
1839 /* this occurs for [propput] or [propget] methods, so
1840 * we should just set the name of the parameter to the
1841 * name of the method. */
1842 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1844 (*pptfd)->pParamDesc[j].Name =
1845 MSFT_ReadName( pcx, paraminfo.oName );
1846 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1848 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1851 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1852 (pFuncRec->FKCCIC & 0x1000) )
1854 INT* pInt = (INT *)((char *)pFuncRec +
1856 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1858 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1860 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1861 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1863 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1867 elemdesc->u.paramdesc.pparamdescex = NULL;
1869 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1872 pFuncRec->OptAttr[7+j],
1873 &(*pptfd)->pParamDesc[j].pCustData);
1876 /* SEEK value = jump to offset,
1877 * from there jump to the end of record,
1878 * go back by (j-1) arguments
1880 MSFT_ReadLEDWords( ¶minfo ,
1881 sizeof(MSFT_ParameterInfo), pcx,
1882 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1883 * sizeof(MSFT_ParameterInfo)));
1887 /* scode is not used: archaic win16 stuff FIXME: right? */
1888 (*pptfd)->funcdesc.cScodes = 0 ;
1889 (*pptfd)->funcdesc.lprgscode = NULL ;
1892 pptfd = & ((*pptfd)->next);
1893 recoffset += reclength;
1897 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1898 int cVars, int offset, TLBVarDesc ** pptvd)
1900 int infolen, nameoffset, reclength;
1902 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1906 TRACE_(typelib)("\n");
1908 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1909 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1910 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1911 recoffset += offset+sizeof(INT);
1912 for(i=0;i<cVars;i++){
1913 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1914 /* name, eventually add to a hash table */
1915 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1916 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1917 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1918 /* read the variable information record */
1919 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1921 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1923 if(reclength >(6*sizeof(INT)) )
1924 (*pptvd)->HelpContext=pVarRec->HelpContext;
1925 if(reclength >(7*sizeof(INT)) )
1926 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1927 if(reclength >(8*sizeof(INT)) )
1928 if(reclength >(9*sizeof(INT)) )
1929 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1930 /* fill the VarDesc Structure */
1931 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1932 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1933 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1934 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1935 MSFT_GetTdesc(pcx, pVarRec->DataType,
1936 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1937 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1938 if(pVarRec->VarKind == VAR_CONST ){
1939 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1940 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1941 pVarRec->OffsValue, pcx);
1943 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1944 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1945 pptvd=&((*pptvd)->next);
1946 recoffset += reclength;
1949 /* fill in data for a hreftype (offset). When the referenced type is contained
1950 * in the typelib, it's just an (file) offset in the type info base dir.
1951 * If comes from import, it's an offset+1 in the ImpInfo table
1953 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1957 TLBRefType **ppRefType = &pTI->reflist;
1959 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1962 if((*ppRefType)->reference == offset)
1964 ppRefType = &(*ppRefType)->next;
1967 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1968 sizeof(**ppRefType));
1970 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1971 /* external typelib */
1972 MSFT_ImpInfo impinfo;
1973 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1975 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1977 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1978 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1979 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1980 if(pImpLib->offset==impinfo.oImpFile) break;
1981 pImpLib=pImpLib->next;
1984 (*ppRefType)->reference=offset;
1985 (*ppRefType)->pImpTLInfo = pImpLib;
1986 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1987 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1988 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
1989 (*ppRefType)->index = TLB_REF_USE_GUID;
1991 (*ppRefType)->index = impinfo.oGuid;
1993 ERR("Cannot find a reference\n");
1994 (*ppRefType)->reference=-1;
1995 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1998 /* in this typelib */
1999 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2000 (*ppRefType)->reference=offset;
2001 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2005 /* process Implemented Interfaces of a com class */
2006 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2010 MSFT_RefRecord refrec;
2011 TLBImplType **ppImpl = &pTI->impltypelist;
2013 TRACE_(typelib)("\n");
2015 for(i=0;i<count;i++){
2016 if(offset<0) break; /* paranoia */
2017 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2018 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2019 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2020 (*ppImpl)->hRef = refrec.reftype;
2021 (*ppImpl)->implflags=refrec.flags;
2022 (*ppImpl)->ctCustData=
2023 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2024 offset=refrec.onext;
2025 ppImpl=&((*ppImpl)->next);
2029 * process a typeinfo record
2031 static ITypeInfoImpl * MSFT_DoTypeInfo(
2035 ITypeLibImpl * pLibInfo)
2037 MSFT_TypeInfoBase tiBase;
2038 ITypeInfoImpl *ptiRet;
2040 TRACE_(typelib)("count=%u\n", count);
2042 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2043 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2044 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2046 /* this is where we are coming from */
2047 ptiRet->pTypeLib = pLibInfo;
2048 ptiRet->index=count;
2049 /* fill in the typeattr fields */
2050 WARN("Assign constructor/destructor memid\n");
2052 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2053 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2054 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2055 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2056 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2057 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2058 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2059 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2060 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2061 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2062 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2063 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2064 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2065 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2066 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2067 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2068 MSFT_GetTdesc(pcx, tiBase.datatype1,
2069 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2072 /* IDLDESC idldescType; *//* never saw this one != zero */
2074 /* name, eventually add to a hash table */
2075 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2076 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2077 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2079 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2080 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2081 ptiRet->dwHelpContext=tiBase.helpcontext;
2083 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2084 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2086 /* note: InfoType's Help file and HelpStringDll come from the containing
2087 * library. Further HelpString and Docstring appear to be the same thing :(
2090 if(ptiRet->TypeAttr.cFuncs >0 )
2091 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2092 ptiRet->TypeAttr.cVars,
2093 tiBase.memoffset, & ptiRet->funclist);
2095 if(ptiRet->TypeAttr.cVars >0 )
2096 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2097 ptiRet->TypeAttr.cVars,
2098 tiBase.memoffset, & ptiRet->varlist);
2099 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2100 switch(ptiRet->TypeAttr.typekind)
2103 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2106 case TKIND_DISPATCH:
2107 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2109 if (tiBase.datatype1 != -1)
2111 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2112 ptiRet->impltypelist->hRef = tiBase.datatype1;
2116 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2117 ptiRet->impltypelist->hRef = dispatch_href;
2121 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2122 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2123 ptiRet->impltypelist->hRef = tiBase.datatype1;
2128 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2130 TRACE_(typelib)("%s guid: %s kind:%s\n",
2131 debugstr_w(ptiRet->Name),
2132 debugstr_guid(&ptiRet->TypeAttr.guid),
2133 typekind_desc[ptiRet->TypeAttr.typekind]);
2138 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2139 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2140 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2143 static ITypeLibImpl *tlb_cache_first;
2144 static CRITICAL_SECTION cache_section;
2145 static CRITICAL_SECTION_DEBUG cache_section_debug =
2147 0, 0, &cache_section,
2148 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2149 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2151 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2154 /****************************************************************************
2157 * find the type of the typelib file and map the typelib resource into
2160 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2161 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2162 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2164 ITypeLibImpl *entry;
2165 int ret = TYPE_E_CANTLOADLIBRARY;
2171 lstrcpynW(pszPath, pszFileName, cchPath);
2173 /* first try loading as a dll and access the typelib as a resource */
2174 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2175 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2178 /* it may have been specified with resource index appended to the
2179 * path, so remove it and try again */
2180 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2181 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2183 index = atoiW(pIndexStr);
2184 pszPath[pIndexStr - pszFileName - 1] = '\0';
2186 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2187 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2191 /* get the path to the specified typelib file */
2194 /* otherwise, try loading as a regular file */
2195 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2196 return TYPE_E_CANTLOADLIBRARY;
2199 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2201 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2202 EnterCriticalSection(&cache_section);
2203 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2205 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2207 TRACE("cache hit\n");
2208 *ppTypeLib = (ITypeLib2*)entry;
2209 ITypeLib_AddRef(*ppTypeLib);
2210 LeaveCriticalSection(&cache_section);
2214 LeaveCriticalSection(&cache_section);
2216 /* now actually load and parse the typelib */
2219 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2220 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2223 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2226 LPVOID pBase = LockResource(hGlobal);
2227 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2231 /* try to load as incore resource */
2232 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2233 if (dwSignature == MSFT_SIGNATURE)
2234 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2235 else if (dwSignature == SLTG_SIGNATURE)
2236 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2238 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2240 FreeResource( hGlobal );
2243 FreeLibrary(hinstDLL);
2247 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2248 if (INVALID_HANDLE_VALUE != hFile)
2250 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2253 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2256 /* retrieve file size */
2257 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2258 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2260 if (dwSignature == MSFT_SIGNATURE)
2261 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2262 else if (dwSignature == SLTG_SIGNATURE)
2263 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2265 UnmapViewOfFile(pBase);
2267 CloseHandle(hMapping);
2274 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2276 TRACE("adding to cache\n");
2277 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2278 lstrcpyW(impl->path, pszPath);
2279 /* We should really canonicalise the path here. */
2280 impl->index = index;
2282 /* FIXME: check if it has added already in the meantime */
2283 EnterCriticalSection(&cache_section);
2284 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2286 tlb_cache_first = impl;
2287 LeaveCriticalSection(&cache_section);
2290 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2295 /*================== ITypeLib(2) Methods ===================================*/
2297 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2299 ITypeLibImpl* pTypeLibImpl;
2301 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2302 if (!pTypeLibImpl) return NULL;
2304 pTypeLibImpl->lpVtbl = &tlbvt;
2305 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2306 pTypeLibImpl->ref = 1;
2308 return pTypeLibImpl;
2311 /****************************************************************************
2312 * ITypeLib2_Constructor_MSFT
2314 * loading an MSFT typelib from an in-memory image
2316 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2320 MSFT_Header tlbHeader;
2321 MSFT_SegDir tlbSegDir;
2322 ITypeLibImpl * pTypeLibImpl;
2324 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2326 pTypeLibImpl = TypeLibImpl_Constructor();
2327 if (!pTypeLibImpl) return NULL;
2329 /* get pointer to beginning of typelib data */
2333 cx.pLibInfo = pTypeLibImpl;
2334 cx.length = dwTLBLength;
2337 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2338 TRACE_(typelib)("header:\n");
2339 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2340 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2341 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2344 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2346 /* there is a small amount of information here until the next important
2348 * the segment directory . Try to calculate the amount of data */
2349 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2351 /* now read the segment directory */
2352 TRACE("read segment directory (at %ld)\n",lPSegDir);
2353 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2354 cx.pTblDir = &tlbSegDir;
2356 /* just check two entries */
2357 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2359 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2360 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2364 /* now fill our internal data */
2365 /* TLIBATTR fields */
2366 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2368 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2369 /* Windows seems to have zero here, is this correct? */
2370 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2371 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2373 pTypeLibImpl->LibAttr.lcid = 0;
2375 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2376 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2377 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2378 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2380 /* name, eventually add to a hash table */
2381 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2384 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2385 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2387 if( tlbHeader.varflags & HELPDLLFLAG)
2390 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2391 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2394 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2397 if(tlbHeader.CustomDataOffset >= 0)
2399 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2402 /* fill in typedescriptions */
2403 if(tlbSegDir.pTypdescTab.length > 0)
2405 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2407 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2408 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2411 /* FIXME: add several sanity checks here */
2412 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2413 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2415 /* FIXME: check safearray */
2417 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2419 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2421 else if(td[0] == VT_CARRAY)
2423 /* array descr table here */
2424 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2426 else if(td[0] == VT_USERDEFINED)
2428 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2430 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2433 /* second time around to fill the array subscript info */
2436 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2437 if(tlbSegDir.pArrayDescriptions.offset>0)
2439 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2440 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2443 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2445 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2447 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2449 for(j = 0; j<td[2]; j++)
2451 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2452 sizeof(INT), &cx, DO_NOT_SEEK);
2453 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2454 sizeof(INT), &cx, DO_NOT_SEEK);
2459 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2460 ERR("didn't find array description data\n");
2465 /* imported type libs */
2466 if(tlbSegDir.pImpFiles.offset>0)
2468 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2469 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2472 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2477 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2478 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2479 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2481 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2482 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2483 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2484 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2487 name = TLB_Alloc(size+1);
2488 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2489 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2490 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2491 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2494 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2495 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2497 ppImpLib = &(*ppImpLib)->next;
2502 if(tlbHeader.nrtypeinfos >= 0 )
2504 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2505 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2508 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2510 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2512 ppTI = &((*ppTI)->next);
2513 (pTypeLibImpl->TypeInfoCount)++;
2517 TRACE("(%p)\n", pTypeLibImpl);
2518 return (ITypeLib2*) pTypeLibImpl;
2522 static BSTR TLB_MultiByteToBSTR(char *ptr)
2528 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2529 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2530 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2531 ret = SysAllocString(nameW);
2532 HeapFree(GetProcessHeap(), 0, nameW);
2536 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2542 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2543 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2547 guid->Data4[0] = s >> 8;
2548 guid->Data4[1] = s & 0xff;
2551 for(i = 0; i < 6; i++) {
2552 memcpy(b, str + 24 + 2 * i, 2);
2553 guid->Data4[i + 2] = strtol(b, NULL, 16);
2558 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2565 bytelen = *(WORD*)ptr;
2566 if(bytelen == 0xffff) return 2;
2567 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2568 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2569 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2570 *pBstr = SysAllocStringLen(nameW, len);
2571 HeapFree(GetProcessHeap(), 0, nameW);
2575 static WORD SLTG_ReadStringA(char *ptr, char **str)
2580 bytelen = *(WORD*)ptr;
2581 if(bytelen == 0xffff) return 2;
2582 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2583 memcpy(*str, ptr + 2, bytelen);
2584 (*str)[bytelen] = '\0';
2588 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2590 char *ptr = pLibBlk;
2593 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2594 FIXME("libblk magic = %04x\n", w);
2599 if((w = *(WORD*)ptr) != 0xffff) {
2600 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2605 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2607 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2609 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2612 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2615 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2616 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2618 pTypeLibImpl->LibAttr.lcid = 0;
2621 ptr += 4; /* skip res12 */
2623 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2626 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2629 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2632 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2633 ptr += sizeof(GUID);
2635 return ptr - (char*)pLibBlk;
2638 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2641 TYPEDESC *pTD = &pElem->tdesc;
2643 /* Handle [in/out] first */
2644 if((*pType & 0xc000) == 0xc000)
2645 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2646 else if(*pType & 0x8000)
2647 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2648 else if(*pType & 0x4000)
2649 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2651 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2654 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2657 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2660 if((*pType & 0xe00) == 0xe00) {
2662 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2664 pTD = pTD->u.lptdesc;
2666 switch(*pType & 0x7f) {
2669 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2671 pTD = pTD->u.lptdesc;
2674 case VT_USERDEFINED:
2675 pTD->vt = VT_USERDEFINED;
2676 pTD->u.hreftype = *(++pType) / 4;
2682 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2685 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2687 pTD->vt = VT_CARRAY;
2688 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2690 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2691 pTD->u.lpadesc->cDims = pSA->cDims;
2692 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2693 pSA->cDims * sizeof(SAFEARRAYBOUND));
2695 pTD = &pTD->u.lpadesc->tdescElem;
2701 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2705 pTD->vt = VT_SAFEARRAY;
2706 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2708 pTD = pTD->u.lptdesc;
2712 pTD->vt = *pType & 0x7f;
2722 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2727 TLBRefType **ppRefType;
2729 if(pRef->magic != SLTG_REF_MAGIC) {
2730 FIXME("Ref magic = %x\n", pRef->magic);
2733 name = ( (char*)(&pRef->names) + pRef->number);
2735 ppRefType = &pTI->reflist;
2736 for(ref = 0; ref < pRef->number >> 3; ref++) {
2738 unsigned int lib_offs, type_num;
2740 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2741 sizeof(**ppRefType));
2743 name += SLTG_ReadStringA(name, &refname);
2744 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2745 FIXME("Can't sscanf ref\n");
2746 if(lib_offs != 0xffff) {
2747 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2750 if((*import)->offset == lib_offs)
2752 import = &(*import)->next;
2755 char fname[MAX_PATH+1];
2758 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2760 (*import)->offset = lib_offs;
2761 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2763 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2764 &(*import)->wVersionMajor,
2765 &(*import)->wVersionMinor,
2766 &(*import)->lcid, fname) != 4) {
2767 FIXME("can't sscanf ref %s\n",
2768 pNameTable + lib_offs + 40);
2770 len = strlen(fname);
2771 if(fname[len-1] != '#')
2772 FIXME("fname = %s\n", fname);
2773 fname[len-1] = '\0';
2774 (*import)->name = TLB_MultiByteToBSTR(fname);
2776 (*ppRefType)->pImpTLInfo = *import;
2777 } else { /* internal ref */
2778 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2780 (*ppRefType)->reference = ref;
2781 (*ppRefType)->index = type_num;
2783 HeapFree(GetProcessHeap(), 0, refname);
2784 ppRefType = &(*ppRefType)->next;
2786 if((BYTE)*name != SLTG_REF_MAGIC)
2787 FIXME("End of ref block magic = %x\n", *name);
2788 dump_TLBRefType(pTI->reflist);
2791 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2794 SLTG_ImplInfo *info;
2795 TLBImplType **ppImplType = &pTI->impltypelist;
2796 /* I don't really get this structure, usually it's 0x16 bytes
2797 long, but iuser.tlb contains some that are 0x18 bytes long.
2798 That's ok because we can use the next ptr to jump to the next
2799 one. But how do we know the length of the last one? The WORD
2800 at offs 0x8 might be the clue. For now I'm just assuming that
2801 the last one is the regular 0x16 bytes. */
2803 info = (SLTG_ImplInfo*)pBlk;
2805 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2806 sizeof(**ppImplType));
2807 (*ppImplType)->hRef = info->ref;
2808 (*ppImplType)->implflags = info->impltypeflags;
2809 pTI->TypeAttr.cImplTypes++;
2810 ppImplType = &(*ppImplType)->next;
2812 if(info->next == 0xffff)
2815 FIXME("Interface inheriting more than one interface\n");
2816 info = (SLTG_ImplInfo*)(pBlk + info->next);
2818 info++; /* see comment at top of function */
2822 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2825 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2826 SLTG_MemberHeader *pMemHeader;
2827 char *pFirstItem, *pNextItem;
2829 if(pTIHeader->href_table != 0xffffffff) {
2830 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2835 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2837 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2839 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2840 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2843 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2847 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2850 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2851 SLTG_MemberHeader *pMemHeader;
2852 SLTG_Function *pFunc;
2853 char *pFirstItem, *pNextItem;
2854 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2857 if(pTIHeader->href_table != 0xffffffff) {
2858 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2862 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2864 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2866 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2867 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2870 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2871 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2876 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2877 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2878 FIXME("func magic = %02x\n", pFunc->magic);
2881 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2882 sizeof(**ppFuncDesc));
2883 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2885 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2886 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2887 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2888 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2889 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2890 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2892 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2893 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2895 if(pFunc->retnextopt & 0x80)
2896 pType = &pFunc->rettype;
2898 pType = (WORD*)(pFirstItem + pFunc->rettype);
2901 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2903 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2904 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2905 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2906 (*ppFuncDesc)->pParamDesc =
2907 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2908 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2910 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2912 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2913 char *paramName = pNameTable + *pArg;
2915 /* If arg type follows then paramName points to the 2nd
2916 letter of the name, else the next WORD is an offset to
2917 the arg type and paramName points to the first letter.
2918 So let's take one char off paramName and see if we're
2919 pointing at an alpha-numeric char. However if *pArg is
2920 0xffff or 0xfffe then the param has no name, the former
2921 meaning that the next WORD is the type, the latter
2922 meaning the the next WORD is an offset to the type. */
2927 else if(*pArg == 0xfffe) {
2931 else if(paramName[-1] && !isalnum(paramName[-1]))
2936 if(HaveOffs) { /* the next word is an offset to type */
2937 pType = (WORD*)(pFirstItem + *pArg);
2938 SLTG_DoType(pType, pFirstItem,
2939 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2944 pArg = SLTG_DoType(pArg, pFirstItem,
2945 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2948 /* Are we an optional param ? */
2949 if((*ppFuncDesc)->funcdesc.cParams - param <=
2950 (*ppFuncDesc)->funcdesc.cParamsOpt)
2951 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2954 (*ppFuncDesc)->pParamDesc[param].Name =
2955 TLB_MultiByteToBSTR(paramName);
2959 ppFuncDesc = &((*ppFuncDesc)->next);
2960 if(pFunc->next == 0xffff) break;
2962 pTI->TypeAttr.cFuncs = num;
2963 if (TRACE_ON(typelib))
2964 dump_TLBFuncDesc(pTI->funclist);
2965 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2968 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2971 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2972 SLTG_MemberHeader *pMemHeader;
2973 SLTG_RecordItem *pItem;
2975 TLBVarDesc **ppVarDesc = &pTI->varlist;
2980 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2982 pFirstItem = (char*)(pMemHeader + 1);
2983 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2984 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2985 if(pItem->magic != SLTG_RECORD_MAGIC) {
2986 FIXME("record magic = %02x\n", pItem->magic);
2989 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2990 sizeof(**ppVarDesc));
2991 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2992 (*ppVarDesc)->vardesc.memid = pItem->memid;
2993 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2994 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2996 if(pItem->typepos == 0x02)
2997 pType = &pItem->type;
2998 else if(pItem->typepos == 0x00)
2999 pType = (WORD*)(pFirstItem + pItem->type);
3001 FIXME("typepos = %02x\n", pItem->typepos);
3005 SLTG_DoType(pType, pFirstItem,
3006 &(*ppVarDesc)->vardesc.elemdescVar);
3008 /* FIXME("helpcontext, helpstring\n"); */
3010 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3012 ppVarDesc = &((*ppVarDesc)->next);
3013 if(pItem->next == 0xffff) break;
3015 pTI->TypeAttr.cVars = num;
3016 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3019 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3022 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3023 SLTG_MemberHeader *pMemHeader;
3024 SLTG_AliasItem *pItem;
3027 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3028 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3031 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3032 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3033 if (pItem->vt == 0xffff) {
3034 if (i<(pMemHeader->cbExtra/4-1))
3035 FIXME("Endmarker too early in process alias data!\n");
3039 FIXME("Chain extends over last entry?\n");
3042 if (pItem->vt == VT_USERDEFINED) {
3043 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3044 /* guessing here ... */
3045 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3046 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3049 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3050 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3054 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3057 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3060 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3061 SLTG_MemberHeader *pMemHeader;
3062 SLTG_AliasItem *pItem;
3064 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3065 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3066 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3067 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3068 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3071 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3074 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3075 SLTG_MemberHeader *pMemHeader;
3076 SLTG_EnumItem *pItem;
3078 TLBVarDesc **ppVarDesc = &pTI->varlist;
3081 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3083 pFirstItem = (char*)(pMemHeader + 1);
3084 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3085 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3086 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3087 FIXME("enumitem magic = %04x\n", pItem->magic);
3090 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3091 sizeof(**ppVarDesc));
3092 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3093 (*ppVarDesc)->vardesc.memid = pItem->memid;
3094 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3096 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3097 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3098 *(INT*)(pItem->value + pFirstItem);
3099 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3100 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3101 /* FIXME("helpcontext, helpstring\n"); */
3103 ppVarDesc = &((*ppVarDesc)->next);
3104 if(pItem->next == 0xffff) break;
3106 pTI->TypeAttr.cVars = num;
3107 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3110 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3111 managable copy of it into this */
3124 } SLTG_InternalOtherTypeInfo;
3126 /****************************************************************************
3127 * ITypeLib2_Constructor_SLTG
3129 * loading a SLTG typelib from an in-memory image
3131 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3133 ITypeLibImpl *pTypeLibImpl;
3134 SLTG_Header *pHeader;
3135 SLTG_BlkEntry *pBlkEntry;
3139 LPVOID pBlk, pFirstBlk;
3140 SLTG_LibBlk *pLibBlk;
3141 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3142 char *pAfterOTIBlks = NULL;
3143 char *pNameTable, *ptr;
3146 ITypeInfoImpl **ppTypeInfoImpl;
3148 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3151 pTypeLibImpl = TypeLibImpl_Constructor();
3152 if (!pTypeLibImpl) return NULL;
3156 TRACE_(typelib)("header:\n");
3157 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3158 pHeader->nrOfFileBlks );
3159 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3160 FIXME("Header type magic 0x%08lx not supported.\n",
3161 pHeader->SLTG_magic);
3165 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3166 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3168 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3169 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3171 /* Next we have a magic block */
3172 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3174 /* Let's see if we're still in sync */
3175 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3176 sizeof(SLTG_COMPOBJ_MAGIC))) {
3177 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3180 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3181 sizeof(SLTG_DIR_MAGIC))) {
3182 FIXME("dir magic = %s\n", pMagic->dir_magic);
3186 pIndex = (SLTG_Index*)(pMagic+1);
3188 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3190 pFirstBlk = (LPVOID)(pPad9 + 1);
3192 /* We'll set up a ptr to the main library block, which is the last one. */
3194 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3195 pBlkEntry[order].next != 0;
3196 order = pBlkEntry[order].next - 1, i++) {
3197 pBlk = (char*)pBlk + pBlkEntry[order].len;
3201 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3203 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3208 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3210 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3211 sizeof(*pOtherTypeInfoBlks) *
3212 pTypeLibImpl->TypeInfoCount);
3215 ptr = (char*)pLibBlk + len;
3217 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3221 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3223 w = *(WORD*)(ptr + 2);
3226 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3228 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3229 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3231 w = *(WORD*)(ptr + 4 + len);
3233 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3235 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3237 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3238 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3240 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3241 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3242 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3244 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3246 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3249 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3250 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3251 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3252 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3253 len += sizeof(SLTG_OtherTypeInfo);
3257 pAfterOTIBlks = ptr;
3259 /* Skip this WORD and get the next DWORD */
3260 len = *(DWORD*)(pAfterOTIBlks + 2);
3262 /* Now add this to pLibBLk look at what we're pointing at and
3263 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3264 dust and we should be pointing at the beginning of the name
3267 pNameTable = (char*)pLibBlk + len;
3269 switch(*(WORD*)pNameTable) {
3276 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3280 pNameTable += 0x216;
3284 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3286 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3289 /* Hopefully we now have enough ptrs set up to actually read in
3290 some TypeInfos. It's not clear which order to do them in, so
3291 I'll just follow the links along the BlkEntry chain and read
3292 them in in the order in which they're in the file */
3294 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3296 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3297 pBlkEntry[order].next != 0;
3298 order = pBlkEntry[order].next - 1, i++) {
3300 SLTG_TypeInfoHeader *pTIHeader;
3301 SLTG_TypeInfoTail *pTITail;
3303 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3304 pOtherTypeInfoBlks[i].index_name)) {
3305 FIXME("Index strings don't match\n");
3310 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3311 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3314 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3315 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3316 (*ppTypeInfoImpl)->index = i;
3317 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3318 pOtherTypeInfoBlks[i].name_offs +
3320 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3321 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3323 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3324 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3325 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3326 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3327 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3329 if((pTIHeader->typeflags1 & 7) != 2)
3330 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3331 if(pTIHeader->typeflags3 != 2)
3332 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3334 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3335 debugstr_w((*ppTypeInfoImpl)->Name),
3336 typekind_desc[pTIHeader->typekind],
3337 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3338 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3340 switch(pTIHeader->typekind) {
3342 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3346 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3349 case TKIND_INTERFACE:
3350 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3354 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3358 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3359 if (pTITail->tdescalias_vt)
3360 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3363 case TKIND_DISPATCH:
3364 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3368 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3374 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3375 but we've already set those */
3376 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3377 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3378 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3380 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3402 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3403 pBlk = (char*)pBlk + pBlkEntry[order].len;
3406 if(i != pTypeLibImpl->TypeInfoCount) {
3407 FIXME("Somehow processed %d TypeInfos\n", i);
3411 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3412 return (ITypeLib2*)pTypeLibImpl;
3415 /* ITypeLib::QueryInterface
3417 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3422 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3424 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3427 if(IsEqualIID(riid, &IID_IUnknown) ||
3428 IsEqualIID(riid,&IID_ITypeLib)||
3429 IsEqualIID(riid,&IID_ITypeLib2))
3436 ITypeLib2_AddRef(iface);
3437 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3440 TRACE("-- Interface: E_NOINTERFACE\n");
3441 return E_NOINTERFACE;
3446 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3448 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3449 ULONG ref = InterlockedIncrement(&This->ref);
3451 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3456 /* ITypeLib::Release
3458 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3460 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3461 ULONG ref = InterlockedDecrement(&This->ref);
3463 TRACE("(%p)->(%lu)\n",This, ref);
3467 /* remove cache entry */
3470 TRACE("removing from cache list\n");
3471 EnterCriticalSection(&cache_section);
3472 if (This->next) This->next->prev = This->prev;
3473 if (This->prev) This->prev->next = This->next;
3474 else tlb_cache_first = This->next;
3475 LeaveCriticalSection(&cache_section);
3476 HeapFree(GetProcessHeap(), 0, This->path);
3478 /* FIXME destroy child objects */
3479 TRACE(" destroying ITypeLib(%p)\n",This);
3483 SysFreeString(This->Name);
3487 if (This->DocString)
3489 SysFreeString(This->DocString);
3490 This->DocString = NULL;
3495 SysFreeString(This->HelpFile);
3496 This->HelpFile = NULL;
3499 if (This->HelpStringDll)
3501 SysFreeString(This->HelpStringDll);
3502 This->HelpStringDll = NULL;
3505 if (This->pTypeInfo) /* can be NULL */
3506 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3507 HeapFree(GetProcessHeap(),0,This);
3514 /* ITypeLib::GetTypeInfoCount
3516 * Returns the number of type descriptions in the type library
3518 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3520 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3521 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3522 return This->TypeInfoCount;
3525 /* ITypeLib::GetTypeInfo
3527 * retrieves the specified type description in the library.
3529 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3532 ITypeInfo **ppTInfo)
3536 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3537 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3539 TRACE("(%p)->(index=%d)\n", This, index);
3541 if (!ppTInfo) return E_INVALIDARG;
3543 /* search element n in list */
3544 for(i=0; i < index; i++)
3546 pTypeInfo = pTypeInfo->next;
3549 TRACE("-- element not found\n");
3550 return TYPE_E_ELEMENTNOTFOUND;
3554 *ppTInfo = (ITypeInfo *) pTypeInfo;
3556 ITypeInfo_AddRef(*ppTInfo);
3557 TRACE("-- found (%p)\n",*ppTInfo);
3562 /* ITypeLibs::GetTypeInfoType
3564 * Retrieves the type of a type description.
3566 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3571 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3573 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3575 TRACE("(%p) index %d\n", This, index);
3577 if(!pTKind) return E_INVALIDARG;
3579 /* search element n in list */
3580 for(i=0; i < index; i++)
3584 TRACE("-- element not found\n");
3585 return TYPE_E_ELEMENTNOTFOUND;
3587 pTInfo = pTInfo->next;
3590 *pTKind = pTInfo->TypeAttr.typekind;
3591 TRACE("-- found Type (%d)\n", *pTKind);
3595 /* ITypeLib::GetTypeInfoOfGuid
3597 * Retrieves the type description that corresponds to the specified GUID.
3600 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3603 ITypeInfo **ppTInfo)
3605 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3606 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3608 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3612 WARN("-- element not found\n");
3613 return TYPE_E_ELEMENTNOTFOUND;
3616 /* search linked list for guid */
3617 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3619 pTypeInfo = pTypeInfo->next;
3623 /* end of list reached */
3624 WARN("-- element not found\n");
3625 return TYPE_E_ELEMENTNOTFOUND;
3629 TRACE("-- found (%p, %s)\n",
3631 debugstr_w(pTypeInfo->Name));
3633 *ppTInfo = (ITypeInfo*)pTypeInfo;
3634 ITypeInfo_AddRef(*ppTInfo);
3638 /* ITypeLib::GetLibAttr
3640 * Retrieves the structure that contains the library's attributes.
3643 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3645 LPTLIBATTR *ppTLibAttr)
3647 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3648 TRACE("(%p)\n",This);
3649 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3650 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3654 /* ITypeLib::GetTypeComp
3656 * Enables a client compiler to bind to a library's types, variables,
3657 * constants, and global functions.
3660 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3662 ITypeComp **ppTComp)
3664 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3666 TRACE("(%p)->(%p)\n",This,ppTComp);
3667 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3668 ITypeComp_AddRef(*ppTComp);
3673 /* ITypeLib::GetDocumentation
3675 * Retrieves the library's documentation string, the complete Help file name
3676 * and path, and the context identifier for the library Help topic in the Help
3679 * On a successful return all non-null BSTR pointers will have been set,
3682 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3686 BSTR *pBstrDocString,
3687 DWORD *pdwHelpContext,
3688 BSTR *pBstrHelpFile)
3690 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3692 HRESULT result = E_INVALIDARG;
3697 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3699 pBstrName, pBstrDocString,
3700 pdwHelpContext, pBstrHelpFile);
3704 /* documentation for the typelib */
3709 if(!(*pBstrName = SysAllocString(This->Name)))
3717 if (This->DocString)
3719 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3722 else if (This->Name)
3724 if(!(*pBstrDocString = SysAllocString(This->Name)))
3728 *pBstrDocString = NULL;
3732 *pdwHelpContext = This->dwHelpContext;
3738 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3742 *pBstrHelpFile = NULL;
3749 /* for a typeinfo */
3750 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3752 if(SUCCEEDED(result))
3754 result = ITypeInfo_GetDocumentation(pTInfo,
3758 pdwHelpContext, pBstrHelpFile);
3760 ITypeInfo_Release(pTInfo);
3765 if (pBstrDocString) SysFreeString (*pBstrDocString);
3767 if (pBstrName) SysFreeString (*pBstrName);
3769 return STG_E_INSUFFICIENTMEMORY;
3774 * Indicates whether a passed-in string contains the name of a type or member
3775 * described in the library.
3778 static HRESULT WINAPI ITypeLib2_fnIsName(
3784 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3785 ITypeInfoImpl *pTInfo;
3786 TLBFuncDesc *pFInfo;
3789 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3791 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3795 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3796 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3797 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3798 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3799 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3800 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3801 goto ITypeLib2_fnIsName_exit;
3803 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3804 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3809 ITypeLib2_fnIsName_exit:
3810 TRACE("(%p)slow! search for %s: %s found!\n", This,
3811 debugstr_w(szNameBuf), *pfName?"NOT":"");
3816 /* ITypeLib::FindName
3818 * Finds occurrences of a type description in a type library. This may be used
3819 * to quickly verify that a name exists in a type library.
3822 static HRESULT WINAPI ITypeLib2_fnFindName(
3826 ITypeInfo **ppTInfo,
3830 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3831 ITypeInfoImpl *pTInfo;
3832 TLBFuncDesc *pFInfo;
3835 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3837 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3838 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3839 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3840 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3841 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3842 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3843 goto ITypeLib2_fnFindName_exit;
3846 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3847 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3849 ITypeLib2_fnFindName_exit:
3850 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3851 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3854 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3855 This, *pcFound, debugstr_w(szNameBuf), j);
3862 /* ITypeLib::ReleaseTLibAttr
3864 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3867 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3869 TLIBATTR *pTLibAttr)
3871 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3872 TRACE("freeing (%p)\n",This);
3873 HeapFree(GetProcessHeap(),0,pTLibAttr);
3877 /* ITypeLib2::GetCustData
3879 * gets the custom data
3881 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3886 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3887 TLBCustData *pCData;
3889 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3891 if( IsEqualIID(guid, &pCData->guid)) break;
3894 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3898 VariantInit( pVarVal);
3899 VariantCopy( pVarVal, &pCData->data);
3902 return E_INVALIDARG; /* FIXME: correct? */
3905 /* ITypeLib2::GetLibStatistics
3907 * Returns statistics about a type library that are required for efficient
3908 * sizing of hash tables.
3911 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3913 ULONG *pcUniqueNames,
3914 ULONG *pcchUniqueNames)
3916 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3918 FIXME("(%p): stub!\n", This);
3920 if(pcUniqueNames) *pcUniqueNames=1;
3921 if(pcchUniqueNames) *pcchUniqueNames=1;
3925 /* ITypeLib2::GetDocumentation2
3927 * Retrieves the library's documentation string, the complete Help file name
3928 * and path, the localization context to use, and the context ID for the
3929 * library Help topic in the Help file.
3932 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3936 BSTR *pbstrHelpString,
3937 DWORD *pdwHelpStringContext,
3938 BSTR *pbstrHelpStringDll)
3940 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3944 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3946 /* the help string should be obtained from the helpstringdll,
3947 * using the _DLLGetDocumentation function, based on the supplied
3948 * lcid. Nice to do sometime...
3952 /* documentation for the typelib */
3954 *pbstrHelpString=SysAllocString(This->DocString);
3955 if(pdwHelpStringContext)
3956 *pdwHelpStringContext=This->dwHelpContext;
3957 if(pbstrHelpStringDll)
3958 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3964 /* for a typeinfo */
3965 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3967 if(SUCCEEDED(result))
3969 ITypeInfo2 * pTInfo2;
3970 result = ITypeInfo_QueryInterface(pTInfo,
3972 (LPVOID*) &pTInfo2);
3974 if(SUCCEEDED(result))
3976 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3980 pdwHelpStringContext,
3981 pbstrHelpStringDll);
3983 ITypeInfo2_Release(pTInfo2);
3986 ITypeInfo_Release(pTInfo);
3992 /* ITypeLib2::GetAllCustData
3994 * Gets all custom data items for the library.
3997 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3999 CUSTDATA *pCustData)
4001 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4002 TLBCustData *pCData;
4004 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4005 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4006 if(pCustData->prgCustData ){
4007 pCustData->cCustData=This->ctCustData;
4008 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4009 pCustData->prgCustData[i].guid=pCData->guid;
4010 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4013 ERR(" OUT OF MEMORY!\n");
4014 return E_OUTOFMEMORY;
4019 static const ITypeLib2Vtbl tlbvt = {
4020 ITypeLib2_fnQueryInterface,
4022 ITypeLib2_fnRelease,
4023 ITypeLib2_fnGetTypeInfoCount,
4024 ITypeLib2_fnGetTypeInfo,
4025 ITypeLib2_fnGetTypeInfoType,
4026 ITypeLib2_fnGetTypeInfoOfGuid,
4027 ITypeLib2_fnGetLibAttr,
4028 ITypeLib2_fnGetTypeComp,
4029 ITypeLib2_fnGetDocumentation,
4031 ITypeLib2_fnFindName,
4032 ITypeLib2_fnReleaseTLibAttr,
4034 ITypeLib2_fnGetCustData,
4035 ITypeLib2_fnGetLibStatistics,
4036 ITypeLib2_fnGetDocumentation2,
4037 ITypeLib2_fnGetAllCustData
4041 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4043 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4045 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4048 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4050 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4052 return ITypeLib2_AddRef((ITypeLib2 *)This);
4055 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4057 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4059 return ITypeLib2_Release((ITypeLib2 *)This);
4062 static HRESULT WINAPI ITypeLibComp_fnBind(
4067 ITypeInfo ** ppTInfo,
4068 DESCKIND * pDescKind,
4071 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4072 ITypeInfoImpl *pTypeInfo;
4074 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4076 *pDescKind = DESCKIND_NONE;
4077 pBindPtr->lptcomp = NULL;
4080 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4082 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4084 /* FIXME: check wFlags here? */
4085 /* FIXME: we should use a hash table to look this info up using lHash
4086 * instead of an O(n) search */
4087 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4088 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4090 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4092 *pDescKind = DESCKIND_TYPECOMP;
4093 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4094 ITypeComp_AddRef(pBindPtr->lptcomp);
4095 TRACE("module or enum: %s\n", debugstr_w(szName));
4100 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4101 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4103 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4106 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4107 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4109 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4114 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4115 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4117 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4119 ITypeInfo *subtypeinfo;
4121 DESCKIND subdesckind;
4123 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4124 &subtypeinfo, &subdesckind, &subbindptr);
4125 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4127 TYPEDESC tdesc_appobject =
4130 (TYPEDESC *)pTypeInfo->hreftype
4134 const VARDESC vardesc_appobject =
4137 NULL, /* lpstrSchema */
4152 VAR_STATIC /* varkind */
4155 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4157 /* cleanup things filled in by Bind call so we can put our
4158 * application object data in there instead */
4159 switch (subdesckind)
4161 case DESCKIND_FUNCDESC:
4162 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4164 case DESCKIND_VARDESC:
4165 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4170 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4172 if (pTypeInfo->hreftype == -1)
4173 FIXME("no hreftype for interface %p\n", pTypeInfo);
4175 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4179 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4180 *ppTInfo = (ITypeInfo *)pTypeInfo;
4181 ITypeInfo_AddRef(*ppTInfo);
4187 TRACE("name not found %s\n", debugstr_w(szName));
4191 static HRESULT WINAPI ITypeLibComp_fnBindType(
4195 ITypeInfo ** ppTInfo,
4196 ITypeComp ** ppTComp)
4198 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4202 static const ITypeCompVtbl tlbtcvt =
4205 ITypeLibComp_fnQueryInterface,
4206 ITypeLibComp_fnAddRef,
4207 ITypeLibComp_fnRelease,
4209 ITypeLibComp_fnBind,
4210 ITypeLibComp_fnBindType
4213 /*================== ITypeInfo(2) Methods ===================================*/
4214 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4216 ITypeInfoImpl * pTypeInfoImpl;
4218 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4221 pTypeInfoImpl->lpVtbl = &tinfvt;
4222 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4223 pTypeInfoImpl->ref=1;
4224 pTypeInfoImpl->hreftype = -1;
4226 TRACE("(%p)\n", pTypeInfoImpl);
4227 return (ITypeInfo2*) pTypeInfoImpl;
4230 /* ITypeInfo::QueryInterface
4232 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4237 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4239 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4242 if(IsEqualIID(riid, &IID_IUnknown) ||
4243 IsEqualIID(riid,&IID_ITypeInfo)||
4244 IsEqualIID(riid,&IID_ITypeInfo2))
4248 ITypeInfo_AddRef(iface);
4249 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4252 TRACE("-- Interface: E_NOINTERFACE\n");
4253 return E_NOINTERFACE;
4256 /* ITypeInfo::AddRef
4258 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4260 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4261 ULONG ref = InterlockedIncrement(&This->ref);
4263 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4265 TRACE("(%p)->ref is %lu\n",This, ref);
4269 /* ITypeInfo::Release
4271 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4273 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4274 ULONG ref = InterlockedDecrement(&This->ref);
4276 TRACE("(%p)->(%lu)\n",This, ref);
4279 /* We don't release ITypeLib when ref=0 because
4280 it means that function is called by ITypeLib2_Release */
4281 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4283 static int once = 0;
4287 FIXME("destroy child objects\n");
4290 TRACE("destroying ITypeInfo(%p)\n",This);
4293 SysFreeString(This->Name);
4297 if (This->DocString)
4299 SysFreeString(This->DocString);
4300 This->DocString = 0;
4305 SysFreeString(This->DllName);
4311 ITypeInfo_Release((ITypeInfo*)This->next);
4314 HeapFree(GetProcessHeap(),0,This);
4320 /* ITypeInfo::GetTypeAttr
4322 * Retrieves a TYPEATTR structure that contains the attributes of the type
4326 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4327 LPTYPEATTR *ppTypeAttr)
4329 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4332 TRACE("(%p)\n",This);
4334 size = sizeof(**ppTypeAttr);
4335 if (This->TypeAttr.typekind == TKIND_ALIAS)
4336 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4338 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4340 return E_OUTOFMEMORY;
4342 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4344 if (This->TypeAttr.typekind == TKIND_ALIAS)
4345 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4346 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4348 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4349 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4351 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4352 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4357 /* ITypeInfo::GetTypeComp
4359 * Retrieves the ITypeComp interface for the type description, which enables a
4360 * client compiler to bind to the type description's members.
4363 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4364 ITypeComp * *ppTComp)
4366 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4368 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4370 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4371 ITypeComp_AddRef(*ppTComp);
4375 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4377 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4378 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4379 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4383 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4385 memcpy(dest, src, sizeof(ELEMDESC));
4386 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4387 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4389 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4390 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4391 *buffer += sizeof(PARAMDESCEX);
4392 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4393 VariantInit(&pparamdescex_dest->varDefaultValue);
4394 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4395 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4398 dest->u.paramdesc.pparamdescex = NULL;
4402 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4404 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4405 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4408 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4412 SIZE_T size = sizeof(*src);
4416 size += sizeof(*src->lprgscode) * src->cScodes;
4417 size += TLB_SizeElemDesc(&src->elemdescFunc);
4418 for (i = 0; i < src->cParams; i++)
4420 size += sizeof(ELEMDESC);
4421 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4424 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4425 if (!dest) return E_OUTOFMEMORY;
4427 memcpy(dest, src, sizeof(FUNCDESC));
4428 buffer = (char *)(dest + 1);
4430 dest->lprgscode = (SCODE *)buffer;
4431 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4432 buffer += sizeof(*src->lprgscode) * src->cScodes;
4434 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4437 SysFreeString((BSTR)dest);
4441 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4442 buffer += sizeof(ELEMDESC) * src->cParams;
4443 for (i = 0; i < src->cParams; i++)
4445 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4451 /* undo the above actions */
4452 for (i = i - 1; i >= 0; i--)
4453 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4454 TLB_FreeElemDesc(&dest->elemdescFunc);
4455 SysFreeString((BSTR)dest);
4459 /* special treatment for dispinterfaces: this makes functions appear
4460 * to return their [retval] value when it is really returning an
4462 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4464 if (dest->cParams &&
4465 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4467 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4468 if (elemdesc->tdesc.vt != VT_PTR)
4470 ERR("elemdesc should have started with VT_PTR instead of:\n");
4472 dump_ELEMDESC(elemdesc);
4473 return E_UNEXPECTED;
4476 /* copy last parameter to the return value. we are using a flat
4477 * buffer so there is no danger of leaking memory in
4479 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4481 /* remove the last parameter */
4485 /* otherwise this function is made to appear to have no return
4487 dest->elemdescFunc.tdesc.vt = VT_VOID;
4495 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4497 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4498 const TLBFuncDesc *pFDesc;
4501 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4506 *ppFuncDesc = &pFDesc->funcdesc;
4510 return E_INVALIDARG;
4513 /* ITypeInfo::GetFuncDesc
4515 * Retrieves the FUNCDESC structure that contains information about a
4516 * specified function.
4519 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4520 LPFUNCDESC *ppFuncDesc)
4522 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4523 const FUNCDESC *internal_funcdesc;
4526 TRACE("(%p) index %d\n", This, index);
4528 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4532 return TLB_AllocAndInitFuncDesc(
4535 This->TypeAttr.typekind == TKIND_DISPATCH);
4538 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4542 SIZE_T size = sizeof(*src);
4545 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4546 if (src->varkind == VAR_CONST)
4547 size += sizeof(VARIANT);
4548 size += TLB_SizeElemDesc(&src->elemdescVar);
4550 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4551 if (!dest) return E_OUTOFMEMORY;
4554 buffer = (char *)(dest + 1);
4555 if (src->lpstrSchema)
4558 dest->lpstrSchema = (LPOLESTR)buffer;
4559 len = strlenW(src->lpstrSchema);
4560 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4561 buffer += (len + 1) * sizeof(WCHAR);
4564 if (src->varkind == VAR_CONST)
4568 dest->u.lpvarValue = (VARIANT *)buffer;
4569 *dest->u.lpvarValue = *src->u.lpvarValue;
4570 buffer += sizeof(VARIANT);
4571 VariantInit(dest->u.lpvarValue);
4572 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4575 SysFreeString((BSTR)dest_ptr);
4579 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4582 if (src->varkind == VAR_CONST)
4583 VariantClear(dest->u.lpvarValue);
4584 SysFreeString((BSTR)dest);
4591 /* ITypeInfo::GetVarDesc
4593 * Retrieves a VARDESC structure that describes the specified variable.
4596 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4597 LPVARDESC *ppVarDesc)
4599 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4601 const TLBVarDesc *pVDesc;
4603 TRACE("(%p) index %d\n", This, index);
4605 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4609 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4611 return E_INVALIDARG;
4614 /* ITypeInfo_GetNames
4616 * Retrieves the variable with the specified member ID (or the name of the
4617 * property or method and its parameters) that correspond to the specified
4620 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4621 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4623 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4624 const TLBFuncDesc *pFDesc;
4625 const TLBVarDesc *pVDesc;
4627 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4628 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4631 /* function found, now return function and parameter names */
4632 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4635 *rgBstrNames=SysAllocString(pFDesc->Name);
4637 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4643 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4646 *rgBstrNames=SysAllocString(pVDesc->Name);
4651 if(This->TypeAttr.cImplTypes &&
4652 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4653 /* recursive search */
4656 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4658 if(SUCCEEDED(result))
4660 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4661 ITypeInfo_Release(pTInfo);
4664 WARN("Could not search inherited interface!\n");
4668 WARN("no names found\n");
4671 return TYPE_E_ELEMENTNOTFOUND;
4678 /* ITypeInfo::GetRefTypeOfImplType
4680 * If a type description describes a COM class, it retrieves the type
4681 * description of the implemented interface types. For an interface,
4682 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4686 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4691 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4694 const TLBImplType *pImpl = This->impltypelist;
4696 TRACE("(%p) index %d\n", This, index);
4697 if (TRACE_ON(ole)) dump_TypeInfo(This);
4701 /* only valid on dual interfaces;
4702 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4704 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4706 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4707 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4713 hr = TYPE_E_ELEMENTNOTFOUND;
4718 /* get element n from linked list */
4719 for(i=0; pImpl && i<index; i++)
4721 pImpl = pImpl->next;
4725 *pRefType = pImpl->hRef;
4727 hr = TYPE_E_ELEMENTNOTFOUND;
4733 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4735 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4741 /* ITypeInfo::GetImplTypeFlags
4743 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4744 * or base interface in a type description.
4746 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4747 UINT index, INT *pImplTypeFlags)
4749 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4753 TRACE("(%p) index %d\n", This, index);
4754 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4755 i++, pImpl=pImpl->next)
4757 if(i==index && pImpl){
4758 *pImplTypeFlags=pImpl->implflags;
4762 return TYPE_E_ELEMENTNOTFOUND;
4766 * Maps between member names and member IDs, and parameter names and
4769 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4770 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4772 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4773 const TLBFuncDesc *pFDesc;
4774 const TLBVarDesc *pVDesc;
4778 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4781 /* init out parameters in case of failure */
4782 for (i = 0; i < cNames; i++)
4783 pMemId[i] = MEMBERID_NIL;
4785 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4787 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4788 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4789 for(i=1; i < cNames; i++){
4790 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4791 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4793 if( j<pFDesc->funcdesc.cParams)
4796 ret=DISP_E_UNKNOWNNAME;
4798 TRACE("-- 0x%08lx\n", ret);
4802 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4803 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4804 if(cNames) *pMemId=pVDesc->vardesc.memid;
4808 /* not found, see if it can be found in an inherited interface */
4809 if(This->TypeAttr.cImplTypes) {
4810 /* recursive search */
4812 ret=ITypeInfo_GetRefTypeInfo(iface,
4813 This->impltypelist->hRef, &pTInfo);
4815 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4816 ITypeInfo_Release(pTInfo);
4819 WARN("Could not search inherited interface!\n");
4821 WARN("no names found\n");
4822 return DISP_E_UNKNOWNNAME;
4825 /* ITypeInfo::Invoke
4827 * Invokes a method, or accesses a property of an object, that implements the
4828 * interface described by the type description.
4831 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4834 if (TRACE_ON(ole)) {
4836 TRACE("Calling %p(",func);
4837 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4849 res = func(args[0]);
4852 res = func(args[0],args[1]);
4855 res = func(args[0],args[1],args[2]);
4858 res = func(args[0],args[1],args[2],args[3]);
4861 res = func(args[0],args[1],args[2],args[3],args[4]);
4864 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4867 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4870 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4873 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4876 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4879 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4882 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
4885 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
4888 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
4891 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
4894 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
4897 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
4900 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]);
4903 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]);
4906 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]);
4909 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]);
4912 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]);
4915 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]);
4918 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4924 FIXME("unsupported calling convention %d\n",callconv);
4928 TRACE("returns %08lx\n",res);
4932 extern int _argsize(DWORD vt);
4934 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4937 ITypeInfo *tinfo2 = NULL;
4938 TYPEATTR *tattr = NULL;
4940 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4943 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4945 tdesc->u.hreftype, hr);
4948 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4951 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4952 ITypeInfo_Release(tinfo2);
4956 switch (tattr->typekind)
4963 tdesc = &tattr->tdescAlias;
4964 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4967 case TKIND_INTERFACE:
4968 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4974 case TKIND_DISPATCH:
4979 FIXME("TKIND_RECORD unhandled.\n");
4984 FIXME("TKIND_RECORD unhandled.\n");
4989 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4993 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4994 ITypeInfo_Release(tinfo2);
4998 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5002 /* enforce only one level of pointer indirection */
5003 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5005 tdesc = tdesc->u.lptdesc;
5007 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5008 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5009 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5010 if ((tdesc->vt == VT_USERDEFINED) ||
5011 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5013 VARTYPE vt_userdefined = 0;
5014 const TYPEDESC *tdesc_userdefined = tdesc;
5015 if (tdesc->vt == VT_PTR)
5017 vt_userdefined = VT_BYREF;
5018 tdesc_userdefined = tdesc->u.lptdesc;
5020 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5022 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5023 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5025 *vt |= vt_userdefined;
5037 case VT_USERDEFINED:
5038 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5045 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5046 hr = DISP_E_BADVARTYPE;
5050 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5059 /***********************************************************************
5060 * DispCallFunc (OLEAUT32.@)
5062 * Invokes a function of the specifed calling convention, passing the
5063 * specified arguments and returns the result.
5066 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5067 * oVft [I] The offset in the vtable. See notes.
5068 * cc [I] Calling convention of the function to call.
5069 * vtReturn [I] The return type of the function.
5070 * cActuals [I] Number of parameters.
5071 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5072 * prgpvarg [I] The arguments to pass.
5073 * pvargResult [O] The return value of the function. Can be NULL.
5077 * Failure: HRESULT code.
5080 * The HRESULT return value of this function is not affected by the return
5081 * value of the user supplied function, which is returned in pvargResult.
5083 * If pvInstance is NULL then a non-object function is to be called and oVft
5084 * is the address of the function to call.
5086 * The cc parameter can be one of the following values:
5099 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5100 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5102 int i, argsize, argspos;
5106 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5107 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5108 pvargResult, V_VT(pvargResult));
5112 argsize++; /* for This pointer */
5114 for (i=0;i<cActuals;i++)
5116 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5117 dump_Variant(prgpvarg[i]);
5118 argsize += _argsize(prgvt[i]);
5120 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5125 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5129 for (i=0;i<cActuals;i++)
5131 VARIANT *arg = prgpvarg[i];
5132 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5133 if (prgvt[i] == VT_VARIANT)
5134 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5136 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5137 argspos += _argsize(prgvt[i]);
5142 FARPROC *vtable = *(FARPROC**)pvInstance;
5143 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5146 /* if we aren't invoking an object then the function pointer is stored
5148 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5150 if (pvargResult && (vtReturn != VT_EMPTY))
5152 TRACE("Method returned 0x%08lx\n",hres);
5153 V_VT(pvargResult) = vtReturn;
5154 V_UI4(pvargResult) = hres;
5157 HeapFree(GetProcessHeap(),0,args);
5161 #define INVBUF_ELEMENT_SIZE \
5162 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5163 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5164 ((VARIANTARG *)(buffer))
5165 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5166 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5167 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5168 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5169 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5170 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5172 static HRESULT WINAPI ITypeInfo_fnInvoke(
5177 DISPPARAMS *pDispParams,
5178 VARIANT *pVarResult,
5179 EXCEPINFO *pExcepInfo,
5182 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5184 unsigned int var_index;
5187 const TLBFuncDesc *pFuncInfo;
5189 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5190 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5192 dump_DispParms(pDispParams);
5194 /* we do this instead of using GetFuncDesc since it will return a fake
5195 * FUNCDESC for dispinterfaces and we want the real function description */
5196 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5197 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5201 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5205 TRACE("invoking:\n");
5206 dump_TLBFuncDescOne(pFuncInfo);
5209 switch (func_desc->funckind) {
5210 case FUNC_PUREVIRTUAL:
5211 case FUNC_VIRTUAL: {
5212 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5214 VARIANT retval; /* pointer for storing byref retvals in */
5215 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5216 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5217 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5220 for (i = 0; i < func_desc->cParams; i++)
5222 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5223 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5228 TRACE("changing args\n");
5229 for (i = 0; i < func_desc->cParams; i++)
5231 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5233 if (wParamFlags & PARAMFLAG_FRETVAL)
5235 /* note: this check is placed so that if the caller passes
5236 * in a VARIANTARG for the retval we just ignore it, like
5238 if (i == func_desc->cParams - 1)
5241 arg = prgpvarg[i] = &rgvarg[i];
5242 memset(arg, 0, sizeof(*arg));
5243 V_VT(arg) = rgvt[i];
5244 memset(&retval, 0, sizeof(retval));
5245 V_BYREF(arg) = &retval;
5249 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5250 hres = E_UNEXPECTED;
5254 else if (i < pDispParams->cArgs)
5256 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5257 dump_Variant(src_arg);
5259 if (rgvt[i] == VT_VARIANT)
5260 hres = VariantCopy(&rgvarg[i], src_arg);
5261 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5263 if (rgvt[i] == V_VT(src_arg))
5264 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5267 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5268 hres = VariantCopy(&missing_arg[i], src_arg);
5269 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5271 V_VT(&rgvarg[i]) = rgvt[i];
5273 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5275 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5276 V_VT(&missing_arg[i]) = V_VT(src_arg);
5277 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5278 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5279 V_VT(&rgvarg[i]) = rgvt[i];
5281 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5283 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5284 V_VT(&rgvarg[i]) = rgvt[i];
5288 /* FIXME: this doesn't work for VT_BYREF arguments if
5289 * they are not the same type as in the paramdesc */
5290 V_VT(&rgvarg[i]) = V_VT(src_arg);
5291 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5292 V_VT(&rgvarg[i]) = rgvt[i];
5297 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5298 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5299 debugstr_VT(src_arg), debugstr_VF(src_arg));
5302 prgpvarg[i] = &rgvarg[i];
5304 else if (wParamFlags & PARAMFLAG_FOPT)
5307 arg = prgpvarg[i] = &rgvarg[i];
5308 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5310 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5316 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5317 V_VT(arg) = VT_VARIANT | VT_BYREF;
5318 V_VARIANTREF(arg) = &missing_arg[i];
5319 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5320 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5325 hres = DISP_E_BADPARAMCOUNT;
5329 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5330 if (func_desc->cParamsOpt < 0)
5332 FIXME("Does not support safearray optional parameters\n");
5333 hres = DISP_E_BADPARAMCOUNT;
5334 goto func_fail; /* FIXME: we don't free changed types here */
5337 V_VT(&varresult) = 0;
5338 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5339 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5341 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5342 V_VT(&varresult), func_desc->cParams, rgvt,
5343 prgpvarg, &varresult);
5345 for (i = 0; i < func_desc->cParams; i++)
5347 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5348 if (wParamFlags & PARAMFLAG_FRETVAL)
5352 TRACE("[retval] value: ");
5353 dump_Variant(prgpvarg[i]);
5357 /* deref return value */
5358 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5360 /* free data stored in varresult. Note that
5361 * VariantClear doesn't do what we want because we are
5362 * working with byref types. */
5363 /* FIXME: clear safearrays, bstrs, records and
5364 * variants here too */
5365 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5366 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5368 if(*V_UNKNOWNREF(prgpvarg[i]))
5369 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5373 else if (i < pDispParams->cArgs)
5375 if (wParamFlags & PARAMFLAG_FOUT)
5377 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5379 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5380 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5384 ERR("failed to convert param %d to vt %d\n", i,
5385 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5389 VariantClear(&rgvarg[i]);
5391 else if (wParamFlags & PARAMFLAG_FOPT)
5393 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5394 VariantClear(&rgvarg[i]);
5398 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5400 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5401 hres = DISP_E_EXCEPTION;
5402 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5406 HeapFree(GetProcessHeap(), 0, buffer);
5409 case FUNC_DISPATCH: {
5412 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5413 if (SUCCEEDED(hres)) {
5414 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5415 hres = IDispatch_Invoke(
5416 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5417 pVarResult,pExcepInfo,pArgErr
5420 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5421 IDispatch_Release(disp);
5423 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5427 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5432 TRACE("-- 0x%08lx\n", hres);
5435 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5438 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5439 if(FAILED(hres)) return hres;
5441 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5442 dump_VARDESC(var_desc);
5443 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5447 /* not found, look for it in inherited interfaces */
5448 ITypeInfo2_GetTypeKind(iface, &type_kind);
5449 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5451 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5452 /* recursive search */
5454 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5455 if(SUCCEEDED(hres)){
5456 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5457 ITypeInfo_Release(pTInfo);
5460 WARN("Could not search inherited interface!\n");
5463 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5464 return DISP_E_MEMBERNOTFOUND;
5467 /* ITypeInfo::GetDocumentation
5469 * Retrieves the documentation string, the complete Help file name and path,
5470 * and the context ID for the Help topic for a specified type description.
5472 * (Can be tested by the Visual Basic Editor in Word for instance.)
5474 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5475 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5476 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5478 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5479 const TLBFuncDesc *pFDesc;
5480 const TLBVarDesc *pVDesc;
5481 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5482 " HelpContext(%p) HelpFile(%p)\n",
5483 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5484 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5486 *pBstrName=SysAllocString(This->Name);
5488 *pBstrDocString=SysAllocString(This->DocString);
5490 *pdwHelpContext=This->dwHelpContext;
5492 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5494 }else {/* for a member */
5495 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5496 if(pFDesc->funcdesc.memid==memid){
5498 *pBstrName = SysAllocString(pFDesc->Name);
5500 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5502 *pdwHelpContext=pFDesc->helpcontext;
5505 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5506 if(pVDesc->vardesc.memid==memid){
5508 *pBstrName = SysAllocString(pVDesc->Name);
5510 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5512 *pdwHelpContext=pVDesc->HelpContext;
5516 WARN("member %ld not found\n", memid);
5517 return TYPE_E_ELEMENTNOTFOUND;
5520 /* ITypeInfo::GetDllEntry
5522 * Retrieves a description or specification of an entry point for a function
5525 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5526 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5529 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5530 const TLBFuncDesc *pFDesc;
5532 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5534 if (pBstrDllName) *pBstrDllName = NULL;
5535 if (pBstrName) *pBstrName = NULL;
5536 if (pwOrdinal) *pwOrdinal = 0;
5538 if (This->TypeAttr.typekind != TKIND_MODULE)
5539 return TYPE_E_BADMODULEKIND;
5541 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5542 if(pFDesc->funcdesc.memid==memid){
5543 dump_TypeInfo(This);
5545 dump_TLBFuncDescOne(pFDesc);
5548 *pBstrDllName = SysAllocString(This->DllName);
5550 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5552 *pBstrName = SysAllocString(pFDesc->Entry);
5560 *pwOrdinal = (DWORD)pFDesc->Entry;
5563 return TYPE_E_ELEMENTNOTFOUND;
5566 /* ITypeInfo::GetRefTypeInfo
5568 * If a type description references other type descriptions, it retrieves
5569 * the referenced type descriptions.
5571 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5574 ITypeInfo **ppTInfo)
5576 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5577 HRESULT result = E_FAIL;
5579 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5581 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5582 ITypeInfo_AddRef(*ppTInfo);
5585 else if (hRefType == -1 &&
5586 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5587 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5589 /* when we meet a DUAL dispinterface, we must create the interface
5592 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5595 /* the interface version contains the same information as the dispinterface
5596 * copy the contents of the structs.
5598 *pTypeInfoImpl = *This;
5599 pTypeInfoImpl->ref = 1;
5601 /* change the type to interface */
5602 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5604 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5606 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5611 TLBRefType *pRefType;
5612 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5613 if(pRefType->reference == hRefType)
5617 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5618 if(pRefType && hRefType != -1) {
5619 ITypeLib *pTLib = NULL;
5621 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5623 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5625 if(pRefType->pImpTLInfo->pImpTypeLib) {
5626 TRACE("typeinfo in imported typelib that is already loaded\n");
5627 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5628 ITypeLib2_AddRef((ITypeLib*) pTLib);
5631 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5632 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5633 pRefType->pImpTLInfo->wVersionMajor,
5634 pRefType->pImpTLInfo->wVersionMinor,
5635 pRefType->pImpTLInfo->lcid,
5638 if(!SUCCEEDED(result)) {
5639 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5640 result=LoadTypeLib(libnam, &pTLib);
5641 SysFreeString(libnam);
5643 if(SUCCEEDED(result)) {
5644 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5645 ITypeLib2_AddRef(pTLib);
5649 if(SUCCEEDED(result)) {
5650 if(pRefType->index == TLB_REF_USE_GUID)
5651 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5655 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5659 ITypeLib2_Release(pTLib);
5663 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5664 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5668 /* ITypeInfo::AddressOfMember
5670 * Retrieves the addresses of static functions or variables, such as those
5673 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5674 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5676 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5682 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5684 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5688 module = LoadLibraryW(dll);
5691 ERR("couldn't load %s\n", debugstr_w(dll));
5693 if (entry) SysFreeString(entry);
5694 return STG_E_FILENOTFOUND;
5696 /* FIXME: store library somewhere where we can free it */
5701 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5702 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5703 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5705 *ppv = GetProcAddress(module, entryA);
5707 ERR("function not found %s\n", debugstr_a(entryA));
5709 HeapFree(GetProcessHeap(), 0, entryA);
5713 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5715 ERR("function not found %d\n", ordinal);
5719 if (entry) SysFreeString(entry);
5722 return TYPE_E_DLLFUNCTIONNOTFOUND;
5727 /* ITypeInfo::CreateInstance
5729 * Creates a new instance of a type that describes a component object class
5732 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5733 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5735 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5736 FIXME("(%p) stub!\n", This);
5740 /* ITypeInfo::GetMops
5742 * Retrieves marshalling information.
5744 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5747 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5748 FIXME("(%p) stub!\n", This);
5752 /* ITypeInfo::GetContainingTypeLib
5754 * Retrieves the containing type library and the index of the type description
5755 * within that type library.
5757 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5758 ITypeLib * *ppTLib, UINT *pIndex)
5760 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5762 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5764 *pIndex=This->index;
5765 TRACE("returning pIndex=%d\n", *pIndex);
5769 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5770 ITypeLib2_AddRef(*ppTLib);
5771 TRACE("returning ppTLib=%p\n", *ppTLib);
5777 /* ITypeInfo::ReleaseTypeAttr
5779 * Releases a TYPEATTR previously returned by GetTypeAttr.
5782 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5783 TYPEATTR* pTypeAttr)
5785 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5786 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5787 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5790 /* ITypeInfo::ReleaseFuncDesc
5792 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5794 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5796 FUNCDESC *pFuncDesc)
5798 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5801 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5803 for (i = 0; i < pFuncDesc->cParams; i++)
5804 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5805 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5807 SysFreeString((BSTR)pFuncDesc);
5810 /* ITypeInfo::ReleaseVarDesc
5812 * Releases a VARDESC previously returned by GetVarDesc.
5814 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5817 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5818 TRACE("(%p)->(%p)\n", This, pVarDesc);
5820 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5821 if (pVarDesc->varkind == VAR_CONST)
5822 VariantClear(pVarDesc->u.lpvarValue);
5823 SysFreeString((BSTR)pVarDesc);
5826 /* ITypeInfo2::GetTypeKind
5828 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5831 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5832 TYPEKIND *pTypeKind)
5834 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5835 *pTypeKind=This->TypeAttr.typekind;
5836 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5840 /* ITypeInfo2::GetTypeFlags
5842 * Returns the type flags without any allocations. This returns a DWORD type
5843 * flag, which expands the type flags without growing the TYPEATTR (type
5847 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5849 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5850 *pTypeFlags=This->TypeAttr.wTypeFlags;
5851 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5855 /* ITypeInfo2::GetFuncIndexOfMemId
5856 * Binds to a specific member based on a known DISPID, where the member name
5857 * is not known (for example, when binding to a default member).
5860 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5861 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5863 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5864 const TLBFuncDesc *pFuncInfo;
5868 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5869 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5875 result = TYPE_E_ELEMENTNOTFOUND;
5877 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5878 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5882 /* TypeInfo2::GetVarIndexOfMemId
5884 * Binds to a specific member based on a known DISPID, where the member name
5885 * is not known (for example, when binding to a default member).
5888 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5889 MEMBERID memid, UINT *pVarIndex)
5891 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5892 TLBVarDesc *pVarInfo;
5895 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5896 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5902 result = TYPE_E_ELEMENTNOTFOUND;
5904 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5905 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5909 /* ITypeInfo2::GetCustData
5911 * Gets the custom data
5913 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5918 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5919 TLBCustData *pCData;
5921 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5922 if( IsEqualIID(guid, &pCData->guid)) break;
5924 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5928 VariantInit( pVarVal);
5929 VariantCopy( pVarVal, &pCData->data);
5932 return E_INVALIDARG; /* FIXME: correct? */
5935 /* ITypeInfo2::GetFuncCustData
5937 * Gets the custom data
5939 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5945 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5946 TLBCustData *pCData=NULL;
5947 TLBFuncDesc * pFDesc;
5949 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5950 pFDesc=pFDesc->next);
5953 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5954 if( IsEqualIID(guid, &pCData->guid)) break;
5956 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5959 VariantInit( pVarVal);
5960 VariantCopy( pVarVal, &pCData->data);
5963 return E_INVALIDARG; /* FIXME: correct? */
5966 /* ITypeInfo2::GetParamCustData
5968 * Gets the custom data
5970 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5977 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5978 TLBCustData *pCData=NULL;
5979 TLBFuncDesc * pFDesc;
5982 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5984 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5985 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5986 pCData = pCData->next)
5987 if( IsEqualIID(guid, &pCData->guid)) break;
5989 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5993 VariantInit( pVarVal);
5994 VariantCopy( pVarVal, &pCData->data);
5997 return E_INVALIDARG; /* FIXME: correct? */
6000 /* ITypeInfo2::GetVarCustData
6002 * Gets the custom data
6004 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6010 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6011 TLBCustData *pCData=NULL;
6012 TLBVarDesc * pVDesc;
6015 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6019 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6021 if( IsEqualIID(guid, &pCData->guid)) break;
6025 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6029 VariantInit( pVarVal);
6030 VariantCopy( pVarVal, &pCData->data);
6033 return E_INVALIDARG; /* FIXME: correct? */
6036 /* ITypeInfo2::GetImplCustData
6038 * Gets the custom data
6040 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6046 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6047 TLBCustData *pCData=NULL;
6048 TLBImplType * pRDesc;
6051 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6055 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6057 if( IsEqualIID(guid, &pCData->guid)) break;
6061 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6065 VariantInit( pVarVal);
6066 VariantCopy( pVarVal, &pCData->data);
6069 return E_INVALIDARG; /* FIXME: correct? */
6072 /* ITypeInfo2::GetDocumentation2
6074 * Retrieves the documentation string, the complete Help file name and path,
6075 * the localization context to use, and the context ID for the library Help
6076 * topic in the Help file.
6079 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6083 BSTR *pbstrHelpString,
6084 DWORD *pdwHelpStringContext,
6085 BSTR *pbstrHelpStringDll)
6087 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6088 const TLBFuncDesc *pFDesc;
6089 const TLBVarDesc *pVDesc;
6090 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6091 "HelpStringContext(%p) HelpStringDll(%p)\n",
6092 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6093 pbstrHelpStringDll );
6094 /* the help string should be obtained from the helpstringdll,
6095 * using the _DLLGetDocumentation function, based on the supplied
6096 * lcid. Nice to do sometime...
6098 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6100 *pbstrHelpString=SysAllocString(This->Name);
6101 if(pdwHelpStringContext)
6102 *pdwHelpStringContext=This->dwHelpStringContext;
6103 if(pbstrHelpStringDll)
6104 *pbstrHelpStringDll=
6105 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6107 }else {/* for a member */
6108 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6109 if(pFDesc->funcdesc.memid==memid){
6111 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6112 if(pdwHelpStringContext)
6113 *pdwHelpStringContext=pFDesc->HelpStringContext;
6114 if(pbstrHelpStringDll)
6115 *pbstrHelpStringDll=
6116 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6119 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6120 if(pVDesc->vardesc.memid==memid){
6122 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6123 if(pdwHelpStringContext)
6124 *pdwHelpStringContext=pVDesc->HelpStringContext;
6125 if(pbstrHelpStringDll)
6126 *pbstrHelpStringDll=
6127 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6131 return TYPE_E_ELEMENTNOTFOUND;
6134 /* ITypeInfo2::GetAllCustData
6136 * Gets all custom data items for the Type info.
6139 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6141 CUSTDATA *pCustData)
6143 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6144 TLBCustData *pCData;
6147 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6149 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6150 if(pCustData->prgCustData ){
6151 pCustData->cCustData=This->ctCustData;
6152 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6153 pCustData->prgCustData[i].guid=pCData->guid;
6154 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6157 ERR(" OUT OF MEMORY!\n");
6158 return E_OUTOFMEMORY;
6163 /* ITypeInfo2::GetAllFuncCustData
6165 * Gets all custom data items for the specified Function
6168 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6171 CUSTDATA *pCustData)
6173 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6174 TLBCustData *pCData;
6175 TLBFuncDesc * pFDesc;
6177 TRACE("(%p) index %d\n", This, index);
6178 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6179 pFDesc=pFDesc->next)
6182 pCustData->prgCustData =
6183 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6184 if(pCustData->prgCustData ){
6185 pCustData->cCustData=pFDesc->ctCustData;
6186 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6187 pCData = pCData->next){
6188 pCustData->prgCustData[i].guid=pCData->guid;
6189 VariantCopy(& pCustData->prgCustData[i].varValue,
6193 ERR(" OUT OF MEMORY!\n");
6194 return E_OUTOFMEMORY;
6198 return TYPE_E_ELEMENTNOTFOUND;
6201 /* ITypeInfo2::GetAllParamCustData
6203 * Gets all custom data items for the Functions
6206 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6207 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6209 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6210 TLBCustData *pCData=NULL;
6211 TLBFuncDesc * pFDesc;
6213 TRACE("(%p) index %d\n", This, indexFunc);
6214 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6215 pFDesc=pFDesc->next)
6217 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6218 pCustData->prgCustData =
6219 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6220 sizeof(CUSTDATAITEM));
6221 if(pCustData->prgCustData ){
6222 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6223 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6224 pCData; i++, pCData = pCData->next){
6225 pCustData->prgCustData[i].guid=pCData->guid;
6226 VariantCopy(& pCustData->prgCustData[i].varValue,
6230 ERR(" OUT OF MEMORY!\n");
6231 return E_OUTOFMEMORY;
6235 return TYPE_E_ELEMENTNOTFOUND;
6238 /* ITypeInfo2::GetAllVarCustData
6240 * Gets all custom data items for the specified Variable
6243 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6244 UINT index, CUSTDATA *pCustData)
6246 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6247 TLBCustData *pCData;
6248 TLBVarDesc * pVDesc;
6250 TRACE("(%p) index %d\n", This, index);
6251 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6252 pVDesc=pVDesc->next)
6255 pCustData->prgCustData =
6256 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6257 if(pCustData->prgCustData ){
6258 pCustData->cCustData=pVDesc->ctCustData;
6259 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6260 pCData = pCData->next){
6261 pCustData->prgCustData[i].guid=pCData->guid;
6262 VariantCopy(& pCustData->prgCustData[i].varValue,
6266 ERR(" OUT OF MEMORY!\n");
6267 return E_OUTOFMEMORY;
6271 return TYPE_E_ELEMENTNOTFOUND;
6274 /* ITypeInfo2::GetAllImplCustData
6276 * Gets all custom data items for the specified implementation type
6279 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6282 CUSTDATA *pCustData)
6284 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6285 TLBCustData *pCData;
6286 TLBImplType * pRDesc;
6288 TRACE("(%p) index %d\n", This, index);
6289 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6290 pRDesc=pRDesc->next)
6293 pCustData->prgCustData =
6294 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6295 if(pCustData->prgCustData ){
6296 pCustData->cCustData=pRDesc->ctCustData;
6297 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6298 pCData = pCData->next){
6299 pCustData->prgCustData[i].guid=pCData->guid;
6300 VariantCopy(& pCustData->prgCustData[i].varValue,
6304 ERR(" OUT OF MEMORY!\n");
6305 return E_OUTOFMEMORY;
6309 return TYPE_E_ELEMENTNOTFOUND;
6312 static const ITypeInfo2Vtbl tinfvt =
6315 ITypeInfo_fnQueryInterface,
6317 ITypeInfo_fnRelease,
6319 ITypeInfo_fnGetTypeAttr,
6320 ITypeInfo_fnGetTypeComp,
6321 ITypeInfo_fnGetFuncDesc,
6322 ITypeInfo_fnGetVarDesc,
6323 ITypeInfo_fnGetNames,
6324 ITypeInfo_fnGetRefTypeOfImplType,
6325 ITypeInfo_fnGetImplTypeFlags,
6326 ITypeInfo_fnGetIDsOfNames,
6328 ITypeInfo_fnGetDocumentation,
6329 ITypeInfo_fnGetDllEntry,
6330 ITypeInfo_fnGetRefTypeInfo,
6331 ITypeInfo_fnAddressOfMember,
6332 ITypeInfo_fnCreateInstance,
6333 ITypeInfo_fnGetMops,
6334 ITypeInfo_fnGetContainingTypeLib,
6335 ITypeInfo_fnReleaseTypeAttr,
6336 ITypeInfo_fnReleaseFuncDesc,
6337 ITypeInfo_fnReleaseVarDesc,
6339 ITypeInfo2_fnGetTypeKind,
6340 ITypeInfo2_fnGetTypeFlags,
6341 ITypeInfo2_fnGetFuncIndexOfMemId,
6342 ITypeInfo2_fnGetVarIndexOfMemId,
6343 ITypeInfo2_fnGetCustData,
6344 ITypeInfo2_fnGetFuncCustData,
6345 ITypeInfo2_fnGetParamCustData,
6346 ITypeInfo2_fnGetVarCustData,
6347 ITypeInfo2_fnGetImplTypeCustData,
6348 ITypeInfo2_fnGetDocumentation2,
6349 ITypeInfo2_fnGetAllCustData,
6350 ITypeInfo2_fnGetAllFuncCustData,
6351 ITypeInfo2_fnGetAllParamCustData,
6352 ITypeInfo2_fnGetAllVarCustData,
6353 ITypeInfo2_fnGetAllImplTypeCustData,
6356 /******************************************************************************
6357 * CreateDispTypeInfo [OLEAUT32.31]
6359 * Build type information for an object so it can be called through an
6360 * IDispatch interface.
6363 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6364 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6367 * This call allows an objects methods to be accessed through IDispatch, by
6368 * building an ITypeInfo object that IDispatch can use to call through.
6370 HRESULT WINAPI CreateDispTypeInfo(
6371 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6372 LCID lcid, /* [I] Locale Id */
6373 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6375 ITypeInfoImpl *pTIClass, *pTIIface;
6376 ITypeLibImpl *pTypeLibImpl;
6378 TLBFuncDesc **ppFuncDesc;
6381 pTypeLibImpl = TypeLibImpl_Constructor();
6382 if (!pTypeLibImpl) return E_FAIL;
6384 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6385 pTIIface->pTypeLib = pTypeLibImpl;
6386 pTIIface->index = 0;
6387 pTIIface->Name = NULL;
6388 pTIIface->dwHelpContext = -1;
6389 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6390 pTIIface->TypeAttr.lcid = lcid;
6391 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6392 pTIIface->TypeAttr.wMajorVerNum = 0;
6393 pTIIface->TypeAttr.wMinorVerNum = 0;
6394 pTIIface->TypeAttr.cbAlignment = 2;
6395 pTIIface->TypeAttr.cbSizeInstance = -1;
6396 pTIIface->TypeAttr.cbSizeVft = -1;
6397 pTIIface->TypeAttr.cFuncs = 0;
6398 pTIIface->TypeAttr.cImplTypes = 0;
6399 pTIIface->TypeAttr.cVars = 0;
6400 pTIIface->TypeAttr.wTypeFlags = 0;
6402 ppFuncDesc = &pTIIface->funclist;
6403 for(func = 0; func < pidata->cMembers; func++) {
6404 METHODDATA *md = pidata->pmethdata + func;
6405 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6406 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6407 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6408 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6409 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6410 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6411 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6412 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6413 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6414 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6415 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6416 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6417 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6418 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6419 md->cArgs * sizeof(ELEMDESC));
6420 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6421 md->cArgs * sizeof(TLBParDesc));
6422 for(param = 0; param < md->cArgs; param++) {
6423 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6424 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6426 (*ppFuncDesc)->helpcontext = 0;
6427 (*ppFuncDesc)->HelpStringContext = 0;
6428 (*ppFuncDesc)->HelpString = NULL;
6429 (*ppFuncDesc)->Entry = NULL;
6430 (*ppFuncDesc)->ctCustData = 0;
6431 (*ppFuncDesc)->pCustData = NULL;
6432 (*ppFuncDesc)->next = NULL;
6433 ppFuncDesc = &(*ppFuncDesc)->next;
6436 dump_TypeInfo(pTIIface);
6438 pTypeLibImpl->pTypeInfo = pTIIface;
6439 pTypeLibImpl->TypeInfoCount++;
6441 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6442 pTIClass->pTypeLib = pTypeLibImpl;
6443 pTIClass->index = 1;
6444 pTIClass->Name = NULL;
6445 pTIClass->dwHelpContext = -1;
6446 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6447 pTIClass->TypeAttr.lcid = lcid;
6448 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6449 pTIClass->TypeAttr.wMajorVerNum = 0;
6450 pTIClass->TypeAttr.wMinorVerNum = 0;
6451 pTIClass->TypeAttr.cbAlignment = 2;
6452 pTIClass->TypeAttr.cbSizeInstance = -1;
6453 pTIClass->TypeAttr.cbSizeVft = -1;
6454 pTIClass->TypeAttr.cFuncs = 0;
6455 pTIClass->TypeAttr.cImplTypes = 1;
6456 pTIClass->TypeAttr.cVars = 0;
6457 pTIClass->TypeAttr.wTypeFlags = 0;
6459 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6460 pTIClass->impltypelist->hRef = 1;
6462 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6463 pTIClass->reflist->index = 0;
6464 pTIClass->reflist->reference = 1;
6465 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6467 dump_TypeInfo(pTIClass);
6469 pTIIface->next = pTIClass;
6470 pTypeLibImpl->TypeInfoCount++;
6472 *pptinfo = (ITypeInfo*)pTIClass;
6477 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6479 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6481 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6484 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6486 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6488 return ITypeInfo_AddRef((ITypeInfo *)This);
6491 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6493 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6495 return ITypeInfo_Release((ITypeInfo *)This);
6498 static HRESULT WINAPI ITypeComp_fnBind(
6503 ITypeInfo ** ppTInfo,
6504 DESCKIND * pDescKind,
6507 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6508 const TLBFuncDesc *pFDesc;
6509 const TLBVarDesc *pVDesc;
6511 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6513 *pDescKind = DESCKIND_NONE;
6514 pBindPtr->lpfuncdesc = NULL;
6517 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6518 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6519 if (!strcmpW(pFDesc->Name, szName)) {
6525 HRESULT hr = TLB_AllocAndInitFuncDesc(
6527 &pBindPtr->lpfuncdesc,
6528 This->TypeAttr.typekind == TKIND_DISPATCH);
6531 *pDescKind = DESCKIND_FUNCDESC;
6532 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6533 ITypeInfo_AddRef(*ppTInfo);
6536 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6537 if (!strcmpW(pVDesc->Name, szName)) {
6538 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6541 *pDescKind = DESCKIND_VARDESC;
6542 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6543 ITypeInfo_AddRef(*ppTInfo);
6548 /* FIXME: search each inherited interface, not just the first */
6549 if (This->TypeAttr.cImplTypes) {
6550 /* recursive search */
6554 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6557 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6558 ITypeInfo_Release(pTInfo);
6562 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6563 ITypeComp_Release(pTComp);
6566 WARN("Could not search inherited interface!\n");
6568 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6569 return DISP_E_MEMBERNOTFOUND;
6572 static HRESULT WINAPI ITypeComp_fnBindType(
6576 ITypeInfo ** ppTInfo,
6577 ITypeComp ** ppTComp)
6579 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6581 /* strange behaviour (does nothing) but like the
6584 if (!ppTInfo || !ppTComp)
6593 static const ITypeCompVtbl tcompvt =
6596 ITypeComp_fnQueryInterface,
6598 ITypeComp_fnRelease,
6601 ITypeComp_fnBindType