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 FIXME("func magic = %02x\n", pFunc->magic);
2904 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2905 sizeof(**ppFuncDesc));
2906 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2908 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2909 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2910 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2911 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2912 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2913 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2915 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2916 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2918 if(pFunc->retnextopt & 0x80)
2919 pType = &pFunc->rettype;
2921 pType = (WORD*)(pBlk + pFunc->rettype);
2923 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2925 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2926 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2927 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2928 (*ppFuncDesc)->pParamDesc =
2929 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2930 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2932 pArg = (WORD*)(pBlk + pFunc->arg_off);
2934 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2935 char *paramName = pNameTable + *pArg;
2937 /* If arg type follows then paramName points to the 2nd
2938 letter of the name, else the next WORD is an offset to
2939 the arg type and paramName points to the first letter.
2940 So let's take one char off paramName and see if we're
2941 pointing at an alpha-numeric char. However if *pArg is
2942 0xffff or 0xfffe then the param has no name, the former
2943 meaning that the next WORD is the type, the latter
2944 meaning the the next WORD is an offset to the type. */
2949 else if(*pArg == 0xfffe) {
2953 else if(paramName[-1] && !isalnum(paramName[-1]))
2958 if(HaveOffs) { /* the next word is an offset to type */
2959 pType = (WORD*)(pBlk + *pArg);
2960 SLTG_DoElem(pType, pBlk,
2961 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2966 pArg = SLTG_DoElem(pArg, pBlk,
2967 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2970 /* Are we an optional param ? */
2971 if((*ppFuncDesc)->funcdesc.cParams - param <=
2972 (*ppFuncDesc)->funcdesc.cParamsOpt)
2973 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2976 (*ppFuncDesc)->pParamDesc[param].Name =
2977 TLB_MultiByteToBSTR(paramName);
2981 ppFuncDesc = &((*ppFuncDesc)->next);
2982 if(pFunc->next == 0xffff) break;
2984 pTI->TypeAttr.cFuncs = cFuncs;
2987 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2988 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
2989 SLTG_TypeInfoTail *pTITail)
2991 char *pFirstItem, *pNextItem;
2993 if(pTIHeader->href_table != 0xffffffff) {
2994 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
2998 pFirstItem = pNextItem = pBlk;
3000 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3001 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3006 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3007 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3008 SLTG_TypeInfoTail *pTITail)
3010 char *pFirstItem, *pNextItem;
3012 if(pTIHeader->href_table != 0xffffffff) {
3013 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3017 pFirstItem = pNextItem = pBlk;
3019 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3020 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3023 if (pTITail->funcs_off != 0xffff)
3024 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3026 if (TRACE_ON(typelib))
3027 dump_TLBFuncDesc(pTI->funclist);
3030 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3031 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3032 SLTG_TypeInfoTail *pTITail)
3034 SLTG_DoVars(pBlk, pTI, pTITail->cVars, pNameTable);
3037 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3038 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3039 SLTG_TypeInfoTail *pTITail)
3043 if (pTITail->simple_alias) {
3044 /* if simple alias, no more processing required */
3045 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3049 if(pTIHeader->href_table != 0xffffffff) {
3050 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3054 /* otherwise it is an offset to a type */
3055 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3057 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3060 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3061 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3062 SLTG_TypeInfoTail *pTITail)
3064 if (pTIHeader->href_table != 0xffffffff)
3065 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3068 if (pTITail->vars_off != 0xffff)
3069 SLTG_DoVars(pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3071 if (pTITail->funcs_off != 0xffff)
3072 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3075 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3076 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3077 SLTG_TypeInfoTail *pTITail)
3079 SLTG_DoVars(pBlk, pTI, pTITail->cVars, pNameTable);
3082 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3083 managable copy of it into this */
3096 } SLTG_InternalOtherTypeInfo;
3098 /****************************************************************************
3099 * ITypeLib2_Constructor_SLTG
3101 * loading a SLTG typelib from an in-memory image
3103 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3105 ITypeLibImpl *pTypeLibImpl;
3106 SLTG_Header *pHeader;
3107 SLTG_BlkEntry *pBlkEntry;
3111 LPVOID pBlk, pFirstBlk;
3112 SLTG_LibBlk *pLibBlk;
3113 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3114 char *pAfterOTIBlks = NULL;
3115 char *pNameTable, *ptr;
3118 ITypeInfoImpl **ppTypeInfoImpl;
3120 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3123 pTypeLibImpl = TypeLibImpl_Constructor();
3124 if (!pTypeLibImpl) return NULL;
3128 TRACE_(typelib)("header:\n");
3129 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3130 pHeader->nrOfFileBlks );
3131 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3132 FIXME("Header type magic 0x%08lx not supported.\n",
3133 pHeader->SLTG_magic);
3137 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3138 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3140 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3141 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3143 /* Next we have a magic block */
3144 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3146 /* Let's see if we're still in sync */
3147 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3148 sizeof(SLTG_COMPOBJ_MAGIC))) {
3149 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3152 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3153 sizeof(SLTG_DIR_MAGIC))) {
3154 FIXME("dir magic = %s\n", pMagic->dir_magic);
3158 pIndex = (SLTG_Index*)(pMagic+1);
3160 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3162 pFirstBlk = (LPVOID)(pPad9 + 1);
3164 /* We'll set up a ptr to the main library block, which is the last one. */
3166 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3167 pBlkEntry[order].next != 0;
3168 order = pBlkEntry[order].next - 1, i++) {
3169 pBlk = (char*)pBlk + pBlkEntry[order].len;
3173 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3175 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3180 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3182 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3183 sizeof(*pOtherTypeInfoBlks) *
3184 pTypeLibImpl->TypeInfoCount);
3187 ptr = (char*)pLibBlk + len;
3189 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3193 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3195 w = *(WORD*)(ptr + 2);
3198 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3200 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3201 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3203 w = *(WORD*)(ptr + 4 + len);
3205 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3207 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3209 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3210 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3212 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3213 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3214 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3216 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3218 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3221 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3222 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3223 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3224 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3225 len += sizeof(SLTG_OtherTypeInfo);
3229 pAfterOTIBlks = ptr;
3231 /* Skip this WORD and get the next DWORD */
3232 len = *(DWORD*)(pAfterOTIBlks + 2);
3234 /* Now add this to pLibBLk look at what we're pointing at and
3235 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3236 dust and we should be pointing at the beginning of the name
3239 pNameTable = (char*)pLibBlk + len;
3241 switch(*(WORD*)pNameTable) {
3248 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3252 pNameTable += 0x216;
3256 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3258 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3261 /* Hopefully we now have enough ptrs set up to actually read in
3262 some TypeInfos. It's not clear which order to do them in, so
3263 I'll just follow the links along the BlkEntry chain and read
3264 them in in the order in which they're in the file */
3266 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3268 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3269 pBlkEntry[order].next != 0;
3270 order = pBlkEntry[order].next - 1, i++) {
3272 SLTG_TypeInfoHeader *pTIHeader;
3273 SLTG_TypeInfoTail *pTITail;
3274 SLTG_MemberHeader *pMemHeader;
3276 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3277 pOtherTypeInfoBlks[i].index_name)) {
3278 FIXME("Index strings don't match\n");
3283 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3284 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3287 TRACE("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
3288 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3290 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3291 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3292 (*ppTypeInfoImpl)->index = i;
3293 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3294 pOtherTypeInfoBlks[i].name_offs +
3296 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3297 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3299 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3300 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3301 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3302 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3303 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3305 if((pTIHeader->typeflags1 & 7) != 2)
3306 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3307 if(pTIHeader->typeflags3 != 2)
3308 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3310 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3311 debugstr_w((*ppTypeInfoImpl)->Name),
3312 typekind_desc[pTIHeader->typekind],
3313 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3314 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3316 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3318 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3320 switch(pTIHeader->typekind) {
3322 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3323 pTIHeader, pTITail);
3327 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3328 pTIHeader, pTITail);
3331 case TKIND_INTERFACE:
3332 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3333 pTIHeader, pTITail);
3337 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3338 pTIHeader, pTITail);
3342 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3343 pTIHeader, pTITail);
3346 case TKIND_DISPATCH:
3347 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3348 pTIHeader, pTITail);
3352 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3357 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3358 but we've already set those */
3359 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3360 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3361 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3363 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3378 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3379 pBlk = (char*)pBlk + pBlkEntry[order].len;
3382 if(i != pTypeLibImpl->TypeInfoCount) {
3383 FIXME("Somehow processed %d TypeInfos\n", i);
3387 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3388 return (ITypeLib2*)pTypeLibImpl;
3391 /* ITypeLib::QueryInterface
3393 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3398 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3400 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3403 if(IsEqualIID(riid, &IID_IUnknown) ||
3404 IsEqualIID(riid,&IID_ITypeLib)||
3405 IsEqualIID(riid,&IID_ITypeLib2))
3412 ITypeLib2_AddRef(iface);
3413 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3416 TRACE("-- Interface: E_NOINTERFACE\n");
3417 return E_NOINTERFACE;
3422 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3424 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3425 ULONG ref = InterlockedIncrement(&This->ref);
3427 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3432 /* ITypeLib::Release
3434 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3436 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3437 ULONG ref = InterlockedDecrement(&This->ref);
3439 TRACE("(%p)->(%lu)\n",This, ref);
3443 /* remove cache entry */
3446 TRACE("removing from cache list\n");
3447 EnterCriticalSection(&cache_section);
3448 if (This->next) This->next->prev = This->prev;
3449 if (This->prev) This->prev->next = This->next;
3450 else tlb_cache_first = This->next;
3451 LeaveCriticalSection(&cache_section);
3452 HeapFree(GetProcessHeap(), 0, This->path);
3454 /* FIXME destroy child objects */
3455 TRACE(" destroying ITypeLib(%p)\n",This);
3459 SysFreeString(This->Name);
3463 if (This->DocString)
3465 SysFreeString(This->DocString);
3466 This->DocString = NULL;
3471 SysFreeString(This->HelpFile);
3472 This->HelpFile = NULL;
3475 if (This->HelpStringDll)
3477 SysFreeString(This->HelpStringDll);
3478 This->HelpStringDll = NULL;
3481 if (This->pTypeInfo) /* can be NULL */
3482 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3483 HeapFree(GetProcessHeap(),0,This);
3490 /* ITypeLib::GetTypeInfoCount
3492 * Returns the number of type descriptions in the type library
3494 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3496 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3497 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3498 return This->TypeInfoCount;
3501 /* ITypeLib::GetTypeInfo
3503 * retrieves the specified type description in the library.
3505 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3508 ITypeInfo **ppTInfo)
3512 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3513 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3515 TRACE("(%p)->(index=%d)\n", This, index);
3517 if (!ppTInfo) return E_INVALIDARG;
3519 /* search element n in list */
3520 for(i=0; i < index; i++)
3522 pTypeInfo = pTypeInfo->next;
3525 TRACE("-- element not found\n");
3526 return TYPE_E_ELEMENTNOTFOUND;
3530 *ppTInfo = (ITypeInfo *) pTypeInfo;
3532 ITypeInfo_AddRef(*ppTInfo);
3533 TRACE("-- found (%p)\n",*ppTInfo);
3538 /* ITypeLibs::GetTypeInfoType
3540 * Retrieves the type of a type description.
3542 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3547 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3549 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3551 TRACE("(%p) index %d\n", This, index);
3553 if(!pTKind) return E_INVALIDARG;
3555 /* search element n in list */
3556 for(i=0; i < index; i++)
3560 TRACE("-- element not found\n");
3561 return TYPE_E_ELEMENTNOTFOUND;
3563 pTInfo = pTInfo->next;
3566 *pTKind = pTInfo->TypeAttr.typekind;
3567 TRACE("-- found Type (%d)\n", *pTKind);
3571 /* ITypeLib::GetTypeInfoOfGuid
3573 * Retrieves the type description that corresponds to the specified GUID.
3576 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3579 ITypeInfo **ppTInfo)
3581 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3582 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3584 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3588 WARN("-- element not found\n");
3589 return TYPE_E_ELEMENTNOTFOUND;
3592 /* search linked list for guid */
3593 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3595 pTypeInfo = pTypeInfo->next;
3599 /* end of list reached */
3600 WARN("-- element not found\n");
3601 return TYPE_E_ELEMENTNOTFOUND;
3605 TRACE("-- found (%p, %s)\n",
3607 debugstr_w(pTypeInfo->Name));
3609 *ppTInfo = (ITypeInfo*)pTypeInfo;
3610 ITypeInfo_AddRef(*ppTInfo);
3614 /* ITypeLib::GetLibAttr
3616 * Retrieves the structure that contains the library's attributes.
3619 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3621 LPTLIBATTR *ppTLibAttr)
3623 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3624 TRACE("(%p)\n",This);
3625 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3626 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3630 /* ITypeLib::GetTypeComp
3632 * Enables a client compiler to bind to a library's types, variables,
3633 * constants, and global functions.
3636 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3638 ITypeComp **ppTComp)
3640 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3642 TRACE("(%p)->(%p)\n",This,ppTComp);
3643 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3644 ITypeComp_AddRef(*ppTComp);
3649 /* ITypeLib::GetDocumentation
3651 * Retrieves the library's documentation string, the complete Help file name
3652 * and path, and the context identifier for the library Help topic in the Help
3655 * On a successful return all non-null BSTR pointers will have been set,
3658 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3662 BSTR *pBstrDocString,
3663 DWORD *pdwHelpContext,
3664 BSTR *pBstrHelpFile)
3666 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3668 HRESULT result = E_INVALIDARG;
3673 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3675 pBstrName, pBstrDocString,
3676 pdwHelpContext, pBstrHelpFile);
3680 /* documentation for the typelib */
3685 if(!(*pBstrName = SysAllocString(This->Name)))
3693 if (This->DocString)
3695 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3698 else if (This->Name)
3700 if(!(*pBstrDocString = SysAllocString(This->Name)))
3704 *pBstrDocString = NULL;
3708 *pdwHelpContext = This->dwHelpContext;
3714 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3718 *pBstrHelpFile = NULL;
3725 /* for a typeinfo */
3726 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3728 if(SUCCEEDED(result))
3730 result = ITypeInfo_GetDocumentation(pTInfo,
3734 pdwHelpContext, pBstrHelpFile);
3736 ITypeInfo_Release(pTInfo);
3741 if (pBstrDocString) SysFreeString (*pBstrDocString);
3743 if (pBstrName) SysFreeString (*pBstrName);
3745 return STG_E_INSUFFICIENTMEMORY;
3750 * Indicates whether a passed-in string contains the name of a type or member
3751 * described in the library.
3754 static HRESULT WINAPI ITypeLib2_fnIsName(
3760 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3761 ITypeInfoImpl *pTInfo;
3762 TLBFuncDesc *pFInfo;
3765 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3767 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3771 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3772 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3773 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3774 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3775 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3776 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3777 goto ITypeLib2_fnIsName_exit;
3779 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3780 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3785 ITypeLib2_fnIsName_exit:
3786 TRACE("(%p)slow! search for %s: %s found!\n", This,
3787 debugstr_w(szNameBuf), *pfName?"NOT":"");
3792 /* ITypeLib::FindName
3794 * Finds occurrences of a type description in a type library. This may be used
3795 * to quickly verify that a name exists in a type library.
3798 static HRESULT WINAPI ITypeLib2_fnFindName(
3802 ITypeInfo **ppTInfo,
3806 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3807 ITypeInfoImpl *pTInfo;
3808 TLBFuncDesc *pFInfo;
3811 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3813 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3814 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3815 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3816 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3817 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3818 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3819 goto ITypeLib2_fnFindName_exit;
3822 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3823 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3825 ITypeLib2_fnFindName_exit:
3826 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3827 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3830 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3831 This, *pcFound, debugstr_w(szNameBuf), j);
3838 /* ITypeLib::ReleaseTLibAttr
3840 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3843 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3845 TLIBATTR *pTLibAttr)
3847 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3848 TRACE("freeing (%p)\n",This);
3849 HeapFree(GetProcessHeap(),0,pTLibAttr);
3853 /* ITypeLib2::GetCustData
3855 * gets the custom data
3857 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3862 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3863 TLBCustData *pCData;
3865 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3867 if( IsEqualIID(guid, &pCData->guid)) break;
3870 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3874 VariantInit( pVarVal);
3875 VariantCopy( pVarVal, &pCData->data);
3878 return E_INVALIDARG; /* FIXME: correct? */
3881 /* ITypeLib2::GetLibStatistics
3883 * Returns statistics about a type library that are required for efficient
3884 * sizing of hash tables.
3887 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3889 ULONG *pcUniqueNames,
3890 ULONG *pcchUniqueNames)
3892 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3894 FIXME("(%p): stub!\n", This);
3896 if(pcUniqueNames) *pcUniqueNames=1;
3897 if(pcchUniqueNames) *pcchUniqueNames=1;
3901 /* ITypeLib2::GetDocumentation2
3903 * Retrieves the library's documentation string, the complete Help file name
3904 * and path, the localization context to use, and the context ID for the
3905 * library Help topic in the Help file.
3908 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3912 BSTR *pbstrHelpString,
3913 DWORD *pdwHelpStringContext,
3914 BSTR *pbstrHelpStringDll)
3916 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3920 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3922 /* the help string should be obtained from the helpstringdll,
3923 * using the _DLLGetDocumentation function, based on the supplied
3924 * lcid. Nice to do sometime...
3928 /* documentation for the typelib */
3930 *pbstrHelpString=SysAllocString(This->DocString);
3931 if(pdwHelpStringContext)
3932 *pdwHelpStringContext=This->dwHelpContext;
3933 if(pbstrHelpStringDll)
3934 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3940 /* for a typeinfo */
3941 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3943 if(SUCCEEDED(result))
3945 ITypeInfo2 * pTInfo2;
3946 result = ITypeInfo_QueryInterface(pTInfo,
3948 (LPVOID*) &pTInfo2);
3950 if(SUCCEEDED(result))
3952 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3956 pdwHelpStringContext,
3957 pbstrHelpStringDll);
3959 ITypeInfo2_Release(pTInfo2);
3962 ITypeInfo_Release(pTInfo);
3968 /* ITypeLib2::GetAllCustData
3970 * Gets all custom data items for the library.
3973 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3975 CUSTDATA *pCustData)
3977 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3978 TLBCustData *pCData;
3980 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3981 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3982 if(pCustData->prgCustData ){
3983 pCustData->cCustData=This->ctCustData;
3984 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3985 pCustData->prgCustData[i].guid=pCData->guid;
3986 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3989 ERR(" OUT OF MEMORY!\n");
3990 return E_OUTOFMEMORY;
3995 static const ITypeLib2Vtbl tlbvt = {
3996 ITypeLib2_fnQueryInterface,
3998 ITypeLib2_fnRelease,
3999 ITypeLib2_fnGetTypeInfoCount,
4000 ITypeLib2_fnGetTypeInfo,
4001 ITypeLib2_fnGetTypeInfoType,
4002 ITypeLib2_fnGetTypeInfoOfGuid,
4003 ITypeLib2_fnGetLibAttr,
4004 ITypeLib2_fnGetTypeComp,
4005 ITypeLib2_fnGetDocumentation,
4007 ITypeLib2_fnFindName,
4008 ITypeLib2_fnReleaseTLibAttr,
4010 ITypeLib2_fnGetCustData,
4011 ITypeLib2_fnGetLibStatistics,
4012 ITypeLib2_fnGetDocumentation2,
4013 ITypeLib2_fnGetAllCustData
4017 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4019 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4021 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4024 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4026 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4028 return ITypeLib2_AddRef((ITypeLib2 *)This);
4031 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4033 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4035 return ITypeLib2_Release((ITypeLib2 *)This);
4038 static HRESULT WINAPI ITypeLibComp_fnBind(
4043 ITypeInfo ** ppTInfo,
4044 DESCKIND * pDescKind,
4047 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4048 ITypeInfoImpl *pTypeInfo;
4050 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4052 *pDescKind = DESCKIND_NONE;
4053 pBindPtr->lptcomp = NULL;
4056 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4058 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4060 /* FIXME: check wFlags here? */
4061 /* FIXME: we should use a hash table to look this info up using lHash
4062 * instead of an O(n) search */
4063 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4064 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4066 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4068 *pDescKind = DESCKIND_TYPECOMP;
4069 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4070 ITypeComp_AddRef(pBindPtr->lptcomp);
4071 TRACE("module or enum: %s\n", debugstr_w(szName));
4076 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4077 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4079 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4082 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4083 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4085 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4090 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4091 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4093 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4095 ITypeInfo *subtypeinfo;
4097 DESCKIND subdesckind;
4099 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4100 &subtypeinfo, &subdesckind, &subbindptr);
4101 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4103 TYPEDESC tdesc_appobject =
4106 (TYPEDESC *)pTypeInfo->hreftype
4110 const VARDESC vardesc_appobject =
4113 NULL, /* lpstrSchema */
4128 VAR_STATIC /* varkind */
4131 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4133 /* cleanup things filled in by Bind call so we can put our
4134 * application object data in there instead */
4135 switch (subdesckind)
4137 case DESCKIND_FUNCDESC:
4138 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4140 case DESCKIND_VARDESC:
4141 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4146 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4148 if (pTypeInfo->hreftype == -1)
4149 FIXME("no hreftype for interface %p\n", pTypeInfo);
4151 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4155 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4156 *ppTInfo = (ITypeInfo *)pTypeInfo;
4157 ITypeInfo_AddRef(*ppTInfo);
4163 TRACE("name not found %s\n", debugstr_w(szName));
4167 static HRESULT WINAPI ITypeLibComp_fnBindType(
4171 ITypeInfo ** ppTInfo,
4172 ITypeComp ** ppTComp)
4174 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4178 static const ITypeCompVtbl tlbtcvt =
4181 ITypeLibComp_fnQueryInterface,
4182 ITypeLibComp_fnAddRef,
4183 ITypeLibComp_fnRelease,
4185 ITypeLibComp_fnBind,
4186 ITypeLibComp_fnBindType
4189 /*================== ITypeInfo(2) Methods ===================================*/
4190 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4192 ITypeInfoImpl * pTypeInfoImpl;
4194 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4197 pTypeInfoImpl->lpVtbl = &tinfvt;
4198 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4199 pTypeInfoImpl->ref=1;
4200 pTypeInfoImpl->hreftype = -1;
4201 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4202 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4204 TRACE("(%p)\n", pTypeInfoImpl);
4205 return (ITypeInfo2*) pTypeInfoImpl;
4208 /* ITypeInfo::QueryInterface
4210 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4215 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4217 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4220 if(IsEqualIID(riid, &IID_IUnknown) ||
4221 IsEqualIID(riid,&IID_ITypeInfo)||
4222 IsEqualIID(riid,&IID_ITypeInfo2))
4226 ITypeInfo_AddRef(iface);
4227 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4230 TRACE("-- Interface: E_NOINTERFACE\n");
4231 return E_NOINTERFACE;
4234 /* ITypeInfo::AddRef
4236 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4238 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4239 ULONG ref = InterlockedIncrement(&This->ref);
4241 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4243 TRACE("(%p)->ref is %lu\n",This, ref);
4247 /* ITypeInfo::Release
4249 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4251 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4252 ULONG ref = InterlockedDecrement(&This->ref);
4254 TRACE("(%p)->(%lu)\n",This, ref);
4257 /* We don't release ITypeLib when ref=0 because
4258 it means that function is called by ITypeLib2_Release */
4259 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4261 static int once = 0;
4265 FIXME("destroy child objects\n");
4268 TRACE("destroying ITypeInfo(%p)\n",This);
4271 SysFreeString(This->Name);
4275 if (This->DocString)
4277 SysFreeString(This->DocString);
4278 This->DocString = 0;
4283 SysFreeString(This->DllName);
4289 ITypeInfo_Release((ITypeInfo*)This->next);
4292 HeapFree(GetProcessHeap(),0,This);
4298 /* ITypeInfo::GetTypeAttr
4300 * Retrieves a TYPEATTR structure that contains the attributes of the type
4304 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4305 LPTYPEATTR *ppTypeAttr)
4307 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4310 TRACE("(%p)\n",This);
4312 size = sizeof(**ppTypeAttr);
4313 if (This->TypeAttr.typekind == TKIND_ALIAS)
4314 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4316 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4318 return E_OUTOFMEMORY;
4320 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4322 if (This->TypeAttr.typekind == TKIND_ALIAS)
4323 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4324 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4326 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4327 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4329 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4330 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4335 /* ITypeInfo::GetTypeComp
4337 * Retrieves the ITypeComp interface for the type description, which enables a
4338 * client compiler to bind to the type description's members.
4341 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4342 ITypeComp * *ppTComp)
4344 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4346 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4348 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4349 ITypeComp_AddRef(*ppTComp);
4353 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4355 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4356 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4357 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4361 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4363 memcpy(dest, src, sizeof(ELEMDESC));
4364 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4365 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4367 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4368 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4369 *buffer += sizeof(PARAMDESCEX);
4370 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4371 VariantInit(&pparamdescex_dest->varDefaultValue);
4372 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4373 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4376 dest->u.paramdesc.pparamdescex = NULL;
4380 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4382 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4383 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4386 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4390 SIZE_T size = sizeof(*src);
4394 size += sizeof(*src->lprgscode) * src->cScodes;
4395 size += TLB_SizeElemDesc(&src->elemdescFunc);
4396 for (i = 0; i < src->cParams; i++)
4398 size += sizeof(ELEMDESC);
4399 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4402 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4403 if (!dest) return E_OUTOFMEMORY;
4405 memcpy(dest, src, sizeof(FUNCDESC));
4406 buffer = (char *)(dest + 1);
4408 dest->lprgscode = (SCODE *)buffer;
4409 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4410 buffer += sizeof(*src->lprgscode) * src->cScodes;
4412 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4415 SysFreeString((BSTR)dest);
4419 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4420 buffer += sizeof(ELEMDESC) * src->cParams;
4421 for (i = 0; i < src->cParams; i++)
4423 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4429 /* undo the above actions */
4430 for (i = i - 1; i >= 0; i--)
4431 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4432 TLB_FreeElemDesc(&dest->elemdescFunc);
4433 SysFreeString((BSTR)dest);
4437 /* special treatment for dispinterfaces: this makes functions appear
4438 * to return their [retval] value when it is really returning an
4440 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4442 if (dest->cParams &&
4443 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4445 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4446 if (elemdesc->tdesc.vt != VT_PTR)
4448 ERR("elemdesc should have started with VT_PTR instead of:\n");
4450 dump_ELEMDESC(elemdesc);
4451 return E_UNEXPECTED;
4454 /* copy last parameter to the return value. we are using a flat
4455 * buffer so there is no danger of leaking memory in
4457 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4459 /* remove the last parameter */
4463 /* otherwise this function is made to appear to have no return
4465 dest->elemdescFunc.tdesc.vt = VT_VOID;
4473 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4475 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4476 const TLBFuncDesc *pFDesc;
4479 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4484 *ppFuncDesc = &pFDesc->funcdesc;
4488 return E_INVALIDARG;
4491 /* ITypeInfo::GetFuncDesc
4493 * Retrieves the FUNCDESC structure that contains information about a
4494 * specified function.
4497 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4498 LPFUNCDESC *ppFuncDesc)
4500 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4501 const FUNCDESC *internal_funcdesc;
4504 TRACE("(%p) index %d\n", This, index);
4506 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4510 return TLB_AllocAndInitFuncDesc(
4513 This->TypeAttr.typekind == TKIND_DISPATCH);
4516 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4520 SIZE_T size = sizeof(*src);
4523 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4524 if (src->varkind == VAR_CONST)
4525 size += sizeof(VARIANT);
4526 size += TLB_SizeElemDesc(&src->elemdescVar);
4528 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4529 if (!dest) return E_OUTOFMEMORY;
4532 buffer = (char *)(dest + 1);
4533 if (src->lpstrSchema)
4536 dest->lpstrSchema = (LPOLESTR)buffer;
4537 len = strlenW(src->lpstrSchema);
4538 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4539 buffer += (len + 1) * sizeof(WCHAR);
4542 if (src->varkind == VAR_CONST)
4546 dest->u.lpvarValue = (VARIANT *)buffer;
4547 *dest->u.lpvarValue = *src->u.lpvarValue;
4548 buffer += sizeof(VARIANT);
4549 VariantInit(dest->u.lpvarValue);
4550 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4553 SysFreeString((BSTR)dest_ptr);
4557 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4560 if (src->varkind == VAR_CONST)
4561 VariantClear(dest->u.lpvarValue);
4562 SysFreeString((BSTR)dest);
4569 /* ITypeInfo::GetVarDesc
4571 * Retrieves a VARDESC structure that describes the specified variable.
4574 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4575 LPVARDESC *ppVarDesc)
4577 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4579 const TLBVarDesc *pVDesc;
4581 TRACE("(%p) index %d\n", This, index);
4583 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4587 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4589 return E_INVALIDARG;
4592 /* ITypeInfo_GetNames
4594 * Retrieves the variable with the specified member ID (or the name of the
4595 * property or method and its parameters) that correspond to the specified
4598 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4599 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4601 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4602 const TLBFuncDesc *pFDesc;
4603 const TLBVarDesc *pVDesc;
4605 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4606 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4609 /* function found, now return function and parameter names */
4610 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4613 *rgBstrNames=SysAllocString(pFDesc->Name);
4615 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4621 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4624 *rgBstrNames=SysAllocString(pVDesc->Name);
4629 if(This->TypeAttr.cImplTypes &&
4630 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4631 /* recursive search */
4634 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4636 if(SUCCEEDED(result))
4638 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4639 ITypeInfo_Release(pTInfo);
4642 WARN("Could not search inherited interface!\n");
4646 WARN("no names found\n");
4649 return TYPE_E_ELEMENTNOTFOUND;
4656 /* ITypeInfo::GetRefTypeOfImplType
4658 * If a type description describes a COM class, it retrieves the type
4659 * description of the implemented interface types. For an interface,
4660 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4664 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4669 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4672 const TLBImplType *pImpl = This->impltypelist;
4674 TRACE("(%p) index %d\n", This, index);
4675 if (TRACE_ON(ole)) dump_TypeInfo(This);
4679 /* only valid on dual interfaces;
4680 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4682 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4684 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4685 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4691 hr = TYPE_E_ELEMENTNOTFOUND;
4696 /* get element n from linked list */
4697 for(i=0; pImpl && i<index; i++)
4699 pImpl = pImpl->next;
4703 *pRefType = pImpl->hRef;
4705 hr = TYPE_E_ELEMENTNOTFOUND;
4711 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4713 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4719 /* ITypeInfo::GetImplTypeFlags
4721 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4722 * or base interface in a type description.
4724 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4725 UINT index, INT *pImplTypeFlags)
4727 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4731 TRACE("(%p) index %d\n", This, index);
4732 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4733 i++, pImpl=pImpl->next)
4735 if(i==index && pImpl){
4736 *pImplTypeFlags=pImpl->implflags;
4740 return TYPE_E_ELEMENTNOTFOUND;
4744 * Maps between member names and member IDs, and parameter names and
4747 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4748 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4750 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4751 const TLBFuncDesc *pFDesc;
4752 const TLBVarDesc *pVDesc;
4756 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4759 /* init out parameters in case of failure */
4760 for (i = 0; i < cNames; i++)
4761 pMemId[i] = MEMBERID_NIL;
4763 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4765 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4766 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4767 for(i=1; i < cNames; i++){
4768 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4769 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4771 if( j<pFDesc->funcdesc.cParams)
4774 ret=DISP_E_UNKNOWNNAME;
4776 TRACE("-- 0x%08lx\n", ret);
4780 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4781 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4782 if(cNames) *pMemId=pVDesc->vardesc.memid;
4786 /* not found, see if it can be found in an inherited interface */
4787 if(This->TypeAttr.cImplTypes) {
4788 /* recursive search */
4790 ret=ITypeInfo_GetRefTypeInfo(iface,
4791 This->impltypelist->hRef, &pTInfo);
4793 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4794 ITypeInfo_Release(pTInfo);
4797 WARN("Could not search inherited interface!\n");
4799 WARN("no names found\n");
4800 return DISP_E_UNKNOWNNAME;
4803 /* ITypeInfo::Invoke
4805 * Invokes a method, or accesses a property of an object, that implements the
4806 * interface described by the type description.
4809 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4812 if (TRACE_ON(ole)) {
4814 TRACE("Calling %p(",func);
4815 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4827 res = func(args[0]);
4830 res = func(args[0],args[1]);
4833 res = func(args[0],args[1],args[2]);
4836 res = func(args[0],args[1],args[2],args[3]);
4839 res = func(args[0],args[1],args[2],args[3],args[4]);
4842 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4845 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4848 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4851 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4854 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4857 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4860 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]);
4863 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]);
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],args[11],args[12],args[13]);
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],args[12],args[13],args[14]);
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],args[13],args[14],args[15]);
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],args[14],args[15],args[16]);
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],args[15],args[16],args[17]);
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],args[16],args[17],args[18]);
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],args[17],args[18],args[19]);
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],args[18],args[19],args[20]);
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],args[19],args[20],args[21]);
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],args[20],args[21],args[22]);
4896 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4902 FIXME("unsupported calling convention %d\n",callconv);
4906 TRACE("returns %08lx\n",res);
4910 extern int _argsize(DWORD vt);
4912 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4915 ITypeInfo *tinfo2 = NULL;
4916 TYPEATTR *tattr = NULL;
4918 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4921 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4923 tdesc->u.hreftype, hr);
4926 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4929 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4930 ITypeInfo_Release(tinfo2);
4934 switch (tattr->typekind)
4941 tdesc = &tattr->tdescAlias;
4942 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4945 case TKIND_INTERFACE:
4946 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4952 case TKIND_DISPATCH:
4957 FIXME("TKIND_RECORD unhandled.\n");
4962 FIXME("TKIND_UNION unhandled.\n");
4967 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4971 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4972 ITypeInfo_Release(tinfo2);
4976 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4980 /* enforce only one level of pointer indirection */
4981 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
4983 tdesc = tdesc->u.lptdesc;
4985 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4986 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4987 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4988 if ((tdesc->vt == VT_USERDEFINED) ||
4989 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4991 VARTYPE vt_userdefined = 0;
4992 const TYPEDESC *tdesc_userdefined = tdesc;
4993 if (tdesc->vt == VT_PTR)
4995 vt_userdefined = VT_BYREF;
4996 tdesc_userdefined = tdesc->u.lptdesc;
4998 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5000 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5001 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5003 *vt |= vt_userdefined;
5015 case VT_USERDEFINED:
5016 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5023 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5024 hr = DISP_E_BADVARTYPE;
5028 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5037 /***********************************************************************
5038 * DispCallFunc (OLEAUT32.@)
5040 * Invokes a function of the specifed calling convention, passing the
5041 * specified arguments and returns the result.
5044 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5045 * oVft [I] The offset in the vtable. See notes.
5046 * cc [I] Calling convention of the function to call.
5047 * vtReturn [I] The return type of the function.
5048 * cActuals [I] Number of parameters.
5049 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5050 * prgpvarg [I] The arguments to pass.
5051 * pvargResult [O] The return value of the function. Can be NULL.
5055 * Failure: HRESULT code.
5058 * The HRESULT return value of this function is not affected by the return
5059 * value of the user supplied function, which is returned in pvargResult.
5061 * If pvInstance is NULL then a non-object function is to be called and oVft
5062 * is the address of the function to call.
5064 * The cc parameter can be one of the following values:
5077 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5078 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5080 int i, argsize, argspos;
5084 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5085 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5086 pvargResult, V_VT(pvargResult));
5090 argsize++; /* for This pointer */
5092 for (i=0;i<cActuals;i++)
5094 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5095 dump_Variant(prgpvarg[i]);
5096 argsize += _argsize(prgvt[i]);
5098 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5103 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5107 for (i=0;i<cActuals;i++)
5109 VARIANT *arg = prgpvarg[i];
5110 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5111 if (prgvt[i] == VT_VARIANT)
5112 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5114 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5115 argspos += _argsize(prgvt[i]);
5120 FARPROC *vtable = *(FARPROC**)pvInstance;
5121 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5124 /* if we aren't invoking an object then the function pointer is stored
5126 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5128 if (pvargResult && (vtReturn != VT_EMPTY))
5130 TRACE("Method returned 0x%08lx\n",hres);
5131 V_VT(pvargResult) = vtReturn;
5132 V_UI4(pvargResult) = hres;
5135 HeapFree(GetProcessHeap(),0,args);
5139 #define INVBUF_ELEMENT_SIZE \
5140 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5141 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5142 ((VARIANTARG *)(buffer))
5143 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5144 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5145 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5146 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5147 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5148 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5150 static HRESULT WINAPI ITypeInfo_fnInvoke(
5155 DISPPARAMS *pDispParams,
5156 VARIANT *pVarResult,
5157 EXCEPINFO *pExcepInfo,
5160 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5162 unsigned int var_index;
5165 const TLBFuncDesc *pFuncInfo;
5167 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5168 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5170 dump_DispParms(pDispParams);
5172 /* we do this instead of using GetFuncDesc since it will return a fake
5173 * FUNCDESC for dispinterfaces and we want the real function description */
5174 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5175 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5179 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5183 TRACE("invoking:\n");
5184 dump_TLBFuncDescOne(pFuncInfo);
5187 switch (func_desc->funckind) {
5188 case FUNC_PUREVIRTUAL:
5189 case FUNC_VIRTUAL: {
5190 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5192 VARIANT retval; /* pointer for storing byref retvals in */
5193 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5194 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5195 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5198 for (i = 0; i < func_desc->cParams; i++)
5200 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5201 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5206 TRACE("changing args\n");
5207 for (i = 0; i < func_desc->cParams; i++)
5209 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5211 if (wParamFlags & PARAMFLAG_FRETVAL)
5213 /* note: this check is placed so that if the caller passes
5214 * in a VARIANTARG for the retval we just ignore it, like
5216 if (i == func_desc->cParams - 1)
5219 arg = prgpvarg[i] = &rgvarg[i];
5220 memset(arg, 0, sizeof(*arg));
5221 V_VT(arg) = rgvt[i];
5222 memset(&retval, 0, sizeof(retval));
5223 V_BYREF(arg) = &retval;
5227 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5228 hres = E_UNEXPECTED;
5232 else if (i < pDispParams->cArgs)
5234 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5235 dump_Variant(src_arg);
5237 if (rgvt[i] == VT_VARIANT)
5238 hres = VariantCopy(&rgvarg[i], src_arg);
5239 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5241 if (rgvt[i] == V_VT(src_arg))
5242 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5245 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5246 hres = VariantCopy(&missing_arg[i], src_arg);
5247 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5249 V_VT(&rgvarg[i]) = rgvt[i];
5251 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5253 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5254 V_VT(&missing_arg[i]) = V_VT(src_arg);
5255 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5256 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5257 V_VT(&rgvarg[i]) = rgvt[i];
5259 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5261 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5262 V_VT(&rgvarg[i]) = rgvt[i];
5266 /* FIXME: this doesn't work for VT_BYREF arguments if
5267 * they are not the same type as in the paramdesc */
5268 V_VT(&rgvarg[i]) = V_VT(src_arg);
5269 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5270 V_VT(&rgvarg[i]) = rgvt[i];
5275 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5276 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5277 debugstr_VT(src_arg), debugstr_VF(src_arg));
5280 prgpvarg[i] = &rgvarg[i];
5282 else if (wParamFlags & PARAMFLAG_FOPT)
5285 arg = prgpvarg[i] = &rgvarg[i];
5286 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5288 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5294 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5295 V_VT(arg) = VT_VARIANT | VT_BYREF;
5296 V_VARIANTREF(arg) = &missing_arg[i];
5297 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5298 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5303 hres = DISP_E_BADPARAMCOUNT;
5307 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5308 if (func_desc->cParamsOpt < 0)
5310 FIXME("Does not support safearray optional parameters\n");
5311 hres = DISP_E_BADPARAMCOUNT;
5312 goto func_fail; /* FIXME: we don't free changed types here */
5315 V_VT(&varresult) = 0;
5316 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5317 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5319 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5320 V_VT(&varresult), func_desc->cParams, rgvt,
5321 prgpvarg, &varresult);
5323 for (i = 0; i < func_desc->cParams; i++)
5325 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5326 if (wParamFlags & PARAMFLAG_FRETVAL)
5330 TRACE("[retval] value: ");
5331 dump_Variant(prgpvarg[i]);
5335 /* deref return value */
5336 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5338 /* free data stored in varresult. Note that
5339 * VariantClear doesn't do what we want because we are
5340 * working with byref types. */
5341 /* FIXME: clear safearrays, bstrs, records and
5342 * variants here too */
5343 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5344 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5346 if(*V_UNKNOWNREF(prgpvarg[i]))
5347 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5351 else if (i < pDispParams->cArgs)
5353 if (wParamFlags & PARAMFLAG_FOUT)
5355 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5357 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5358 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5362 ERR("failed to convert param %d to vt %d\n", i,
5363 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5367 VariantClear(&rgvarg[i]);
5369 else if (wParamFlags & PARAMFLAG_FOPT)
5371 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5372 VariantClear(&rgvarg[i]);
5376 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5378 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5379 hres = DISP_E_EXCEPTION;
5380 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5384 HeapFree(GetProcessHeap(), 0, buffer);
5387 case FUNC_DISPATCH: {
5390 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5391 if (SUCCEEDED(hres)) {
5392 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5393 hres = IDispatch_Invoke(
5394 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5395 pVarResult,pExcepInfo,pArgErr
5398 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5399 IDispatch_Release(disp);
5401 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5405 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5410 TRACE("-- 0x%08lx\n", hres);
5413 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5416 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5417 if(FAILED(hres)) return hres;
5419 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5420 dump_VARDESC(var_desc);
5421 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5425 /* not found, look for it in inherited interfaces */
5426 ITypeInfo2_GetTypeKind(iface, &type_kind);
5427 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5429 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5430 /* recursive search */
5432 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5433 if(SUCCEEDED(hres)){
5434 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5435 ITypeInfo_Release(pTInfo);
5438 WARN("Could not search inherited interface!\n");
5441 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5442 return DISP_E_MEMBERNOTFOUND;
5445 /* ITypeInfo::GetDocumentation
5447 * Retrieves the documentation string, the complete Help file name and path,
5448 * and the context ID for the Help topic for a specified type description.
5450 * (Can be tested by the Visual Basic Editor in Word for instance.)
5452 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5453 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5454 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5456 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5457 const TLBFuncDesc *pFDesc;
5458 const TLBVarDesc *pVDesc;
5459 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5460 " HelpContext(%p) HelpFile(%p)\n",
5461 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5462 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5464 *pBstrName=SysAllocString(This->Name);
5466 *pBstrDocString=SysAllocString(This->DocString);
5468 *pdwHelpContext=This->dwHelpContext;
5470 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5472 }else {/* for a member */
5473 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5474 if(pFDesc->funcdesc.memid==memid){
5476 *pBstrName = SysAllocString(pFDesc->Name);
5478 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5480 *pdwHelpContext=pFDesc->helpcontext;
5483 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5484 if(pVDesc->vardesc.memid==memid){
5486 *pBstrName = SysAllocString(pVDesc->Name);
5488 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5490 *pdwHelpContext=pVDesc->HelpContext;
5494 WARN("member %ld not found\n", memid);
5495 return TYPE_E_ELEMENTNOTFOUND;
5498 /* ITypeInfo::GetDllEntry
5500 * Retrieves a description or specification of an entry point for a function
5503 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5504 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5507 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5508 const TLBFuncDesc *pFDesc;
5510 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5512 if (pBstrDllName) *pBstrDllName = NULL;
5513 if (pBstrName) *pBstrName = NULL;
5514 if (pwOrdinal) *pwOrdinal = 0;
5516 if (This->TypeAttr.typekind != TKIND_MODULE)
5517 return TYPE_E_BADMODULEKIND;
5519 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5520 if(pFDesc->funcdesc.memid==memid){
5521 dump_TypeInfo(This);
5523 dump_TLBFuncDescOne(pFDesc);
5526 *pBstrDllName = SysAllocString(This->DllName);
5528 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5530 *pBstrName = SysAllocString(pFDesc->Entry);
5538 *pwOrdinal = (DWORD)pFDesc->Entry;
5541 return TYPE_E_ELEMENTNOTFOUND;
5544 /* ITypeInfo::GetRefTypeInfo
5546 * If a type description references other type descriptions, it retrieves
5547 * the referenced type descriptions.
5549 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5552 ITypeInfo **ppTInfo)
5554 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5555 HRESULT result = E_FAIL;
5557 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5559 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5560 ITypeInfo_AddRef(*ppTInfo);
5563 else if (hRefType == -1 &&
5564 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5565 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5567 /* when we meet a DUAL dispinterface, we must create the interface
5570 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5573 /* the interface version contains the same information as the dispinterface
5574 * copy the contents of the structs.
5576 *pTypeInfoImpl = *This;
5577 pTypeInfoImpl->ref = 1;
5579 /* change the type to interface */
5580 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5582 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5584 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5589 TLBRefType *pRefType;
5590 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5591 if(pRefType->reference == hRefType)
5595 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5596 if(pRefType && hRefType != -1) {
5597 ITypeLib *pTLib = NULL;
5599 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5601 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5603 if(pRefType->pImpTLInfo->pImpTypeLib) {
5604 TRACE("typeinfo in imported typelib that is already loaded\n");
5605 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5606 ITypeLib2_AddRef((ITypeLib*) pTLib);
5609 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5610 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5611 pRefType->pImpTLInfo->wVersionMajor,
5612 pRefType->pImpTLInfo->wVersionMinor,
5613 pRefType->pImpTLInfo->lcid,
5616 if(!SUCCEEDED(result)) {
5617 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5618 result=LoadTypeLib(libnam, &pTLib);
5619 SysFreeString(libnam);
5621 if(SUCCEEDED(result)) {
5622 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5623 ITypeLib2_AddRef(pTLib);
5627 if(SUCCEEDED(result)) {
5628 if(pRefType->index == TLB_REF_USE_GUID)
5629 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5633 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5637 ITypeLib2_Release(pTLib);
5641 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5642 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5646 /* ITypeInfo::AddressOfMember
5648 * Retrieves the addresses of static functions or variables, such as those
5651 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5652 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5654 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5660 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5662 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5666 module = LoadLibraryW(dll);
5669 ERR("couldn't load %s\n", debugstr_w(dll));
5671 if (entry) SysFreeString(entry);
5672 return STG_E_FILENOTFOUND;
5674 /* FIXME: store library somewhere where we can free it */
5679 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5680 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5681 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5683 *ppv = GetProcAddress(module, entryA);
5685 ERR("function not found %s\n", debugstr_a(entryA));
5687 HeapFree(GetProcessHeap(), 0, entryA);
5691 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5693 ERR("function not found %d\n", ordinal);
5697 if (entry) SysFreeString(entry);
5700 return TYPE_E_DLLFUNCTIONNOTFOUND;
5705 /* ITypeInfo::CreateInstance
5707 * Creates a new instance of a type that describes a component object class
5710 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5711 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5713 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5714 FIXME("(%p) stub!\n", This);
5718 /* ITypeInfo::GetMops
5720 * Retrieves marshalling information.
5722 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5725 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5726 FIXME("(%p) stub!\n", This);
5730 /* ITypeInfo::GetContainingTypeLib
5732 * Retrieves the containing type library and the index of the type description
5733 * within that type library.
5735 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5736 ITypeLib * *ppTLib, UINT *pIndex)
5738 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5740 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5742 *pIndex=This->index;
5743 TRACE("returning pIndex=%d\n", *pIndex);
5747 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5748 ITypeLib2_AddRef(*ppTLib);
5749 TRACE("returning ppTLib=%p\n", *ppTLib);
5755 /* ITypeInfo::ReleaseTypeAttr
5757 * Releases a TYPEATTR previously returned by GetTypeAttr.
5760 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5761 TYPEATTR* pTypeAttr)
5763 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5764 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5765 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5768 /* ITypeInfo::ReleaseFuncDesc
5770 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5772 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5774 FUNCDESC *pFuncDesc)
5776 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5779 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5781 for (i = 0; i < pFuncDesc->cParams; i++)
5782 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5783 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5785 SysFreeString((BSTR)pFuncDesc);
5788 /* ITypeInfo::ReleaseVarDesc
5790 * Releases a VARDESC previously returned by GetVarDesc.
5792 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5795 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5796 TRACE("(%p)->(%p)\n", This, pVarDesc);
5798 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5799 if (pVarDesc->varkind == VAR_CONST)
5800 VariantClear(pVarDesc->u.lpvarValue);
5801 SysFreeString((BSTR)pVarDesc);
5804 /* ITypeInfo2::GetTypeKind
5806 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5809 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5810 TYPEKIND *pTypeKind)
5812 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5813 *pTypeKind=This->TypeAttr.typekind;
5814 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5818 /* ITypeInfo2::GetTypeFlags
5820 * Returns the type flags without any allocations. This returns a DWORD type
5821 * flag, which expands the type flags without growing the TYPEATTR (type
5825 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5827 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5828 *pTypeFlags=This->TypeAttr.wTypeFlags;
5829 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5833 /* ITypeInfo2::GetFuncIndexOfMemId
5834 * Binds to a specific member based on a known DISPID, where the member name
5835 * is not known (for example, when binding to a default member).
5838 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5839 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5841 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5842 const TLBFuncDesc *pFuncInfo;
5846 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5847 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5853 result = TYPE_E_ELEMENTNOTFOUND;
5855 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5856 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5860 /* TypeInfo2::GetVarIndexOfMemId
5862 * Binds to a specific member based on a known DISPID, where the member name
5863 * is not known (for example, when binding to a default member).
5866 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5867 MEMBERID memid, UINT *pVarIndex)
5869 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5870 TLBVarDesc *pVarInfo;
5873 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5874 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5880 result = TYPE_E_ELEMENTNOTFOUND;
5882 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5883 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5887 /* ITypeInfo2::GetCustData
5889 * Gets the custom data
5891 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5896 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5897 TLBCustData *pCData;
5899 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5900 if( IsEqualIID(guid, &pCData->guid)) break;
5902 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5906 VariantInit( pVarVal);
5907 VariantCopy( pVarVal, &pCData->data);
5910 return E_INVALIDARG; /* FIXME: correct? */
5913 /* ITypeInfo2::GetFuncCustData
5915 * Gets the custom data
5917 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5923 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5924 TLBCustData *pCData=NULL;
5925 TLBFuncDesc * pFDesc;
5927 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5928 pFDesc=pFDesc->next);
5931 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5932 if( IsEqualIID(guid, &pCData->guid)) break;
5934 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5937 VariantInit( pVarVal);
5938 VariantCopy( pVarVal, &pCData->data);
5941 return E_INVALIDARG; /* FIXME: correct? */
5944 /* ITypeInfo2::GetParamCustData
5946 * Gets the custom data
5948 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5955 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5956 TLBCustData *pCData=NULL;
5957 TLBFuncDesc * pFDesc;
5960 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5962 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5963 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5964 pCData = pCData->next)
5965 if( IsEqualIID(guid, &pCData->guid)) break;
5967 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5971 VariantInit( pVarVal);
5972 VariantCopy( pVarVal, &pCData->data);
5975 return E_INVALIDARG; /* FIXME: correct? */
5978 /* ITypeInfo2::GetVarCustData
5980 * Gets the custom data
5982 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5988 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5989 TLBCustData *pCData=NULL;
5990 TLBVarDesc * pVDesc;
5993 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5997 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5999 if( IsEqualIID(guid, &pCData->guid)) break;
6003 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6007 VariantInit( pVarVal);
6008 VariantCopy( pVarVal, &pCData->data);
6011 return E_INVALIDARG; /* FIXME: correct? */
6014 /* ITypeInfo2::GetImplCustData
6016 * Gets the custom data
6018 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6024 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6025 TLBCustData *pCData=NULL;
6026 TLBImplType * pRDesc;
6029 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6033 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6035 if( IsEqualIID(guid, &pCData->guid)) break;
6039 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6043 VariantInit( pVarVal);
6044 VariantCopy( pVarVal, &pCData->data);
6047 return E_INVALIDARG; /* FIXME: correct? */
6050 /* ITypeInfo2::GetDocumentation2
6052 * Retrieves the documentation string, the complete Help file name and path,
6053 * the localization context to use, and the context ID for the library Help
6054 * topic in the Help file.
6057 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6061 BSTR *pbstrHelpString,
6062 DWORD *pdwHelpStringContext,
6063 BSTR *pbstrHelpStringDll)
6065 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6066 const TLBFuncDesc *pFDesc;
6067 const TLBVarDesc *pVDesc;
6068 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6069 "HelpStringContext(%p) HelpStringDll(%p)\n",
6070 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6071 pbstrHelpStringDll );
6072 /* the help string should be obtained from the helpstringdll,
6073 * using the _DLLGetDocumentation function, based on the supplied
6074 * lcid. Nice to do sometime...
6076 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6078 *pbstrHelpString=SysAllocString(This->Name);
6079 if(pdwHelpStringContext)
6080 *pdwHelpStringContext=This->dwHelpStringContext;
6081 if(pbstrHelpStringDll)
6082 *pbstrHelpStringDll=
6083 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6085 }else {/* for a member */
6086 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6087 if(pFDesc->funcdesc.memid==memid){
6089 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6090 if(pdwHelpStringContext)
6091 *pdwHelpStringContext=pFDesc->HelpStringContext;
6092 if(pbstrHelpStringDll)
6093 *pbstrHelpStringDll=
6094 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6097 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6098 if(pVDesc->vardesc.memid==memid){
6100 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6101 if(pdwHelpStringContext)
6102 *pdwHelpStringContext=pVDesc->HelpStringContext;
6103 if(pbstrHelpStringDll)
6104 *pbstrHelpStringDll=
6105 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6109 return TYPE_E_ELEMENTNOTFOUND;
6112 /* ITypeInfo2::GetAllCustData
6114 * Gets all custom data items for the Type info.
6117 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6119 CUSTDATA *pCustData)
6121 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6122 TLBCustData *pCData;
6125 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6127 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6128 if(pCustData->prgCustData ){
6129 pCustData->cCustData=This->ctCustData;
6130 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6131 pCustData->prgCustData[i].guid=pCData->guid;
6132 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6135 ERR(" OUT OF MEMORY!\n");
6136 return E_OUTOFMEMORY;
6141 /* ITypeInfo2::GetAllFuncCustData
6143 * Gets all custom data items for the specified Function
6146 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6149 CUSTDATA *pCustData)
6151 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6152 TLBCustData *pCData;
6153 TLBFuncDesc * pFDesc;
6155 TRACE("(%p) index %d\n", This, index);
6156 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6157 pFDesc=pFDesc->next)
6160 pCustData->prgCustData =
6161 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6162 if(pCustData->prgCustData ){
6163 pCustData->cCustData=pFDesc->ctCustData;
6164 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6165 pCData = pCData->next){
6166 pCustData->prgCustData[i].guid=pCData->guid;
6167 VariantCopy(& pCustData->prgCustData[i].varValue,
6171 ERR(" OUT OF MEMORY!\n");
6172 return E_OUTOFMEMORY;
6176 return TYPE_E_ELEMENTNOTFOUND;
6179 /* ITypeInfo2::GetAllParamCustData
6181 * Gets all custom data items for the Functions
6184 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6185 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6187 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6188 TLBCustData *pCData=NULL;
6189 TLBFuncDesc * pFDesc;
6191 TRACE("(%p) index %d\n", This, indexFunc);
6192 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6193 pFDesc=pFDesc->next)
6195 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6196 pCustData->prgCustData =
6197 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6198 sizeof(CUSTDATAITEM));
6199 if(pCustData->prgCustData ){
6200 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6201 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6202 pCData; i++, pCData = pCData->next){
6203 pCustData->prgCustData[i].guid=pCData->guid;
6204 VariantCopy(& pCustData->prgCustData[i].varValue,
6208 ERR(" OUT OF MEMORY!\n");
6209 return E_OUTOFMEMORY;
6213 return TYPE_E_ELEMENTNOTFOUND;
6216 /* ITypeInfo2::GetAllVarCustData
6218 * Gets all custom data items for the specified Variable
6221 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6222 UINT index, CUSTDATA *pCustData)
6224 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6225 TLBCustData *pCData;
6226 TLBVarDesc * pVDesc;
6228 TRACE("(%p) index %d\n", This, index);
6229 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6230 pVDesc=pVDesc->next)
6233 pCustData->prgCustData =
6234 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6235 if(pCustData->prgCustData ){
6236 pCustData->cCustData=pVDesc->ctCustData;
6237 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6238 pCData = pCData->next){
6239 pCustData->prgCustData[i].guid=pCData->guid;
6240 VariantCopy(& pCustData->prgCustData[i].varValue,
6244 ERR(" OUT OF MEMORY!\n");
6245 return E_OUTOFMEMORY;
6249 return TYPE_E_ELEMENTNOTFOUND;
6252 /* ITypeInfo2::GetAllImplCustData
6254 * Gets all custom data items for the specified implementation type
6257 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6260 CUSTDATA *pCustData)
6262 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6263 TLBCustData *pCData;
6264 TLBImplType * pRDesc;
6266 TRACE("(%p) index %d\n", This, index);
6267 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6268 pRDesc=pRDesc->next)
6271 pCustData->prgCustData =
6272 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6273 if(pCustData->prgCustData ){
6274 pCustData->cCustData=pRDesc->ctCustData;
6275 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6276 pCData = pCData->next){
6277 pCustData->prgCustData[i].guid=pCData->guid;
6278 VariantCopy(& pCustData->prgCustData[i].varValue,
6282 ERR(" OUT OF MEMORY!\n");
6283 return E_OUTOFMEMORY;
6287 return TYPE_E_ELEMENTNOTFOUND;
6290 static const ITypeInfo2Vtbl tinfvt =
6293 ITypeInfo_fnQueryInterface,
6295 ITypeInfo_fnRelease,
6297 ITypeInfo_fnGetTypeAttr,
6298 ITypeInfo_fnGetTypeComp,
6299 ITypeInfo_fnGetFuncDesc,
6300 ITypeInfo_fnGetVarDesc,
6301 ITypeInfo_fnGetNames,
6302 ITypeInfo_fnGetRefTypeOfImplType,
6303 ITypeInfo_fnGetImplTypeFlags,
6304 ITypeInfo_fnGetIDsOfNames,
6306 ITypeInfo_fnGetDocumentation,
6307 ITypeInfo_fnGetDllEntry,
6308 ITypeInfo_fnGetRefTypeInfo,
6309 ITypeInfo_fnAddressOfMember,
6310 ITypeInfo_fnCreateInstance,
6311 ITypeInfo_fnGetMops,
6312 ITypeInfo_fnGetContainingTypeLib,
6313 ITypeInfo_fnReleaseTypeAttr,
6314 ITypeInfo_fnReleaseFuncDesc,
6315 ITypeInfo_fnReleaseVarDesc,
6317 ITypeInfo2_fnGetTypeKind,
6318 ITypeInfo2_fnGetTypeFlags,
6319 ITypeInfo2_fnGetFuncIndexOfMemId,
6320 ITypeInfo2_fnGetVarIndexOfMemId,
6321 ITypeInfo2_fnGetCustData,
6322 ITypeInfo2_fnGetFuncCustData,
6323 ITypeInfo2_fnGetParamCustData,
6324 ITypeInfo2_fnGetVarCustData,
6325 ITypeInfo2_fnGetImplTypeCustData,
6326 ITypeInfo2_fnGetDocumentation2,
6327 ITypeInfo2_fnGetAllCustData,
6328 ITypeInfo2_fnGetAllFuncCustData,
6329 ITypeInfo2_fnGetAllParamCustData,
6330 ITypeInfo2_fnGetAllVarCustData,
6331 ITypeInfo2_fnGetAllImplTypeCustData,
6334 /******************************************************************************
6335 * CreateDispTypeInfo [OLEAUT32.31]
6337 * Build type information for an object so it can be called through an
6338 * IDispatch interface.
6341 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6342 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6345 * This call allows an objects methods to be accessed through IDispatch, by
6346 * building an ITypeInfo object that IDispatch can use to call through.
6348 HRESULT WINAPI CreateDispTypeInfo(
6349 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6350 LCID lcid, /* [I] Locale Id */
6351 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6353 ITypeInfoImpl *pTIClass, *pTIIface;
6354 ITypeLibImpl *pTypeLibImpl;
6356 TLBFuncDesc **ppFuncDesc;
6359 pTypeLibImpl = TypeLibImpl_Constructor();
6360 if (!pTypeLibImpl) return E_FAIL;
6362 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6363 pTIIface->pTypeLib = pTypeLibImpl;
6364 pTIIface->index = 0;
6365 pTIIface->Name = NULL;
6366 pTIIface->dwHelpContext = -1;
6367 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6368 pTIIface->TypeAttr.lcid = lcid;
6369 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6370 pTIIface->TypeAttr.wMajorVerNum = 0;
6371 pTIIface->TypeAttr.wMinorVerNum = 0;
6372 pTIIface->TypeAttr.cbAlignment = 2;
6373 pTIIface->TypeAttr.cbSizeInstance = -1;
6374 pTIIface->TypeAttr.cbSizeVft = -1;
6375 pTIIface->TypeAttr.cFuncs = 0;
6376 pTIIface->TypeAttr.cImplTypes = 0;
6377 pTIIface->TypeAttr.cVars = 0;
6378 pTIIface->TypeAttr.wTypeFlags = 0;
6380 ppFuncDesc = &pTIIface->funclist;
6381 for(func = 0; func < pidata->cMembers; func++) {
6382 METHODDATA *md = pidata->pmethdata + func;
6383 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6384 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6385 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6386 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6387 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6388 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6389 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6390 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6391 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6392 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6393 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6394 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6395 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6396 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6397 md->cArgs * sizeof(ELEMDESC));
6398 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6399 md->cArgs * sizeof(TLBParDesc));
6400 for(param = 0; param < md->cArgs; param++) {
6401 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6402 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6404 (*ppFuncDesc)->helpcontext = 0;
6405 (*ppFuncDesc)->HelpStringContext = 0;
6406 (*ppFuncDesc)->HelpString = NULL;
6407 (*ppFuncDesc)->Entry = NULL;
6408 (*ppFuncDesc)->ctCustData = 0;
6409 (*ppFuncDesc)->pCustData = NULL;
6410 (*ppFuncDesc)->next = NULL;
6411 ppFuncDesc = &(*ppFuncDesc)->next;
6414 dump_TypeInfo(pTIIface);
6416 pTypeLibImpl->pTypeInfo = pTIIface;
6417 pTypeLibImpl->TypeInfoCount++;
6419 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6420 pTIClass->pTypeLib = pTypeLibImpl;
6421 pTIClass->index = 1;
6422 pTIClass->Name = NULL;
6423 pTIClass->dwHelpContext = -1;
6424 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6425 pTIClass->TypeAttr.lcid = lcid;
6426 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6427 pTIClass->TypeAttr.wMajorVerNum = 0;
6428 pTIClass->TypeAttr.wMinorVerNum = 0;
6429 pTIClass->TypeAttr.cbAlignment = 2;
6430 pTIClass->TypeAttr.cbSizeInstance = -1;
6431 pTIClass->TypeAttr.cbSizeVft = -1;
6432 pTIClass->TypeAttr.cFuncs = 0;
6433 pTIClass->TypeAttr.cImplTypes = 1;
6434 pTIClass->TypeAttr.cVars = 0;
6435 pTIClass->TypeAttr.wTypeFlags = 0;
6437 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6438 pTIClass->impltypelist->hRef = 1;
6440 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6441 pTIClass->reflist->index = 0;
6442 pTIClass->reflist->reference = 1;
6443 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6445 dump_TypeInfo(pTIClass);
6447 pTIIface->next = pTIClass;
6448 pTypeLibImpl->TypeInfoCount++;
6450 *pptinfo = (ITypeInfo*)pTIClass;
6455 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6457 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6459 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6462 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6464 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6466 return ITypeInfo_AddRef((ITypeInfo *)This);
6469 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6471 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6473 return ITypeInfo_Release((ITypeInfo *)This);
6476 static HRESULT WINAPI ITypeComp_fnBind(
6481 ITypeInfo ** ppTInfo,
6482 DESCKIND * pDescKind,
6485 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6486 const TLBFuncDesc *pFDesc;
6487 const TLBVarDesc *pVDesc;
6489 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6491 *pDescKind = DESCKIND_NONE;
6492 pBindPtr->lpfuncdesc = NULL;
6495 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6496 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6497 if (!strcmpW(pFDesc->Name, szName)) {
6503 HRESULT hr = TLB_AllocAndInitFuncDesc(
6505 &pBindPtr->lpfuncdesc,
6506 This->TypeAttr.typekind == TKIND_DISPATCH);
6509 *pDescKind = DESCKIND_FUNCDESC;
6510 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6511 ITypeInfo_AddRef(*ppTInfo);
6514 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6515 if (!strcmpW(pVDesc->Name, szName)) {
6516 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6519 *pDescKind = DESCKIND_VARDESC;
6520 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6521 ITypeInfo_AddRef(*ppTInfo);
6526 /* FIXME: search each inherited interface, not just the first */
6527 if (This->TypeAttr.cImplTypes) {
6528 /* recursive search */
6532 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6535 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6536 ITypeInfo_Release(pTInfo);
6540 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6541 ITypeComp_Release(pTComp);
6544 WARN("Could not search inherited interface!\n");
6546 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6547 return DISP_E_MEMBERNOTFOUND;
6550 static HRESULT WINAPI ITypeComp_fnBindType(
6554 ITypeInfo ** ppTInfo,
6555 ITypeComp ** ppTComp)
6557 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6559 /* strange behaviour (does nothing) but like the
6562 if (!ppTInfo || !ppTComp)
6571 static const ITypeCompVtbl tcompvt =
6574 ITypeComp_fnQueryInterface,
6576 ITypeComp_fnRelease,
6579 ITypeComp_fnBindType