4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
32 * So when you release the dispinterface, you delete the vtable-interface structures
33 * as well... fortunately, clean up of structures is not implemented.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
38 * - some garbage is read from function names on some very rare occasions.
40 * --------------------------------------------------------------------------------------
41 * Known problems left from previous implementation (1999, Rein Klazes) :
43 * -. Data structures are straightforward, but slow for look-ups.
44 * -. (related) nothing is hashed
45 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
46 * of them I don't know yet how to implement them.
47 * -. Most error return values are just guessed not checked with windows
49 * -. didn't bother with a c++ interface
50 * -. lousy fatal error handling
51 * -. some methods just return pointers to internal data structures, this is
52 * partly laziness, partly I want to check how windows does it.
57 #include "wine/port.h"
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
76 #include "wine/unicode.h"
79 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(ole);
83 WINE_DECLARE_DEBUG_CHANNEL(typelib);
85 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
86 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
88 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt);
89 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
91 /****************************************************************************
94 * Takes p_iVal (which is in little endian) and returns it
95 * in the host machine's byte order.
97 #ifdef WORDS_BIGENDIAN
98 static WORD FromLEWord(WORD p_iVal)
100 return (((p_iVal & 0x00FF) << 8) |
101 ((p_iVal & 0xFF00) >> 8));
105 static DWORD FromLEDWord(DWORD p_iVal)
107 return (((p_iVal & 0x000000FF) << 24) |
108 ((p_iVal & 0x0000FF00) << 8) |
109 ((p_iVal & 0x00FF0000) >> 8) |
110 ((p_iVal & 0xFF000000) >> 24));
113 #define FromLEWord(X) (X)
114 #define FromLEDWord(X) (X)
118 /****************************************************************************
121 * Fix byte order in any structure if necessary
123 #ifdef WORDS_BIGENDIAN
124 static void FromLEWords(void *p_Val, int p_iSize)
128 p_iSize /= sizeof(WORD);
131 *Val = FromLEWord(*Val);
138 static void FromLEDWords(void *p_Val, int p_iSize)
142 p_iSize /= sizeof(DWORD);
145 *Val = FromLEDWord(*Val);
151 #define FromLEWords(X,Y) /*nothing*/
152 #define FromLEDWords(X,Y) /*nothing*/
155 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
156 /* buffer must be at least 60 characters long */
157 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
159 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
160 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
162 memcpy( buffer, TypelibW, sizeof(TypelibW) );
163 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
164 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
168 /* get the path of an interface key, in the form "Interface\\<guid>" */
169 /* buffer must be at least 50 characters long */
170 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
172 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
174 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
175 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
179 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
180 /* buffer must be at least 16 characters long */
181 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
183 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
184 static const WCHAR win16W[] = {'w','i','n','1','6',0};
185 static const WCHAR win32W[] = {'w','i','n','3','2',0};
187 sprintfW( buffer, LcidFormatW, lcid );
190 case SYS_WIN16: strcatW( buffer, win16W ); break;
191 case SYS_WIN32: strcatW( buffer, win32W ); break;
193 TRACE("Typelib is for unsupported syskind %i\n", syskind);
199 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
202 /****************************************************************************
203 * QueryPathOfRegTypeLib [OLEAUT32.164]
205 * Gets the path to a registered type library.
208 * guid [I] referenced guid
209 * wMaj [I] major version
210 * wMin [I] minor version
212 * path [O] path of typelib
216 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
217 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
220 HRESULT WINAPI QueryPathOfRegTypeLib(
227 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
231 WCHAR Path[MAX_PATH];
234 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
236 get_typelib_key( guid, wMaj, wMin, buffer );
238 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
239 if (res == ERROR_FILE_NOT_FOUND)
241 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
242 return TYPE_E_LIBNOTREGISTERED;
244 else if (res != ERROR_SUCCESS)
246 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
247 return TYPE_E_REGISTRYACCESS;
252 LONG dwPathLen = sizeof(Path);
254 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
256 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
260 else if (myLCID == lcid)
262 /* try with sub-langid */
263 myLCID = SUBLANGID(lcid);
265 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
267 /* try with system langid */
277 *path = SysAllocString( Path );
282 TRACE_(typelib)("-- 0x%08lx\n", hr);
286 /******************************************************************************
287 * CreateTypeLib [OLEAUT32.160] creates a typelib
293 HRESULT WINAPI CreateTypeLib(
294 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
296 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
300 /******************************************************************************
301 * LoadTypeLib [OLEAUT32.161]
303 * Loads a type library
306 * szFile [I] Name of file to load from.
307 * pptLib [O] Pointer that receives ITypeLib object on success.
314 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
316 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
318 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
319 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
322 /******************************************************************************
323 * LoadTypeLibEx [OLEAUT32.183]
325 * Loads and optionally registers a type library
331 HRESULT WINAPI LoadTypeLibEx(
332 LPCOLESTR szFile, /* [in] Name of file to load from */
333 REGKIND regkind, /* [in] Specify kind of registration */
334 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
336 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
341 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
343 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
344 memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));
347 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
350 /* Look for a trailing '\\' followed by an index */
351 pIndexStr = strrchrW(szFile, '\\');
352 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
353 index = atoiW(pIndexStr);
354 memcpy(szFileCopy, szFile,
355 (pIndexStr - szFile - 1) * sizeof(WCHAR));
356 szFileCopy[pIndexStr - szFile - 1] = '\0';
357 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
359 return TYPE_E_CANTLOADLIBRARY;
360 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
361 return TYPE_E_CANTLOADLIBRARY;
365 TRACE("File %s index %d\n", debugstr_w(szPath), index);
367 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
372 case REGKIND_DEFAULT:
373 /* don't register typelibs supplied with full path. Experimentation confirms the following */
375 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
376 (szFile[0] && (szFile[1] == ':'))) break;
377 /* else fall-through */
379 case REGKIND_REGISTER:
380 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
382 IUnknown_Release(*pptLib);
390 TRACE(" returns %08lx\n",res);
394 /******************************************************************************
395 * LoadRegTypeLib [OLEAUT32.162]
397 * Loads a registered type library.
400 * rguid [I] GUID of the registered type library.
401 * wVerMajor [I] major version.
402 * wVerMinor [I] minor version.
403 * lcid [I] locale ID.
404 * ppTLib [O] pointer that receives an ITypeLib object on success.
408 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
411 HRESULT WINAPI LoadRegTypeLib(
419 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
423 res= LoadTypeLib(bstr, ppTLib);
427 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
433 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
434 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
435 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
436 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
437 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
438 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
440 /******************************************************************************
441 * RegisterTypeLib [OLEAUT32.163]
442 * Adds information about a type library to the System Registry
444 * Docs: ITypeLib FAR * ptlib
445 * Docs: OLECHAR FAR* szFullPath
446 * Docs: OLECHAR FAR* szHelpDir
452 HRESULT WINAPI RegisterTypeLib(
453 ITypeLib * ptlib, /* [in] Pointer to the library*/
454 OLECHAR * szFullPath, /* [in] full Path of the library*/
455 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
458 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
459 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
460 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
470 if (ptlib == NULL || szFullPath == NULL)
473 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
476 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
479 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
480 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
484 /* Set the human-readable name of the typelib */
485 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
487 if (RegSetValueExW(key, NULL, 0, REG_SZ,
488 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
496 /* Make up the name of the typelib path subkey */
497 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
499 /* Create the typelib path subkey */
500 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
501 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
503 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
504 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
512 /* Create the flags subkey */
513 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
514 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
516 /* FIXME: is %u correct? */
517 static const WCHAR formatW[] = {'%','u',0};
519 sprintfW(buf, formatW, attr->wLibFlags);
520 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
521 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
529 /* create the helpdir subkey */
530 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
531 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
533 BOOL freeHelpDir = FALSE;
536 /* if we created a new key, and helpDir was null, set the helpdir
537 to the directory which contains the typelib. However,
538 if we just opened an existing key, we leave the helpdir alone */
539 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
540 szHelpDir = SysAllocString(szFullPath);
541 pIndexStr = strrchrW(szHelpDir, '\\');
548 /* if we have an szHelpDir, set it! */
549 if (szHelpDir != NULL) {
550 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
551 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
557 if (freeHelpDir) SysFreeString(szHelpDir);
569 /* register OLE Automation-compatible interfaces for this typelib */
570 types = ITypeLib_GetTypeInfoCount(ptlib);
571 for (tidx=0; tidx<types; tidx++) {
572 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
573 LPOLESTR name = NULL;
574 ITypeInfo *tinfo = NULL;
576 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
579 case TKIND_INTERFACE:
580 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
581 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
585 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
586 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
590 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
595 TYPEATTR *tattr = NULL;
596 ITypeInfo_GetTypeAttr(tinfo, &tattr);
599 TRACE_(typelib)("guid=%s, flags=%04x (",
600 debugstr_guid(&tattr->guid),
603 if (TRACE_ON(typelib)) {
604 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
624 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
626 /* register interface<->typelib coupling */
627 get_interface_key( &tattr->guid, keyName );
628 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
629 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
632 RegSetValueExW(key, NULL, 0, REG_SZ,
633 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
635 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
636 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
637 RegSetValueExW(subKey, NULL, 0, REG_SZ,
638 (BYTE*)PSOA, sizeof PSOA);
642 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
643 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
644 RegSetValueExW(subKey, NULL, 0, REG_SZ,
645 (BYTE*)PSOA, sizeof PSOA);
649 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
650 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
653 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
654 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
656 StringFromGUID2(&attr->guid, buffer, 40);
657 RegSetValueExW(subKey, NULL, 0, REG_SZ,
658 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
659 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
660 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
661 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
669 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
672 ITypeInfo_Release(tinfo);
679 ITypeLib_ReleaseTLibAttr(ptlib, attr);
685 /******************************************************************************
686 * UnRegisterTypeLib [OLEAUT32.186]
687 * Removes information about a type library from the System Registry
694 HRESULT WINAPI UnRegisterTypeLib(
695 REFGUID libid, /* [in] Guid of the library */
696 WORD wVerMajor, /* [in] major version */
697 WORD wVerMinor, /* [in] minor version */
698 LCID lcid, /* [in] locale id */
701 BSTR tlibPath = NULL;
704 WCHAR subKeyName[50];
707 BOOL deleteOtherStuff;
710 TYPEATTR* typeAttr = NULL;
712 ITypeInfo* typeInfo = NULL;
713 ITypeLib* typeLib = NULL;
716 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
718 /* Create the path to the key */
719 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
721 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
723 TRACE("Unsupported syskind %i\n", syskind);
724 result = E_INVALIDARG;
728 /* get the path to the typelib on disk */
729 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
730 result = E_INVALIDARG;
734 /* Try and open the key to the type library. */
735 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
736 result = E_INVALIDARG;
740 /* Try and load the type library */
741 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
742 result = TYPE_E_INVALIDSTATE;
746 /* remove any types registered with this typelib */
747 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
748 for (i=0; i<numTypes; i++) {
749 /* get the kind of type */
750 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
754 /* skip non-interfaces, and get type info for the type */
755 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
758 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
761 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
765 /* the path to the type */
766 get_interface_key( &typeAttr->guid, subKeyName );
768 /* Delete its bits */
769 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
772 RegDeleteKeyW(subKey, ProxyStubClsidW);
773 RegDeleteKeyW(subKey, ProxyStubClsid32W);
774 RegDeleteKeyW(subKey, TypeLibW);
777 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
780 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
782 if (typeInfo) ITypeInfo_Release(typeInfo);
786 /* Now, delete the type library path subkey */
787 get_lcid_subkey( lcid, syskind, subKeyName );
788 RegDeleteKeyW(key, subKeyName);
789 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
790 RegDeleteKeyW(key, subKeyName);
792 /* check if there is anything besides the FLAGS/HELPDIR keys.
793 If there is, we don't delete them */
794 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
795 deleteOtherStuff = TRUE;
797 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
798 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
800 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
801 if (!strcmpW(subKeyName, FLAGSW)) continue;
802 if (!strcmpW(subKeyName, HELPDIRW)) continue;
803 deleteOtherStuff = FALSE;
807 /* only delete the other parts of the key if we're absolutely sure */
808 if (deleteOtherStuff) {
809 RegDeleteKeyW(key, FLAGSW);
810 RegDeleteKeyW(key, HELPDIRW);
814 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
815 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
816 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
820 if (tlibPath) SysFreeString(tlibPath);
821 if (typeLib) ITypeLib_Release(typeLib);
822 if (subKey) RegCloseKey(subKey);
823 if (key) RegCloseKey(key);
827 /*======================= ITypeLib implementation =======================*/
829 typedef struct tagTLBCustData
833 struct tagTLBCustData* next;
836 /* data structure for import typelibs */
837 typedef struct tagTLBImpLib
839 int offset; /* offset in the file (MSFT)
840 offset in nametable (SLTG)
841 just used to identify library while reading
843 GUID guid; /* libid */
844 BSTR name; /* name */
846 LCID lcid; /* lcid of imported typelib */
848 WORD wVersionMajor; /* major version number */
849 WORD wVersionMinor; /* minor version number */
851 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
852 NULL if not yet loaded */
853 struct tagTLBImpLib * next;
856 /* internal ITypeLib data */
857 typedef struct tagITypeLibImpl
859 const ITypeLib2Vtbl *lpVtbl;
860 const ITypeCompVtbl *lpVtblTypeComp;
862 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
864 /* strings can be stored in tlb as multibyte strings BUT they are *always*
865 * exported to the application as a UNICODE string.
871 unsigned long dwHelpContext;
872 int TypeInfoCount; /* nr of typeinfo's in librarry */
873 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
874 int ctCustData; /* number of items in cust data list */
875 TLBCustData * pCustData; /* linked list to cust data */
876 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
877 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
878 libary. Only used while read MSFT
881 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
882 struct tagITypeLibImpl *next, *prev;
887 static const ITypeLib2Vtbl tlbvt;
888 static const ITypeCompVtbl tlbtcvt;
890 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
892 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
895 /* ITypeLib methods */
896 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
897 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
899 /*======================= ITypeInfo implementation =======================*/
901 /* data for referenced types */
902 typedef struct tagTLBRefType
904 INT index; /* Type index for internal ref or for external ref
905 it the format is SLTG. -2 indicates to
908 GUID guid; /* guid of the referenced type */
909 /* if index == TLB_REF_USE_GUID */
911 HREFTYPE reference; /* The href of this ref */
912 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
913 TLB_REF_INTERNAL for internal refs
914 TLB_REF_NOT_FOUND for broken refs */
916 struct tagTLBRefType * next;
919 #define TLB_REF_USE_GUID -2
921 #define TLB_REF_INTERNAL (void*)-2
922 #define TLB_REF_NOT_FOUND (void*)-1
924 /* internal Parameter data */
925 typedef struct tagTLBParDesc
929 TLBCustData * pCustData; /* linked list to cust data */
932 /* internal Function data */
933 typedef struct tagTLBFuncDesc
935 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
936 BSTR Name; /* the name of this function */
937 TLBParDesc *pParamDesc; /* array with param names and custom data */
939 int HelpStringContext;
941 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
943 TLBCustData * pCustData; /* linked list to cust data; */
944 struct tagTLBFuncDesc * next;
947 /* internal Variable data */
948 typedef struct tagTLBVarDesc
950 VARDESC vardesc; /* lots of info on the variable and its attributes. */
951 BSTR Name; /* the name of this variable */
953 int HelpStringContext; /* FIXME: where? */
956 TLBCustData * pCustData;/* linked list to cust data; */
957 struct tagTLBVarDesc * next;
960 /* internal implemented interface data */
961 typedef struct tagTLBImplType
963 HREFTYPE hRef; /* hRef of interface */
964 int implflags; /* IMPLFLAG_*s */
966 TLBCustData * pCustData;/* linked list to custom data; */
967 struct tagTLBImplType *next;
970 /* internal TypeInfo data */
971 typedef struct tagITypeInfoImpl
973 const ITypeInfo2Vtbl *lpVtbl;
974 const ITypeCompVtbl *lpVtblTypeComp;
976 TYPEATTR TypeAttr ; /* _lots_ of type information. */
977 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
978 int index; /* index in this typelib; */
979 /* type libs seem to store the doc strings in ascii
980 * so why should we do it in unicode?
985 unsigned long dwHelpContext;
986 unsigned long dwHelpStringContext;
989 TLBFuncDesc * funclist; /* linked list with function descriptions */
992 TLBVarDesc * varlist; /* linked list with variable descriptions */
994 /* Implemented Interfaces */
995 TLBImplType * impltypelist;
997 TLBRefType * reflist;
999 TLBCustData * pCustData; /* linked list to cust data; */
1000 struct tagITypeInfoImpl * next;
1003 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1005 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1008 static const ITypeInfo2Vtbl tinfvt;
1009 static const ITypeCompVtbl tcompvt;
1011 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1013 typedef struct tagTLBContext
1015 unsigned int oStart; /* start of TLB in file */
1016 unsigned int pos; /* current pos */
1017 unsigned int length; /* total length */
1018 void *mapping; /* memory mapping */
1019 MSFT_SegDir * pTblDir;
1020 ITypeLibImpl* pLibInfo;
1024 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1029 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1030 if (pTD->vt & VT_RESERVED)
1031 szVarType += strlen(strcpy(szVarType, "reserved | "));
1032 if (pTD->vt & VT_BYREF)
1033 szVarType += strlen(strcpy(szVarType, "ref to "));
1034 if (pTD->vt & VT_ARRAY)
1035 szVarType += strlen(strcpy(szVarType, "array of "));
1036 if (pTD->vt & VT_VECTOR)
1037 szVarType += strlen(strcpy(szVarType, "vector of "));
1038 switch(pTD->vt & VT_TYPEMASK) {
1039 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1040 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1041 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1042 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1043 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1044 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1045 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1046 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1047 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1048 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1049 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1050 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1051 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1052 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1053 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1054 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1055 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1056 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1057 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1058 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1059 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1060 pTD->u.hreftype); break;
1061 case VT_PTR: sprintf(szVarType, "ptr to ");
1062 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1064 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1065 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1067 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1068 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1069 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1072 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1076 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1078 USHORT flags = edesc->u.paramdesc.wParamFlags;
1079 dump_TypeDesc(&edesc->tdesc,buf);
1080 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1081 MESSAGE("\t\tu.paramdesc.wParamFlags");
1082 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1083 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1084 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1085 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1086 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1087 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1088 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1089 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1090 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1092 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1094 MESSAGE("memid is %08lx\n",funcdesc->memid);
1095 for (i=0;i<funcdesc->cParams;i++) {
1096 MESSAGE("Param %d:\n",i);
1097 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1099 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1100 switch (funcdesc->funckind) {
1101 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1102 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1103 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1104 case FUNC_STATIC: MESSAGE("static");break;
1105 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1106 default: MESSAGE("unknown");break;
1108 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1109 switch (funcdesc->invkind) {
1110 case INVOKE_FUNC: MESSAGE("func");break;
1111 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1112 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1113 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1115 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1116 switch (funcdesc->callconv) {
1117 case CC_CDECL: MESSAGE("cdecl");break;
1118 case CC_PASCAL: MESSAGE("pascal");break;
1119 case CC_STDCALL: MESSAGE("stdcall");break;
1120 case CC_SYSCALL: MESSAGE("syscall");break;
1123 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1124 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1125 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1127 MESSAGE("\telemdescFunc (return value type):\n");
1128 dump_ELEMDESC(&funcdesc->elemdescFunc);
1131 static const char * typekind_desc[] =
1144 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1147 if (!TRACE_ON(typelib))
1149 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1150 for (i=0;i<pfd->funcdesc.cParams;i++)
1151 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1154 dump_FUNCDESC(&(pfd->funcdesc));
1156 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1157 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1159 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1163 dump_TLBFuncDescOne(pfd);
1167 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1171 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1176 static void dump_TLBImpLib(const TLBImpLib *import)
1178 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1179 debugstr_w(import->name));
1180 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1181 import->wVersionMinor, import->lcid, import->offset);
1184 static void dump_TLBRefType(const TLBRefType * prt)
1188 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1189 if(prt->index == -1)
1190 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1192 TRACE_(typelib)("type no: %d\n", prt->index);
1194 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1195 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1196 TRACE_(typelib)("in lib\n");
1197 dump_TLBImpLib(prt->pImpTLInfo);
1203 static void dump_TLBImplType(const TLBImplType * impl)
1207 "implementing/inheriting interface hRef = %lx implflags %x\n",
1208 impl->hRef, impl->implflags);
1213 void dump_Variant(const VARIANT * pvar)
1217 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1221 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1222 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1224 TRACE(",%p", V_BYREF(pvar));
1226 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1230 else switch (V_TYPE(pvar))
1232 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1233 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1234 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1235 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1237 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1239 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1240 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1241 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1242 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1243 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1244 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1245 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1246 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1247 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1248 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1249 V_CY(pvar).s.Lo); break;
1251 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1252 TRACE(",<invalid>");
1254 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1255 st.wHour, st.wMinute, st.wSecond);
1259 case VT_USERDEFINED:
1261 case VT_NULL: break;
1262 default: TRACE(",?"); break;
1268 static void dump_DispParms(const DISPPARAMS * pdp)
1272 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1274 while (index < pdp->cArgs)
1276 dump_Variant( &pdp->rgvarg[index] );
1281 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1283 TRACE("%p ref=%lu\n", pty, pty->ref);
1284 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1285 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1286 TRACE("fct:%u var:%u impl:%u\n",
1287 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1288 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1289 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1290 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1291 dump_TLBFuncDesc(pty->funclist);
1292 dump_TLBVarDesc(pty->varlist);
1293 dump_TLBImplType(pty->impltypelist);
1296 static void dump_VARDESC(const VARDESC *v)
1298 MESSAGE("memid %ld\n",v->memid);
1299 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1300 MESSAGE("oInst %ld\n",v->u.oInst);
1301 dump_ELEMDESC(&(v->elemdescVar));
1302 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1303 MESSAGE("varkind %d\n",v->varkind);
1306 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1308 /* VT_LPWSTR is largest type that */
1309 /* may appear in type description*/
1310 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1311 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1312 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1313 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1314 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1315 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1319 static void TLB_abort(void)
1323 static void * TLB_Alloc(unsigned size)
1326 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1328 ERR("cannot allocate memory\n");
1333 static void TLB_Free(void * ptr)
1335 HeapFree(GetProcessHeap(), 0, ptr);
1338 /* returns the size required for a deep copy of a typedesc into a
1340 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1344 if (alloc_initial_space)
1345 size += sizeof(TYPEDESC);
1351 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1354 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1355 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1361 /* deep copy a typedesc into a flat buffer */
1362 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1367 buffer = (char *)buffer + sizeof(TYPEDESC);
1376 dest->u.lptdesc = buffer;
1377 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1380 dest->u.lpadesc = buffer;
1381 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1382 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1383 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1389 /**********************************************************************
1391 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1394 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1396 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1397 pcx->pos, count, pcx->oStart, pcx->length, where);
1399 if (where != DO_NOT_SEEK)
1401 where += pcx->oStart;
1402 if (where > pcx->length)
1405 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1410 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1411 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1416 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1421 ret = MSFT_Read(buffer, count, pcx, where);
1422 FromLEDWords(buffer, ret);
1427 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1432 ret = MSFT_Read(buffer, count, pcx, where);
1433 FromLEWords(buffer, ret);
1438 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1440 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1441 memset(pGuid,0, sizeof(GUID));
1444 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1445 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1446 pGuid->Data2 = FromLEWord(pGuid->Data2);
1447 pGuid->Data3 = FromLEWord(pGuid->Data3);
1448 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1451 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1454 MSFT_NameIntro niName;
1456 WCHAR* pwstring = NULL;
1457 BSTR bstrName = NULL;
1461 ERR_(typelib)("bad offset %d\n", offset);
1464 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1465 pcx->pTblDir->pNametab.offset+offset);
1466 niName.namelen &= 0xFF; /* FIXME: correct ? */
1467 name=TLB_Alloc((niName.namelen & 0xff) +1);
1468 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1469 name[niName.namelen & 0xff]='\0';
1471 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1474 /* no invalid characters in string */
1477 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1479 /* don't check for invalid character since this has been done previously */
1480 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1482 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1483 lengthInChars = SysStringLen(bstrName);
1484 HeapFree(GetProcessHeap(), 0, pwstring);
1487 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1491 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1498 if(offset<0) return NULL;
1499 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1500 if(length <= 0) return 0;
1501 string=TLB_Alloc(length +1);
1502 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1503 string[length]='\0';
1505 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1506 string, -1, NULL, 0);
1508 /* no invalid characters in string */
1511 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1513 /* don't check for invalid character since this has been done previously */
1514 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1516 bstr = SysAllocStringLen(pwstring, lengthInChars);
1517 lengthInChars = SysStringLen(bstr);
1518 HeapFree(GetProcessHeap(), 0, pwstring);
1521 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1525 * read a value and fill a VARIANT structure
1527 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1531 TRACE_(typelib)("\n");
1533 if(offset <0) { /* data are packed in here */
1534 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1535 V_I4(pVar) = offset & 0x3ffffff;
1538 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1539 pcx->pTblDir->pCustData.offset + offset );
1540 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1541 switch (V_VT(pVar)){
1542 case VT_EMPTY: /* FIXME: is this right? */
1543 case VT_NULL: /* FIXME: is this right? */
1544 case VT_I2 : /* this should not happen */
1555 case VT_VOID : /* FIXME: is this right? */
1563 case VT_DECIMAL : /* FIXME: is this right? */
1566 /* pointer types with known behaviour */
1569 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1571 FIXME("BSTR length = %d?\n", size);
1573 ptr=TLB_Alloc(size);/* allocate temp buffer */
1574 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1575 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1576 /* FIXME: do we need a AtoW conversion here? */
1577 V_UNION(pVar, bstrVal[size])=L'\0';
1578 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1583 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1590 case VT_USERDEFINED :
1596 case VT_STREAMED_OBJECT :
1597 case VT_STORED_OBJECT :
1598 case VT_BLOB_OBJECT :
1603 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1607 if(size>0) /* (big|small) endian correct? */
1608 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1612 * create a linked list with custom data
1614 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1620 TRACE_(typelib)("\n");
1624 pNew=TLB_Alloc(sizeof(TLBCustData));
1625 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1626 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1627 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1628 /* add new custom data at head of the list */
1629 pNew->next=*ppCustData;
1631 offset = entry.next;
1636 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1640 pTd->vt=type & VT_TYPEMASK;
1642 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1644 if(pTd->vt == VT_USERDEFINED)
1645 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1647 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1651 MSFT_DoFuncs(TLBContext* pcx,
1656 TLBFuncDesc** pptfd)
1659 * member information is stored in a data structure at offset
1660 * indicated by the memoffset field of the typeinfo structure
1661 * There are several distinctive parts.
1662 * The first part starts with a field that holds the total length
1663 * of this (first) part excluding this field. Then follow the records,
1664 * for each member there is one record.
1666 * The first entry is always the length of the record (including this
1668 * The rest of the record depends on the type of the member. If there is
1669 * a field indicating the member type (function, variable, interface, etc)
1670 * I have not found it yet. At this time we depend on the information
1671 * in the type info and the usual order how things are stored.
1673 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1676 * Third is an equal sized array with file offsets to the name entry
1679 * The fourth and last (?) part is an array with offsets to the records
1680 * in the first part of this file segment.
1683 int infolen, nameoffset, reclength, nrattributes, i;
1684 int recoffset = offset + sizeof(INT);
1687 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1688 TLBFuncDesc *ptfd_prev = NULL;
1690 TRACE_(typelib)("\n");
1692 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1694 for ( i = 0; i < cFuncs ; i++ )
1696 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1698 /* name, eventually add to a hash table */
1699 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1700 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1702 /* nameoffset is sometimes -1 on the second half of a propget/propput
1703 * pair of functions */
1704 if ((nameoffset == -1) && (i > 0))
1705 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1707 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1709 /* read the function information record */
1710 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1714 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1716 /* do the attributes */
1717 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1720 if ( nrattributes > 0 )
1722 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1724 if ( nrattributes > 1 )
1726 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1727 pFuncRec->OptAttr[1]) ;
1729 if ( nrattributes > 2 )
1731 if ( pFuncRec->FKCCIC & 0x2000 )
1733 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1737 (*pptfd)->Entry = MSFT_ReadString(pcx,
1738 pFuncRec->OptAttr[2]);
1740 if( nrattributes > 5 )
1742 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1744 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1747 pFuncRec->OptAttr[6],
1748 &(*pptfd)->pCustData);
1755 /* fill the FuncDesc Structure */
1756 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1757 offset + infolen + ( i + 1) * sizeof(INT));
1759 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1760 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1761 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1762 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1763 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1764 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1765 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1769 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1772 /* do the parameters/arguments */
1773 if(pFuncRec->nrargs)
1776 MSFT_ParameterInfo paraminfo;
1778 (*pptfd)->funcdesc.lprgelemdescParam =
1779 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1781 (*pptfd)->pParamDesc =
1782 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1784 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1785 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1787 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1789 TYPEDESC *lpArgTypeDesc;
1790 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1797 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1800 if (paraminfo.oName == -1)
1801 /* this occurs for [propput] or [propget] methods, so
1802 * we should just set the name of the parameter to the
1803 * name of the method. */
1804 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1806 (*pptfd)->pParamDesc[j].Name =
1807 MSFT_ReadName( pcx, paraminfo.oName );
1808 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1810 lpArgTypeDesc = &elemdesc->tdesc;
1812 /* resolve referenced type if any */
1813 while ( lpArgTypeDesc != NULL )
1815 switch ( lpArgTypeDesc->vt )
1818 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1822 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1825 case VT_USERDEFINED:
1826 MSFT_DoRefType(pcx, pTI,
1827 lpArgTypeDesc->u.hreftype);
1829 lpArgTypeDesc = NULL;
1833 lpArgTypeDesc = NULL;
1838 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1839 (pFuncRec->FKCCIC & 0x1000) )
1841 INT* pInt = (INT *)((char *)pFuncRec +
1843 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1845 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1847 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1848 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1850 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1854 elemdesc->u.paramdesc.pparamdescex = NULL;
1856 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1859 pFuncRec->OptAttr[7+j],
1860 &(*pptfd)->pParamDesc[j].pCustData);
1863 /* SEEK value = jump to offset,
1864 * from there jump to the end of record,
1865 * go back by (j-1) arguments
1867 MSFT_ReadLEDWords( ¶minfo ,
1868 sizeof(MSFT_ParameterInfo), pcx,
1869 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1870 * sizeof(MSFT_ParameterInfo)));
1874 /* scode is not used: archaic win16 stuff FIXME: right? */
1875 (*pptfd)->funcdesc.cScodes = 0 ;
1876 (*pptfd)->funcdesc.lprgscode = NULL ;
1879 pptfd = & ((*pptfd)->next);
1880 recoffset += reclength;
1884 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1885 int cVars, int offset, TLBVarDesc ** pptvd)
1887 int infolen, nameoffset, reclength;
1889 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1893 TRACE_(typelib)("\n");
1895 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1896 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1897 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1898 recoffset += offset+sizeof(INT);
1899 for(i=0;i<cVars;i++){
1900 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1901 /* name, eventually add to a hash table */
1902 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1903 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1904 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1905 /* read the variable information record */
1906 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1908 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1910 if(reclength >(6*sizeof(INT)) )
1911 (*pptvd)->HelpContext=pVarRec->HelpContext;
1912 if(reclength >(7*sizeof(INT)) )
1913 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1914 if(reclength >(8*sizeof(INT)) )
1915 if(reclength >(9*sizeof(INT)) )
1916 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1917 /* fill the VarDesc Structure */
1918 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1919 offset + infolen + ( i + 1) * sizeof(INT));
1920 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1921 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1922 MSFT_GetTdesc(pcx, pVarRec->DataType,
1923 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1924 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1925 if(pVarRec->VarKind == VAR_CONST ){
1926 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1927 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1928 pVarRec->OffsValue, pcx);
1930 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1931 pptvd=&((*pptvd)->next);
1932 recoffset += reclength;
1935 /* fill in data for a hreftype (offset). When the referenced type is contained
1936 * in the typelib, it's just an (file) offset in the type info base dir.
1937 * If comes from import, it's an offset+1 in the ImpInfo table
1939 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1943 TLBRefType **ppRefType = &pTI->reflist;
1945 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1948 if((*ppRefType)->reference == offset)
1950 ppRefType = &(*ppRefType)->next;
1953 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1954 sizeof(**ppRefType));
1956 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1957 /* external typelib */
1958 MSFT_ImpInfo impinfo;
1959 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1961 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1963 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1964 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1965 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1966 if(pImpLib->offset==impinfo.oImpFile) break;
1967 pImpLib=pImpLib->next;
1970 (*ppRefType)->reference=offset;
1971 (*ppRefType)->pImpTLInfo = pImpLib;
1972 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1973 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1974 (*ppRefType)->index = TLB_REF_USE_GUID;
1976 (*ppRefType)->index = impinfo.oGuid;
1978 ERR("Cannot find a reference\n");
1979 (*ppRefType)->reference=-1;
1980 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1983 /* in this typelib */
1984 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1985 (*ppRefType)->reference=offset;
1986 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1990 /* process Implemented Interfaces of a com class */
1991 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
1995 MSFT_RefRecord refrec;
1996 TLBImplType **ppImpl = &pTI->impltypelist;
1998 TRACE_(typelib)("\n");
2000 for(i=0;i<count;i++){
2001 if(offset<0) break; /* paranoia */
2002 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2003 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2004 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2005 (*ppImpl)->hRef = refrec.reftype;
2006 (*ppImpl)->implflags=refrec.flags;
2007 (*ppImpl)->ctCustData=
2008 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2009 offset=refrec.onext;
2010 ppImpl=&((*ppImpl)->next);
2014 * process a typeinfo record
2016 static ITypeInfoImpl * MSFT_DoTypeInfo(
2019 ITypeLibImpl * pLibInfo)
2021 MSFT_TypeInfoBase tiBase;
2022 ITypeInfoImpl *ptiRet;
2024 TRACE_(typelib)("count=%u\n", count);
2026 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2027 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2028 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2030 /* this is where we are coming from */
2031 ptiRet->pTypeLib = pLibInfo;
2032 ptiRet->index=count;
2033 /* fill in the typeattr fields */
2034 WARN("Assign constructor/destructor memid\n");
2036 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2037 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2038 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2039 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2040 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2041 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2042 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2043 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2044 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2045 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2046 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2047 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2048 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2049 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2050 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2051 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2052 MSFT_GetTdesc(pcx, tiBase.datatype1,
2053 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2056 /* IDLDESC idldescType; *//* never saw this one != zero */
2058 /* name, eventually add to a hash table */
2059 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2060 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2062 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2063 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2064 ptiRet->dwHelpContext=tiBase.helpcontext;
2066 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2067 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2069 /* note: InfoType's Help file and HelpStringDll come from the containing
2070 * library. Further HelpString and Docstring appear to be the same thing :(
2073 if(ptiRet->TypeAttr.cFuncs >0 )
2074 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2075 ptiRet->TypeAttr.cVars,
2076 tiBase.memoffset, & ptiRet->funclist);
2078 if(ptiRet->TypeAttr.cVars >0 )
2079 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2080 ptiRet->TypeAttr.cVars,
2081 tiBase.memoffset, & ptiRet->varlist);
2082 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2083 switch(ptiRet->TypeAttr.typekind)
2086 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2089 case TKIND_DISPATCH:
2090 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2092 if (tiBase.datatype1 != -1)
2094 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2095 ptiRet->impltypelist->hRef = tiBase.datatype1;
2098 { /* FIXME: This is a really bad hack to add IDispatch */
2099 const char* szStdOle = "stdole2.tlb\0";
2100 int nStdOleLen = strlen(szStdOle);
2101 TLBRefType **ppRef = &ptiRet->reflist;
2104 if((*ppRef)->reference == -1)
2106 ppRef = &(*ppRef)->next;
2109 *ppRef = TLB_Alloc(sizeof(**ppRef));
2110 (*ppRef)->guid = IID_IDispatch;
2111 (*ppRef)->reference = -1;
2112 (*ppRef)->index = TLB_REF_USE_GUID;
2113 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2114 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2115 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2118 MultiByteToWideChar(CP_ACP,
2122 (*ppRef)->pImpTLInfo->name,
2123 SysStringLen((*ppRef)->pImpTLInfo->name));
2125 (*ppRef)->pImpTLInfo->lcid = 0;
2126 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2127 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2132 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2133 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2134 ptiRet->impltypelist->hRef = tiBase.datatype1;
2139 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2141 TRACE_(typelib)("%s guid: %s kind:%s\n",
2142 debugstr_w(ptiRet->Name),
2143 debugstr_guid(&ptiRet->TypeAttr.guid),
2144 typekind_desc[ptiRet->TypeAttr.typekind]);
2149 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2150 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2151 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2154 static ITypeLibImpl *tlb_cache_first;
2155 static CRITICAL_SECTION cache_section;
2156 static CRITICAL_SECTION_DEBUG cache_section_debug =
2158 0, 0, &cache_section,
2159 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2160 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2162 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2165 /****************************************************************************
2168 * find the type of the typelib file and map the typelib resource into
2171 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2172 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2173 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2175 ITypeLibImpl *entry;
2176 int ret = TYPE_E_CANTLOADLIBRARY;
2177 DWORD dwSignature = 0;
2180 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2184 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2185 EnterCriticalSection(&cache_section);
2186 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2188 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2190 TRACE("cache hit\n");
2191 *ppTypeLib = (ITypeLib2*)entry;
2192 ITypeLib_AddRef(*ppTypeLib);
2193 LeaveCriticalSection(&cache_section);
2197 LeaveCriticalSection(&cache_section);
2199 /* check the signature of the file */
2200 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2201 if (INVALID_HANDLE_VALUE != hFile)
2203 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2206 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2209 /* retrieve file size */
2210 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2212 /* first try to load as *.tlb */
2213 dwSignature = FromLEDWord(*((DWORD*) pBase));
2214 if ( dwSignature == MSFT_SIGNATURE)
2216 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2218 else if ( dwSignature == SLTG_SIGNATURE)
2220 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2222 UnmapViewOfFile(pBase);
2224 CloseHandle(hMapping);
2230 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2233 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2234 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2236 /* find the typelibrary resource*/
2237 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2238 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2241 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2242 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2245 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2248 LPVOID pBase = LockResource(hGlobal);
2249 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2253 /* try to load as incore resource */
2254 dwSignature = FromLEDWord(*((DWORD*) pBase));
2255 if ( dwSignature == MSFT_SIGNATURE)
2257 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2259 else if ( dwSignature == SLTG_SIGNATURE)
2261 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2265 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2268 FreeResource( hGlobal );
2271 FreeLibrary(hinstDLL);
2276 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2278 TRACE("adding to cache\n");
2279 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2280 lstrcpyW(impl->path, pszFileName);
2281 /* We should really canonicalise the path here. */
2282 impl->index = index;
2284 /* FIXME: check if it has added already in the meantime */
2285 EnterCriticalSection(&cache_section);
2286 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2288 tlb_cache_first = impl;
2289 LeaveCriticalSection(&cache_section);
2292 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2297 /*================== ITypeLib(2) Methods ===================================*/
2299 /****************************************************************************
2300 * ITypeLib2_Constructor_MSFT
2302 * loading an MSFT typelib from an in-memory image
2304 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2308 MSFT_Header tlbHeader;
2309 MSFT_SegDir tlbSegDir;
2310 ITypeLibImpl * pTypeLibImpl;
2312 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2314 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2315 if (!pTypeLibImpl) return NULL;
2317 pTypeLibImpl->lpVtbl = &tlbvt;
2318 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2319 pTypeLibImpl->ref = 1;
2321 /* get pointer to beginning of typelib data */
2325 cx.pLibInfo = pTypeLibImpl;
2326 cx.length = dwTLBLength;
2329 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2331 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2332 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2333 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2336 /* there is a small amount of information here until the next important
2338 * the segment directory . Try to calculate the amount of data */
2339 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2341 /* now read the segment directory */
2342 TRACE("read segment directory (at %ld)\n",lPSegDir);
2343 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2344 cx.pTblDir = &tlbSegDir;
2346 /* just check two entries */
2347 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2349 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2350 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2354 /* now fill our internal data */
2355 /* TLIBATTR fields */
2356 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2358 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2359 /* Windows seems to have zero here, is this correct? */
2360 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2361 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2363 pTypeLibImpl->LibAttr.lcid = 0;
2365 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2366 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2367 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2368 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2370 /* name, eventually add to a hash table */
2371 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2374 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2375 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2377 if( tlbHeader.varflags & HELPDLLFLAG)
2380 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2381 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2384 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2387 if(tlbHeader.CustomDataOffset >= 0)
2389 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2392 /* fill in typedescriptions */
2393 if(tlbSegDir.pTypdescTab.length > 0)
2395 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2397 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2398 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2401 /* FIXME: add several sanity checks here */
2402 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2403 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2405 /* FIXME: check safearray */
2407 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2409 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2411 else if(td[0] == VT_CARRAY)
2413 /* array descr table here */
2414 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2416 else if(td[0] == VT_USERDEFINED)
2418 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2420 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2423 /* second time around to fill the array subscript info */
2426 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2427 if(tlbSegDir.pArrayDescriptions.offset>0)
2429 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2430 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2433 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2435 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2437 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2439 for(j = 0; j<td[2]; j++)
2441 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2442 sizeof(INT), &cx, DO_NOT_SEEK);
2443 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2444 sizeof(INT), &cx, DO_NOT_SEEK);
2449 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2450 ERR("didn't find array description data\n");
2455 /* imported type libs */
2456 if(tlbSegDir.pImpFiles.offset>0)
2458 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2459 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2462 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2467 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2468 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2469 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2471 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2472 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2473 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2474 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2477 name = TLB_Alloc(size+1);
2478 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2479 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2480 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2481 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2484 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2485 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2487 ppImpLib = &(*ppImpLib)->next;
2492 if(tlbHeader.nrtypeinfos >= 0 )
2494 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2495 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2498 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2500 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2502 ppTI = &((*ppTI)->next);
2503 (pTypeLibImpl->TypeInfoCount)++;
2507 TRACE("(%p)\n", pTypeLibImpl);
2508 return (ITypeLib2*) pTypeLibImpl;
2512 static BSTR TLB_MultiByteToBSTR(char *ptr)
2518 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2519 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2520 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2521 ret = SysAllocString(nameW);
2522 HeapFree(GetProcessHeap(), 0, nameW);
2526 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2532 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2533 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2537 guid->Data4[0] = s >> 8;
2538 guid->Data4[1] = s & 0xff;
2541 for(i = 0; i < 6; i++) {
2542 memcpy(b, str + 24 + 2 * i, 2);
2543 guid->Data4[i + 2] = strtol(b, NULL, 16);
2548 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2555 bytelen = *(WORD*)ptr;
2556 if(bytelen == 0xffff) return 2;
2557 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2558 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2559 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2560 *pBstr = SysAllocStringLen(nameW, len);
2561 HeapFree(GetProcessHeap(), 0, nameW);
2565 static WORD SLTG_ReadStringA(char *ptr, char **str)
2570 bytelen = *(WORD*)ptr;
2571 if(bytelen == 0xffff) return 2;
2572 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2573 memcpy(*str, ptr + 2, bytelen);
2574 (*str)[bytelen] = '\0';
2578 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2580 char *ptr = pLibBlk;
2583 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2584 FIXME("libblk magic = %04x\n", w);
2589 if((w = *(WORD*)ptr) != 0xffff) {
2590 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2595 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2597 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2599 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2602 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2605 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2606 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2608 pTypeLibImpl->LibAttr.lcid = 0;
2611 ptr += 4; /* skip res12 */
2613 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2616 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2619 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2622 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2623 ptr += sizeof(GUID);
2625 return ptr - (char*)pLibBlk;
2628 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2631 TYPEDESC *pTD = &pElem->tdesc;
2633 /* Handle [in/out] first */
2634 if((*pType & 0xc000) == 0xc000)
2635 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2636 else if(*pType & 0x8000)
2637 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2638 else if(*pType & 0x4000)
2639 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2641 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2644 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2647 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2650 if((*pType & 0xe00) == 0xe00) {
2652 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2654 pTD = pTD->u.lptdesc;
2656 switch(*pType & 0x7f) {
2659 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2661 pTD = pTD->u.lptdesc;
2664 case VT_USERDEFINED:
2665 pTD->vt = VT_USERDEFINED;
2666 pTD->u.hreftype = *(++pType) / 4;
2672 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2675 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2677 pTD->vt = VT_CARRAY;
2678 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2680 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2681 pTD->u.lpadesc->cDims = pSA->cDims;
2682 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2683 pSA->cDims * sizeof(SAFEARRAYBOUND));
2685 pTD = &pTD->u.lpadesc->tdescElem;
2691 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2695 pTD->vt = VT_SAFEARRAY;
2696 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2698 pTD = pTD->u.lptdesc;
2702 pTD->vt = *pType & 0x7f;
2712 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2717 TLBRefType **ppRefType;
2719 if(pRef->magic != SLTG_REF_MAGIC) {
2720 FIXME("Ref magic = %x\n", pRef->magic);
2723 name = ( (char*)(&pRef->names) + pRef->number);
2725 ppRefType = &pTI->reflist;
2726 for(ref = 0; ref < pRef->number >> 3; ref++) {
2728 unsigned int lib_offs, type_num;
2730 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2731 sizeof(**ppRefType));
2733 name += SLTG_ReadStringA(name, &refname);
2734 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2735 FIXME("Can't sscanf ref\n");
2736 if(lib_offs != 0xffff) {
2737 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2740 if((*import)->offset == lib_offs)
2742 import = &(*import)->next;
2745 char fname[MAX_PATH+1];
2748 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2750 (*import)->offset = lib_offs;
2751 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2753 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2754 &(*import)->wVersionMajor,
2755 &(*import)->wVersionMinor,
2756 &(*import)->lcid, fname) != 4) {
2757 FIXME("can't sscanf ref %s\n",
2758 pNameTable + lib_offs + 40);
2760 len = strlen(fname);
2761 if(fname[len-1] != '#')
2762 FIXME("fname = %s\n", fname);
2763 fname[len-1] = '\0';
2764 (*import)->name = TLB_MultiByteToBSTR(fname);
2766 (*ppRefType)->pImpTLInfo = *import;
2767 } else { /* internal ref */
2768 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2770 (*ppRefType)->reference = ref;
2771 (*ppRefType)->index = type_num;
2773 HeapFree(GetProcessHeap(), 0, refname);
2774 ppRefType = &(*ppRefType)->next;
2776 if((BYTE)*name != SLTG_REF_MAGIC)
2777 FIXME("End of ref block magic = %x\n", *name);
2778 dump_TLBRefType(pTI->reflist);
2781 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2784 SLTG_ImplInfo *info;
2785 TLBImplType **ppImplType = &pTI->impltypelist;
2786 /* I don't really get this structure, usually it's 0x16 bytes
2787 long, but iuser.tlb contains some that are 0x18 bytes long.
2788 That's ok because we can use the next ptr to jump to the next
2789 one. But how do we know the length of the last one? The WORD
2790 at offs 0x8 might be the clue. For now I'm just assuming that
2791 the last one is the regular 0x16 bytes. */
2793 info = (SLTG_ImplInfo*)pBlk;
2795 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2796 sizeof(**ppImplType));
2797 (*ppImplType)->hRef = info->ref;
2798 (*ppImplType)->implflags = info->impltypeflags;
2799 pTI->TypeAttr.cImplTypes++;
2800 ppImplType = &(*ppImplType)->next;
2802 if(info->next == 0xffff)
2805 FIXME("Interface inheriting more than one interface\n");
2806 info = (SLTG_ImplInfo*)(pBlk + info->next);
2808 info++; /* see comment at top of function */
2812 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2815 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2816 SLTG_MemberHeader *pMemHeader;
2817 char *pFirstItem, *pNextItem;
2819 if(pTIHeader->href_table != 0xffffffff) {
2820 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2825 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2827 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2829 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2830 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2833 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2837 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2840 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2841 SLTG_MemberHeader *pMemHeader;
2842 SLTG_Function *pFunc;
2843 char *pFirstItem, *pNextItem;
2844 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2847 if(pTIHeader->href_table != 0xffffffff) {
2848 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2852 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2854 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2856 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2857 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2860 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2861 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2866 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2867 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2868 FIXME("func magic = %02x\n", pFunc->magic);
2871 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2872 sizeof(**ppFuncDesc));
2873 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2875 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2876 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2877 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2878 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2879 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2880 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2882 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2883 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2885 if(pFunc->retnextopt & 0x80)
2886 pType = &pFunc->rettype;
2888 pType = (WORD*)(pFirstItem + pFunc->rettype);
2891 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2893 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2894 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2895 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2896 (*ppFuncDesc)->pParamDesc =
2897 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2898 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2900 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2902 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2903 char *paramName = pNameTable + *pArg;
2905 /* If arg type follows then paramName points to the 2nd
2906 letter of the name, else the next WORD is an offset to
2907 the arg type and paramName points to the first letter.
2908 So let's take one char off paramName and see if we're
2909 pointing at an alpha-numeric char. However if *pArg is
2910 0xffff or 0xfffe then the param has no name, the former
2911 meaning that the next WORD is the type, the latter
2912 meaning the the next WORD is an offset to the type. */
2917 else if(*pArg == 0xfffe) {
2921 else if(paramName[-1] && !isalnum(paramName[-1]))
2926 if(HaveOffs) { /* the next word is an offset to type */
2927 pType = (WORD*)(pFirstItem + *pArg);
2928 SLTG_DoType(pType, pFirstItem,
2929 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2934 pArg = SLTG_DoType(pArg, pFirstItem,
2935 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2938 /* Are we an optional param ? */
2939 if((*ppFuncDesc)->funcdesc.cParams - param <=
2940 (*ppFuncDesc)->funcdesc.cParamsOpt)
2941 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2944 (*ppFuncDesc)->pParamDesc[param].Name =
2945 TLB_MultiByteToBSTR(paramName);
2949 ppFuncDesc = &((*ppFuncDesc)->next);
2950 if(pFunc->next == 0xffff) break;
2952 pTI->TypeAttr.cFuncs = num;
2953 dump_TLBFuncDesc(pTI->funclist);
2954 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2957 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2960 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2961 SLTG_MemberHeader *pMemHeader;
2962 SLTG_RecordItem *pItem;
2964 TLBVarDesc **ppVarDesc = &pTI->varlist;
2969 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2971 pFirstItem = (char*)(pMemHeader + 1);
2972 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2973 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2974 if(pItem->magic != SLTG_RECORD_MAGIC) {
2975 FIXME("record magic = %02x\n", pItem->magic);
2978 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2979 sizeof(**ppVarDesc));
2980 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2981 (*ppVarDesc)->vardesc.memid = pItem->memid;
2982 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2983 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2985 if(pItem->typepos == 0x02)
2986 pType = &pItem->type;
2987 else if(pItem->typepos == 0x00)
2988 pType = (WORD*)(pFirstItem + pItem->type);
2990 FIXME("typepos = %02x\n", pItem->typepos);
2994 SLTG_DoType(pType, pFirstItem,
2995 &(*ppVarDesc)->vardesc.elemdescVar);
2997 /* FIXME("helpcontext, helpstring\n"); */
2999 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3001 ppVarDesc = &((*ppVarDesc)->next);
3002 if(pItem->next == 0xffff) break;
3004 pTI->TypeAttr.cVars = num;
3005 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3008 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3011 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3012 SLTG_MemberHeader *pMemHeader;
3013 SLTG_AliasItem *pItem;
3016 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3017 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3020 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3021 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3022 if (pItem->vt == 0xffff) {
3023 if (i<(pMemHeader->cbExtra/4-1))
3024 FIXME("Endmarker too early in process alias data!\n");
3028 FIXME("Chain extends over last entry?\n");
3031 if (pItem->vt == VT_USERDEFINED) {
3032 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3033 /* guessing here ... */
3034 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3035 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3038 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3039 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3043 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3046 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3049 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3050 SLTG_MemberHeader *pMemHeader;
3051 SLTG_AliasItem *pItem;
3053 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3054 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3055 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3056 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3057 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3060 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3063 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3064 SLTG_MemberHeader *pMemHeader;
3065 SLTG_EnumItem *pItem;
3067 TLBVarDesc **ppVarDesc = &pTI->varlist;
3070 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3072 pFirstItem = (char*)(pMemHeader + 1);
3073 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3074 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3075 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3076 FIXME("enumitem magic = %04x\n", pItem->magic);
3079 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3080 sizeof(**ppVarDesc));
3081 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3082 (*ppVarDesc)->vardesc.memid = pItem->memid;
3083 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3085 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3086 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3087 *(INT*)(pItem->value + pFirstItem);
3088 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3089 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3090 /* FIXME("helpcontext, helpstring\n"); */
3092 ppVarDesc = &((*ppVarDesc)->next);
3093 if(pItem->next == 0xffff) break;
3095 pTI->TypeAttr.cVars = num;
3096 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3099 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3100 managable copy of it into this */
3113 } SLTG_InternalOtherTypeInfo;
3115 /****************************************************************************
3116 * ITypeLib2_Constructor_SLTG
3118 * loading a SLTG typelib from an in-memory image
3120 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3122 ITypeLibImpl *pTypeLibImpl;
3123 SLTG_Header *pHeader;
3124 SLTG_BlkEntry *pBlkEntry;
3128 LPVOID pBlk, pFirstBlk;
3129 SLTG_LibBlk *pLibBlk;
3130 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3131 char *pAfterOTIBlks = NULL;
3132 char *pNameTable, *ptr;
3135 ITypeInfoImpl **ppTypeInfoImpl;
3137 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3139 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3140 if (!pTypeLibImpl) return NULL;
3142 pTypeLibImpl->lpVtbl = &tlbvt;
3143 pTypeLibImpl->ref = 1;
3147 TRACE_(typelib)("header:\n");
3148 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3149 pHeader->nrOfFileBlks );
3150 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3151 FIXME("Header type magic 0x%08lx not supported.\n",
3152 pHeader->SLTG_magic);
3156 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3157 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3159 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3160 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3162 /* Next we have a magic block */
3163 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3165 /* Let's see if we're still in sync */
3166 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3167 sizeof(SLTG_COMPOBJ_MAGIC))) {
3168 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3171 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3172 sizeof(SLTG_DIR_MAGIC))) {
3173 FIXME("dir magic = %s\n", pMagic->dir_magic);
3177 pIndex = (SLTG_Index*)(pMagic+1);
3179 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3181 pFirstBlk = (LPVOID)(pPad9 + 1);
3183 /* We'll set up a ptr to the main library block, which is the last one. */
3185 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3186 pBlkEntry[order].next != 0;
3187 order = pBlkEntry[order].next - 1, i++) {
3188 pBlk = (char*)pBlk + pBlkEntry[order].len;
3192 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3194 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3199 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3201 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3202 sizeof(*pOtherTypeInfoBlks) *
3203 pTypeLibImpl->TypeInfoCount);
3206 ptr = (char*)pLibBlk + len;
3208 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3212 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3214 w = *(WORD*)(ptr + 2);
3217 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3219 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3220 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3222 w = *(WORD*)(ptr + 4 + len);
3224 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3226 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3228 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3229 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3231 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3232 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3233 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3235 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3237 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3240 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3241 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3242 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3243 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3244 len += sizeof(SLTG_OtherTypeInfo);
3248 pAfterOTIBlks = ptr;
3250 /* Skip this WORD and get the next DWORD */
3251 len = *(DWORD*)(pAfterOTIBlks + 2);
3253 /* Now add this to pLibBLk look at what we're pointing at and
3254 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3255 dust and we should be pointing at the beginning of the name
3258 pNameTable = (char*)pLibBlk + len;
3260 switch(*(WORD*)pNameTable) {
3267 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3271 pNameTable += 0x216;
3275 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3277 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3280 /* Hopefully we now have enough ptrs set up to actually read in
3281 some TypeInfos. It's not clear which order to do them in, so
3282 I'll just follow the links along the BlkEntry chain and read
3283 them in in the order in which they're in the file */
3285 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3287 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3288 pBlkEntry[order].next != 0;
3289 order = pBlkEntry[order].next - 1, i++) {
3291 SLTG_TypeInfoHeader *pTIHeader;
3292 SLTG_TypeInfoTail *pTITail;
3294 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3295 pOtherTypeInfoBlks[i].index_name)) {
3296 FIXME("Index strings don't match\n");
3301 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3302 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3305 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3306 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3307 (*ppTypeInfoImpl)->index = i;
3308 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3309 pOtherTypeInfoBlks[i].name_offs +
3311 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3312 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3314 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3315 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3316 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3317 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3318 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3320 if((pTIHeader->typeflags1 & 7) != 2)
3321 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3322 if(pTIHeader->typeflags3 != 2)
3323 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3325 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3326 debugstr_w((*ppTypeInfoImpl)->Name),
3327 typekind_desc[pTIHeader->typekind],
3328 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3329 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3331 switch(pTIHeader->typekind) {
3333 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3337 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3340 case TKIND_INTERFACE:
3341 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3345 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3349 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3350 if (pTITail->tdescalias_vt)
3351 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3354 case TKIND_DISPATCH:
3355 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3359 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3365 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3366 but we've already set those */
3367 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3368 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3369 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3371 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3393 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3394 pBlk = (char*)pBlk + pBlkEntry[order].len;
3397 if(i != pTypeLibImpl->TypeInfoCount) {
3398 FIXME("Somehow processed %d TypeInfos\n", i);
3402 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3403 return (ITypeLib2*)pTypeLibImpl;
3406 /* ITypeLib::QueryInterface
3408 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3413 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3415 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3418 if(IsEqualIID(riid, &IID_IUnknown) ||
3419 IsEqualIID(riid,&IID_ITypeLib)||
3420 IsEqualIID(riid,&IID_ITypeLib2))
3427 ITypeLib2_AddRef(iface);
3428 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3431 TRACE("-- Interface: E_NOINTERFACE\n");
3432 return E_NOINTERFACE;
3437 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3439 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3440 ULONG ref = InterlockedIncrement(&This->ref);
3442 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3447 /* ITypeLib::Release
3449 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3451 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3452 ULONG ref = InterlockedDecrement(&This->ref);
3454 TRACE("(%p)->(%lu)\n",This, ref);
3458 /* remove cache entry */
3459 TRACE("removing from cache list\n");
3460 EnterCriticalSection(&cache_section);
3461 if (This->next) This->next->prev = This->prev;
3462 if (This->prev) This->prev->next = This->next;
3463 else tlb_cache_first = This->next;
3464 LeaveCriticalSection(&cache_section);
3466 /* FIXME destroy child objects */
3467 TRACE(" destroying ITypeLib(%p)\n",This);
3471 SysFreeString(This->Name);
3475 if (This->DocString)
3477 SysFreeString(This->DocString);
3478 This->DocString = NULL;
3483 SysFreeString(This->HelpFile);
3484 This->HelpFile = NULL;
3487 if (This->HelpStringDll)
3489 SysFreeString(This->HelpStringDll);
3490 This->HelpStringDll = NULL;
3493 if (This->pTypeInfo) /* can be NULL */
3494 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3495 HeapFree(GetProcessHeap(),0,This);
3502 /* ITypeLib::GetTypeInfoCount
3504 * Returns the number of type descriptions in the type library
3506 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3508 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3509 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3510 return This->TypeInfoCount;
3513 /* ITypeLib::GetTypeInfo
3515 * retrieves the specified type description in the library.
3517 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3520 ITypeInfo **ppTInfo)
3524 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3525 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3527 TRACE("(%p)->(index=%d)\n", This, index);
3529 if (!ppTInfo) return E_INVALIDARG;
3531 /* search element n in list */
3532 for(i=0; i < index; i++)
3534 pTypeInfo = pTypeInfo->next;
3537 TRACE("-- element not found\n");
3538 return TYPE_E_ELEMENTNOTFOUND;
3542 *ppTInfo = (ITypeInfo *) pTypeInfo;
3544 ITypeInfo_AddRef(*ppTInfo);
3545 TRACE("-- found (%p)\n",*ppTInfo);
3550 /* ITypeLibs::GetTypeInfoType
3552 * Retrieves the type of a type description.
3554 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3559 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3561 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3563 TRACE("(%p) index %d\n", This, index);
3565 if(!pTKind) return E_INVALIDARG;
3567 /* search element n in list */
3568 for(i=0; i < index; i++)
3572 TRACE("-- element not found\n");
3573 return TYPE_E_ELEMENTNOTFOUND;
3575 pTInfo = pTInfo->next;
3578 *pTKind = pTInfo->TypeAttr.typekind;
3579 TRACE("-- found Type (%d)\n", *pTKind);
3583 /* ITypeLib::GetTypeInfoOfGuid
3585 * Retrieves the type description that corresponds to the specified GUID.
3588 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3591 ITypeInfo **ppTInfo)
3593 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3594 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3596 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3598 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3600 /* search linked list for guid */
3601 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3603 pTypeInfo = pTypeInfo->next;
3607 /* end of list reached */
3608 TRACE("-- element not found\n");
3609 return TYPE_E_ELEMENTNOTFOUND;
3613 TRACE("-- found (%p, %s)\n",
3615 debugstr_w(pTypeInfo->Name));
3617 *ppTInfo = (ITypeInfo*)pTypeInfo;
3618 ITypeInfo_AddRef(*ppTInfo);
3622 /* ITypeLib::GetLibAttr
3624 * Retrieves the structure that contains the library's attributes.
3627 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3629 LPTLIBATTR *ppTLibAttr)
3631 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3632 TRACE("(%p)\n",This);
3633 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3634 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3638 /* ITypeLib::GetTypeComp
3640 * Enables a client compiler to bind to a library's types, variables,
3641 * constants, and global functions.
3644 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3646 ITypeComp **ppTComp)
3648 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3650 TRACE("(%p)->(%p)\n",This,ppTComp);
3651 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3652 ITypeComp_AddRef(*ppTComp);
3657 /* ITypeLib::GetDocumentation
3659 * Retrieves the library's documentation string, the complete Help file name
3660 * and path, and the context identifier for the library Help topic in the Help
3663 * On a successful return all non-null BSTR pointers will have been set,
3666 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3670 BSTR *pBstrDocString,
3671 DWORD *pdwHelpContext,
3672 BSTR *pBstrHelpFile)
3674 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3676 HRESULT result = E_INVALIDARG;
3681 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3683 pBstrName, pBstrDocString,
3684 pdwHelpContext, pBstrHelpFile);
3688 /* documentation for the typelib */
3693 if(!(*pBstrName = SysAllocString(This->Name)))
3701 if (This->DocString)
3703 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3706 else if (This->Name)
3708 if(!(*pBstrDocString = SysAllocString(This->Name)))
3712 *pBstrDocString = NULL;
3716 *pdwHelpContext = This->dwHelpContext;
3722 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3726 *pBstrHelpFile = NULL;
3733 /* for a typeinfo */
3734 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3736 if(SUCCEEDED(result))
3738 result = ITypeInfo_GetDocumentation(pTInfo,
3742 pdwHelpContext, pBstrHelpFile);
3744 ITypeInfo_Release(pTInfo);
3749 if (pBstrDocString) SysFreeString (*pBstrDocString);
3751 if (pBstrName) SysFreeString (*pBstrName);
3753 return STG_E_INSUFFICIENTMEMORY;
3758 * Indicates whether a passed-in string contains the name of a type or member
3759 * described in the library.
3762 static HRESULT WINAPI ITypeLib2_fnIsName(
3768 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3769 ITypeInfoImpl *pTInfo;
3770 TLBFuncDesc *pFInfo;
3773 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3775 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3779 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3780 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3781 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3782 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3783 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3784 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3785 goto ITypeLib2_fnIsName_exit;
3787 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3788 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3793 ITypeLib2_fnIsName_exit:
3794 TRACE("(%p)slow! search for %s: %s found!\n", This,
3795 debugstr_w(szNameBuf), *pfName?"NOT":"");
3800 /* ITypeLib::FindName
3802 * Finds occurrences of a type description in a type library. This may be used
3803 * to quickly verify that a name exists in a type library.
3806 static HRESULT WINAPI ITypeLib2_fnFindName(
3810 ITypeInfo **ppTInfo,
3814 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3815 ITypeInfoImpl *pTInfo;
3816 TLBFuncDesc *pFInfo;
3819 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3821 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3822 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3823 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3824 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3825 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3826 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3827 goto ITypeLib2_fnFindName_exit;
3830 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3831 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3833 ITypeLib2_fnFindName_exit:
3834 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3835 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3838 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3839 This, *pcFound, debugstr_w(szNameBuf), j);
3846 /* ITypeLib::ReleaseTLibAttr
3848 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3851 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3853 TLIBATTR *pTLibAttr)
3855 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3856 TRACE("freeing (%p)\n",This);
3857 HeapFree(GetProcessHeap(),0,pTLibAttr);
3861 /* ITypeLib2::GetCustData
3863 * gets the custom data
3865 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3870 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3871 TLBCustData *pCData;
3873 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3875 if( IsEqualIID(guid, &pCData->guid)) break;
3878 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3882 VariantInit( pVarVal);
3883 VariantCopy( pVarVal, &pCData->data);
3886 return E_INVALIDARG; /* FIXME: correct? */
3889 /* ITypeLib2::GetLibStatistics
3891 * Returns statistics about a type library that are required for efficient
3892 * sizing of hash tables.
3895 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3897 ULONG *pcUniqueNames,
3898 ULONG *pcchUniqueNames)
3900 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3902 FIXME("(%p): stub!\n", This);
3904 if(pcUniqueNames) *pcUniqueNames=1;
3905 if(pcchUniqueNames) *pcchUniqueNames=1;
3909 /* ITypeLib2::GetDocumentation2
3911 * Retrieves the library's documentation string, the complete Help file name
3912 * and path, the localization context to use, and the context ID for the
3913 * library Help topic in the Help file.
3916 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3920 BSTR *pbstrHelpString,
3921 DWORD *pdwHelpStringContext,
3922 BSTR *pbstrHelpStringDll)
3924 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3928 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3930 /* the help string should be obtained from the helpstringdll,
3931 * using the _DLLGetDocumentation function, based on the supplied
3932 * lcid. Nice to do sometime...
3936 /* documentation for the typelib */
3938 *pbstrHelpString=SysAllocString(This->DocString);
3939 if(pdwHelpStringContext)
3940 *pdwHelpStringContext=This->dwHelpContext;
3941 if(pbstrHelpStringDll)
3942 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3948 /* for a typeinfo */
3949 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3951 if(SUCCEEDED(result))
3953 ITypeInfo2 * pTInfo2;
3954 result = ITypeInfo_QueryInterface(pTInfo,
3956 (LPVOID*) &pTInfo2);
3958 if(SUCCEEDED(result))
3960 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3964 pdwHelpStringContext,
3965 pbstrHelpStringDll);
3967 ITypeInfo2_Release(pTInfo2);
3970 ITypeInfo_Release(pTInfo);
3976 /* ITypeLib2::GetAllCustData
3978 * Gets all custom data items for the library.
3981 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3983 CUSTDATA *pCustData)
3985 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3986 TLBCustData *pCData;
3988 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3989 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3990 if(pCustData->prgCustData ){
3991 pCustData->cCustData=This->ctCustData;
3992 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3993 pCustData->prgCustData[i].guid=pCData->guid;
3994 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3997 ERR(" OUT OF MEMORY!\n");
3998 return E_OUTOFMEMORY;
4003 static const ITypeLib2Vtbl tlbvt = {
4004 ITypeLib2_fnQueryInterface,
4006 ITypeLib2_fnRelease,
4007 ITypeLib2_fnGetTypeInfoCount,
4008 ITypeLib2_fnGetTypeInfo,
4009 ITypeLib2_fnGetTypeInfoType,
4010 ITypeLib2_fnGetTypeInfoOfGuid,
4011 ITypeLib2_fnGetLibAttr,
4012 ITypeLib2_fnGetTypeComp,
4013 ITypeLib2_fnGetDocumentation,
4015 ITypeLib2_fnFindName,
4016 ITypeLib2_fnReleaseTLibAttr,
4018 ITypeLib2_fnGetCustData,
4019 ITypeLib2_fnGetLibStatistics,
4020 ITypeLib2_fnGetDocumentation2,
4021 ITypeLib2_fnGetAllCustData
4025 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4027 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4029 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4032 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4034 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4036 return ITypeLib2_AddRef((ITypeLib2 *)This);
4039 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4041 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4043 return ITypeLib2_Release((ITypeLib2 *)This);
4046 static HRESULT WINAPI ITypeLibComp_fnBind(
4051 ITypeInfo ** ppTInfo,
4052 DESCKIND * pDescKind,
4055 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4056 ITypeInfoImpl *pTypeInfo;
4058 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4060 *pDescKind = DESCKIND_NONE;
4061 pBindPtr->lptcomp = NULL;
4064 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4066 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4068 /* FIXME: check wFlags here? */
4069 /* FIXME: we should use a hash table to look this info up using lHash
4070 * instead of an O(n) search */
4071 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4072 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4074 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4076 *pDescKind = DESCKIND_TYPECOMP;
4077 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4078 ITypeComp_AddRef(pBindPtr->lptcomp);
4079 TRACE("module or enum: %s\n", debugstr_w(szName));
4084 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4085 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4087 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4090 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4091 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4093 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4098 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4099 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4101 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4103 ITypeInfo *subtypeinfo;
4105 DESCKIND subdesckind;
4107 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4108 &subtypeinfo, &subdesckind, &subbindptr);
4109 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4111 TYPEDESC tdesc_appobject =
4118 const VARDESC vardesc_appobject =
4121 NULL, /* lpstrSchema */
4136 VAR_STATIC /* varkind */
4139 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4141 /* cleanup things filled in by Bind call so we can put our
4142 * application object data in there instead */
4143 switch (subdesckind)
4145 case DESCKIND_FUNCDESC:
4146 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4148 case DESCKIND_VARDESC:
4149 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4154 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4156 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4160 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4161 *ppTInfo = (ITypeInfo *)pTypeInfo;
4162 ITypeInfo_AddRef(*ppTInfo);
4168 TRACE("name not found %s\n", debugstr_w(szName));
4172 static HRESULT WINAPI ITypeLibComp_fnBindType(
4176 ITypeInfo ** ppTInfo,
4177 ITypeComp ** ppTComp)
4179 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4183 static const ITypeCompVtbl tlbtcvt =
4186 ITypeLibComp_fnQueryInterface,
4187 ITypeLibComp_fnAddRef,
4188 ITypeLibComp_fnRelease,
4190 ITypeLibComp_fnBind,
4191 ITypeLibComp_fnBindType
4194 /*================== ITypeInfo(2) Methods ===================================*/
4195 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4197 ITypeInfoImpl * pTypeInfoImpl;
4199 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4202 pTypeInfoImpl->lpVtbl = &tinfvt;
4203 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4204 pTypeInfoImpl->ref=1;
4206 TRACE("(%p)\n", pTypeInfoImpl);
4207 return (ITypeInfo2*) pTypeInfoImpl;
4210 /* ITypeInfo::QueryInterface
4212 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4217 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4219 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4222 if(IsEqualIID(riid, &IID_IUnknown) ||
4223 IsEqualIID(riid,&IID_ITypeInfo)||
4224 IsEqualIID(riid,&IID_ITypeInfo2))
4228 ITypeInfo_AddRef(iface);
4229 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4232 TRACE("-- Interface: E_NOINTERFACE\n");
4233 return E_NOINTERFACE;
4236 /* ITypeInfo::AddRef
4238 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4240 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4241 ULONG ref = InterlockedIncrement(&This->ref);
4243 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4245 TRACE("(%p)->ref is %lu\n",This, ref);
4249 /* ITypeInfo::Release
4251 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4253 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4254 ULONG ref = InterlockedDecrement(&This->ref);
4256 TRACE("(%p)->(%lu)\n",This, ref);
4259 /* We don't release ITypeLib when ref=0 because
4260 it means that function is called by ITypeLib2_Release */
4261 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4263 FIXME("destroy child objects\n");
4265 TRACE("destroying ITypeInfo(%p)\n",This);
4268 SysFreeString(This->Name);
4272 if (This->DocString)
4274 SysFreeString(This->DocString);
4275 This->DocString = 0;
4280 SysFreeString(This->DllName);
4286 ITypeInfo_Release((ITypeInfo*)This->next);
4289 HeapFree(GetProcessHeap(),0,This);
4295 /* ITypeInfo::GetTypeAttr
4297 * Retrieves a TYPEATTR structure that contains the attributes of the type
4301 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4302 LPTYPEATTR *ppTypeAttr)
4304 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4307 TRACE("(%p)\n",This);
4309 size = sizeof(**ppTypeAttr);
4310 if (This->TypeAttr.typekind == TKIND_ALIAS)
4311 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4313 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4315 return E_OUTOFMEMORY;
4317 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4319 if (This->TypeAttr.typekind == TKIND_ALIAS)
4320 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4321 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4323 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4324 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4326 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4327 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4332 /* ITypeInfo::GetTypeComp
4334 * Retrieves the ITypeComp interface for the type description, which enables a
4335 * client compiler to bind to the type description's members.
4338 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4339 ITypeComp * *ppTComp)
4341 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4343 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4345 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4346 ITypeComp_AddRef(*ppTComp);
4350 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4352 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4353 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4354 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4358 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4360 memcpy(dest, src, sizeof(ELEMDESC));
4361 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4362 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4364 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4365 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4366 *buffer += sizeof(PARAMDESCEX);
4367 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4368 VariantInit(&pparamdescex_dest->varDefaultValue);
4369 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4370 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4373 dest->u.paramdesc.pparamdescex = NULL;
4377 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4379 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4380 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4383 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4387 SIZE_T size = sizeof(*src);
4391 size += sizeof(*src->lprgscode) * src->cScodes;
4392 size += TLB_SizeElemDesc(&src->elemdescFunc);
4393 for (i = 0; i < src->cParams; i++)
4395 size += sizeof(ELEMDESC);
4396 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4399 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4400 if (!dest) return E_OUTOFMEMORY;
4402 memcpy(dest, src, sizeof(FUNCDESC));
4403 buffer = (char *)(dest + 1);
4405 dest->lprgscode = (SCODE *)buffer;
4406 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4407 buffer += sizeof(*src->lprgscode) * src->cScodes;
4409 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4412 SysFreeString((BSTR)dest);
4416 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4417 buffer += sizeof(ELEMDESC) * src->cParams;
4418 for (i = 0; i < src->cParams; i++)
4420 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4426 /* undo the above actions */
4427 for (i = i - 1; i >= 0; i--)
4428 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4429 TLB_FreeElemDesc(&dest->elemdescFunc);
4430 SysFreeString((BSTR)dest);
4434 /* special treatment for dispinterfaces: this makes functions appear
4435 * to return their [retval] value when it is really returning an
4437 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4439 if (dest->cParams &&
4440 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4442 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4443 if (elemdesc->tdesc.vt != VT_PTR)
4445 ERR("elemdesc should have started with VT_PTR instead of:\n");
4447 dump_ELEMDESC(elemdesc);
4448 return E_UNEXPECTED;
4451 /* copy last parameter to the return value. we are using a flat
4452 * buffer so there is no danger of leaking memory in
4454 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4456 /* remove the last parameter */
4460 /* otherwise this function is made to appear to have no return
4462 dest->elemdescFunc.tdesc.vt = VT_VOID;
4470 /* ITypeInfo::GetFuncDesc
4472 * Retrieves the FUNCDESC structure that contains information about a
4473 * specified function.
4476 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4477 LPFUNCDESC *ppFuncDesc)
4479 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4481 const TLBFuncDesc *pFDesc;
4483 TRACE("(%p) index %d\n", This, index);
4485 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4489 return TLB_AllocAndInitFuncDesc(
4492 This->TypeAttr.typekind == TKIND_DISPATCH);
4494 return E_INVALIDARG;
4497 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4501 SIZE_T size = sizeof(*src);
4504 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4505 if (src->varkind == VAR_CONST)
4506 size += sizeof(VARIANT);
4507 size += TLB_SizeElemDesc(&src->elemdescVar);
4509 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4510 if (!dest) return E_OUTOFMEMORY;
4513 buffer = (char *)(dest + 1);
4514 if (src->lpstrSchema)
4517 dest->lpstrSchema = (LPOLESTR)buffer;
4518 len = strlenW(src->lpstrSchema);
4519 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4520 buffer += (len + 1) * sizeof(WCHAR);
4523 if (src->varkind == VAR_CONST)
4527 dest->u.lpvarValue = (VARIANT *)buffer;
4528 *dest->u.lpvarValue = *src->u.lpvarValue;
4529 buffer += sizeof(VARIANT);
4530 VariantInit(dest->u.lpvarValue);
4531 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4534 SysFreeString((BSTR)dest_ptr);
4538 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4541 if (src->varkind == VAR_CONST)
4542 VariantClear(dest->u.lpvarValue);
4543 SysFreeString((BSTR)dest);
4550 /* ITypeInfo::GetVarDesc
4552 * Retrieves a VARDESC structure that describes the specified variable.
4555 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4556 LPVARDESC *ppVarDesc)
4558 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4560 const TLBVarDesc *pVDesc;
4562 TRACE("(%p) index %d\n", This, index);
4564 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4568 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4570 return E_INVALIDARG;
4573 /* ITypeInfo_GetNames
4575 * Retrieves the variable with the specified member ID (or the name of the
4576 * property or method and its parameters) that correspond to the specified
4579 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4580 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4582 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4583 TLBFuncDesc * pFDesc;
4584 TLBVarDesc * pVDesc;
4586 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4587 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4590 /* function found, now return function and parameter names */
4591 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4594 *rgBstrNames=SysAllocString(pFDesc->Name);
4596 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4602 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4605 *rgBstrNames=SysAllocString(pVDesc->Name);
4610 if(This->TypeAttr.cImplTypes &&
4611 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4612 /* recursive search */
4615 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4617 if(SUCCEEDED(result))
4619 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4620 ITypeInfo_Release(pTInfo);
4623 WARN("Could not search inherited interface!\n");
4627 WARN("no names found\n");
4630 return TYPE_E_ELEMENTNOTFOUND;
4637 /* ITypeInfo::GetRefTypeOfImplType
4639 * If a type description describes a COM class, it retrieves the type
4640 * description of the implemented interface types. For an interface,
4641 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4645 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4650 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4653 TLBImplType *pImpl = This->impltypelist;
4655 TRACE("(%p) index %d\n", This, index);
4656 if (TRACE_ON(ole)) dump_TypeInfo(This);
4660 /* only valid on dual interfaces;
4661 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4663 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4665 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4666 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4672 hr = TYPE_E_ELEMENTNOTFOUND;
4677 /* get element n from linked list */
4678 for(i=0; pImpl && i<index; i++)
4680 pImpl = pImpl->next;
4684 *pRefType = pImpl->hRef;
4686 hr = TYPE_E_ELEMENTNOTFOUND;
4692 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4694 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4700 /* ITypeInfo::GetImplTypeFlags
4702 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4703 * or base interface in a type description.
4705 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4706 UINT index, INT *pImplTypeFlags)
4708 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4712 TRACE("(%p) index %d\n", This, index);
4713 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4714 i++, pImpl=pImpl->next)
4716 if(i==index && pImpl){
4717 *pImplTypeFlags=pImpl->implflags;
4721 return TYPE_E_ELEMENTNOTFOUND;
4725 * Maps between member names and member IDs, and parameter names and
4728 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4729 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4731 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4732 TLBFuncDesc * pFDesc;
4733 TLBVarDesc * pVDesc;
4736 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4738 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4740 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4741 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4742 for(i=1; i < cNames; i++){
4743 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4744 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4746 if( j<pFDesc->funcdesc.cParams)
4749 ret=DISP_E_UNKNOWNNAME;
4754 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4755 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4756 if(cNames) *pMemId=pVDesc->vardesc.memid;
4760 /* not found, see if this is and interface with an inheritance */
4761 if(This->TypeAttr.cImplTypes &&
4762 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4763 /* recursive search */
4765 ret=ITypeInfo_GetRefTypeInfo(iface,
4766 This->impltypelist->hRef, &pTInfo);
4768 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4769 ITypeInfo_Release(pTInfo);
4772 WARN("Could not search inherited interface!\n");
4774 WARN("no names found\n");
4775 return DISP_E_UNKNOWNNAME;
4778 /* ITypeInfo::Invoke
4780 * Invokes a method, or accesses a property of an object, that implements the
4781 * interface described by the type description.
4784 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4787 if (TRACE_ON(ole)) {
4789 TRACE("Calling %p(",func);
4790 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4802 res = func(args[0]);
4805 res = func(args[0],args[1]);
4808 res = func(args[0],args[1],args[2]);
4811 res = func(args[0],args[1],args[2],args[3]);
4814 res = func(args[0],args[1],args[2],args[3],args[4]);
4817 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4820 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4823 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4826 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4829 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4832 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4835 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]);
4838 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]);
4841 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]);
4844 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4850 FIXME("unsupported calling convention %d\n",callconv);
4854 TRACE("returns %08lx\n",res);
4858 extern int _argsize(DWORD vt);
4860 /****************************************************************************
4861 * Helper functions for Dispcall / Invoke, which copies one variant
4862 * with target type onto the argument stack.
4865 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4866 DWORD *argpos, VARIANT *arg, VARTYPE vt
4868 UINT arglen = _argsize(vt)*sizeof(DWORD);
4871 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4872 memcpy(argpos,&arg,sizeof(void*));
4876 if (V_VT(arg) == vt) {
4877 memcpy(argpos, &V_I4(arg), arglen);
4881 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4882 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4886 if (vt == VT_VARIANT) {
4887 memcpy(argpos, arg, arglen);
4890 /* Deref BYREF vars if there is need */
4891 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4892 memcpy(argpos,(void*)V_I4(arg), arglen);
4895 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4896 /* in this context, if the type lib specifies IUnknown*, giving an
4897 IDispatch* is correct; so, don't invoke VariantChangeType */
4898 memcpy(argpos,&V_I4(arg), arglen);
4901 if ((vt == VT_PTR) && tdesc)
4902 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4904 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4905 ITypeInfo *tinfo2 = NULL;
4906 TYPEATTR *tattr = NULL;
4909 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4911 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4912 "while coercing from vt 0x%x. Copying 4 byte.\n",
4913 tdesc->u.hreftype,V_VT(arg));
4914 memcpy(argpos, &V_I4(arg), 4);
4917 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4920 ERR("GetTypeAttr failed\n");
4921 ITypeInfo_Release(tinfo2);
4924 switch (tattr->typekind) {
4926 switch ( V_VT( arg ) ) {
4928 *argpos = V_I2(arg);
4932 memcpy(argpos, &V_I4(arg), 4);
4935 case VT_BYREF|VT_I4:
4936 memcpy(argpos, V_I4REF(arg), 4);
4940 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4947 tdesc = &(tattr->tdescAlias);
4948 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4951 case TKIND_INTERFACE:
4952 if (V_VT(arg) == VT_DISPATCH) {
4954 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4955 memcpy(argpos, &V_DISPATCH(arg), 4);
4959 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4960 &IID_IDispatch,(LPVOID*)&disp);
4961 if (SUCCEEDED(hres)) {
4962 memcpy(argpos,&disp,4);
4963 IUnknown_Release(V_DISPATCH(arg));
4967 FIXME("Failed to query IDispatch interface from %s while "
4968 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4972 if (V_VT(arg) == VT_UNKNOWN) {
4973 memcpy(argpos, &V_UNKNOWN(arg), 4);
4977 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4978 V_VT(arg),debugstr_guid(&(tattr->guid)));
4982 case TKIND_DISPATCH:
4983 if (V_VT(arg) == VT_DISPATCH) {
4984 memcpy(argpos, &V_DISPATCH(arg), 4);
4989 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4993 FIXME("TKIND_RECORD unhandled.\n");
4997 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5001 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5002 ITypeInfo_Release(tinfo2);
5007 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
5008 memcpy(argpos,&V_I4(&va), arglen);
5009 FIXME("Should not use VariantChangeType here."
5010 " (conversion from 0x%x -> 0x%x) %08lx\n",
5011 V_VT(arg), vt, *argpos
5015 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
5019 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
5022 ITypeInfo *tinfo2 = NULL;
5023 TYPEATTR *tattr = NULL;
5025 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5028 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
5030 tdesc->u.hreftype, hr);
5033 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5036 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
5037 ITypeInfo_Release(tinfo2);
5041 switch (tattr->typekind)
5048 tdesc = &tattr->tdescAlias;
5049 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5052 case TKIND_INTERFACE:
5053 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5059 case TKIND_DISPATCH:
5064 FIXME("TKIND_RECORD unhandled.\n");
5069 FIXME("TKIND_RECORD unhandled.\n");
5074 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5078 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5079 ITypeInfo_Release(tinfo2);
5083 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
5087 /* enforce only one level of pointer indirection */
5088 if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
5090 tdesc = tdesc->u.lptdesc;
5092 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5093 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5094 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5095 if ((tdesc->vt == VT_USERDEFINED) ||
5096 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5098 VARTYPE vt_userdefined = 0;
5099 TYPEDESC *tdesc_userdefined = tdesc;
5100 if (tdesc->vt == VT_PTR)
5102 vt_userdefined = VT_BYREF;
5103 tdesc_userdefined = tdesc->u.lptdesc;
5105 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5107 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5108 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5110 *vt |= vt_userdefined;
5122 case VT_USERDEFINED:
5123 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5126 ERR("cannot convert VT_PTR into variant VT\n");
5136 /***********************************************************************
5137 * DispCallFunc (OLEAUT32.@)
5141 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5142 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5144 int i, argsize, argspos;
5148 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5149 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5150 pvargResult, V_VT(pvargResult));
5152 /* DispCallFunc is only used to invoke methods belonging to an
5153 * IDispatch-derived COM interface. So we need to add a first parameter
5154 * to the list of arguments, to supply the interface pointer */
5156 for (i=0;i<cActuals;i++)
5158 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5159 dump_Variant(prgpvarg[i]);
5160 argsize += _argsize(prgvt[i]);
5162 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5163 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
5165 for (i=0;i<cActuals;i++)
5167 VARIANT *arg = prgpvarg[i];
5168 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5169 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5170 argspos += _argsize(prgvt[i]);
5173 hres = _invoke((*(FARPROC**)pvInstance)[oVft/sizeof(void *)],cc,argsize,args);
5174 if (pvargResult && (vtReturn != VT_EMPTY))
5176 TRACE("Method returned 0x%08lx\n",hres);
5177 V_VT(pvargResult) = vtReturn;
5178 V_UI4(pvargResult) = hres;
5181 HeapFree(GetProcessHeap(),0,args);
5185 static HRESULT WINAPI ITypeInfo_fnInvoke(
5190 DISPPARAMS *pDispParams,
5191 VARIANT *pVarResult,
5192 EXCEPINFO *pExcepInfo,
5195 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5197 unsigned int var_index;
5200 const TLBFuncDesc *pFuncInfo;
5202 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
5203 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5205 dump_DispParms(pDispParams);
5207 /* we do this instead of using GetFuncDesc since it will return a fake
5208 * FUNCDESC for dispinterfaces and we want the real function description */
5209 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5210 if (memid == pFuncInfo->funcdesc.memid && (dwFlags & pFuncInfo->funcdesc.invkind))
5214 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5218 TRACE("invoking:\n");
5219 dump_TLBFuncDesc(pFuncInfo);
5222 switch (func_desc->funckind) {
5223 case FUNC_PUREVIRTUAL:
5224 case FUNC_VIRTUAL: {
5226 int numargs, numargs2, argspos, args2pos;
5227 DWORD *args , *args2;
5228 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
5229 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
5232 numargs = 1; /* sizeof(thisptr) */
5234 for (i = 0; i < func_desc->cParams; i++) {
5235 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5237 numargs += _argsize(tdesc->vt);
5238 if (i>=pDispParams->cArgs) { /* arguments to return */
5239 if (tdesc->vt == VT_PTR) {
5240 numargs2 += _argsize(tdesc->u.lptdesc->vt);
5242 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
5243 numargs2 += _argsize(tdesc->vt);
5248 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
5249 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
5251 args[0] = (DWORD)pIUnk;
5252 argspos = 1; args2pos = 0;
5253 for (i = 0; i < func_desc->cParams; i++) {
5254 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
5255 TYPEDESC *tdesc = &(elemdesc->tdesc);
5256 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
5257 int arglen = _argsize(tdesc->vt);
5259 if (i<pDispParams->cArgs) {
5260 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
5262 if (paramFlags & PARAMFLAG_FOPT) {
5263 if(i < func_desc->cParams - func_desc->cParamsOpt)
5264 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5265 if(V_VT(arg) == VT_EMPTY
5266 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
5267 /* FIXME: Documentation says that we do this when parameter is left unspecified.
5268 How to determine it? */
5270 if(paramFlags & PARAMFLAG_FHASDEFAULT)
5271 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5272 V_VT(arg) = VT_ERROR;
5273 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5274 arglen = _argsize(VT_ERROR);
5277 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5278 if (FAILED(hres)) goto func_fail;
5280 } else if (paramFlags & PARAMFLAG_FOPT) {
5281 VARIANT *arg = &rgvarg[i];
5283 if (i < func_desc->cParams - func_desc->cParamsOpt)
5284 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5285 if (paramFlags & PARAMFLAG_FHASDEFAULT)
5286 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5288 V_VT(arg) = VT_ERROR;
5289 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5290 arglen = _argsize(VT_ERROR);
5291 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5292 if (FAILED(hres)) goto func_fail;
5295 if (tdesc->vt == VT_PTR)
5296 arglen = _argsize(tdesc->u.lptdesc->vt);
5298 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
5300 /* Supply pointers for the rest, so propertyget works*/
5301 args[argspos] = (DWORD)&args2[args2pos];
5303 /* If pointer to variant, pass reference it. */
5304 if ((tdesc->vt == VT_PTR) &&
5305 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
5308 args[argspos]= (DWORD)pVarResult;
5313 if (func_desc->cParamsOpt < 0)
5314 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
5316 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
5317 func_desc->callconv,
5323 for (i = 0; i < func_desc->cParams; i++) {
5324 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5325 if (wParamFlags & PARAMFLAG_FRETVAL) {
5326 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5327 TYPEDESC *tdesc = &elemdesc->tdesc;
5328 VARIANTARG varresult;
5329 V_VT(&varresult) = 0;
5330 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5333 /* FIXME: this is really messy - we should keep the
5334 * args in VARIANTARGs rather than a DWORD array */
5335 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5338 TRACE("varresult: ");
5339 dump_Variant(&varresult);
5341 hres = VariantCopyInd(pVarResult, &varresult);
5342 /* free data stored in varresult. Note that
5343 * VariantClear doesn't do what we want because we are
5344 * working with byref types. */
5345 /* FIXME: clear safearrays, bstrs, records and
5346 * variants here too */
5347 if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
5348 (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
5350 if(*V_UNKNOWNREF(&varresult))
5351 IUnknown_Release(*V_UNKNOWNREF(&varresult));
5358 if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
5359 WARN("invoked function failed with error 0x%08lx\n", res);
5360 hres = DISP_E_EXCEPTION;
5361 if (pExcepInfo) pExcepInfo->scode = res;
5364 HeapFree(GetProcessHeap(), 0, rgvarg);
5365 HeapFree(GetProcessHeap(),0,args2);
5366 HeapFree(GetProcessHeap(),0,args);
5369 case FUNC_DISPATCH: {
5372 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5373 if (SUCCEEDED(hres)) {
5374 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5375 hres = IDispatch_Invoke(
5376 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
5377 pVarResult,pExcepInfo,pArgErr
5380 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5381 IDispatch_Release(disp);
5383 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5387 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5392 TRACE("-- 0x%08lx\n", hres);
5395 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5398 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5399 if(FAILED(hres)) return hres;
5401 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5402 dump_VARDESC(var_desc);
5403 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5407 /* not found, look for it in inherited interfaces */
5408 ITypeInfo2_GetTypeKind(iface, &type_kind);
5409 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5411 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5412 /* recursive search */
5414 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5415 if(SUCCEEDED(hres)){
5416 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5417 ITypeInfo_Release(pTInfo);
5420 WARN("Could not search inherited interface!\n");
5423 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
5424 return DISP_E_MEMBERNOTFOUND;
5427 /* ITypeInfo::GetDocumentation
5429 * Retrieves the documentation string, the complete Help file name and path,
5430 * and the context ID for the Help topic for a specified type description.
5432 * (Can be tested by the Visual Basic Editor in Word for instance.)
5434 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5435 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5436 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5438 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5439 TLBFuncDesc * pFDesc;
5440 TLBVarDesc * pVDesc;
5441 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5442 " HelpContext(%p) HelpFile(%p)\n",
5443 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5444 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5446 *pBstrName=SysAllocString(This->Name);
5448 *pBstrDocString=SysAllocString(This->DocString);
5450 *pdwHelpContext=This->dwHelpContext;
5452 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5454 }else {/* for a member */
5455 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5456 if(pFDesc->funcdesc.memid==memid){
5458 *pBstrName = SysAllocString(pFDesc->Name);
5460 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5462 *pdwHelpContext=pFDesc->helpcontext;
5465 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5466 if(pVDesc->vardesc.memid==memid){
5468 *pBstrName = SysAllocString(pVDesc->Name);
5470 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5472 *pdwHelpContext=pVDesc->HelpContext;
5476 WARN("member %ld not found\n", memid);
5477 return TYPE_E_ELEMENTNOTFOUND;
5480 /* ITypeInfo::GetDllEntry
5482 * Retrieves a description or specification of an entry point for a function
5485 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5486 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5489 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5490 TLBFuncDesc *pFDesc;
5492 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5494 if (pBstrDllName) *pBstrDllName = NULL;
5495 if (pBstrName) *pBstrName = NULL;
5496 if (pwOrdinal) *pwOrdinal = 0;
5498 if (This->TypeAttr.typekind != TKIND_MODULE)
5499 return TYPE_E_BADMODULEKIND;
5501 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5502 if(pFDesc->funcdesc.memid==memid){
5503 dump_TypeInfo(This);
5504 dump_TLBFuncDescOne(pFDesc);
5507 *pBstrDllName = SysAllocString(This->DllName);
5509 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5511 *pBstrName = SysAllocString(pFDesc->Entry);
5519 *pwOrdinal = (DWORD)pFDesc->Entry;
5522 return TYPE_E_ELEMENTNOTFOUND;
5525 /* ITypeInfo::GetRefTypeInfo
5527 * If a type description references other type descriptions, it retrieves
5528 * the referenced type descriptions.
5530 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5533 ITypeInfo **ppTInfo)
5535 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5536 HRESULT result = E_FAIL;
5538 if (hRefType == -1 &&
5539 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5540 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5542 /* when we meet a DUAL dispinterface, we must create the interface
5545 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5548 /* the interface version contains the same information as the dispinterface
5549 * copy the contents of the structs.
5551 *pTypeInfoImpl = *This;
5552 pTypeInfoImpl->ref = 1;
5554 /* change the type to interface */
5555 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5557 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5559 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5564 TLBRefType *pRefType;
5565 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5566 if(pRefType->reference == hRefType)
5570 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5571 if(pRefType && hRefType != -1) {
5572 ITypeLib *pTLib = NULL;
5574 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5576 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5578 if(pRefType->pImpTLInfo->pImpTypeLib) {
5579 TRACE("typeinfo in imported typelib that is already loaded\n");
5580 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5581 ITypeLib2_AddRef((ITypeLib*) pTLib);
5584 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5585 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5586 pRefType->pImpTLInfo->wVersionMajor,
5587 pRefType->pImpTLInfo->wVersionMinor,
5588 pRefType->pImpTLInfo->lcid,
5591 if(!SUCCEEDED(result)) {
5592 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5593 result=LoadTypeLib(libnam, &pTLib);
5594 SysFreeString(libnam);
5596 if(SUCCEEDED(result)) {
5597 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5598 ITypeLib2_AddRef(pTLib);
5602 if(SUCCEEDED(result)) {
5603 if(pRefType->index == TLB_REF_USE_GUID)
5604 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5608 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5612 ITypeLib2_Release(pTLib);
5616 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5617 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5621 /* ITypeInfo::AddressOfMember
5623 * Retrieves the addresses of static functions or variables, such as those
5626 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5627 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5629 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5630 FIXME("(%p) stub!\n", This);
5634 /* ITypeInfo::CreateInstance
5636 * Creates a new instance of a type that describes a component object class
5639 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5640 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5642 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5643 FIXME("(%p) stub!\n", This);
5647 /* ITypeInfo::GetMops
5649 * Retrieves marshalling information.
5651 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5654 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5655 FIXME("(%p) stub!\n", This);
5659 /* ITypeInfo::GetContainingTypeLib
5661 * Retrieves the containing type library and the index of the type description
5662 * within that type library.
5664 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5665 ITypeLib * *ppTLib, UINT *pIndex)
5667 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5669 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5671 *pIndex=This->index;
5672 TRACE("returning pIndex=%d\n", *pIndex);
5676 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5677 ITypeLib2_AddRef(*ppTLib);
5678 TRACE("returning ppTLib=%p\n", *ppTLib);
5684 /* ITypeInfo::ReleaseTypeAttr
5686 * Releases a TYPEATTR previously returned by GetTypeAttr.
5689 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5690 TYPEATTR* pTypeAttr)
5692 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5693 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5694 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5697 /* ITypeInfo::ReleaseFuncDesc
5699 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5701 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5703 FUNCDESC *pFuncDesc)
5705 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5708 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5710 for (i = 0; i < pFuncDesc->cParams; i++)
5711 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5712 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5714 SysFreeString((BSTR)pFuncDesc);
5717 /* ITypeInfo::ReleaseVarDesc
5719 * Releases a VARDESC previously returned by GetVarDesc.
5721 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5724 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5725 TRACE("(%p)->(%p)\n", This, pVarDesc);
5727 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5728 if (pVarDesc->varkind == VAR_CONST)
5729 VariantClear(pVarDesc->u.lpvarValue);
5730 SysFreeString((BSTR)pVarDesc);
5733 /* ITypeInfo2::GetTypeKind
5735 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5738 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5739 TYPEKIND *pTypeKind)
5741 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5742 *pTypeKind=This->TypeAttr.typekind;
5743 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5747 /* ITypeInfo2::GetTypeFlags
5749 * Returns the type flags without any allocations. This returns a DWORD type
5750 * flag, which expands the type flags without growing the TYPEATTR (type
5754 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5756 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5757 *pTypeFlags=This->TypeAttr.wTypeFlags;
5758 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5762 /* ITypeInfo2::GetFuncIndexOfMemId
5763 * Binds to a specific member based on a known DISPID, where the member name
5764 * is not known (for example, when binding to a default member).
5767 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5768 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5770 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5771 TLBFuncDesc *pFuncInfo;
5775 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5776 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5782 result = TYPE_E_ELEMENTNOTFOUND;
5784 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5785 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5789 /* TypeInfo2::GetVarIndexOfMemId
5791 * Binds to a specific member based on a known DISPID, where the member name
5792 * is not known (for example, when binding to a default member).
5795 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5796 MEMBERID memid, UINT *pVarIndex)
5798 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5799 TLBVarDesc *pVarInfo;
5802 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5803 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5809 result = TYPE_E_ELEMENTNOTFOUND;
5811 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5812 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5816 /* ITypeInfo2::GetCustData
5818 * Gets the custom data
5820 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5825 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5826 TLBCustData *pCData;
5828 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5829 if( IsEqualIID(guid, &pCData->guid)) break;
5831 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5835 VariantInit( pVarVal);
5836 VariantCopy( pVarVal, &pCData->data);
5839 return E_INVALIDARG; /* FIXME: correct? */
5842 /* ITypeInfo2::GetFuncCustData
5844 * Gets the custom data
5846 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5852 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5853 TLBCustData *pCData=NULL;
5854 TLBFuncDesc * pFDesc;
5856 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5857 pFDesc=pFDesc->next);
5860 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5861 if( IsEqualIID(guid, &pCData->guid)) break;
5863 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5866 VariantInit( pVarVal);
5867 VariantCopy( pVarVal, &pCData->data);
5870 return E_INVALIDARG; /* FIXME: correct? */
5873 /* ITypeInfo2::GetParamCustData
5875 * Gets the custom data
5877 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5884 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5885 TLBCustData *pCData=NULL;
5886 TLBFuncDesc * pFDesc;
5889 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5891 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5892 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5893 pCData = pCData->next)
5894 if( IsEqualIID(guid, &pCData->guid)) break;
5896 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5900 VariantInit( pVarVal);
5901 VariantCopy( pVarVal, &pCData->data);
5904 return E_INVALIDARG; /* FIXME: correct? */
5907 /* ITypeInfo2::GetVarCustData
5909 * Gets the custom data
5911 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5917 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5918 TLBCustData *pCData=NULL;
5919 TLBVarDesc * pVDesc;
5922 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5926 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5928 if( IsEqualIID(guid, &pCData->guid)) break;
5932 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5936 VariantInit( pVarVal);
5937 VariantCopy( pVarVal, &pCData->data);
5940 return E_INVALIDARG; /* FIXME: correct? */
5943 /* ITypeInfo2::GetImplCustData
5945 * Gets the custom data
5947 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5953 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5954 TLBCustData *pCData=NULL;
5955 TLBImplType * pRDesc;
5958 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5962 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5964 if( IsEqualIID(guid, &pCData->guid)) break;
5968 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5972 VariantInit( pVarVal);
5973 VariantCopy( pVarVal, &pCData->data);
5976 return E_INVALIDARG; /* FIXME: correct? */
5979 /* ITypeInfo2::GetDocumentation2
5981 * Retrieves the documentation string, the complete Help file name and path,
5982 * the localization context to use, and the context ID for the library Help
5983 * topic in the Help file.
5986 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5990 BSTR *pbstrHelpString,
5991 DWORD *pdwHelpStringContext,
5992 BSTR *pbstrHelpStringDll)
5994 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5995 TLBFuncDesc * pFDesc;
5996 TLBVarDesc * pVDesc;
5997 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5998 "HelpStringContext(%p) HelpStringDll(%p)\n",
5999 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6000 pbstrHelpStringDll );
6001 /* the help string should be obtained from the helpstringdll,
6002 * using the _DLLGetDocumentation function, based on the supplied
6003 * lcid. Nice to do sometime...
6005 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6007 *pbstrHelpString=SysAllocString(This->Name);
6008 if(pdwHelpStringContext)
6009 *pdwHelpStringContext=This->dwHelpStringContext;
6010 if(pbstrHelpStringDll)
6011 *pbstrHelpStringDll=
6012 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6014 }else {/* for a member */
6015 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6016 if(pFDesc->funcdesc.memid==memid){
6018 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6019 if(pdwHelpStringContext)
6020 *pdwHelpStringContext=pFDesc->HelpStringContext;
6021 if(pbstrHelpStringDll)
6022 *pbstrHelpStringDll=
6023 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6026 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6027 if(pVDesc->vardesc.memid==memid){
6029 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6030 if(pdwHelpStringContext)
6031 *pdwHelpStringContext=pVDesc->HelpStringContext;
6032 if(pbstrHelpStringDll)
6033 *pbstrHelpStringDll=
6034 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6038 return TYPE_E_ELEMENTNOTFOUND;
6041 /* ITypeInfo2::GetAllCustData
6043 * Gets all custom data items for the Type info.
6046 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6048 CUSTDATA *pCustData)
6050 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6051 TLBCustData *pCData;
6054 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6056 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6057 if(pCustData->prgCustData ){
6058 pCustData->cCustData=This->ctCustData;
6059 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6060 pCustData->prgCustData[i].guid=pCData->guid;
6061 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6064 ERR(" OUT OF MEMORY!\n");
6065 return E_OUTOFMEMORY;
6070 /* ITypeInfo2::GetAllFuncCustData
6072 * Gets all custom data items for the specified Function
6075 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6078 CUSTDATA *pCustData)
6080 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6081 TLBCustData *pCData;
6082 TLBFuncDesc * pFDesc;
6084 TRACE("(%p) index %d\n", This, index);
6085 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6086 pFDesc=pFDesc->next)
6089 pCustData->prgCustData =
6090 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6091 if(pCustData->prgCustData ){
6092 pCustData->cCustData=pFDesc->ctCustData;
6093 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6094 pCData = pCData->next){
6095 pCustData->prgCustData[i].guid=pCData->guid;
6096 VariantCopy(& pCustData->prgCustData[i].varValue,
6100 ERR(" OUT OF MEMORY!\n");
6101 return E_OUTOFMEMORY;
6105 return TYPE_E_ELEMENTNOTFOUND;
6108 /* ITypeInfo2::GetAllParamCustData
6110 * Gets all custom data items for the Functions
6113 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6114 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6116 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6117 TLBCustData *pCData=NULL;
6118 TLBFuncDesc * pFDesc;
6120 TRACE("(%p) index %d\n", This, indexFunc);
6121 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6122 pFDesc=pFDesc->next)
6124 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6125 pCustData->prgCustData =
6126 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6127 sizeof(CUSTDATAITEM));
6128 if(pCustData->prgCustData ){
6129 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6130 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6131 pCData; i++, pCData = pCData->next){
6132 pCustData->prgCustData[i].guid=pCData->guid;
6133 VariantCopy(& pCustData->prgCustData[i].varValue,
6137 ERR(" OUT OF MEMORY!\n");
6138 return E_OUTOFMEMORY;
6142 return TYPE_E_ELEMENTNOTFOUND;
6145 /* ITypeInfo2::GetAllVarCustData
6147 * Gets all custom data items for the specified Variable
6150 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6151 UINT index, CUSTDATA *pCustData)
6153 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6154 TLBCustData *pCData;
6155 TLBVarDesc * pVDesc;
6157 TRACE("(%p) index %d\n", This, index);
6158 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6159 pVDesc=pVDesc->next)
6162 pCustData->prgCustData =
6163 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6164 if(pCustData->prgCustData ){
6165 pCustData->cCustData=pVDesc->ctCustData;
6166 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6167 pCData = pCData->next){
6168 pCustData->prgCustData[i].guid=pCData->guid;
6169 VariantCopy(& pCustData->prgCustData[i].varValue,
6173 ERR(" OUT OF MEMORY!\n");
6174 return E_OUTOFMEMORY;
6178 return TYPE_E_ELEMENTNOTFOUND;
6181 /* ITypeInfo2::GetAllImplCustData
6183 * Gets all custom data items for the specified implementation type
6186 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6189 CUSTDATA *pCustData)
6191 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6192 TLBCustData *pCData;
6193 TLBImplType * pRDesc;
6195 TRACE("(%p) index %d\n", This, index);
6196 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6197 pRDesc=pRDesc->next)
6200 pCustData->prgCustData =
6201 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6202 if(pCustData->prgCustData ){
6203 pCustData->cCustData=pRDesc->ctCustData;
6204 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6205 pCData = pCData->next){
6206 pCustData->prgCustData[i].guid=pCData->guid;
6207 VariantCopy(& pCustData->prgCustData[i].varValue,
6211 ERR(" OUT OF MEMORY!\n");
6212 return E_OUTOFMEMORY;
6216 return TYPE_E_ELEMENTNOTFOUND;
6219 static const ITypeInfo2Vtbl tinfvt =
6222 ITypeInfo_fnQueryInterface,
6224 ITypeInfo_fnRelease,
6226 ITypeInfo_fnGetTypeAttr,
6227 ITypeInfo_fnGetTypeComp,
6228 ITypeInfo_fnGetFuncDesc,
6229 ITypeInfo_fnGetVarDesc,
6230 ITypeInfo_fnGetNames,
6231 ITypeInfo_fnGetRefTypeOfImplType,
6232 ITypeInfo_fnGetImplTypeFlags,
6233 ITypeInfo_fnGetIDsOfNames,
6235 ITypeInfo_fnGetDocumentation,
6236 ITypeInfo_fnGetDllEntry,
6237 ITypeInfo_fnGetRefTypeInfo,
6238 ITypeInfo_fnAddressOfMember,
6239 ITypeInfo_fnCreateInstance,
6240 ITypeInfo_fnGetMops,
6241 ITypeInfo_fnGetContainingTypeLib,
6242 ITypeInfo_fnReleaseTypeAttr,
6243 ITypeInfo_fnReleaseFuncDesc,
6244 ITypeInfo_fnReleaseVarDesc,
6246 ITypeInfo2_fnGetTypeKind,
6247 ITypeInfo2_fnGetTypeFlags,
6248 ITypeInfo2_fnGetFuncIndexOfMemId,
6249 ITypeInfo2_fnGetVarIndexOfMemId,
6250 ITypeInfo2_fnGetCustData,
6251 ITypeInfo2_fnGetFuncCustData,
6252 ITypeInfo2_fnGetParamCustData,
6253 ITypeInfo2_fnGetVarCustData,
6254 ITypeInfo2_fnGetImplTypeCustData,
6255 ITypeInfo2_fnGetDocumentation2,
6256 ITypeInfo2_fnGetAllCustData,
6257 ITypeInfo2_fnGetAllFuncCustData,
6258 ITypeInfo2_fnGetAllParamCustData,
6259 ITypeInfo2_fnGetAllVarCustData,
6260 ITypeInfo2_fnGetAllImplTypeCustData,
6263 /******************************************************************************
6264 * CreateDispTypeInfo [OLEAUT32.31]
6266 * Build type information for an object so it can be called through an
6267 * IDispatch interface.
6270 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6271 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6274 * This call allows an objects methods to be accessed through IDispatch, by
6275 * building an ITypeInfo object that IDispatch can use to call through.
6277 HRESULT WINAPI CreateDispTypeInfo(
6278 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6279 LCID lcid, /* [I] Locale Id */
6280 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6282 ITypeInfoImpl *pTIImpl;
6284 TLBFuncDesc **ppFuncDesc;
6286 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
6287 pTIImpl->pTypeLib = NULL;
6289 pTIImpl->Name = NULL;
6290 pTIImpl->dwHelpContext = -1;
6291 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
6292 pTIImpl->TypeAttr.lcid = lcid;
6293 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
6294 pTIImpl->TypeAttr.wMajorVerNum = 0;
6295 pTIImpl->TypeAttr.wMinorVerNum = 0;
6296 pTIImpl->TypeAttr.cbAlignment = 2;
6297 pTIImpl->TypeAttr.cbSizeInstance = -1;
6298 pTIImpl->TypeAttr.cbSizeVft = -1;
6299 pTIImpl->TypeAttr.cFuncs = 0;
6300 pTIImpl->TypeAttr.cImplTypes = 1;
6301 pTIImpl->TypeAttr.cVars = 0;
6302 pTIImpl->TypeAttr.wTypeFlags = 0;
6304 ppFuncDesc = &pTIImpl->funclist;
6305 for(func = 0; func < pidata->cMembers; func++) {
6306 METHODDATA *md = pidata->pmethdata + func;
6307 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6308 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6309 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6310 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6311 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6312 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6313 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6314 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
6315 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
6316 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6317 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6318 md->cArgs * sizeof(ELEMDESC));
6319 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6320 md->cArgs * sizeof(TLBParDesc));
6321 for(param = 0; param < md->cArgs; param++) {
6322 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6323 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6325 ppFuncDesc = &(*ppFuncDesc)->next;
6327 *pptinfo = (ITypeInfo*)pTIImpl;
6332 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6334 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6336 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6339 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6341 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6343 return ITypeInfo_AddRef((ITypeInfo *)This);
6346 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6348 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6350 return ITypeInfo_Release((ITypeInfo *)This);
6353 static HRESULT WINAPI ITypeComp_fnBind(
6358 ITypeInfo ** ppTInfo,
6359 DESCKIND * pDescKind,
6362 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6363 TLBFuncDesc * pFDesc;
6364 TLBVarDesc * pVDesc;
6366 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6368 *pDescKind = DESCKIND_NONE;
6369 pBindPtr->lpfuncdesc = NULL;
6372 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6373 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6374 if (!strcmpW(pFDesc->Name, szName)) {
6380 HRESULT hr = TLB_AllocAndInitFuncDesc(
6382 &pBindPtr->lpfuncdesc,
6383 This->TypeAttr.typekind == TKIND_DISPATCH);
6386 *pDescKind = DESCKIND_FUNCDESC;
6387 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6388 ITypeInfo_AddRef(*ppTInfo);
6391 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6392 if (!strcmpW(pVDesc->Name, szName)) {
6393 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6396 *pDescKind = DESCKIND_VARDESC;
6397 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6398 ITypeInfo_AddRef(*ppTInfo);
6403 /* FIXME: search each inherited interface, not just the first */
6404 if (This->TypeAttr.cImplTypes) {
6405 /* recursive search */
6409 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6412 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6413 ITypeInfo_Release(pTInfo);
6417 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6418 ITypeComp_Release(pTComp);
6421 WARN("Could not search inherited interface!\n");
6423 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6424 return DISP_E_MEMBERNOTFOUND;
6427 static HRESULT WINAPI ITypeComp_fnBindType(
6431 ITypeInfo ** ppTInfo,
6432 ITypeComp ** ppTComp)
6434 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6436 /* strange behaviour (does nothing) but like the
6439 if (!ppTInfo || !ppTComp)
6448 static const ITypeCompVtbl tcompvt =
6451 ITypeComp_fnQueryInterface,
6453 ITypeComp_fnRelease,
6456 ITypeComp_fnBindType