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_FDISPATCHABLE))
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 */
2051 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2052 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2053 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2054 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2055 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2056 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2057 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2058 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2059 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2060 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2061 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2062 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2063 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2064 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2065 MSFT_GetTdesc(pcx, tiBase.datatype1,
2066 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2069 /* IDLDESC idldescType; *//* never saw this one != zero */
2071 /* name, eventually add to a hash table */
2072 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2073 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2074 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2076 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2077 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2078 ptiRet->dwHelpContext=tiBase.helpcontext;
2080 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2081 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2083 /* note: InfoType's Help file and HelpStringDll come from the containing
2084 * library. Further HelpString and Docstring appear to be the same thing :(
2087 if(ptiRet->TypeAttr.cFuncs >0 )
2088 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2089 ptiRet->TypeAttr.cVars,
2090 tiBase.memoffset, & ptiRet->funclist);
2092 if(ptiRet->TypeAttr.cVars >0 )
2093 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2094 ptiRet->TypeAttr.cVars,
2095 tiBase.memoffset, & ptiRet->varlist);
2096 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2097 switch(ptiRet->TypeAttr.typekind)
2100 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2103 case TKIND_DISPATCH:
2104 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2106 if (tiBase.datatype1 != -1)
2108 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2109 ptiRet->impltypelist->hRef = tiBase.datatype1;
2113 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2114 ptiRet->impltypelist->hRef = dispatch_href;
2118 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2119 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2120 ptiRet->impltypelist->hRef = tiBase.datatype1;
2125 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2127 TRACE_(typelib)("%s guid: %s kind:%s\n",
2128 debugstr_w(ptiRet->Name),
2129 debugstr_guid(&ptiRet->TypeAttr.guid),
2130 typekind_desc[ptiRet->TypeAttr.typekind]);
2135 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2136 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2137 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2140 static ITypeLibImpl *tlb_cache_first;
2141 static CRITICAL_SECTION cache_section;
2142 static CRITICAL_SECTION_DEBUG cache_section_debug =
2144 0, 0, &cache_section,
2145 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2146 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2148 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2151 /****************************************************************************
2154 * find the type of the typelib file and map the typelib resource into
2157 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2158 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2159 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2161 ITypeLibImpl *entry;
2162 int ret = TYPE_E_CANTLOADLIBRARY;
2168 lstrcpynW(pszPath, pszFileName, cchPath);
2170 /* first try loading as a dll and access the typelib as a resource */
2171 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2172 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2175 /* it may have been specified with resource index appended to the
2176 * path, so remove it and try again */
2177 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2178 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2180 index = atoiW(pIndexStr);
2181 pszPath[pIndexStr - pszFileName - 1] = '\0';
2183 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2184 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2188 /* get the path to the specified typelib file */
2191 /* otherwise, try loading as a regular file */
2192 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2193 return TYPE_E_CANTLOADLIBRARY;
2196 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2198 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2199 EnterCriticalSection(&cache_section);
2200 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2202 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2204 TRACE("cache hit\n");
2205 *ppTypeLib = (ITypeLib2*)entry;
2206 ITypeLib_AddRef(*ppTypeLib);
2207 LeaveCriticalSection(&cache_section);
2211 LeaveCriticalSection(&cache_section);
2213 /* now actually load and parse the typelib */
2216 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2217 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2220 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2223 LPVOID pBase = LockResource(hGlobal);
2224 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2228 /* try to load as incore resource */
2229 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2230 if (dwSignature == MSFT_SIGNATURE)
2231 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2232 else if (dwSignature == SLTG_SIGNATURE)
2233 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2235 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2237 FreeResource( hGlobal );
2240 FreeLibrary(hinstDLL);
2244 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2245 if (INVALID_HANDLE_VALUE != hFile)
2247 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2250 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2253 /* retrieve file size */
2254 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2255 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2257 if (dwSignature == MSFT_SIGNATURE)
2258 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2259 else if (dwSignature == SLTG_SIGNATURE)
2260 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2262 UnmapViewOfFile(pBase);
2264 CloseHandle(hMapping);
2271 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2273 TRACE("adding to cache\n");
2274 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2275 lstrcpyW(impl->path, pszPath);
2276 /* We should really canonicalise the path here. */
2277 impl->index = index;
2279 /* FIXME: check if it has added already in the meantime */
2280 EnterCriticalSection(&cache_section);
2281 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2283 tlb_cache_first = impl;
2284 LeaveCriticalSection(&cache_section);
2287 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2292 /*================== ITypeLib(2) Methods ===================================*/
2294 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2296 ITypeLibImpl* pTypeLibImpl;
2298 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2299 if (!pTypeLibImpl) return NULL;
2301 pTypeLibImpl->lpVtbl = &tlbvt;
2302 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2303 pTypeLibImpl->ref = 1;
2305 return pTypeLibImpl;
2308 /****************************************************************************
2309 * ITypeLib2_Constructor_MSFT
2311 * loading an MSFT typelib from an in-memory image
2313 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2317 MSFT_Header tlbHeader;
2318 MSFT_SegDir tlbSegDir;
2319 ITypeLibImpl * pTypeLibImpl;
2321 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2323 pTypeLibImpl = TypeLibImpl_Constructor();
2324 if (!pTypeLibImpl) return NULL;
2326 /* get pointer to beginning of typelib data */
2330 cx.pLibInfo = pTypeLibImpl;
2331 cx.length = dwTLBLength;
2334 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2335 TRACE_(typelib)("header:\n");
2336 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2337 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2338 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2341 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2343 /* there is a small amount of information here until the next important
2345 * the segment directory . Try to calculate the amount of data */
2346 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2348 /* now read the segment directory */
2349 TRACE("read segment directory (at %ld)\n",lPSegDir);
2350 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2351 cx.pTblDir = &tlbSegDir;
2353 /* just check two entries */
2354 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2356 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2357 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2361 /* now fill our internal data */
2362 /* TLIBATTR fields */
2363 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2365 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2366 /* Windows seems to have zero here, is this correct? */
2367 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2368 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2370 pTypeLibImpl->LibAttr.lcid = 0;
2372 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2373 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2374 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2375 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2377 /* name, eventually add to a hash table */
2378 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2381 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2382 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2384 if( tlbHeader.varflags & HELPDLLFLAG)
2387 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2388 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2391 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2394 if(tlbHeader.CustomDataOffset >= 0)
2396 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2399 /* fill in typedescriptions */
2400 if(tlbSegDir.pTypdescTab.length > 0)
2402 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2404 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2405 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2408 /* FIXME: add several sanity checks here */
2409 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2410 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2412 /* FIXME: check safearray */
2414 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2416 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2418 else if(td[0] == VT_CARRAY)
2420 /* array descr table here */
2421 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2423 else if(td[0] == VT_USERDEFINED)
2425 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2427 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2430 /* second time around to fill the array subscript info */
2433 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2434 if(tlbSegDir.pArrayDescriptions.offset>0)
2436 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2437 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2440 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2442 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2444 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2446 for(j = 0; j<td[2]; j++)
2448 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2449 sizeof(INT), &cx, DO_NOT_SEEK);
2450 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2451 sizeof(INT), &cx, DO_NOT_SEEK);
2456 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2457 ERR("didn't find array description data\n");
2462 /* imported type libs */
2463 if(tlbSegDir.pImpFiles.offset>0)
2465 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2466 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2469 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2474 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2475 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2476 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2478 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2479 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2480 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2481 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2484 name = TLB_Alloc(size+1);
2485 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2486 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2487 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2488 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2491 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2492 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2494 ppImpLib = &(*ppImpLib)->next;
2499 if(tlbHeader.nrtypeinfos >= 0 )
2501 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2502 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2505 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2507 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2509 ppTI = &((*ppTI)->next);
2510 (pTypeLibImpl->TypeInfoCount)++;
2514 TRACE("(%p)\n", pTypeLibImpl);
2515 return (ITypeLib2*) pTypeLibImpl;
2519 static BSTR TLB_MultiByteToBSTR(char *ptr)
2525 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2526 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2527 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2528 ret = SysAllocString(nameW);
2529 HeapFree(GetProcessHeap(), 0, nameW);
2533 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2539 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2540 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2544 guid->Data4[0] = s >> 8;
2545 guid->Data4[1] = s & 0xff;
2548 for(i = 0; i < 6; i++) {
2549 memcpy(b, str + 24 + 2 * i, 2);
2550 guid->Data4[i + 2] = strtol(b, NULL, 16);
2555 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2562 bytelen = *(WORD*)ptr;
2563 if(bytelen == 0xffff) return 2;
2564 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2565 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2566 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2567 *pBstr = SysAllocStringLen(nameW, len);
2568 HeapFree(GetProcessHeap(), 0, nameW);
2572 static WORD SLTG_ReadStringA(char *ptr, char **str)
2577 bytelen = *(WORD*)ptr;
2578 if(bytelen == 0xffff) return 2;
2579 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2580 memcpy(*str, ptr + 2, bytelen);
2581 (*str)[bytelen] = '\0';
2585 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2587 char *ptr = pLibBlk;
2590 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2591 FIXME("libblk magic = %04x\n", w);
2596 if((w = *(WORD*)ptr) != 0xffff) {
2597 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2602 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2604 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2606 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2609 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2612 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2613 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2615 pTypeLibImpl->LibAttr.lcid = 0;
2618 ptr += 4; /* skip res12 */
2620 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2623 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2626 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2629 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2630 ptr += sizeof(GUID);
2632 return ptr - (char*)pLibBlk;
2635 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2640 if((*pType & 0xe00) == 0xe00) {
2642 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2644 pTD = pTD->u.lptdesc;
2646 switch(*pType & 0x3f) {
2649 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2651 pTD = pTD->u.lptdesc;
2654 case VT_USERDEFINED:
2655 pTD->vt = VT_USERDEFINED;
2656 pTD->u.hreftype = *(++pType) / 4;
2662 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2665 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2667 pTD->vt = VT_CARRAY;
2668 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2670 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2671 pTD->u.lpadesc->cDims = pSA->cDims;
2672 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2673 pSA->cDims * sizeof(SAFEARRAYBOUND));
2675 pTD = &pTD->u.lpadesc->tdescElem;
2681 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2685 pTD->vt = VT_SAFEARRAY;
2686 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2688 pTD = pTD->u.lptdesc;
2692 pTD->vt = *pType & 0x3f;
2701 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2703 /* Handle [in/out] first */
2704 if((*pType & 0xc000) == 0xc000)
2705 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2706 else if(*pType & 0x8000)
2707 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2708 else if(*pType & 0x4000)
2709 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2711 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2714 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2717 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2719 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2723 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2728 TLBRefType **ppRefType;
2730 if(pRef->magic != SLTG_REF_MAGIC) {
2731 FIXME("Ref magic = %x\n", pRef->magic);
2734 name = ( (char*)(&pRef->names) + pRef->number);
2736 ppRefType = &pTI->reflist;
2737 for(ref = 0; ref < pRef->number >> 3; ref++) {
2739 unsigned int lib_offs, type_num;
2741 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2742 sizeof(**ppRefType));
2744 name += SLTG_ReadStringA(name, &refname);
2745 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2746 FIXME("Can't sscanf ref\n");
2747 if(lib_offs != 0xffff) {
2748 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2751 if((*import)->offset == lib_offs)
2753 import = &(*import)->next;
2756 char fname[MAX_PATH+1];
2759 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2761 (*import)->offset = lib_offs;
2762 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2764 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2765 &(*import)->wVersionMajor,
2766 &(*import)->wVersionMinor,
2767 &(*import)->lcid, fname) != 4) {
2768 FIXME("can't sscanf ref %s\n",
2769 pNameTable + lib_offs + 40);
2771 len = strlen(fname);
2772 if(fname[len-1] != '#')
2773 FIXME("fname = %s\n", fname);
2774 fname[len-1] = '\0';
2775 (*import)->name = TLB_MultiByteToBSTR(fname);
2777 (*ppRefType)->pImpTLInfo = *import;
2778 } else { /* internal ref */
2779 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2781 (*ppRefType)->reference = ref;
2782 (*ppRefType)->index = type_num;
2784 HeapFree(GetProcessHeap(), 0, refname);
2785 ppRefType = &(*ppRefType)->next;
2787 if((BYTE)*name != SLTG_REF_MAGIC)
2788 FIXME("End of ref block magic = %x\n", *name);
2789 dump_TLBRefType(pTI->reflist);
2792 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2795 SLTG_ImplInfo *info;
2796 TLBImplType **ppImplType = &pTI->impltypelist;
2797 /* I don't really get this structure, usually it's 0x16 bytes
2798 long, but iuser.tlb contains some that are 0x18 bytes long.
2799 That's ok because we can use the next ptr to jump to the next
2800 one. But how do we know the length of the last one? The WORD
2801 at offs 0x8 might be the clue. For now I'm just assuming that
2802 the last one is the regular 0x16 bytes. */
2804 info = (SLTG_ImplInfo*)pBlk;
2806 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2807 sizeof(**ppImplType));
2808 (*ppImplType)->hRef = info->ref;
2809 (*ppImplType)->implflags = info->impltypeflags;
2810 pTI->TypeAttr.cImplTypes++;
2811 ppImplType = &(*ppImplType)->next;
2813 if(info->next == 0xffff)
2816 FIXME("Interface inheriting more than one interface\n");
2817 info = (SLTG_ImplInfo*)(pBlk + info->next);
2819 info++; /* see comment at top of function */
2823 static void SLTG_DoVars(char *pBlk, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2825 TLBVarDesc **ppVarDesc = &pTI->varlist;
2826 SLTG_Variable *pItem;
2831 for(pItem = (SLTG_Variable *)pBlk, i = 0; i < cVars;
2832 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2834 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2835 sizeof(**ppVarDesc));
2836 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2837 (*ppVarDesc)->vardesc.memid = pItem->memid;
2839 if(pItem->magic != SLTG_VAR_MAGIC) {
2840 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2844 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2845 TRACE_(typelib)("memid = 0x%lx\n", pItem->memid);
2847 if (pItem->flags & 0x40) {
2848 TRACE_(typelib)("VAR_DISPATCH\n");
2849 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2851 else if (pItem->flags & 0x10) {
2852 TRACE_(typelib)("VAR_CONST\n");
2853 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2854 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2856 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2857 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2858 *(INT*)(pBlk + pItem->byte_offs);
2861 TRACE_(typelib)("VAR_PERINSTANCE\n");
2862 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2863 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2866 if (pItem->flags & 0x80)
2867 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2869 if(pItem->flags & 0x02)
2870 pType = &pItem->type;
2872 pType = (WORD*)(pBlk + pItem->type);
2874 if (pItem->flags & ~0xd2)
2875 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2877 SLTG_DoElem(pType, pBlk,
2878 &(*ppVarDesc)->vardesc.elemdescVar);
2880 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2882 ppVarDesc = &((*ppVarDesc)->next);
2884 pTI->TypeAttr.cVars = cVars;
2887 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2889 SLTG_Function *pFunc;
2891 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2893 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2894 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2899 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2900 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC &&
2901 pFunc->magic != SLTG_DISPATCH_FUNCTION_MAGIC) {
2902 FIXME("func magic = %02x\n", pFunc->magic);
2905 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2906 sizeof(**ppFuncDesc));
2907 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2909 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2910 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2911 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2912 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2913 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2914 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2916 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2917 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2919 if(pFunc->retnextopt & 0x80)
2920 pType = &pFunc->rettype;
2922 pType = (WORD*)(pBlk + pFunc->rettype);
2924 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2926 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2927 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2928 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2929 (*ppFuncDesc)->pParamDesc =
2930 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2931 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2933 pArg = (WORD*)(pBlk + pFunc->arg_off);
2935 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2936 char *paramName = pNameTable + *pArg;
2938 /* If arg type follows then paramName points to the 2nd
2939 letter of the name, else the next WORD is an offset to
2940 the arg type and paramName points to the first letter.
2941 So let's take one char off paramName and see if we're
2942 pointing at an alpha-numeric char. However if *pArg is
2943 0xffff or 0xfffe then the param has no name, the former
2944 meaning that the next WORD is the type, the latter
2945 meaning the the next WORD is an offset to the type. */
2950 else if(*pArg == 0xfffe) {
2954 else if(paramName[-1] && !isalnum(paramName[-1]))
2959 if(HaveOffs) { /* the next word is an offset to type */
2960 pType = (WORD*)(pBlk + *pArg);
2961 SLTG_DoElem(pType, pBlk,
2962 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2967 pArg = SLTG_DoElem(pArg, pBlk,
2968 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2971 /* Are we an optional param ? */
2972 if((*ppFuncDesc)->funcdesc.cParams - param <=
2973 (*ppFuncDesc)->funcdesc.cParamsOpt)
2974 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2977 (*ppFuncDesc)->pParamDesc[param].Name =
2978 TLB_MultiByteToBSTR(paramName);
2982 ppFuncDesc = &((*ppFuncDesc)->next);
2983 if(pFunc->next == 0xffff) break;
2985 pTI->TypeAttr.cFuncs = cFuncs;
2988 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2989 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
2990 SLTG_TypeInfoTail *pTITail)
2992 char *pFirstItem, *pNextItem;
2994 if(pTIHeader->href_table != 0xffffffff) {
2995 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
2999 pFirstItem = pNextItem = pBlk;
3001 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3002 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3007 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3008 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3009 SLTG_TypeInfoTail *pTITail)
3011 char *pFirstItem, *pNextItem;
3013 if(pTIHeader->href_table != 0xffffffff) {
3014 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3018 pFirstItem = pNextItem = pBlk;
3020 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3021 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3024 if (pTITail->funcs_off != 0xffff)
3025 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3027 if (TRACE_ON(typelib))
3028 dump_TLBFuncDesc(pTI->funclist);
3031 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3032 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3033 SLTG_TypeInfoTail *pTITail)
3035 SLTG_DoVars(pBlk, pTI, pTITail->cVars, pNameTable);
3038 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3039 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3040 SLTG_TypeInfoTail *pTITail)
3044 if (pTITail->simple_alias) {
3045 /* if simple alias, no more processing required */
3046 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3050 if(pTIHeader->href_table != 0xffffffff) {
3051 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3055 /* otherwise it is an offset to a type */
3056 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3058 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3061 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3062 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3063 SLTG_TypeInfoTail *pTITail)
3065 if (pTIHeader->href_table != 0xffffffff)
3066 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3069 if (pTITail->vars_off != 0xffff)
3070 SLTG_DoVars(pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3072 if (pTITail->funcs_off != 0xffff)
3073 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3075 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3076 * of dispinterface functons including the IDispatch ones, so
3077 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3078 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3080 if (TRACE_ON(typelib))
3081 dump_TLBFuncDesc(pTI->funclist);
3084 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3085 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3086 SLTG_TypeInfoTail *pTITail)
3088 SLTG_DoVars(pBlk, pTI, pTITail->cVars, pNameTable);
3091 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3092 managable copy of it into this */
3105 } SLTG_InternalOtherTypeInfo;
3107 /****************************************************************************
3108 * ITypeLib2_Constructor_SLTG
3110 * loading a SLTG typelib from an in-memory image
3112 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3114 ITypeLibImpl *pTypeLibImpl;
3115 SLTG_Header *pHeader;
3116 SLTG_BlkEntry *pBlkEntry;
3120 LPVOID pBlk, pFirstBlk;
3121 SLTG_LibBlk *pLibBlk;
3122 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3123 char *pAfterOTIBlks = NULL;
3124 char *pNameTable, *ptr;
3127 ITypeInfoImpl **ppTypeInfoImpl;
3129 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3132 pTypeLibImpl = TypeLibImpl_Constructor();
3133 if (!pTypeLibImpl) return NULL;
3137 TRACE_(typelib)("header:\n");
3138 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3139 pHeader->nrOfFileBlks );
3140 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3141 FIXME("Header type magic 0x%08lx not supported.\n",
3142 pHeader->SLTG_magic);
3146 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3147 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3149 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3150 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3152 /* Next we have a magic block */
3153 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3155 /* Let's see if we're still in sync */
3156 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3157 sizeof(SLTG_COMPOBJ_MAGIC))) {
3158 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3161 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3162 sizeof(SLTG_DIR_MAGIC))) {
3163 FIXME("dir magic = %s\n", pMagic->dir_magic);
3167 pIndex = (SLTG_Index*)(pMagic+1);
3169 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3171 pFirstBlk = (LPVOID)(pPad9 + 1);
3173 /* We'll set up a ptr to the main library block, which is the last one. */
3175 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3176 pBlkEntry[order].next != 0;
3177 order = pBlkEntry[order].next - 1, i++) {
3178 pBlk = (char*)pBlk + pBlkEntry[order].len;
3182 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3184 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3189 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3191 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3192 sizeof(*pOtherTypeInfoBlks) *
3193 pTypeLibImpl->TypeInfoCount);
3196 ptr = (char*)pLibBlk + len;
3198 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3202 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3204 w = *(WORD*)(ptr + 2);
3207 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3209 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3210 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3212 w = *(WORD*)(ptr + 4 + len);
3214 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3216 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3218 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3219 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3221 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3222 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3223 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3225 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3227 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3230 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3231 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3232 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3233 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3234 len += sizeof(SLTG_OtherTypeInfo);
3238 pAfterOTIBlks = ptr;
3240 /* Skip this WORD and get the next DWORD */
3241 len = *(DWORD*)(pAfterOTIBlks + 2);
3243 /* Now add this to pLibBLk look at what we're pointing at and
3244 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3245 dust and we should be pointing at the beginning of the name
3248 pNameTable = (char*)pLibBlk + len;
3250 switch(*(WORD*)pNameTable) {
3257 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3261 pNameTable += 0x216;
3265 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3267 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3270 /* Hopefully we now have enough ptrs set up to actually read in
3271 some TypeInfos. It's not clear which order to do them in, so
3272 I'll just follow the links along the BlkEntry chain and read
3273 them in in the order in which they're in the file */
3275 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3277 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3278 pBlkEntry[order].next != 0;
3279 order = pBlkEntry[order].next - 1, i++) {
3281 SLTG_TypeInfoHeader *pTIHeader;
3282 SLTG_TypeInfoTail *pTITail;
3283 SLTG_MemberHeader *pMemHeader;
3285 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3286 pOtherTypeInfoBlks[i].index_name)) {
3287 FIXME("Index strings don't match\n");
3292 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3293 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3296 TRACE("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
3297 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3299 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3300 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3301 (*ppTypeInfoImpl)->index = i;
3302 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3303 pOtherTypeInfoBlks[i].name_offs +
3305 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3306 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3308 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3309 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3310 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3311 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3312 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3314 if((pTIHeader->typeflags1 & 7) != 2)
3315 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3316 if(pTIHeader->typeflags3 != 2)
3317 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3319 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3320 debugstr_w((*ppTypeInfoImpl)->Name),
3321 typekind_desc[pTIHeader->typekind],
3322 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3323 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3325 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3327 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3329 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3330 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3331 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3333 switch(pTIHeader->typekind) {
3335 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3336 pTIHeader, pTITail);
3340 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3341 pTIHeader, pTITail);
3344 case TKIND_INTERFACE:
3345 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3346 pTIHeader, pTITail);
3350 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3351 pTIHeader, pTITail);
3355 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3356 pTIHeader, pTITail);
3359 case TKIND_DISPATCH:
3360 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3361 pTIHeader, pTITail);
3365 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3370 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3371 but we've already set those */
3372 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3387 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3388 pBlk = (char*)pBlk + pBlkEntry[order].len;
3391 if(i != pTypeLibImpl->TypeInfoCount) {
3392 FIXME("Somehow processed %d TypeInfos\n", i);
3396 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3397 return (ITypeLib2*)pTypeLibImpl;
3400 /* ITypeLib::QueryInterface
3402 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3407 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3409 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3412 if(IsEqualIID(riid, &IID_IUnknown) ||
3413 IsEqualIID(riid,&IID_ITypeLib)||
3414 IsEqualIID(riid,&IID_ITypeLib2))
3421 ITypeLib2_AddRef(iface);
3422 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3425 TRACE("-- Interface: E_NOINTERFACE\n");
3426 return E_NOINTERFACE;
3431 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3433 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3434 ULONG ref = InterlockedIncrement(&This->ref);
3436 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3441 /* ITypeLib::Release
3443 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3445 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3446 ULONG ref = InterlockedDecrement(&This->ref);
3448 TRACE("(%p)->(%lu)\n",This, ref);
3452 /* remove cache entry */
3455 TRACE("removing from cache list\n");
3456 EnterCriticalSection(&cache_section);
3457 if (This->next) This->next->prev = This->prev;
3458 if (This->prev) This->prev->next = This->next;
3459 else tlb_cache_first = This->next;
3460 LeaveCriticalSection(&cache_section);
3461 HeapFree(GetProcessHeap(), 0, This->path);
3463 /* FIXME destroy child objects */
3464 TRACE(" destroying ITypeLib(%p)\n",This);
3468 SysFreeString(This->Name);
3472 if (This->DocString)
3474 SysFreeString(This->DocString);
3475 This->DocString = NULL;
3480 SysFreeString(This->HelpFile);
3481 This->HelpFile = NULL;
3484 if (This->HelpStringDll)
3486 SysFreeString(This->HelpStringDll);
3487 This->HelpStringDll = NULL;
3490 if (This->pTypeInfo) /* can be NULL */
3491 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3492 HeapFree(GetProcessHeap(),0,This);
3499 /* ITypeLib::GetTypeInfoCount
3501 * Returns the number of type descriptions in the type library
3503 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3505 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3506 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3507 return This->TypeInfoCount;
3510 /* ITypeLib::GetTypeInfo
3512 * retrieves the specified type description in the library.
3514 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3517 ITypeInfo **ppTInfo)
3521 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3522 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3524 TRACE("(%p)->(index=%d)\n", This, index);
3526 if (!ppTInfo) return E_INVALIDARG;
3528 /* search element n in list */
3529 for(i=0; i < index; i++)
3531 pTypeInfo = pTypeInfo->next;
3534 TRACE("-- element not found\n");
3535 return TYPE_E_ELEMENTNOTFOUND;
3539 *ppTInfo = (ITypeInfo *) pTypeInfo;
3541 ITypeInfo_AddRef(*ppTInfo);
3542 TRACE("-- found (%p)\n",*ppTInfo);
3547 /* ITypeLibs::GetTypeInfoType
3549 * Retrieves the type of a type description.
3551 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3556 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3558 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3560 TRACE("(%p) index %d\n", This, index);
3562 if(!pTKind) return E_INVALIDARG;
3564 /* search element n in list */
3565 for(i=0; i < index; i++)
3569 TRACE("-- element not found\n");
3570 return TYPE_E_ELEMENTNOTFOUND;
3572 pTInfo = pTInfo->next;
3575 *pTKind = pTInfo->TypeAttr.typekind;
3576 TRACE("-- found Type (%d)\n", *pTKind);
3580 /* ITypeLib::GetTypeInfoOfGuid
3582 * Retrieves the type description that corresponds to the specified GUID.
3585 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3588 ITypeInfo **ppTInfo)
3590 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3591 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3593 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3597 WARN("-- element not found\n");
3598 return TYPE_E_ELEMENTNOTFOUND;
3601 /* search linked list for guid */
3602 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3604 pTypeInfo = pTypeInfo->next;
3608 /* end of list reached */
3609 WARN("-- element not found\n");
3610 return TYPE_E_ELEMENTNOTFOUND;
3614 TRACE("-- found (%p, %s)\n",
3616 debugstr_w(pTypeInfo->Name));
3618 *ppTInfo = (ITypeInfo*)pTypeInfo;
3619 ITypeInfo_AddRef(*ppTInfo);
3623 /* ITypeLib::GetLibAttr
3625 * Retrieves the structure that contains the library's attributes.
3628 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3630 LPTLIBATTR *ppTLibAttr)
3632 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3633 TRACE("(%p)\n",This);
3634 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3635 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3639 /* ITypeLib::GetTypeComp
3641 * Enables a client compiler to bind to a library's types, variables,
3642 * constants, and global functions.
3645 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3647 ITypeComp **ppTComp)
3649 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3651 TRACE("(%p)->(%p)\n",This,ppTComp);
3652 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3653 ITypeComp_AddRef(*ppTComp);
3658 /* ITypeLib::GetDocumentation
3660 * Retrieves the library's documentation string, the complete Help file name
3661 * and path, and the context identifier for the library Help topic in the Help
3664 * On a successful return all non-null BSTR pointers will have been set,
3667 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3671 BSTR *pBstrDocString,
3672 DWORD *pdwHelpContext,
3673 BSTR *pBstrHelpFile)
3675 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3677 HRESULT result = E_INVALIDARG;
3682 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3684 pBstrName, pBstrDocString,
3685 pdwHelpContext, pBstrHelpFile);
3689 /* documentation for the typelib */
3694 if(!(*pBstrName = SysAllocString(This->Name)))
3702 if (This->DocString)
3704 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3707 else if (This->Name)
3709 if(!(*pBstrDocString = SysAllocString(This->Name)))
3713 *pBstrDocString = NULL;
3717 *pdwHelpContext = This->dwHelpContext;
3723 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3727 *pBstrHelpFile = NULL;
3734 /* for a typeinfo */
3735 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3737 if(SUCCEEDED(result))
3739 result = ITypeInfo_GetDocumentation(pTInfo,
3743 pdwHelpContext, pBstrHelpFile);
3745 ITypeInfo_Release(pTInfo);
3750 if (pBstrDocString) SysFreeString (*pBstrDocString);
3752 if (pBstrName) SysFreeString (*pBstrName);
3754 return STG_E_INSUFFICIENTMEMORY;
3759 * Indicates whether a passed-in string contains the name of a type or member
3760 * described in the library.
3763 static HRESULT WINAPI ITypeLib2_fnIsName(
3769 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3770 ITypeInfoImpl *pTInfo;
3771 TLBFuncDesc *pFInfo;
3774 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3776 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3780 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3781 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3782 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3783 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3784 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3785 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3786 goto ITypeLib2_fnIsName_exit;
3788 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3789 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3794 ITypeLib2_fnIsName_exit:
3795 TRACE("(%p)slow! search for %s: %s found!\n", This,
3796 debugstr_w(szNameBuf), *pfName?"NOT":"");
3801 /* ITypeLib::FindName
3803 * Finds occurrences of a type description in a type library. This may be used
3804 * to quickly verify that a name exists in a type library.
3807 static HRESULT WINAPI ITypeLib2_fnFindName(
3811 ITypeInfo **ppTInfo,
3815 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3816 ITypeInfoImpl *pTInfo;
3817 TLBFuncDesc *pFInfo;
3820 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3822 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3823 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3824 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3825 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3826 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3827 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3828 goto ITypeLib2_fnFindName_exit;
3831 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3832 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3834 ITypeLib2_fnFindName_exit:
3835 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3836 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3839 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3840 This, *pcFound, debugstr_w(szNameBuf), j);
3847 /* ITypeLib::ReleaseTLibAttr
3849 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3852 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3854 TLIBATTR *pTLibAttr)
3856 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3857 TRACE("freeing (%p)\n",This);
3858 HeapFree(GetProcessHeap(),0,pTLibAttr);
3862 /* ITypeLib2::GetCustData
3864 * gets the custom data
3866 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3871 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3872 TLBCustData *pCData;
3874 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3876 if( IsEqualIID(guid, &pCData->guid)) break;
3879 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3883 VariantInit( pVarVal);
3884 VariantCopy( pVarVal, &pCData->data);
3887 return E_INVALIDARG; /* FIXME: correct? */
3890 /* ITypeLib2::GetLibStatistics
3892 * Returns statistics about a type library that are required for efficient
3893 * sizing of hash tables.
3896 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3898 ULONG *pcUniqueNames,
3899 ULONG *pcchUniqueNames)
3901 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3903 FIXME("(%p): stub!\n", This);
3905 if(pcUniqueNames) *pcUniqueNames=1;
3906 if(pcchUniqueNames) *pcchUniqueNames=1;
3910 /* ITypeLib2::GetDocumentation2
3912 * Retrieves the library's documentation string, the complete Help file name
3913 * and path, the localization context to use, and the context ID for the
3914 * library Help topic in the Help file.
3917 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3921 BSTR *pbstrHelpString,
3922 DWORD *pdwHelpStringContext,
3923 BSTR *pbstrHelpStringDll)
3925 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3929 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3931 /* the help string should be obtained from the helpstringdll,
3932 * using the _DLLGetDocumentation function, based on the supplied
3933 * lcid. Nice to do sometime...
3937 /* documentation for the typelib */
3939 *pbstrHelpString=SysAllocString(This->DocString);
3940 if(pdwHelpStringContext)
3941 *pdwHelpStringContext=This->dwHelpContext;
3942 if(pbstrHelpStringDll)
3943 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3949 /* for a typeinfo */
3950 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3952 if(SUCCEEDED(result))
3954 ITypeInfo2 * pTInfo2;
3955 result = ITypeInfo_QueryInterface(pTInfo,
3957 (LPVOID*) &pTInfo2);
3959 if(SUCCEEDED(result))
3961 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3965 pdwHelpStringContext,
3966 pbstrHelpStringDll);
3968 ITypeInfo2_Release(pTInfo2);
3971 ITypeInfo_Release(pTInfo);
3977 /* ITypeLib2::GetAllCustData
3979 * Gets all custom data items for the library.
3982 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3984 CUSTDATA *pCustData)
3986 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3987 TLBCustData *pCData;
3989 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3990 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3991 if(pCustData->prgCustData ){
3992 pCustData->cCustData=This->ctCustData;
3993 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3994 pCustData->prgCustData[i].guid=pCData->guid;
3995 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3998 ERR(" OUT OF MEMORY!\n");
3999 return E_OUTOFMEMORY;
4004 static const ITypeLib2Vtbl tlbvt = {
4005 ITypeLib2_fnQueryInterface,
4007 ITypeLib2_fnRelease,
4008 ITypeLib2_fnGetTypeInfoCount,
4009 ITypeLib2_fnGetTypeInfo,
4010 ITypeLib2_fnGetTypeInfoType,
4011 ITypeLib2_fnGetTypeInfoOfGuid,
4012 ITypeLib2_fnGetLibAttr,
4013 ITypeLib2_fnGetTypeComp,
4014 ITypeLib2_fnGetDocumentation,
4016 ITypeLib2_fnFindName,
4017 ITypeLib2_fnReleaseTLibAttr,
4019 ITypeLib2_fnGetCustData,
4020 ITypeLib2_fnGetLibStatistics,
4021 ITypeLib2_fnGetDocumentation2,
4022 ITypeLib2_fnGetAllCustData
4026 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4028 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4030 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4033 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4035 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4037 return ITypeLib2_AddRef((ITypeLib2 *)This);
4040 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4042 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4044 return ITypeLib2_Release((ITypeLib2 *)This);
4047 static HRESULT WINAPI ITypeLibComp_fnBind(
4052 ITypeInfo ** ppTInfo,
4053 DESCKIND * pDescKind,
4056 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4057 ITypeInfoImpl *pTypeInfo;
4059 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4061 *pDescKind = DESCKIND_NONE;
4062 pBindPtr->lptcomp = NULL;
4065 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4067 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4069 /* FIXME: check wFlags here? */
4070 /* FIXME: we should use a hash table to look this info up using lHash
4071 * instead of an O(n) search */
4072 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4073 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4075 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4077 *pDescKind = DESCKIND_TYPECOMP;
4078 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4079 ITypeComp_AddRef(pBindPtr->lptcomp);
4080 TRACE("module or enum: %s\n", debugstr_w(szName));
4085 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4086 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4088 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4091 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4092 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4094 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4099 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4100 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4102 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4104 ITypeInfo *subtypeinfo;
4106 DESCKIND subdesckind;
4108 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4109 &subtypeinfo, &subdesckind, &subbindptr);
4110 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4112 TYPEDESC tdesc_appobject =
4115 (TYPEDESC *)pTypeInfo->hreftype
4119 const VARDESC vardesc_appobject =
4122 NULL, /* lpstrSchema */
4137 VAR_STATIC /* varkind */
4140 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4142 /* cleanup things filled in by Bind call so we can put our
4143 * application object data in there instead */
4144 switch (subdesckind)
4146 case DESCKIND_FUNCDESC:
4147 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4149 case DESCKIND_VARDESC:
4150 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4155 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4157 if (pTypeInfo->hreftype == -1)
4158 FIXME("no hreftype for interface %p\n", pTypeInfo);
4160 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4164 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4165 *ppTInfo = (ITypeInfo *)pTypeInfo;
4166 ITypeInfo_AddRef(*ppTInfo);
4172 TRACE("name not found %s\n", debugstr_w(szName));
4176 static HRESULT WINAPI ITypeLibComp_fnBindType(
4180 ITypeInfo ** ppTInfo,
4181 ITypeComp ** ppTComp)
4183 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4187 static const ITypeCompVtbl tlbtcvt =
4190 ITypeLibComp_fnQueryInterface,
4191 ITypeLibComp_fnAddRef,
4192 ITypeLibComp_fnRelease,
4194 ITypeLibComp_fnBind,
4195 ITypeLibComp_fnBindType
4198 /*================== ITypeInfo(2) Methods ===================================*/
4199 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4201 ITypeInfoImpl * pTypeInfoImpl;
4203 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4206 pTypeInfoImpl->lpVtbl = &tinfvt;
4207 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4208 pTypeInfoImpl->ref=1;
4209 pTypeInfoImpl->hreftype = -1;
4210 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4211 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4213 TRACE("(%p)\n", pTypeInfoImpl);
4214 return (ITypeInfo2*) pTypeInfoImpl;
4217 /* ITypeInfo::QueryInterface
4219 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4224 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4226 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4229 if(IsEqualIID(riid, &IID_IUnknown) ||
4230 IsEqualIID(riid,&IID_ITypeInfo)||
4231 IsEqualIID(riid,&IID_ITypeInfo2))
4235 ITypeInfo_AddRef(iface);
4236 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4239 TRACE("-- Interface: E_NOINTERFACE\n");
4240 return E_NOINTERFACE;
4243 /* ITypeInfo::AddRef
4245 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4247 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4248 ULONG ref = InterlockedIncrement(&This->ref);
4250 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4252 TRACE("(%p)->ref is %lu\n",This, ref);
4256 /* ITypeInfo::Release
4258 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4260 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4261 ULONG ref = InterlockedDecrement(&This->ref);
4263 TRACE("(%p)->(%lu)\n",This, ref);
4266 /* We don't release ITypeLib when ref=0 because
4267 it means that function is called by ITypeLib2_Release */
4268 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4270 static int once = 0;
4274 FIXME("destroy child objects\n");
4277 TRACE("destroying ITypeInfo(%p)\n",This);
4280 SysFreeString(This->Name);
4284 if (This->DocString)
4286 SysFreeString(This->DocString);
4287 This->DocString = 0;
4292 SysFreeString(This->DllName);
4298 ITypeInfo_Release((ITypeInfo*)This->next);
4301 HeapFree(GetProcessHeap(),0,This);
4307 /* ITypeInfo::GetTypeAttr
4309 * Retrieves a TYPEATTR structure that contains the attributes of the type
4313 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4314 LPTYPEATTR *ppTypeAttr)
4316 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4319 TRACE("(%p)\n",This);
4321 size = sizeof(**ppTypeAttr);
4322 if (This->TypeAttr.typekind == TKIND_ALIAS)
4323 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4325 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4327 return E_OUTOFMEMORY;
4329 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4331 if (This->TypeAttr.typekind == TKIND_ALIAS)
4332 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4333 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4335 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4336 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4338 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4339 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4344 /* ITypeInfo::GetTypeComp
4346 * Retrieves the ITypeComp interface for the type description, which enables a
4347 * client compiler to bind to the type description's members.
4350 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4351 ITypeComp * *ppTComp)
4353 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4355 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4357 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4358 ITypeComp_AddRef(*ppTComp);
4362 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4364 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4365 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4366 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4370 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4372 memcpy(dest, src, sizeof(ELEMDESC));
4373 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4374 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4376 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4377 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4378 *buffer += sizeof(PARAMDESCEX);
4379 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4380 VariantInit(&pparamdescex_dest->varDefaultValue);
4381 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4382 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4385 dest->u.paramdesc.pparamdescex = NULL;
4389 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4391 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4392 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4395 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4399 SIZE_T size = sizeof(*src);
4403 size += sizeof(*src->lprgscode) * src->cScodes;
4404 size += TLB_SizeElemDesc(&src->elemdescFunc);
4405 for (i = 0; i < src->cParams; i++)
4407 size += sizeof(ELEMDESC);
4408 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4411 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4412 if (!dest) return E_OUTOFMEMORY;
4414 memcpy(dest, src, sizeof(FUNCDESC));
4415 buffer = (char *)(dest + 1);
4417 dest->lprgscode = (SCODE *)buffer;
4418 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4419 buffer += sizeof(*src->lprgscode) * src->cScodes;
4421 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4424 SysFreeString((BSTR)dest);
4428 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4429 buffer += sizeof(ELEMDESC) * src->cParams;
4430 for (i = 0; i < src->cParams; i++)
4432 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4438 /* undo the above actions */
4439 for (i = i - 1; i >= 0; i--)
4440 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4441 TLB_FreeElemDesc(&dest->elemdescFunc);
4442 SysFreeString((BSTR)dest);
4446 /* special treatment for dispinterfaces: this makes functions appear
4447 * to return their [retval] value when it is really returning an
4449 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4451 if (dest->cParams &&
4452 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4454 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4455 if (elemdesc->tdesc.vt != VT_PTR)
4457 ERR("elemdesc should have started with VT_PTR instead of:\n");
4459 dump_ELEMDESC(elemdesc);
4460 return E_UNEXPECTED;
4463 /* copy last parameter to the return value. we are using a flat
4464 * buffer so there is no danger of leaking memory in
4466 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4468 /* remove the last parameter */
4472 /* otherwise this function is made to appear to have no return
4474 dest->elemdescFunc.tdesc.vt = VT_VOID;
4482 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4484 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4485 const TLBFuncDesc *pFDesc;
4488 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4493 *ppFuncDesc = &pFDesc->funcdesc;
4497 return E_INVALIDARG;
4500 /* ITypeInfo::GetFuncDesc
4502 * Retrieves the FUNCDESC structure that contains information about a
4503 * specified function.
4506 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4507 LPFUNCDESC *ppFuncDesc)
4509 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4510 const FUNCDESC *internal_funcdesc;
4513 TRACE("(%p) index %d\n", This, index);
4515 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4519 return TLB_AllocAndInitFuncDesc(
4522 This->TypeAttr.typekind == TKIND_DISPATCH);
4525 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4529 SIZE_T size = sizeof(*src);
4532 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4533 if (src->varkind == VAR_CONST)
4534 size += sizeof(VARIANT);
4535 size += TLB_SizeElemDesc(&src->elemdescVar);
4537 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4538 if (!dest) return E_OUTOFMEMORY;
4541 buffer = (char *)(dest + 1);
4542 if (src->lpstrSchema)
4545 dest->lpstrSchema = (LPOLESTR)buffer;
4546 len = strlenW(src->lpstrSchema);
4547 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4548 buffer += (len + 1) * sizeof(WCHAR);
4551 if (src->varkind == VAR_CONST)
4555 dest->u.lpvarValue = (VARIANT *)buffer;
4556 *dest->u.lpvarValue = *src->u.lpvarValue;
4557 buffer += sizeof(VARIANT);
4558 VariantInit(dest->u.lpvarValue);
4559 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4562 SysFreeString((BSTR)dest_ptr);
4566 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4569 if (src->varkind == VAR_CONST)
4570 VariantClear(dest->u.lpvarValue);
4571 SysFreeString((BSTR)dest);
4578 /* ITypeInfo::GetVarDesc
4580 * Retrieves a VARDESC structure that describes the specified variable.
4583 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4584 LPVARDESC *ppVarDesc)
4586 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4588 const TLBVarDesc *pVDesc;
4590 TRACE("(%p) index %d\n", This, index);
4592 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4596 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4598 return E_INVALIDARG;
4601 /* ITypeInfo_GetNames
4603 * Retrieves the variable with the specified member ID (or the name of the
4604 * property or method and its parameters) that correspond to the specified
4607 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4608 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4610 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4611 const TLBFuncDesc *pFDesc;
4612 const TLBVarDesc *pVDesc;
4614 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4615 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4618 /* function found, now return function and parameter names */
4619 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4622 *rgBstrNames=SysAllocString(pFDesc->Name);
4624 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4630 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4633 *rgBstrNames=SysAllocString(pVDesc->Name);
4638 if(This->TypeAttr.cImplTypes &&
4639 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4640 /* recursive search */
4643 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4645 if(SUCCEEDED(result))
4647 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4648 ITypeInfo_Release(pTInfo);
4651 WARN("Could not search inherited interface!\n");
4655 WARN("no names found\n");
4658 return TYPE_E_ELEMENTNOTFOUND;
4665 /* ITypeInfo::GetRefTypeOfImplType
4667 * If a type description describes a COM class, it retrieves the type
4668 * description of the implemented interface types. For an interface,
4669 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4673 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4678 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4681 const TLBImplType *pImpl = This->impltypelist;
4683 TRACE("(%p) index %d\n", This, index);
4684 if (TRACE_ON(ole)) dump_TypeInfo(This);
4688 /* only valid on dual interfaces;
4689 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4691 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4693 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4694 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4700 hr = TYPE_E_ELEMENTNOTFOUND;
4705 /* get element n from linked list */
4706 for(i=0; pImpl && i<index; i++)
4708 pImpl = pImpl->next;
4712 *pRefType = pImpl->hRef;
4714 hr = TYPE_E_ELEMENTNOTFOUND;
4720 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4722 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4728 /* ITypeInfo::GetImplTypeFlags
4730 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4731 * or base interface in a type description.
4733 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4734 UINT index, INT *pImplTypeFlags)
4736 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4740 TRACE("(%p) index %d\n", This, index);
4741 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4742 i++, pImpl=pImpl->next)
4744 if(i==index && pImpl){
4745 *pImplTypeFlags=pImpl->implflags;
4749 return TYPE_E_ELEMENTNOTFOUND;
4753 * Maps between member names and member IDs, and parameter names and
4756 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4757 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4759 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4760 const TLBFuncDesc *pFDesc;
4761 const TLBVarDesc *pVDesc;
4765 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4768 /* init out parameters in case of failure */
4769 for (i = 0; i < cNames; i++)
4770 pMemId[i] = MEMBERID_NIL;
4772 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4774 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4775 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4776 for(i=1; i < cNames; i++){
4777 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4778 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4780 if( j<pFDesc->funcdesc.cParams)
4783 ret=DISP_E_UNKNOWNNAME;
4785 TRACE("-- 0x%08lx\n", ret);
4789 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4790 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4791 if(cNames) *pMemId=pVDesc->vardesc.memid;
4795 /* not found, see if it can be found in an inherited interface */
4796 if(This->TypeAttr.cImplTypes) {
4797 /* recursive search */
4799 ret=ITypeInfo_GetRefTypeInfo(iface,
4800 This->impltypelist->hRef, &pTInfo);
4802 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4803 ITypeInfo_Release(pTInfo);
4806 WARN("Could not search inherited interface!\n");
4808 WARN("no names found\n");
4809 return DISP_E_UNKNOWNNAME;
4812 /* ITypeInfo::Invoke
4814 * Invokes a method, or accesses a property of an object, that implements the
4815 * interface described by the type description.
4818 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4821 if (TRACE_ON(ole)) {
4823 TRACE("Calling %p(",func);
4824 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4836 res = func(args[0]);
4839 res = func(args[0],args[1]);
4842 res = func(args[0],args[1],args[2]);
4845 res = func(args[0],args[1],args[2],args[3]);
4848 res = func(args[0],args[1],args[2],args[3],args[4]);
4851 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4854 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4857 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4860 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4863 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4866 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4869 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]);
4872 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]);
4875 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]);
4878 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]);
4881 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]);
4884 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]);
4887 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]);
4890 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]);
4893 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]);
4896 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]);
4899 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]);
4902 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]);
4905 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4911 FIXME("unsupported calling convention %d\n",callconv);
4915 TRACE("returns %08lx\n",res);
4919 extern int _argsize(DWORD vt);
4921 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4924 ITypeInfo *tinfo2 = NULL;
4925 TYPEATTR *tattr = NULL;
4927 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4930 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4932 tdesc->u.hreftype, hr);
4935 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4938 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4939 ITypeInfo_Release(tinfo2);
4943 switch (tattr->typekind)
4950 tdesc = &tattr->tdescAlias;
4951 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4954 case TKIND_INTERFACE:
4955 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4961 case TKIND_DISPATCH:
4966 FIXME("TKIND_RECORD unhandled.\n");
4971 FIXME("TKIND_UNION unhandled.\n");
4976 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4980 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4981 ITypeInfo_Release(tinfo2);
4985 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4989 /* enforce only one level of pointer indirection */
4990 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
4992 tdesc = tdesc->u.lptdesc;
4994 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4995 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4996 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4997 if ((tdesc->vt == VT_USERDEFINED) ||
4998 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5000 VARTYPE vt_userdefined = 0;
5001 const TYPEDESC *tdesc_userdefined = tdesc;
5002 if (tdesc->vt == VT_PTR)
5004 vt_userdefined = VT_BYREF;
5005 tdesc_userdefined = tdesc->u.lptdesc;
5007 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5009 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5010 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5012 *vt |= vt_userdefined;
5024 case VT_USERDEFINED:
5025 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5032 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5033 hr = DISP_E_BADVARTYPE;
5037 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5046 /***********************************************************************
5047 * DispCallFunc (OLEAUT32.@)
5049 * Invokes a function of the specifed calling convention, passing the
5050 * specified arguments and returns the result.
5053 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5054 * oVft [I] The offset in the vtable. See notes.
5055 * cc [I] Calling convention of the function to call.
5056 * vtReturn [I] The return type of the function.
5057 * cActuals [I] Number of parameters.
5058 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5059 * prgpvarg [I] The arguments to pass.
5060 * pvargResult [O] The return value of the function. Can be NULL.
5064 * Failure: HRESULT code.
5067 * The HRESULT return value of this function is not affected by the return
5068 * value of the user supplied function, which is returned in pvargResult.
5070 * If pvInstance is NULL then a non-object function is to be called and oVft
5071 * is the address of the function to call.
5073 * The cc parameter can be one of the following values:
5086 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5087 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5089 int i, argsize, argspos;
5093 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5094 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5095 pvargResult, V_VT(pvargResult));
5099 argsize++; /* for This pointer */
5101 for (i=0;i<cActuals;i++)
5103 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5104 dump_Variant(prgpvarg[i]);
5105 argsize += _argsize(prgvt[i]);
5107 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5112 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5116 for (i=0;i<cActuals;i++)
5118 VARIANT *arg = prgpvarg[i];
5119 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5120 if (prgvt[i] == VT_VARIANT)
5121 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5123 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5124 argspos += _argsize(prgvt[i]);
5129 FARPROC *vtable = *(FARPROC**)pvInstance;
5130 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5133 /* if we aren't invoking an object then the function pointer is stored
5135 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5137 if (pvargResult && (vtReturn != VT_EMPTY))
5139 TRACE("Method returned 0x%08lx\n",hres);
5140 V_VT(pvargResult) = vtReturn;
5141 V_UI4(pvargResult) = hres;
5144 HeapFree(GetProcessHeap(),0,args);
5148 #define INVBUF_ELEMENT_SIZE \
5149 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5150 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5151 ((VARIANTARG *)(buffer))
5152 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5153 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5154 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5155 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5156 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5157 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5159 static HRESULT WINAPI ITypeInfo_fnInvoke(
5164 DISPPARAMS *pDispParams,
5165 VARIANT *pVarResult,
5166 EXCEPINFO *pExcepInfo,
5169 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5171 unsigned int var_index;
5174 const TLBFuncDesc *pFuncInfo;
5176 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5177 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5179 dump_DispParms(pDispParams);
5181 /* we do this instead of using GetFuncDesc since it will return a fake
5182 * FUNCDESC for dispinterfaces and we want the real function description */
5183 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5184 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5188 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5192 TRACE("invoking:\n");
5193 dump_TLBFuncDescOne(pFuncInfo);
5196 switch (func_desc->funckind) {
5197 case FUNC_PUREVIRTUAL:
5198 case FUNC_VIRTUAL: {
5199 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5201 VARIANT retval; /* pointer for storing byref retvals in */
5202 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5203 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5204 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5207 for (i = 0; i < func_desc->cParams; i++)
5209 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5210 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5215 TRACE("changing args\n");
5216 for (i = 0; i < func_desc->cParams; i++)
5218 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5220 if (wParamFlags & PARAMFLAG_FRETVAL)
5222 /* note: this check is placed so that if the caller passes
5223 * in a VARIANTARG for the retval we just ignore it, like
5225 if (i == func_desc->cParams - 1)
5228 arg = prgpvarg[i] = &rgvarg[i];
5229 memset(arg, 0, sizeof(*arg));
5230 V_VT(arg) = rgvt[i];
5231 memset(&retval, 0, sizeof(retval));
5232 V_BYREF(arg) = &retval;
5236 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5237 hres = E_UNEXPECTED;
5241 else if (i < pDispParams->cArgs)
5243 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5244 dump_Variant(src_arg);
5246 if (rgvt[i] == VT_VARIANT)
5247 hres = VariantCopy(&rgvarg[i], src_arg);
5248 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5250 if (rgvt[i] == V_VT(src_arg))
5251 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5254 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5255 hres = VariantCopy(&missing_arg[i], src_arg);
5256 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5258 V_VT(&rgvarg[i]) = rgvt[i];
5260 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5262 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5263 V_VT(&missing_arg[i]) = V_VT(src_arg);
5264 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5265 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5266 V_VT(&rgvarg[i]) = rgvt[i];
5268 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5270 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5271 V_VT(&rgvarg[i]) = rgvt[i];
5275 /* FIXME: this doesn't work for VT_BYREF arguments if
5276 * they are not the same type as in the paramdesc */
5277 V_VT(&rgvarg[i]) = V_VT(src_arg);
5278 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5279 V_VT(&rgvarg[i]) = rgvt[i];
5284 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5285 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5286 debugstr_VT(src_arg), debugstr_VF(src_arg));
5289 prgpvarg[i] = &rgvarg[i];
5291 else if (wParamFlags & PARAMFLAG_FOPT)
5294 arg = prgpvarg[i] = &rgvarg[i];
5295 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5297 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5303 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5304 V_VT(arg) = VT_VARIANT | VT_BYREF;
5305 V_VARIANTREF(arg) = &missing_arg[i];
5306 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5307 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5312 hres = DISP_E_BADPARAMCOUNT;
5316 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5317 if (func_desc->cParamsOpt < 0)
5319 FIXME("Does not support safearray optional parameters\n");
5320 hres = DISP_E_BADPARAMCOUNT;
5321 goto func_fail; /* FIXME: we don't free changed types here */
5324 V_VT(&varresult) = 0;
5325 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5326 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5328 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5329 V_VT(&varresult), func_desc->cParams, rgvt,
5330 prgpvarg, &varresult);
5332 for (i = 0; i < func_desc->cParams; i++)
5334 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5335 if (wParamFlags & PARAMFLAG_FRETVAL)
5339 TRACE("[retval] value: ");
5340 dump_Variant(prgpvarg[i]);
5344 /* deref return value */
5345 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5347 /* free data stored in varresult. Note that
5348 * VariantClear doesn't do what we want because we are
5349 * working with byref types. */
5350 /* FIXME: clear safearrays, bstrs, records and
5351 * variants here too */
5352 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5353 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5355 if(*V_UNKNOWNREF(prgpvarg[i]))
5356 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5360 else if (i < pDispParams->cArgs)
5362 if (wParamFlags & PARAMFLAG_FOUT)
5364 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5366 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5367 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5371 ERR("failed to convert param %d to vt %d\n", i,
5372 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5376 VariantClear(&rgvarg[i]);
5378 else if (wParamFlags & PARAMFLAG_FOPT)
5380 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5381 VariantClear(&rgvarg[i]);
5385 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5387 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5388 hres = DISP_E_EXCEPTION;
5389 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5393 HeapFree(GetProcessHeap(), 0, buffer);
5396 case FUNC_DISPATCH: {
5399 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5400 if (SUCCEEDED(hres)) {
5401 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5402 hres = IDispatch_Invoke(
5403 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5404 pVarResult,pExcepInfo,pArgErr
5407 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5408 IDispatch_Release(disp);
5410 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5414 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5419 TRACE("-- 0x%08lx\n", hres);
5422 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5425 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5426 if(FAILED(hres)) return hres;
5428 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5429 dump_VARDESC(var_desc);
5430 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5434 /* not found, look for it in inherited interfaces */
5435 ITypeInfo2_GetTypeKind(iface, &type_kind);
5436 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5438 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5439 /* recursive search */
5441 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5442 if(SUCCEEDED(hres)){
5443 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5444 ITypeInfo_Release(pTInfo);
5447 WARN("Could not search inherited interface!\n");
5450 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5451 return DISP_E_MEMBERNOTFOUND;
5454 /* ITypeInfo::GetDocumentation
5456 * Retrieves the documentation string, the complete Help file name and path,
5457 * and the context ID for the Help topic for a specified type description.
5459 * (Can be tested by the Visual Basic Editor in Word for instance.)
5461 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5462 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5463 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5465 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5466 const TLBFuncDesc *pFDesc;
5467 const TLBVarDesc *pVDesc;
5468 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5469 " HelpContext(%p) HelpFile(%p)\n",
5470 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5471 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5473 *pBstrName=SysAllocString(This->Name);
5475 *pBstrDocString=SysAllocString(This->DocString);
5477 *pdwHelpContext=This->dwHelpContext;
5479 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5481 }else {/* for a member */
5482 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5483 if(pFDesc->funcdesc.memid==memid){
5485 *pBstrName = SysAllocString(pFDesc->Name);
5487 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5489 *pdwHelpContext=pFDesc->helpcontext;
5492 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5493 if(pVDesc->vardesc.memid==memid){
5495 *pBstrName = SysAllocString(pVDesc->Name);
5497 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5499 *pdwHelpContext=pVDesc->HelpContext;
5503 WARN("member %ld not found\n", memid);
5504 return TYPE_E_ELEMENTNOTFOUND;
5507 /* ITypeInfo::GetDllEntry
5509 * Retrieves a description or specification of an entry point for a function
5512 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5513 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5516 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5517 const TLBFuncDesc *pFDesc;
5519 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5521 if (pBstrDllName) *pBstrDllName = NULL;
5522 if (pBstrName) *pBstrName = NULL;
5523 if (pwOrdinal) *pwOrdinal = 0;
5525 if (This->TypeAttr.typekind != TKIND_MODULE)
5526 return TYPE_E_BADMODULEKIND;
5528 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5529 if(pFDesc->funcdesc.memid==memid){
5530 dump_TypeInfo(This);
5532 dump_TLBFuncDescOne(pFDesc);
5535 *pBstrDllName = SysAllocString(This->DllName);
5537 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5539 *pBstrName = SysAllocString(pFDesc->Entry);
5547 *pwOrdinal = (DWORD)pFDesc->Entry;
5550 return TYPE_E_ELEMENTNOTFOUND;
5553 /* ITypeInfo::GetRefTypeInfo
5555 * If a type description references other type descriptions, it retrieves
5556 * the referenced type descriptions.
5558 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5561 ITypeInfo **ppTInfo)
5563 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5564 HRESULT result = E_FAIL;
5566 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5568 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5569 ITypeInfo_AddRef(*ppTInfo);
5572 else if (hRefType == -1 &&
5573 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5574 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5576 /* when we meet a DUAL dispinterface, we must create the interface
5579 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5582 /* the interface version contains the same information as the dispinterface
5583 * copy the contents of the structs.
5585 *pTypeInfoImpl = *This;
5586 pTypeInfoImpl->ref = 1;
5588 /* change the type to interface */
5589 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5591 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5593 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5598 TLBRefType *pRefType;
5599 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5600 if(pRefType->reference == hRefType)
5604 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5605 if(pRefType && hRefType != -1) {
5606 ITypeLib *pTLib = NULL;
5608 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5610 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5612 if(pRefType->pImpTLInfo->pImpTypeLib) {
5613 TRACE("typeinfo in imported typelib that is already loaded\n");
5614 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5615 ITypeLib2_AddRef((ITypeLib*) pTLib);
5618 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5619 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5620 pRefType->pImpTLInfo->wVersionMajor,
5621 pRefType->pImpTLInfo->wVersionMinor,
5622 pRefType->pImpTLInfo->lcid,
5625 if(!SUCCEEDED(result)) {
5626 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5627 result=LoadTypeLib(libnam, &pTLib);
5628 SysFreeString(libnam);
5630 if(SUCCEEDED(result)) {
5631 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5632 ITypeLib2_AddRef(pTLib);
5636 if(SUCCEEDED(result)) {
5637 if(pRefType->index == TLB_REF_USE_GUID)
5638 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5642 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5646 ITypeLib2_Release(pTLib);
5650 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5651 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5655 /* ITypeInfo::AddressOfMember
5657 * Retrieves the addresses of static functions or variables, such as those
5660 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5661 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5663 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5669 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5671 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5675 module = LoadLibraryW(dll);
5678 ERR("couldn't load %s\n", debugstr_w(dll));
5680 if (entry) SysFreeString(entry);
5681 return STG_E_FILENOTFOUND;
5683 /* FIXME: store library somewhere where we can free it */
5688 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5689 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5690 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5692 *ppv = GetProcAddress(module, entryA);
5694 ERR("function not found %s\n", debugstr_a(entryA));
5696 HeapFree(GetProcessHeap(), 0, entryA);
5700 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5702 ERR("function not found %d\n", ordinal);
5706 if (entry) SysFreeString(entry);
5709 return TYPE_E_DLLFUNCTIONNOTFOUND;
5714 /* ITypeInfo::CreateInstance
5716 * Creates a new instance of a type that describes a component object class
5719 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5720 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5722 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5723 FIXME("(%p) stub!\n", This);
5727 /* ITypeInfo::GetMops
5729 * Retrieves marshalling information.
5731 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5734 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5735 FIXME("(%p) stub!\n", This);
5739 /* ITypeInfo::GetContainingTypeLib
5741 * Retrieves the containing type library and the index of the type description
5742 * within that type library.
5744 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5745 ITypeLib * *ppTLib, UINT *pIndex)
5747 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5749 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5751 *pIndex=This->index;
5752 TRACE("returning pIndex=%d\n", *pIndex);
5756 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5757 ITypeLib2_AddRef(*ppTLib);
5758 TRACE("returning ppTLib=%p\n", *ppTLib);
5764 /* ITypeInfo::ReleaseTypeAttr
5766 * Releases a TYPEATTR previously returned by GetTypeAttr.
5769 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5770 TYPEATTR* pTypeAttr)
5772 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5773 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5774 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5777 /* ITypeInfo::ReleaseFuncDesc
5779 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5781 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5783 FUNCDESC *pFuncDesc)
5785 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5788 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5790 for (i = 0; i < pFuncDesc->cParams; i++)
5791 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5792 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5794 SysFreeString((BSTR)pFuncDesc);
5797 /* ITypeInfo::ReleaseVarDesc
5799 * Releases a VARDESC previously returned by GetVarDesc.
5801 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5804 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5805 TRACE("(%p)->(%p)\n", This, pVarDesc);
5807 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5808 if (pVarDesc->varkind == VAR_CONST)
5809 VariantClear(pVarDesc->u.lpvarValue);
5810 SysFreeString((BSTR)pVarDesc);
5813 /* ITypeInfo2::GetTypeKind
5815 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5818 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5819 TYPEKIND *pTypeKind)
5821 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5822 *pTypeKind=This->TypeAttr.typekind;
5823 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5827 /* ITypeInfo2::GetTypeFlags
5829 * Returns the type flags without any allocations. This returns a DWORD type
5830 * flag, which expands the type flags without growing the TYPEATTR (type
5834 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5836 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5837 *pTypeFlags=This->TypeAttr.wTypeFlags;
5838 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5842 /* ITypeInfo2::GetFuncIndexOfMemId
5843 * Binds to a specific member based on a known DISPID, where the member name
5844 * is not known (for example, when binding to a default member).
5847 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5848 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5850 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5851 const TLBFuncDesc *pFuncInfo;
5855 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5856 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5862 result = TYPE_E_ELEMENTNOTFOUND;
5864 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5865 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5869 /* TypeInfo2::GetVarIndexOfMemId
5871 * Binds to a specific member based on a known DISPID, where the member name
5872 * is not known (for example, when binding to a default member).
5875 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5876 MEMBERID memid, UINT *pVarIndex)
5878 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5879 TLBVarDesc *pVarInfo;
5882 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5883 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5889 result = TYPE_E_ELEMENTNOTFOUND;
5891 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5892 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5896 /* ITypeInfo2::GetCustData
5898 * Gets the custom data
5900 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5905 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5906 TLBCustData *pCData;
5908 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5909 if( IsEqualIID(guid, &pCData->guid)) break;
5911 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5915 VariantInit( pVarVal);
5916 VariantCopy( pVarVal, &pCData->data);
5919 return E_INVALIDARG; /* FIXME: correct? */
5922 /* ITypeInfo2::GetFuncCustData
5924 * Gets the custom data
5926 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5932 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5933 TLBCustData *pCData=NULL;
5934 TLBFuncDesc * pFDesc;
5936 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5937 pFDesc=pFDesc->next);
5940 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5941 if( IsEqualIID(guid, &pCData->guid)) break;
5943 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5946 VariantInit( pVarVal);
5947 VariantCopy( pVarVal, &pCData->data);
5950 return E_INVALIDARG; /* FIXME: correct? */
5953 /* ITypeInfo2::GetParamCustData
5955 * Gets the custom data
5957 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5964 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5965 TLBCustData *pCData=NULL;
5966 TLBFuncDesc * pFDesc;
5969 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5971 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5972 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5973 pCData = pCData->next)
5974 if( IsEqualIID(guid, &pCData->guid)) break;
5976 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5980 VariantInit( pVarVal);
5981 VariantCopy( pVarVal, &pCData->data);
5984 return E_INVALIDARG; /* FIXME: correct? */
5987 /* ITypeInfo2::GetVarCustData
5989 * Gets the custom data
5991 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5997 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5998 TLBCustData *pCData=NULL;
5999 TLBVarDesc * pVDesc;
6002 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6006 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6008 if( IsEqualIID(guid, &pCData->guid)) break;
6012 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6016 VariantInit( pVarVal);
6017 VariantCopy( pVarVal, &pCData->data);
6020 return E_INVALIDARG; /* FIXME: correct? */
6023 /* ITypeInfo2::GetImplCustData
6025 * Gets the custom data
6027 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6033 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6034 TLBCustData *pCData=NULL;
6035 TLBImplType * pRDesc;
6038 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6042 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6044 if( IsEqualIID(guid, &pCData->guid)) break;
6048 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6052 VariantInit( pVarVal);
6053 VariantCopy( pVarVal, &pCData->data);
6056 return E_INVALIDARG; /* FIXME: correct? */
6059 /* ITypeInfo2::GetDocumentation2
6061 * Retrieves the documentation string, the complete Help file name and path,
6062 * the localization context to use, and the context ID for the library Help
6063 * topic in the Help file.
6066 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6070 BSTR *pbstrHelpString,
6071 DWORD *pdwHelpStringContext,
6072 BSTR *pbstrHelpStringDll)
6074 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6075 const TLBFuncDesc *pFDesc;
6076 const TLBVarDesc *pVDesc;
6077 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6078 "HelpStringContext(%p) HelpStringDll(%p)\n",
6079 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6080 pbstrHelpStringDll );
6081 /* the help string should be obtained from the helpstringdll,
6082 * using the _DLLGetDocumentation function, based on the supplied
6083 * lcid. Nice to do sometime...
6085 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6087 *pbstrHelpString=SysAllocString(This->Name);
6088 if(pdwHelpStringContext)
6089 *pdwHelpStringContext=This->dwHelpStringContext;
6090 if(pbstrHelpStringDll)
6091 *pbstrHelpStringDll=
6092 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6094 }else {/* for a member */
6095 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6096 if(pFDesc->funcdesc.memid==memid){
6098 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6099 if(pdwHelpStringContext)
6100 *pdwHelpStringContext=pFDesc->HelpStringContext;
6101 if(pbstrHelpStringDll)
6102 *pbstrHelpStringDll=
6103 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6106 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6107 if(pVDesc->vardesc.memid==memid){
6109 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6110 if(pdwHelpStringContext)
6111 *pdwHelpStringContext=pVDesc->HelpStringContext;
6112 if(pbstrHelpStringDll)
6113 *pbstrHelpStringDll=
6114 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6118 return TYPE_E_ELEMENTNOTFOUND;
6121 /* ITypeInfo2::GetAllCustData
6123 * Gets all custom data items for the Type info.
6126 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6128 CUSTDATA *pCustData)
6130 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6131 TLBCustData *pCData;
6134 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6136 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6137 if(pCustData->prgCustData ){
6138 pCustData->cCustData=This->ctCustData;
6139 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6140 pCustData->prgCustData[i].guid=pCData->guid;
6141 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6144 ERR(" OUT OF MEMORY!\n");
6145 return E_OUTOFMEMORY;
6150 /* ITypeInfo2::GetAllFuncCustData
6152 * Gets all custom data items for the specified Function
6155 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6158 CUSTDATA *pCustData)
6160 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6161 TLBCustData *pCData;
6162 TLBFuncDesc * pFDesc;
6164 TRACE("(%p) index %d\n", This, index);
6165 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6166 pFDesc=pFDesc->next)
6169 pCustData->prgCustData =
6170 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6171 if(pCustData->prgCustData ){
6172 pCustData->cCustData=pFDesc->ctCustData;
6173 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6174 pCData = pCData->next){
6175 pCustData->prgCustData[i].guid=pCData->guid;
6176 VariantCopy(& pCustData->prgCustData[i].varValue,
6180 ERR(" OUT OF MEMORY!\n");
6181 return E_OUTOFMEMORY;
6185 return TYPE_E_ELEMENTNOTFOUND;
6188 /* ITypeInfo2::GetAllParamCustData
6190 * Gets all custom data items for the Functions
6193 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6194 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6196 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6197 TLBCustData *pCData=NULL;
6198 TLBFuncDesc * pFDesc;
6200 TRACE("(%p) index %d\n", This, indexFunc);
6201 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6202 pFDesc=pFDesc->next)
6204 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6205 pCustData->prgCustData =
6206 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6207 sizeof(CUSTDATAITEM));
6208 if(pCustData->prgCustData ){
6209 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6210 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6211 pCData; i++, pCData = pCData->next){
6212 pCustData->prgCustData[i].guid=pCData->guid;
6213 VariantCopy(& pCustData->prgCustData[i].varValue,
6217 ERR(" OUT OF MEMORY!\n");
6218 return E_OUTOFMEMORY;
6222 return TYPE_E_ELEMENTNOTFOUND;
6225 /* ITypeInfo2::GetAllVarCustData
6227 * Gets all custom data items for the specified Variable
6230 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6231 UINT index, CUSTDATA *pCustData)
6233 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6234 TLBCustData *pCData;
6235 TLBVarDesc * pVDesc;
6237 TRACE("(%p) index %d\n", This, index);
6238 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6239 pVDesc=pVDesc->next)
6242 pCustData->prgCustData =
6243 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6244 if(pCustData->prgCustData ){
6245 pCustData->cCustData=pVDesc->ctCustData;
6246 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6247 pCData = pCData->next){
6248 pCustData->prgCustData[i].guid=pCData->guid;
6249 VariantCopy(& pCustData->prgCustData[i].varValue,
6253 ERR(" OUT OF MEMORY!\n");
6254 return E_OUTOFMEMORY;
6258 return TYPE_E_ELEMENTNOTFOUND;
6261 /* ITypeInfo2::GetAllImplCustData
6263 * Gets all custom data items for the specified implementation type
6266 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6269 CUSTDATA *pCustData)
6271 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6272 TLBCustData *pCData;
6273 TLBImplType * pRDesc;
6275 TRACE("(%p) index %d\n", This, index);
6276 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6277 pRDesc=pRDesc->next)
6280 pCustData->prgCustData =
6281 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6282 if(pCustData->prgCustData ){
6283 pCustData->cCustData=pRDesc->ctCustData;
6284 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6285 pCData = pCData->next){
6286 pCustData->prgCustData[i].guid=pCData->guid;
6287 VariantCopy(& pCustData->prgCustData[i].varValue,
6291 ERR(" OUT OF MEMORY!\n");
6292 return E_OUTOFMEMORY;
6296 return TYPE_E_ELEMENTNOTFOUND;
6299 static const ITypeInfo2Vtbl tinfvt =
6302 ITypeInfo_fnQueryInterface,
6304 ITypeInfo_fnRelease,
6306 ITypeInfo_fnGetTypeAttr,
6307 ITypeInfo_fnGetTypeComp,
6308 ITypeInfo_fnGetFuncDesc,
6309 ITypeInfo_fnGetVarDesc,
6310 ITypeInfo_fnGetNames,
6311 ITypeInfo_fnGetRefTypeOfImplType,
6312 ITypeInfo_fnGetImplTypeFlags,
6313 ITypeInfo_fnGetIDsOfNames,
6315 ITypeInfo_fnGetDocumentation,
6316 ITypeInfo_fnGetDllEntry,
6317 ITypeInfo_fnGetRefTypeInfo,
6318 ITypeInfo_fnAddressOfMember,
6319 ITypeInfo_fnCreateInstance,
6320 ITypeInfo_fnGetMops,
6321 ITypeInfo_fnGetContainingTypeLib,
6322 ITypeInfo_fnReleaseTypeAttr,
6323 ITypeInfo_fnReleaseFuncDesc,
6324 ITypeInfo_fnReleaseVarDesc,
6326 ITypeInfo2_fnGetTypeKind,
6327 ITypeInfo2_fnGetTypeFlags,
6328 ITypeInfo2_fnGetFuncIndexOfMemId,
6329 ITypeInfo2_fnGetVarIndexOfMemId,
6330 ITypeInfo2_fnGetCustData,
6331 ITypeInfo2_fnGetFuncCustData,
6332 ITypeInfo2_fnGetParamCustData,
6333 ITypeInfo2_fnGetVarCustData,
6334 ITypeInfo2_fnGetImplTypeCustData,
6335 ITypeInfo2_fnGetDocumentation2,
6336 ITypeInfo2_fnGetAllCustData,
6337 ITypeInfo2_fnGetAllFuncCustData,
6338 ITypeInfo2_fnGetAllParamCustData,
6339 ITypeInfo2_fnGetAllVarCustData,
6340 ITypeInfo2_fnGetAllImplTypeCustData,
6343 /******************************************************************************
6344 * CreateDispTypeInfo [OLEAUT32.31]
6346 * Build type information for an object so it can be called through an
6347 * IDispatch interface.
6350 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6351 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6354 * This call allows an objects methods to be accessed through IDispatch, by
6355 * building an ITypeInfo object that IDispatch can use to call through.
6357 HRESULT WINAPI CreateDispTypeInfo(
6358 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6359 LCID lcid, /* [I] Locale Id */
6360 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6362 ITypeInfoImpl *pTIClass, *pTIIface;
6363 ITypeLibImpl *pTypeLibImpl;
6365 TLBFuncDesc **ppFuncDesc;
6368 pTypeLibImpl = TypeLibImpl_Constructor();
6369 if (!pTypeLibImpl) return E_FAIL;
6371 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6372 pTIIface->pTypeLib = pTypeLibImpl;
6373 pTIIface->index = 0;
6374 pTIIface->Name = NULL;
6375 pTIIface->dwHelpContext = -1;
6376 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6377 pTIIface->TypeAttr.lcid = lcid;
6378 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6379 pTIIface->TypeAttr.wMajorVerNum = 0;
6380 pTIIface->TypeAttr.wMinorVerNum = 0;
6381 pTIIface->TypeAttr.cbAlignment = 2;
6382 pTIIface->TypeAttr.cbSizeInstance = -1;
6383 pTIIface->TypeAttr.cbSizeVft = -1;
6384 pTIIface->TypeAttr.cFuncs = 0;
6385 pTIIface->TypeAttr.cImplTypes = 0;
6386 pTIIface->TypeAttr.cVars = 0;
6387 pTIIface->TypeAttr.wTypeFlags = 0;
6389 ppFuncDesc = &pTIIface->funclist;
6390 for(func = 0; func < pidata->cMembers; func++) {
6391 METHODDATA *md = pidata->pmethdata + func;
6392 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6393 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6394 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6395 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6396 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6397 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6398 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6399 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6400 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6401 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6402 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6403 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6404 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6405 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6406 md->cArgs * sizeof(ELEMDESC));
6407 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6408 md->cArgs * sizeof(TLBParDesc));
6409 for(param = 0; param < md->cArgs; param++) {
6410 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6411 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6413 (*ppFuncDesc)->helpcontext = 0;
6414 (*ppFuncDesc)->HelpStringContext = 0;
6415 (*ppFuncDesc)->HelpString = NULL;
6416 (*ppFuncDesc)->Entry = NULL;
6417 (*ppFuncDesc)->ctCustData = 0;
6418 (*ppFuncDesc)->pCustData = NULL;
6419 (*ppFuncDesc)->next = NULL;
6420 ppFuncDesc = &(*ppFuncDesc)->next;
6423 dump_TypeInfo(pTIIface);
6425 pTypeLibImpl->pTypeInfo = pTIIface;
6426 pTypeLibImpl->TypeInfoCount++;
6428 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6429 pTIClass->pTypeLib = pTypeLibImpl;
6430 pTIClass->index = 1;
6431 pTIClass->Name = NULL;
6432 pTIClass->dwHelpContext = -1;
6433 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6434 pTIClass->TypeAttr.lcid = lcid;
6435 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6436 pTIClass->TypeAttr.wMajorVerNum = 0;
6437 pTIClass->TypeAttr.wMinorVerNum = 0;
6438 pTIClass->TypeAttr.cbAlignment = 2;
6439 pTIClass->TypeAttr.cbSizeInstance = -1;
6440 pTIClass->TypeAttr.cbSizeVft = -1;
6441 pTIClass->TypeAttr.cFuncs = 0;
6442 pTIClass->TypeAttr.cImplTypes = 1;
6443 pTIClass->TypeAttr.cVars = 0;
6444 pTIClass->TypeAttr.wTypeFlags = 0;
6446 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6447 pTIClass->impltypelist->hRef = 1;
6449 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6450 pTIClass->reflist->index = 0;
6451 pTIClass->reflist->reference = 1;
6452 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6454 dump_TypeInfo(pTIClass);
6456 pTIIface->next = pTIClass;
6457 pTypeLibImpl->TypeInfoCount++;
6459 *pptinfo = (ITypeInfo*)pTIClass;
6464 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6466 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6468 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6471 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6473 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6475 return ITypeInfo_AddRef((ITypeInfo *)This);
6478 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6480 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6482 return ITypeInfo_Release((ITypeInfo *)This);
6485 static HRESULT WINAPI ITypeComp_fnBind(
6490 ITypeInfo ** ppTInfo,
6491 DESCKIND * pDescKind,
6494 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6495 const TLBFuncDesc *pFDesc;
6496 const TLBVarDesc *pVDesc;
6498 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6500 *pDescKind = DESCKIND_NONE;
6501 pBindPtr->lpfuncdesc = NULL;
6504 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6505 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6506 if (!strcmpW(pFDesc->Name, szName)) {
6512 HRESULT hr = TLB_AllocAndInitFuncDesc(
6514 &pBindPtr->lpfuncdesc,
6515 This->TypeAttr.typekind == TKIND_DISPATCH);
6518 *pDescKind = DESCKIND_FUNCDESC;
6519 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6520 ITypeInfo_AddRef(*ppTInfo);
6523 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6524 if (!strcmpW(pVDesc->Name, szName)) {
6525 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6528 *pDescKind = DESCKIND_VARDESC;
6529 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6530 ITypeInfo_AddRef(*ppTInfo);
6535 /* FIXME: search each inherited interface, not just the first */
6536 if (This->TypeAttr.cImplTypes) {
6537 /* recursive search */
6541 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6544 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6545 ITypeInfo_Release(pTInfo);
6549 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6550 ITypeComp_Release(pTComp);
6553 WARN("Could not search inherited interface!\n");
6555 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6556 return DISP_E_MEMBERNOTFOUND;
6559 static HRESULT WINAPI ITypeComp_fnBindType(
6563 ITypeInfo ** ppTInfo,
6564 ITypeComp ** ppTComp)
6566 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6568 /* strange behaviour (does nothing) but like the
6571 if (!ppTInfo || !ppTComp)
6580 static const ITypeCompVtbl tcompvt =
6583 ITypeComp_fnQueryInterface,
6585 ITypeComp_fnRelease,
6588 ITypeComp_fnBindType