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;
1689 TRACE_(typelib)("\n");
1691 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1693 for ( i = 0; i < cFuncs ; i++ )
1695 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1697 /* name, eventually add to a hash table */
1698 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1699 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1701 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1703 /* read the function information record */
1704 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1708 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1710 /* do the attributes */
1711 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1714 if ( nrattributes > 0 )
1716 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1718 if ( nrattributes > 1 )
1720 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1721 pFuncRec->OptAttr[1]) ;
1723 if ( nrattributes > 2 )
1725 if ( pFuncRec->FKCCIC & 0x2000 )
1727 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1731 (*pptfd)->Entry = MSFT_ReadString(pcx,
1732 pFuncRec->OptAttr[2]);
1734 if( nrattributes > 5 )
1736 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1738 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1741 pFuncRec->OptAttr[6],
1742 &(*pptfd)->pCustData);
1749 /* fill the FuncDesc Structure */
1750 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1751 offset + infolen + ( i + 1) * sizeof(INT));
1753 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1754 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1755 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1756 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1757 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1758 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1759 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1763 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1766 /* do the parameters/arguments */
1767 if(pFuncRec->nrargs)
1770 MSFT_ParameterInfo paraminfo;
1772 (*pptfd)->funcdesc.lprgelemdescParam =
1773 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1775 (*pptfd)->pParamDesc =
1776 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1778 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1779 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1781 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1783 TYPEDESC *lpArgTypeDesc;
1784 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1791 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1794 if (paraminfo.oName == -1)
1795 /* this occurs for [propput] or [propget] methods, so
1796 * we should just set the name of the parameter to the
1797 * name of the method. */
1798 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1800 (*pptfd)->pParamDesc[j].Name =
1801 MSFT_ReadName( pcx, paraminfo.oName );
1802 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1804 lpArgTypeDesc = &elemdesc->tdesc;
1806 /* resolve referenced type if any */
1807 while ( lpArgTypeDesc != NULL )
1809 switch ( lpArgTypeDesc->vt )
1812 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1816 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1819 case VT_USERDEFINED:
1820 MSFT_DoRefType(pcx, pTI,
1821 lpArgTypeDesc->u.hreftype);
1823 lpArgTypeDesc = NULL;
1827 lpArgTypeDesc = NULL;
1832 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1833 (pFuncRec->FKCCIC & 0x1000) )
1835 INT* pInt = (INT *)((char *)pFuncRec +
1837 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1839 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1841 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1842 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1844 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1848 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1851 pFuncRec->OptAttr[7+j],
1852 &(*pptfd)->pParamDesc[j].pCustData);
1855 /* SEEK value = jump to offset,
1856 * from there jump to the end of record,
1857 * go back by (j-1) arguments
1859 MSFT_ReadLEDWords( ¶minfo ,
1860 sizeof(MSFT_ParameterInfo), pcx,
1861 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1862 * sizeof(MSFT_ParameterInfo)));
1866 /* special treatment for dispinterfaces: this makes functions appear
1867 * to return their [retval] value when it is really returning an
1869 if ((pTI->TypeAttr.typekind == TKIND_DISPATCH) &&
1870 (*pptfd)->funcdesc.elemdescFunc.tdesc.vt == VT_HRESULT)
1872 if (pFuncRec->nrargs &&
1873 ((*pptfd)->funcdesc.lprgelemdescParam[pFuncRec->nrargs - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
1875 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[pFuncRec->nrargs - 1];
1876 if (elemdesc->tdesc.vt != VT_PTR)
1878 ERR_(typelib)("elemdesc should have started with VT_PTR instead of:\n");
1879 if (ERR_ON(typelib))
1880 dump_ELEMDESC(elemdesc);
1881 /* FIXME: return error */
1885 (*pptfd)->funcdesc.elemdescFunc = *elemdesc;
1887 /* dereference parameter */
1888 (*pptfd)->funcdesc.elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
1891 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs;
1894 (*pptfd)->funcdesc.elemdescFunc.tdesc.vt = VT_VOID;
1898 /* scode is not used: archaic win16 stuff FIXME: right? */
1899 (*pptfd)->funcdesc.cScodes = 0 ;
1900 (*pptfd)->funcdesc.lprgscode = NULL ;
1902 pptfd = & ((*pptfd)->next);
1903 recoffset += reclength;
1907 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1908 int cVars, int offset, TLBVarDesc ** pptvd)
1910 int infolen, nameoffset, reclength;
1912 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1916 TRACE_(typelib)("\n");
1918 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1919 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1920 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1921 recoffset += offset+sizeof(INT);
1922 for(i=0;i<cVars;i++){
1923 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1924 /* name, eventually add to a hash table */
1925 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1926 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1927 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1928 /* read the variable information record */
1929 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1931 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1933 if(reclength >(6*sizeof(INT)) )
1934 (*pptvd)->HelpContext=pVarRec->HelpContext;
1935 if(reclength >(7*sizeof(INT)) )
1936 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1937 if(reclength >(8*sizeof(INT)) )
1938 if(reclength >(9*sizeof(INT)) )
1939 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1940 /* fill the VarDesc Structure */
1941 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1942 offset + infolen + ( i + 1) * sizeof(INT));
1943 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1944 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1945 MSFT_GetTdesc(pcx, pVarRec->DataType,
1946 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1947 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1948 if(pVarRec->VarKind == VAR_CONST ){
1949 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1950 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1951 pVarRec->OffsValue, pcx);
1953 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1954 pptvd=&((*pptvd)->next);
1955 recoffset += reclength;
1958 /* fill in data for a hreftype (offset). When the referenced type is contained
1959 * in the typelib, it's just an (file) offset in the type info base dir.
1960 * If comes from import, it's an offset+1 in the ImpInfo table
1962 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1966 TLBRefType **ppRefType = &pTI->reflist;
1968 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1971 if((*ppRefType)->reference == offset)
1973 ppRefType = &(*ppRefType)->next;
1976 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1977 sizeof(**ppRefType));
1979 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1980 /* external typelib */
1981 MSFT_ImpInfo impinfo;
1982 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1984 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1986 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1987 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1988 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1989 if(pImpLib->offset==impinfo.oImpFile) break;
1990 pImpLib=pImpLib->next;
1993 (*ppRefType)->reference=offset;
1994 (*ppRefType)->pImpTLInfo = pImpLib;
1995 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1996 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1997 (*ppRefType)->index = TLB_REF_USE_GUID;
1999 (*ppRefType)->index = impinfo.oGuid;
2001 ERR("Cannot find a reference\n");
2002 (*ppRefType)->reference=-1;
2003 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2006 /* in this typelib */
2007 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2008 (*ppRefType)->reference=offset;
2009 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2013 /* process Implemented Interfaces of a com class */
2014 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2018 MSFT_RefRecord refrec;
2019 TLBImplType **ppImpl = &pTI->impltypelist;
2021 TRACE_(typelib)("\n");
2023 for(i=0;i<count;i++){
2024 if(offset<0) break; /* paranoia */
2025 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2026 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2027 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2028 (*ppImpl)->hRef = refrec.reftype;
2029 (*ppImpl)->implflags=refrec.flags;
2030 (*ppImpl)->ctCustData=
2031 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2032 offset=refrec.onext;
2033 ppImpl=&((*ppImpl)->next);
2037 * process a typeinfo record
2039 static ITypeInfoImpl * MSFT_DoTypeInfo(
2042 ITypeLibImpl * pLibInfo)
2044 MSFT_TypeInfoBase tiBase;
2045 ITypeInfoImpl *ptiRet;
2047 TRACE_(typelib)("count=%u\n", count);
2049 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2050 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2051 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2053 /* this is where we are coming from */
2054 ptiRet->pTypeLib = pLibInfo;
2055 ptiRet->index=count;
2056 /* fill in the typeattr fields */
2057 WARN("Assign constructor/destructor memid\n");
2059 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2060 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2061 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2062 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2063 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2064 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2065 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2066 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2067 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2068 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2069 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2070 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2071 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2072 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2073 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2074 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2075 MSFT_GetTdesc(pcx, tiBase.datatype1,
2076 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2079 /* IDLDESC idldescType; *//* never saw this one != zero */
2081 /* name, eventually add to a hash table */
2082 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2083 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2085 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2086 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2087 ptiRet->dwHelpContext=tiBase.helpcontext;
2089 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2090 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2092 /* note: InfoType's Help file and HelpStringDll come from the containing
2093 * library. Further HelpString and Docstring appear to be the same thing :(
2096 if(ptiRet->TypeAttr.cFuncs >0 )
2097 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2098 ptiRet->TypeAttr.cVars,
2099 tiBase.memoffset, & ptiRet->funclist);
2101 if(ptiRet->TypeAttr.cVars >0 )
2102 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2103 ptiRet->TypeAttr.cVars,
2104 tiBase.memoffset, & ptiRet->varlist);
2105 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2106 switch(ptiRet->TypeAttr.typekind)
2109 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2112 case TKIND_DISPATCH:
2113 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2115 if (tiBase.datatype1 != -1)
2117 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2118 ptiRet->impltypelist->hRef = tiBase.datatype1;
2121 { /* FIXME: This is a really bad hack to add IDispatch */
2122 const char* szStdOle = "stdole2.tlb\0";
2123 int nStdOleLen = strlen(szStdOle);
2124 TLBRefType **ppRef = &ptiRet->reflist;
2127 if((*ppRef)->reference == -1)
2129 ppRef = &(*ppRef)->next;
2132 *ppRef = TLB_Alloc(sizeof(**ppRef));
2133 (*ppRef)->guid = IID_IDispatch;
2134 (*ppRef)->reference = -1;
2135 (*ppRef)->index = TLB_REF_USE_GUID;
2136 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2137 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2138 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2141 MultiByteToWideChar(CP_ACP,
2145 (*ppRef)->pImpTLInfo->name,
2146 SysStringLen((*ppRef)->pImpTLInfo->name));
2148 (*ppRef)->pImpTLInfo->lcid = 0;
2149 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2150 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2155 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2156 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2157 ptiRet->impltypelist->hRef = tiBase.datatype1;
2162 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2164 TRACE_(typelib)("%s guid: %s kind:%s\n",
2165 debugstr_w(ptiRet->Name),
2166 debugstr_guid(&ptiRet->TypeAttr.guid),
2167 typekind_desc[ptiRet->TypeAttr.typekind]);
2172 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2173 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2174 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2177 static ITypeLibImpl *tlb_cache_first;
2178 static CRITICAL_SECTION cache_section;
2179 static CRITICAL_SECTION_DEBUG cache_section_debug =
2181 0, 0, &cache_section,
2182 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2183 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2185 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2188 /****************************************************************************
2191 * find the type of the typelib file and map the typelib resource into
2194 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2195 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2196 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2198 ITypeLibImpl *entry;
2199 int ret = TYPE_E_CANTLOADLIBRARY;
2200 DWORD dwSignature = 0;
2203 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2207 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2208 EnterCriticalSection(&cache_section);
2209 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2211 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2213 TRACE("cache hit\n");
2214 *ppTypeLib = (ITypeLib2*)entry;
2215 ITypeLib_AddRef(*ppTypeLib);
2216 LeaveCriticalSection(&cache_section);
2220 LeaveCriticalSection(&cache_section);
2222 /* check the signature of the file */
2223 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2224 if (INVALID_HANDLE_VALUE != hFile)
2226 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2229 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2232 /* retrieve file size */
2233 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2235 /* first try to load as *.tlb */
2236 dwSignature = FromLEDWord(*((DWORD*) pBase));
2237 if ( dwSignature == MSFT_SIGNATURE)
2239 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2241 else if ( dwSignature == SLTG_SIGNATURE)
2243 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2245 UnmapViewOfFile(pBase);
2247 CloseHandle(hMapping);
2253 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2256 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2257 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2259 /* find the typelibrary resource*/
2260 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2261 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2264 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2265 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2268 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2271 LPVOID pBase = LockResource(hGlobal);
2272 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2276 /* try to load as incore resource */
2277 dwSignature = FromLEDWord(*((DWORD*) pBase));
2278 if ( dwSignature == MSFT_SIGNATURE)
2280 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2282 else if ( dwSignature == SLTG_SIGNATURE)
2284 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2288 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2291 FreeResource( hGlobal );
2294 FreeLibrary(hinstDLL);
2299 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2301 TRACE("adding to cache\n");
2302 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2303 lstrcpyW(impl->path, pszFileName);
2304 /* We should really canonicalise the path here. */
2305 impl->index = index;
2307 /* FIXME: check if it has added already in the meantime */
2308 EnterCriticalSection(&cache_section);
2309 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2311 tlb_cache_first = impl;
2312 LeaveCriticalSection(&cache_section);
2315 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2320 /*================== ITypeLib(2) Methods ===================================*/
2322 /****************************************************************************
2323 * ITypeLib2_Constructor_MSFT
2325 * loading an MSFT typelib from an in-memory image
2327 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2331 MSFT_Header tlbHeader;
2332 MSFT_SegDir tlbSegDir;
2333 ITypeLibImpl * pTypeLibImpl;
2335 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2337 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2338 if (!pTypeLibImpl) return NULL;
2340 pTypeLibImpl->lpVtbl = &tlbvt;
2341 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2342 pTypeLibImpl->ref = 1;
2344 /* get pointer to beginning of typelib data */
2348 cx.pLibInfo = pTypeLibImpl;
2349 cx.length = dwTLBLength;
2352 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2354 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2355 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2356 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2359 /* there is a small amount of information here until the next important
2361 * the segment directory . Try to calculate the amount of data */
2362 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2364 /* now read the segment directory */
2365 TRACE("read segment directory (at %ld)\n",lPSegDir);
2366 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2367 cx.pTblDir = &tlbSegDir;
2369 /* just check two entries */
2370 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2372 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2373 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2377 /* now fill our internal data */
2378 /* TLIBATTR fields */
2379 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2381 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2382 /* Windows seems to have zero here, is this correct? */
2383 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2384 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2386 pTypeLibImpl->LibAttr.lcid = 0;
2388 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2389 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2390 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2391 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2393 /* name, eventually add to a hash table */
2394 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2397 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2398 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2400 if( tlbHeader.varflags & HELPDLLFLAG)
2403 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2404 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2407 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2410 if(tlbHeader.CustomDataOffset >= 0)
2412 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2415 /* fill in typedescriptions */
2416 if(tlbSegDir.pTypdescTab.length > 0)
2418 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2420 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2421 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2424 /* FIXME: add several sanity checks here */
2425 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2426 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2428 /* FIXME: check safearray */
2430 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2432 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2434 else if(td[0] == VT_CARRAY)
2436 /* array descr table here */
2437 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2439 else if(td[0] == VT_USERDEFINED)
2441 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2443 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2446 /* second time around to fill the array subscript info */
2449 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2450 if(tlbSegDir.pArrayDescriptions.offset>0)
2452 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2453 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2456 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2458 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2460 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2462 for(j = 0; j<td[2]; j++)
2464 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2465 sizeof(INT), &cx, DO_NOT_SEEK);
2466 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2467 sizeof(INT), &cx, DO_NOT_SEEK);
2472 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2473 ERR("didn't find array description data\n");
2478 /* imported type libs */
2479 if(tlbSegDir.pImpFiles.offset>0)
2481 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2482 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2485 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2490 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2491 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2492 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2494 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2495 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2496 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2497 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2500 name = TLB_Alloc(size+1);
2501 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2502 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2503 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2504 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2507 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2508 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2510 ppImpLib = &(*ppImpLib)->next;
2515 if(tlbHeader.nrtypeinfos >= 0 )
2517 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2518 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2521 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2523 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2525 ppTI = &((*ppTI)->next);
2526 (pTypeLibImpl->TypeInfoCount)++;
2530 TRACE("(%p)\n", pTypeLibImpl);
2531 return (ITypeLib2*) pTypeLibImpl;
2535 static BSTR TLB_MultiByteToBSTR(char *ptr)
2541 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2542 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2543 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2544 ret = SysAllocString(nameW);
2545 HeapFree(GetProcessHeap(), 0, nameW);
2549 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2555 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2556 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2560 guid->Data4[0] = s >> 8;
2561 guid->Data4[1] = s & 0xff;
2564 for(i = 0; i < 6; i++) {
2565 memcpy(b, str + 24 + 2 * i, 2);
2566 guid->Data4[i + 2] = strtol(b, NULL, 16);
2571 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2578 bytelen = *(WORD*)ptr;
2579 if(bytelen == 0xffff) return 2;
2580 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2581 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2582 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2583 *pBstr = SysAllocStringLen(nameW, len);
2584 HeapFree(GetProcessHeap(), 0, nameW);
2588 static WORD SLTG_ReadStringA(char *ptr, char **str)
2593 bytelen = *(WORD*)ptr;
2594 if(bytelen == 0xffff) return 2;
2595 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2596 memcpy(*str, ptr + 2, bytelen);
2597 (*str)[bytelen] = '\0';
2601 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2603 char *ptr = pLibBlk;
2606 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2607 FIXME("libblk magic = %04x\n", w);
2612 if((w = *(WORD*)ptr) != 0xffff) {
2613 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2618 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2620 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2622 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2625 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2628 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2629 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2631 pTypeLibImpl->LibAttr.lcid = 0;
2634 ptr += 4; /* skip res12 */
2636 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2639 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2642 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2645 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2646 ptr += sizeof(GUID);
2648 return ptr - (char*)pLibBlk;
2651 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2654 TYPEDESC *pTD = &pElem->tdesc;
2656 /* Handle [in/out] first */
2657 if((*pType & 0xc000) == 0xc000)
2658 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2659 else if(*pType & 0x8000)
2660 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2661 else if(*pType & 0x4000)
2662 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2664 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2667 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2670 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2673 if((*pType & 0xe00) == 0xe00) {
2675 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2677 pTD = pTD->u.lptdesc;
2679 switch(*pType & 0x7f) {
2682 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2684 pTD = pTD->u.lptdesc;
2687 case VT_USERDEFINED:
2688 pTD->vt = VT_USERDEFINED;
2689 pTD->u.hreftype = *(++pType) / 4;
2695 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2698 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2700 pTD->vt = VT_CARRAY;
2701 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2703 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2704 pTD->u.lpadesc->cDims = pSA->cDims;
2705 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2706 pSA->cDims * sizeof(SAFEARRAYBOUND));
2708 pTD = &pTD->u.lpadesc->tdescElem;
2714 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2718 pTD->vt = VT_SAFEARRAY;
2719 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2721 pTD = pTD->u.lptdesc;
2725 pTD->vt = *pType & 0x7f;
2735 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2740 TLBRefType **ppRefType;
2742 if(pRef->magic != SLTG_REF_MAGIC) {
2743 FIXME("Ref magic = %x\n", pRef->magic);
2746 name = ( (char*)(&pRef->names) + pRef->number);
2748 ppRefType = &pTI->reflist;
2749 for(ref = 0; ref < pRef->number >> 3; ref++) {
2751 unsigned int lib_offs, type_num;
2753 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2754 sizeof(**ppRefType));
2756 name += SLTG_ReadStringA(name, &refname);
2757 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2758 FIXME("Can't sscanf ref\n");
2759 if(lib_offs != 0xffff) {
2760 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2763 if((*import)->offset == lib_offs)
2765 import = &(*import)->next;
2768 char fname[MAX_PATH+1];
2771 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2773 (*import)->offset = lib_offs;
2774 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2776 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2777 &(*import)->wVersionMajor,
2778 &(*import)->wVersionMinor,
2779 &(*import)->lcid, fname) != 4) {
2780 FIXME("can't sscanf ref %s\n",
2781 pNameTable + lib_offs + 40);
2783 len = strlen(fname);
2784 if(fname[len-1] != '#')
2785 FIXME("fname = %s\n", fname);
2786 fname[len-1] = '\0';
2787 (*import)->name = TLB_MultiByteToBSTR(fname);
2789 (*ppRefType)->pImpTLInfo = *import;
2790 } else { /* internal ref */
2791 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2793 (*ppRefType)->reference = ref;
2794 (*ppRefType)->index = type_num;
2796 HeapFree(GetProcessHeap(), 0, refname);
2797 ppRefType = &(*ppRefType)->next;
2799 if((BYTE)*name != SLTG_REF_MAGIC)
2800 FIXME("End of ref block magic = %x\n", *name);
2801 dump_TLBRefType(pTI->reflist);
2804 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2807 SLTG_ImplInfo *info;
2808 TLBImplType **ppImplType = &pTI->impltypelist;
2809 /* I don't really get this structure, usually it's 0x16 bytes
2810 long, but iuser.tlb contains some that are 0x18 bytes long.
2811 That's ok because we can use the next ptr to jump to the next
2812 one. But how do we know the length of the last one? The WORD
2813 at offs 0x8 might be the clue. For now I'm just assuming that
2814 the last one is the regular 0x16 bytes. */
2816 info = (SLTG_ImplInfo*)pBlk;
2818 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2819 sizeof(**ppImplType));
2820 (*ppImplType)->hRef = info->ref;
2821 (*ppImplType)->implflags = info->impltypeflags;
2822 pTI->TypeAttr.cImplTypes++;
2823 ppImplType = &(*ppImplType)->next;
2825 if(info->next == 0xffff)
2828 FIXME("Interface inheriting more than one interface\n");
2829 info = (SLTG_ImplInfo*)(pBlk + info->next);
2831 info++; /* see comment at top of function */
2835 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2838 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2839 SLTG_MemberHeader *pMemHeader;
2840 char *pFirstItem, *pNextItem;
2842 if(pTIHeader->href_table != 0xffffffff) {
2843 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2848 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2850 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2852 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2853 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2856 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2860 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2863 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2864 SLTG_MemberHeader *pMemHeader;
2865 SLTG_Function *pFunc;
2866 char *pFirstItem, *pNextItem;
2867 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2870 if(pTIHeader->href_table != 0xffffffff) {
2871 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2875 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2877 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2879 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2880 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2883 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2884 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2889 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2890 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2891 FIXME("func magic = %02x\n", pFunc->magic);
2894 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2895 sizeof(**ppFuncDesc));
2896 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2898 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2899 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2900 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2901 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2902 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2903 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2905 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2906 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2908 if(pFunc->retnextopt & 0x80)
2909 pType = &pFunc->rettype;
2911 pType = (WORD*)(pFirstItem + pFunc->rettype);
2914 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2916 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2917 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2918 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2919 (*ppFuncDesc)->pParamDesc =
2920 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2921 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2923 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2925 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2926 char *paramName = pNameTable + *pArg;
2928 /* If arg type follows then paramName points to the 2nd
2929 letter of the name, else the next WORD is an offset to
2930 the arg type and paramName points to the first letter.
2931 So let's take one char off paramName and see if we're
2932 pointing at an alpha-numeric char. However if *pArg is
2933 0xffff or 0xfffe then the param has no name, the former
2934 meaning that the next WORD is the type, the latter
2935 meaning the the next WORD is an offset to the type. */
2940 else if(*pArg == 0xfffe) {
2944 else if(paramName[-1] && !isalnum(paramName[-1]))
2949 if(HaveOffs) { /* the next word is an offset to type */
2950 pType = (WORD*)(pFirstItem + *pArg);
2951 SLTG_DoType(pType, pFirstItem,
2952 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2957 pArg = SLTG_DoType(pArg, pFirstItem,
2958 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2961 /* Are we an optional param ? */
2962 if((*ppFuncDesc)->funcdesc.cParams - param <=
2963 (*ppFuncDesc)->funcdesc.cParamsOpt)
2964 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2967 (*ppFuncDesc)->pParamDesc[param].Name =
2968 TLB_MultiByteToBSTR(paramName);
2972 ppFuncDesc = &((*ppFuncDesc)->next);
2973 if(pFunc->next == 0xffff) break;
2975 pTI->TypeAttr.cFuncs = num;
2976 dump_TLBFuncDesc(pTI->funclist);
2977 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2980 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2983 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2984 SLTG_MemberHeader *pMemHeader;
2985 SLTG_RecordItem *pItem;
2987 TLBVarDesc **ppVarDesc = &pTI->varlist;
2992 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2994 pFirstItem = (char*)(pMemHeader + 1);
2995 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2996 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2997 if(pItem->magic != SLTG_RECORD_MAGIC) {
2998 FIXME("record magic = %02x\n", pItem->magic);
3001 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3002 sizeof(**ppVarDesc));
3003 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3004 (*ppVarDesc)->vardesc.memid = pItem->memid;
3005 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3006 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3008 if(pItem->typepos == 0x02)
3009 pType = &pItem->type;
3010 else if(pItem->typepos == 0x00)
3011 pType = (WORD*)(pFirstItem + pItem->type);
3013 FIXME("typepos = %02x\n", pItem->typepos);
3017 SLTG_DoType(pType, pFirstItem,
3018 &(*ppVarDesc)->vardesc.elemdescVar);
3020 /* FIXME("helpcontext, helpstring\n"); */
3022 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3024 ppVarDesc = &((*ppVarDesc)->next);
3025 if(pItem->next == 0xffff) break;
3027 pTI->TypeAttr.cVars = num;
3028 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3031 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3034 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3035 SLTG_MemberHeader *pMemHeader;
3036 SLTG_AliasItem *pItem;
3039 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3040 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3043 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3044 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3045 if (pItem->vt == 0xffff) {
3046 if (i<(pMemHeader->cbExtra/4-1))
3047 FIXME("Endmarker too early in process alias data!\n");
3051 FIXME("Chain extends over last entry?\n");
3054 if (pItem->vt == VT_USERDEFINED) {
3055 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3056 /* guessing here ... */
3057 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3058 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3061 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3062 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3066 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3069 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3072 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3073 SLTG_MemberHeader *pMemHeader;
3074 SLTG_AliasItem *pItem;
3076 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3077 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3078 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3079 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3080 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3083 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3086 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3087 SLTG_MemberHeader *pMemHeader;
3088 SLTG_EnumItem *pItem;
3090 TLBVarDesc **ppVarDesc = &pTI->varlist;
3093 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3095 pFirstItem = (char*)(pMemHeader + 1);
3096 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3097 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3098 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3099 FIXME("enumitem magic = %04x\n", pItem->magic);
3102 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3103 sizeof(**ppVarDesc));
3104 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3105 (*ppVarDesc)->vardesc.memid = pItem->memid;
3106 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3108 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3109 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3110 *(INT*)(pItem->value + pFirstItem);
3111 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3112 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3113 /* FIXME("helpcontext, helpstring\n"); */
3115 ppVarDesc = &((*ppVarDesc)->next);
3116 if(pItem->next == 0xffff) break;
3118 pTI->TypeAttr.cVars = num;
3119 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3122 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3123 managable copy of it into this */
3136 } SLTG_InternalOtherTypeInfo;
3138 /****************************************************************************
3139 * ITypeLib2_Constructor_SLTG
3141 * loading a SLTG typelib from an in-memory image
3143 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3145 ITypeLibImpl *pTypeLibImpl;
3146 SLTG_Header *pHeader;
3147 SLTG_BlkEntry *pBlkEntry;
3151 LPVOID pBlk, pFirstBlk;
3152 SLTG_LibBlk *pLibBlk;
3153 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3154 char *pAfterOTIBlks = NULL;
3155 char *pNameTable, *ptr;
3158 ITypeInfoImpl **ppTypeInfoImpl;
3160 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3162 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3163 if (!pTypeLibImpl) return NULL;
3165 pTypeLibImpl->lpVtbl = &tlbvt;
3166 pTypeLibImpl->ref = 1;
3170 TRACE_(typelib)("header:\n");
3171 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3172 pHeader->nrOfFileBlks );
3173 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3174 FIXME("Header type magic 0x%08lx not supported.\n",
3175 pHeader->SLTG_magic);
3179 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3180 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3182 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3183 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3185 /* Next we have a magic block */
3186 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3188 /* Let's see if we're still in sync */
3189 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3190 sizeof(SLTG_COMPOBJ_MAGIC))) {
3191 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3194 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3195 sizeof(SLTG_DIR_MAGIC))) {
3196 FIXME("dir magic = %s\n", pMagic->dir_magic);
3200 pIndex = (SLTG_Index*)(pMagic+1);
3202 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3204 pFirstBlk = (LPVOID)(pPad9 + 1);
3206 /* We'll set up a ptr to the main library block, which is the last one. */
3208 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3209 pBlkEntry[order].next != 0;
3210 order = pBlkEntry[order].next - 1, i++) {
3211 pBlk = (char*)pBlk + pBlkEntry[order].len;
3215 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3217 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3222 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3224 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3225 sizeof(*pOtherTypeInfoBlks) *
3226 pTypeLibImpl->TypeInfoCount);
3229 ptr = (char*)pLibBlk + len;
3231 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3235 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3237 w = *(WORD*)(ptr + 2);
3240 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3242 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3243 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3245 w = *(WORD*)(ptr + 4 + len);
3247 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3249 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3251 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3252 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3254 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3255 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3256 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3258 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3260 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3263 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3264 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3265 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3266 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3267 len += sizeof(SLTG_OtherTypeInfo);
3271 pAfterOTIBlks = ptr;
3273 /* Skip this WORD and get the next DWORD */
3274 len = *(DWORD*)(pAfterOTIBlks + 2);
3276 /* Now add this to pLibBLk look at what we're pointing at and
3277 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3278 dust and we should be pointing at the beginning of the name
3281 pNameTable = (char*)pLibBlk + len;
3283 switch(*(WORD*)pNameTable) {
3290 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3294 pNameTable += 0x216;
3298 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3300 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3303 /* Hopefully we now have enough ptrs set up to actually read in
3304 some TypeInfos. It's not clear which order to do them in, so
3305 I'll just follow the links along the BlkEntry chain and read
3306 them in in the order in which they're in the file */
3308 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3310 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3311 pBlkEntry[order].next != 0;
3312 order = pBlkEntry[order].next - 1, i++) {
3314 SLTG_TypeInfoHeader *pTIHeader;
3315 SLTG_TypeInfoTail *pTITail;
3317 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3318 pOtherTypeInfoBlks[i].index_name)) {
3319 FIXME("Index strings don't match\n");
3324 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3325 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3328 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3329 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3330 (*ppTypeInfoImpl)->index = i;
3331 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3332 pOtherTypeInfoBlks[i].name_offs +
3334 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3335 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3337 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3338 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3339 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3340 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3341 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3343 if((pTIHeader->typeflags1 & 7) != 2)
3344 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3345 if(pTIHeader->typeflags3 != 2)
3346 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3348 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3349 debugstr_w((*ppTypeInfoImpl)->Name),
3350 typekind_desc[pTIHeader->typekind],
3351 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3352 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3354 switch(pTIHeader->typekind) {
3356 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3360 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3363 case TKIND_INTERFACE:
3364 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3368 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3372 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3373 if (pTITail->tdescalias_vt)
3374 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3377 case TKIND_DISPATCH:
3378 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3382 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3388 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3389 but we've already set those */
3390 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3391 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3392 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3394 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3416 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3417 pBlk = (char*)pBlk + pBlkEntry[order].len;
3420 if(i != pTypeLibImpl->TypeInfoCount) {
3421 FIXME("Somehow processed %d TypeInfos\n", i);
3425 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3426 return (ITypeLib2*)pTypeLibImpl;
3429 /* ITypeLib::QueryInterface
3431 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3436 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3438 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3441 if(IsEqualIID(riid, &IID_IUnknown) ||
3442 IsEqualIID(riid,&IID_ITypeLib)||
3443 IsEqualIID(riid,&IID_ITypeLib2))
3450 ITypeLib2_AddRef(iface);
3451 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3454 TRACE("-- Interface: E_NOINTERFACE\n");
3455 return E_NOINTERFACE;
3460 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3462 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3463 ULONG ref = InterlockedIncrement(&This->ref);
3465 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3470 /* ITypeLib::Release
3472 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3474 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3475 ULONG ref = InterlockedDecrement(&This->ref);
3477 TRACE("(%p)->(%lu)\n",This, ref);
3481 /* remove cache entry */
3482 TRACE("removing from cache list\n");
3483 EnterCriticalSection(&cache_section);
3484 if (This->next) This->next->prev = This->prev;
3485 if (This->prev) This->prev->next = This->next;
3486 else tlb_cache_first = This->next;
3487 LeaveCriticalSection(&cache_section);
3489 /* FIXME destroy child objects */
3490 TRACE(" destroying ITypeLib(%p)\n",This);
3494 SysFreeString(This->Name);
3498 if (This->DocString)
3500 SysFreeString(This->DocString);
3501 This->DocString = NULL;
3506 SysFreeString(This->HelpFile);
3507 This->HelpFile = NULL;
3510 if (This->HelpStringDll)
3512 SysFreeString(This->HelpStringDll);
3513 This->HelpStringDll = NULL;
3516 if (This->pTypeInfo) /* can be NULL */
3517 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3518 HeapFree(GetProcessHeap(),0,This);
3525 /* ITypeLib::GetTypeInfoCount
3527 * Returns the number of type descriptions in the type library
3529 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3531 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3532 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3533 return This->TypeInfoCount;
3536 /* ITypeLib::GetTypeInfo
3538 * retrieves the specified type description in the library.
3540 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3543 ITypeInfo **ppTInfo)
3547 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3548 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3550 TRACE("(%p)->(index=%d)\n", This, index);
3552 if (!ppTInfo) return E_INVALIDARG;
3554 /* search element n in list */
3555 for(i=0; i < index; i++)
3557 pTypeInfo = pTypeInfo->next;
3560 TRACE("-- element not found\n");
3561 return TYPE_E_ELEMENTNOTFOUND;
3565 *ppTInfo = (ITypeInfo *) pTypeInfo;
3567 ITypeInfo_AddRef(*ppTInfo);
3568 TRACE("-- found (%p)\n",*ppTInfo);
3573 /* ITypeLibs::GetTypeInfoType
3575 * Retrieves the type of a type description.
3577 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3582 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3584 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3586 TRACE("(%p) index %d\n", This, index);
3588 if(!pTKind) return E_INVALIDARG;
3590 /* search element n in list */
3591 for(i=0; i < index; i++)
3595 TRACE("-- element not found\n");
3596 return TYPE_E_ELEMENTNOTFOUND;
3598 pTInfo = pTInfo->next;
3601 *pTKind = pTInfo->TypeAttr.typekind;
3602 TRACE("-- found Type (%d)\n", *pTKind);
3606 /* ITypeLib::GetTypeInfoOfGuid
3608 * Retrieves the type description that corresponds to the specified GUID.
3611 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3614 ITypeInfo **ppTInfo)
3616 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3617 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3619 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3621 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3623 /* search linked list for guid */
3624 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3626 pTypeInfo = pTypeInfo->next;
3630 /* end of list reached */
3631 TRACE("-- element not found\n");
3632 return TYPE_E_ELEMENTNOTFOUND;
3636 TRACE("-- found (%p, %s)\n",
3638 debugstr_w(pTypeInfo->Name));
3640 *ppTInfo = (ITypeInfo*)pTypeInfo;
3641 ITypeInfo_AddRef(*ppTInfo);
3645 /* ITypeLib::GetLibAttr
3647 * Retrieves the structure that contains the library's attributes.
3650 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3652 LPTLIBATTR *ppTLibAttr)
3654 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3655 TRACE("(%p)\n",This);
3656 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3657 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3661 /* ITypeLib::GetTypeComp
3663 * Enables a client compiler to bind to a library's types, variables,
3664 * constants, and global functions.
3667 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3669 ITypeComp **ppTComp)
3671 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3673 TRACE("(%p)->(%p)\n",This,ppTComp);
3674 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3675 ITypeComp_AddRef(*ppTComp);
3680 /* ITypeLib::GetDocumentation
3682 * Retrieves the library's documentation string, the complete Help file name
3683 * and path, and the context identifier for the library Help topic in the Help
3686 * On a successful return all non-null BSTR pointers will have been set,
3689 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3693 BSTR *pBstrDocString,
3694 DWORD *pdwHelpContext,
3695 BSTR *pBstrHelpFile)
3697 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3699 HRESULT result = E_INVALIDARG;
3704 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3706 pBstrName, pBstrDocString,
3707 pdwHelpContext, pBstrHelpFile);
3711 /* documentation for the typelib */
3716 if(!(*pBstrName = SysAllocString(This->Name)))
3724 if (This->DocString)
3726 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3729 else if (This->Name)
3731 if(!(*pBstrDocString = SysAllocString(This->Name)))
3735 *pBstrDocString = NULL;
3739 *pdwHelpContext = This->dwHelpContext;
3745 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3749 *pBstrHelpFile = NULL;
3756 /* for a typeinfo */
3757 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3759 if(SUCCEEDED(result))
3761 result = ITypeInfo_GetDocumentation(pTInfo,
3765 pdwHelpContext, pBstrHelpFile);
3767 ITypeInfo_Release(pTInfo);
3772 if (pBstrDocString) SysFreeString (*pBstrDocString);
3774 if (pBstrName) SysFreeString (*pBstrName);
3776 return STG_E_INSUFFICIENTMEMORY;
3781 * Indicates whether a passed-in string contains the name of a type or member
3782 * described in the library.
3785 static HRESULT WINAPI ITypeLib2_fnIsName(
3791 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3792 ITypeInfoImpl *pTInfo;
3793 TLBFuncDesc *pFInfo;
3796 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3798 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3802 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3803 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3804 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3805 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3806 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3807 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3808 goto ITypeLib2_fnIsName_exit;
3810 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3811 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3816 ITypeLib2_fnIsName_exit:
3817 TRACE("(%p)slow! search for %s: %s found!\n", This,
3818 debugstr_w(szNameBuf), *pfName?"NOT":"");
3823 /* ITypeLib::FindName
3825 * Finds occurrences of a type description in a type library. This may be used
3826 * to quickly verify that a name exists in a type library.
3829 static HRESULT WINAPI ITypeLib2_fnFindName(
3833 ITypeInfo **ppTInfo,
3837 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3838 ITypeInfoImpl *pTInfo;
3839 TLBFuncDesc *pFInfo;
3842 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3844 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3845 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3846 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3847 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3848 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3849 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3850 goto ITypeLib2_fnFindName_exit;
3853 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3854 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3856 ITypeLib2_fnFindName_exit:
3857 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3858 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3861 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3862 This, *pcFound, debugstr_w(szNameBuf), j);
3869 /* ITypeLib::ReleaseTLibAttr
3871 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3874 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3876 TLIBATTR *pTLibAttr)
3878 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3879 TRACE("freeing (%p)\n",This);
3880 HeapFree(GetProcessHeap(),0,pTLibAttr);
3884 /* ITypeLib2::GetCustData
3886 * gets the custom data
3888 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3893 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3894 TLBCustData *pCData;
3896 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3898 if( IsEqualIID(guid, &pCData->guid)) break;
3901 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3905 VariantInit( pVarVal);
3906 VariantCopy( pVarVal, &pCData->data);
3909 return E_INVALIDARG; /* FIXME: correct? */
3912 /* ITypeLib2::GetLibStatistics
3914 * Returns statistics about a type library that are required for efficient
3915 * sizing of hash tables.
3918 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3920 ULONG *pcUniqueNames,
3921 ULONG *pcchUniqueNames)
3923 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3925 FIXME("(%p): stub!\n", This);
3927 if(pcUniqueNames) *pcUniqueNames=1;
3928 if(pcchUniqueNames) *pcchUniqueNames=1;
3932 /* ITypeLib2::GetDocumentation2
3934 * Retrieves the library's documentation string, the complete Help file name
3935 * and path, the localization context to use, and the context ID for the
3936 * library Help topic in the Help file.
3939 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3943 BSTR *pbstrHelpString,
3944 DWORD *pdwHelpStringContext,
3945 BSTR *pbstrHelpStringDll)
3947 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3951 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3953 /* the help string should be obtained from the helpstringdll,
3954 * using the _DLLGetDocumentation function, based on the supplied
3955 * lcid. Nice to do sometime...
3959 /* documentation for the typelib */
3961 *pbstrHelpString=SysAllocString(This->DocString);
3962 if(pdwHelpStringContext)
3963 *pdwHelpStringContext=This->dwHelpContext;
3964 if(pbstrHelpStringDll)
3965 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3971 /* for a typeinfo */
3972 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3974 if(SUCCEEDED(result))
3976 ITypeInfo2 * pTInfo2;
3977 result = ITypeInfo_QueryInterface(pTInfo,
3979 (LPVOID*) &pTInfo2);
3981 if(SUCCEEDED(result))
3983 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3987 pdwHelpStringContext,
3988 pbstrHelpStringDll);
3990 ITypeInfo2_Release(pTInfo2);
3993 ITypeInfo_Release(pTInfo);
3999 /* ITypeLib2::GetAllCustData
4001 * Gets all custom data items for the library.
4004 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4006 CUSTDATA *pCustData)
4008 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4009 TLBCustData *pCData;
4011 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4012 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4013 if(pCustData->prgCustData ){
4014 pCustData->cCustData=This->ctCustData;
4015 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4016 pCustData->prgCustData[i].guid=pCData->guid;
4017 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4020 ERR(" OUT OF MEMORY!\n");
4021 return E_OUTOFMEMORY;
4026 static const ITypeLib2Vtbl tlbvt = {
4027 ITypeLib2_fnQueryInterface,
4029 ITypeLib2_fnRelease,
4030 ITypeLib2_fnGetTypeInfoCount,
4031 ITypeLib2_fnGetTypeInfo,
4032 ITypeLib2_fnGetTypeInfoType,
4033 ITypeLib2_fnGetTypeInfoOfGuid,
4034 ITypeLib2_fnGetLibAttr,
4035 ITypeLib2_fnGetTypeComp,
4036 ITypeLib2_fnGetDocumentation,
4038 ITypeLib2_fnFindName,
4039 ITypeLib2_fnReleaseTLibAttr,
4041 ITypeLib2_fnGetCustData,
4042 ITypeLib2_fnGetLibStatistics,
4043 ITypeLib2_fnGetDocumentation2,
4044 ITypeLib2_fnGetAllCustData
4048 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4050 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4052 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4055 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4057 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4059 return ITypeLib2_AddRef((ITypeLib2 *)This);
4062 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4064 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4066 return ITypeLib2_Release((ITypeLib2 *)This);
4069 static HRESULT WINAPI ITypeLibComp_fnBind(
4074 ITypeInfo ** ppTInfo,
4075 DESCKIND * pDescKind,
4078 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4079 ITypeInfoImpl *pTypeInfo;
4081 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4083 *pDescKind = DESCKIND_NONE;
4084 pBindPtr->lptcomp = NULL;
4087 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4089 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4091 /* FIXME: check wFlags here? */
4092 /* FIXME: we should use a hash table to look this info up using lHash
4093 * instead of an O(n) search */
4094 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4095 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4097 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4099 *pDescKind = DESCKIND_TYPECOMP;
4100 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4101 ITypeComp_AddRef(pBindPtr->lptcomp);
4102 TRACE("module or enum: %s\n", debugstr_w(szName));
4107 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4108 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4110 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4113 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4114 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4116 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4121 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4122 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4124 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4126 ITypeInfo *subtypeinfo;
4128 DESCKIND subdesckind;
4130 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4131 &subtypeinfo, &subdesckind, &subbindptr);
4132 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4134 TYPEDESC tdesc_appobject =
4141 const VARDESC vardesc_appobject =
4144 NULL, /* lpstrSchema */
4159 VAR_STATIC /* varkind */
4162 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4164 /* cleanup things filled in by Bind call so we can put our
4165 * application object data in there instead */
4166 switch (subdesckind)
4168 case DESCKIND_FUNCDESC:
4169 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4171 case DESCKIND_VARDESC:
4172 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4177 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4179 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4183 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4184 *ppTInfo = (ITypeInfo *)pTypeInfo;
4185 ITypeInfo_AddRef(*ppTInfo);
4191 TRACE("name not found %s\n", debugstr_w(szName));
4195 static HRESULT WINAPI ITypeLibComp_fnBindType(
4199 ITypeInfo ** ppTInfo,
4200 ITypeComp ** ppTComp)
4202 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4206 static const ITypeCompVtbl tlbtcvt =
4209 ITypeLibComp_fnQueryInterface,
4210 ITypeLibComp_fnAddRef,
4211 ITypeLibComp_fnRelease,
4213 ITypeLibComp_fnBind,
4214 ITypeLibComp_fnBindType
4217 /*================== ITypeInfo(2) Methods ===================================*/
4218 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4220 ITypeInfoImpl * pTypeInfoImpl;
4222 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4225 pTypeInfoImpl->lpVtbl = &tinfvt;
4226 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4227 pTypeInfoImpl->ref=1;
4229 TRACE("(%p)\n", pTypeInfoImpl);
4230 return (ITypeInfo2*) pTypeInfoImpl;
4233 /* ITypeInfo::QueryInterface
4235 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4240 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4242 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4245 if(IsEqualIID(riid, &IID_IUnknown) ||
4246 IsEqualIID(riid,&IID_ITypeInfo)||
4247 IsEqualIID(riid,&IID_ITypeInfo2))
4251 ITypeInfo_AddRef(iface);
4252 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4255 TRACE("-- Interface: E_NOINTERFACE\n");
4256 return E_NOINTERFACE;
4259 /* ITypeInfo::AddRef
4261 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4263 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4264 ULONG ref = InterlockedIncrement(&This->ref);
4266 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4268 TRACE("(%p)->ref is %lu\n",This, ref);
4272 /* ITypeInfo::Release
4274 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4276 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4277 ULONG ref = InterlockedDecrement(&This->ref);
4279 TRACE("(%p)->(%lu)\n",This, ref);
4282 /* We don't release ITypeLib when ref=0 because
4283 it means that function is called by ITypeLib2_Release */
4284 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4286 FIXME("destroy child objects\n");
4288 TRACE("destroying ITypeInfo(%p)\n",This);
4291 SysFreeString(This->Name);
4295 if (This->DocString)
4297 SysFreeString(This->DocString);
4298 This->DocString = 0;
4303 SysFreeString(This->DllName);
4309 ITypeInfo_Release((ITypeInfo*)This->next);
4312 HeapFree(GetProcessHeap(),0,This);
4318 /* ITypeInfo::GetTypeAttr
4320 * Retrieves a TYPEATTR structure that contains the attributes of the type
4324 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4325 LPTYPEATTR *ppTypeAttr)
4327 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4330 TRACE("(%p)\n",This);
4332 size = sizeof(**ppTypeAttr);
4333 if (This->TypeAttr.typekind == TKIND_ALIAS)
4334 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4336 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4338 return E_OUTOFMEMORY;
4340 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4342 if (This->TypeAttr.typekind == TKIND_ALIAS)
4343 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4344 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4346 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4347 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4349 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4350 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4355 /* ITypeInfo::GetTypeComp
4357 * Retrieves the ITypeComp interface for the type description, which enables a
4358 * client compiler to bind to the type description's members.
4361 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4362 ITypeComp * *ppTComp)
4364 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4366 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4368 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4369 ITypeComp_AddRef(*ppTComp);
4373 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4375 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4376 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4377 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4381 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4383 memcpy(dest, src, sizeof(ELEMDESC));
4384 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4385 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4387 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4388 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4389 *buffer += sizeof(PARAMDESCEX);
4390 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4391 VariantInit(&pparamdescex_dest->varDefaultValue);
4392 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4393 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4396 dest->u.paramdesc.pparamdescex = NULL;
4400 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4402 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4403 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4406 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr )
4410 SIZE_T size = sizeof(*src);
4414 size += sizeof(*src->lprgscode) * src->cScodes;
4415 size += TLB_SizeElemDesc(&src->elemdescFunc);
4416 for (i = 0; i < src->cParams; i++)
4418 size += sizeof(ELEMDESC);
4419 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4422 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4423 if (!dest) return E_OUTOFMEMORY;
4425 memcpy(dest, src, sizeof(FUNCDESC));
4426 buffer = (char *)(dest + 1);
4428 dest->lprgscode = (SCODE *)buffer;
4429 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4430 buffer += sizeof(*src->lprgscode) * src->cScodes;
4432 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4435 SysFreeString((BSTR)dest);
4439 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4440 buffer += sizeof(ELEMDESC) * src->cParams;
4441 for (i = 0; i < src->cParams; i++)
4443 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4449 /* undo the above actions */
4450 for (i = i - 1; i >= 0; i--)
4451 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4452 TLB_FreeElemDesc(&dest->elemdescFunc);
4453 SysFreeString((BSTR)dest);
4461 /* ITypeInfo::GetFuncDesc
4463 * Retrieves the FUNCDESC structure that contains information about a
4464 * specified function.
4467 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4468 LPFUNCDESC *ppFuncDesc)
4470 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4472 const TLBFuncDesc *pFDesc;
4474 TRACE("(%p) index %d\n", This, index);
4476 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4480 return TLB_AllocAndInitFuncDesc(&pFDesc->funcdesc, ppFuncDesc);
4482 return E_INVALIDARG;
4485 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4489 SIZE_T size = sizeof(*src);
4492 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4493 if (src->varkind == VAR_CONST)
4494 size += sizeof(VARIANT);
4495 size += TLB_SizeElemDesc(&src->elemdescVar);
4497 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4498 if (!dest) return E_OUTOFMEMORY;
4501 buffer = (char *)(dest + 1);
4502 if (src->lpstrSchema)
4505 dest->lpstrSchema = (LPOLESTR)buffer;
4506 len = strlenW(src->lpstrSchema);
4507 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4508 buffer += (len + 1) * sizeof(WCHAR);
4511 if (src->varkind == VAR_CONST)
4515 dest->u.lpvarValue = (VARIANT *)buffer;
4516 *dest->u.lpvarValue = *src->u.lpvarValue;
4517 buffer += sizeof(VARIANT);
4518 VariantInit(dest->u.lpvarValue);
4519 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4522 SysFreeString((BSTR)dest_ptr);
4526 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4529 if (src->varkind == VAR_CONST)
4530 VariantClear(dest->u.lpvarValue);
4531 SysFreeString((BSTR)dest);
4538 /* ITypeInfo::GetVarDesc
4540 * Retrieves a VARDESC structure that describes the specified variable.
4543 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4544 LPVARDESC *ppVarDesc)
4546 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4548 const TLBVarDesc *pVDesc;
4550 TRACE("(%p) index %d\n", This, index);
4552 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4556 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4558 return E_INVALIDARG;
4561 /* ITypeInfo_GetNames
4563 * Retrieves the variable with the specified member ID (or the name of the
4564 * property or method and its parameters) that correspond to the specified
4567 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4568 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4570 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4571 TLBFuncDesc * pFDesc;
4572 TLBVarDesc * pVDesc;
4574 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4575 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4578 /* function found, now return function and parameter names */
4579 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4582 *rgBstrNames=SysAllocString(pFDesc->Name);
4584 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4590 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4593 *rgBstrNames=SysAllocString(pVDesc->Name);
4598 if(This->TypeAttr.cImplTypes &&
4599 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4600 /* recursive search */
4603 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4605 if(SUCCEEDED(result))
4607 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4608 ITypeInfo_Release(pTInfo);
4611 WARN("Could not search inherited interface!\n");
4615 WARN("no names found\n");
4618 return TYPE_E_ELEMENTNOTFOUND;
4625 /* ITypeInfo::GetRefTypeOfImplType
4627 * If a type description describes a COM class, it retrieves the type
4628 * description of the implemented interface types. For an interface,
4629 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4633 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4638 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4641 TLBImplType *pImpl = This->impltypelist;
4643 TRACE("(%p) index %d\n", This, index);
4644 if (TRACE_ON(ole)) dump_TypeInfo(This);
4648 /* only valid on dual interfaces;
4649 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4651 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4653 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4654 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4660 hr = TYPE_E_ELEMENTNOTFOUND;
4665 /* get element n from linked list */
4666 for(i=0; pImpl && i<index; i++)
4668 pImpl = pImpl->next;
4672 *pRefType = pImpl->hRef;
4674 hr = TYPE_E_ELEMENTNOTFOUND;
4680 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4682 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4688 /* ITypeInfo::GetImplTypeFlags
4690 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4691 * or base interface in a type description.
4693 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4694 UINT index, INT *pImplTypeFlags)
4696 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4700 TRACE("(%p) index %d\n", This, index);
4701 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4702 i++, pImpl=pImpl->next)
4704 if(i==index && pImpl){
4705 *pImplTypeFlags=pImpl->implflags;
4709 return TYPE_E_ELEMENTNOTFOUND;
4713 * Maps between member names and member IDs, and parameter names and
4716 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4717 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4719 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4720 TLBFuncDesc * pFDesc;
4721 TLBVarDesc * pVDesc;
4724 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4726 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4728 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4729 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4730 for(i=1; i < cNames; i++){
4731 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4732 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4734 if( j<pFDesc->funcdesc.cParams)
4737 ret=DISP_E_UNKNOWNNAME;
4742 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4743 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4744 if(cNames) *pMemId=pVDesc->vardesc.memid;
4748 /* not found, see if this is and interface with an inheritance */
4749 if(This->TypeAttr.cImplTypes &&
4750 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4751 /* recursive search */
4753 ret=ITypeInfo_GetRefTypeInfo(iface,
4754 This->impltypelist->hRef, &pTInfo);
4756 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4757 ITypeInfo_Release(pTInfo);
4760 WARN("Could not search inherited interface!\n");
4762 WARN("no names found\n");
4763 return DISP_E_UNKNOWNNAME;
4766 /* ITypeInfo::Invoke
4768 * Invokes a method, or accesses a property of an object, that implements the
4769 * interface described by the type description.
4772 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4775 if (TRACE_ON(ole)) {
4777 TRACE("Calling %p(",func);
4778 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4790 res = func(args[0]);
4793 res = func(args[0],args[1]);
4796 res = func(args[0],args[1],args[2]);
4799 res = func(args[0],args[1],args[2],args[3]);
4802 res = func(args[0],args[1],args[2],args[3],args[4]);
4805 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4808 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4811 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4814 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4817 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4820 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4823 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]);
4826 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]);
4829 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]);
4832 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4838 FIXME("unsupported calling convention %d\n",callconv);
4842 TRACE("returns %08lx\n",res);
4846 extern int _argsize(DWORD vt);
4848 /****************************************************************************
4849 * Helper functions for Dispcall / Invoke, which copies one variant
4850 * with target type onto the argument stack.
4853 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4854 DWORD *argpos, VARIANT *arg, VARTYPE vt
4856 UINT arglen = _argsize(vt)*sizeof(DWORD);
4859 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4860 memcpy(argpos,&arg,sizeof(void*));
4864 if (V_VT(arg) == vt) {
4865 memcpy(argpos, &V_I4(arg), arglen);
4869 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4870 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4874 if (vt == VT_VARIANT) {
4875 memcpy(argpos, arg, arglen);
4878 /* Deref BYREF vars if there is need */
4879 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4880 memcpy(argpos,(void*)V_I4(arg), arglen);
4883 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4884 /* in this context, if the type lib specifies IUnknown*, giving an
4885 IDispatch* is correct; so, don't invoke VariantChangeType */
4886 memcpy(argpos,&V_I4(arg), arglen);
4889 if ((vt == VT_PTR) && tdesc)
4890 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4892 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4893 ITypeInfo *tinfo2 = NULL;
4894 TYPEATTR *tattr = NULL;
4897 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4899 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4900 "while coercing from vt 0x%x. Copying 4 byte.\n",
4901 tdesc->u.hreftype,V_VT(arg));
4902 memcpy(argpos, &V_I4(arg), 4);
4905 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4908 ERR("GetTypeAttr failed\n");
4909 ITypeInfo_Release(tinfo2);
4912 switch (tattr->typekind) {
4914 switch ( V_VT( arg ) ) {
4916 *argpos = V_I2(arg);
4920 memcpy(argpos, &V_I4(arg), 4);
4923 case VT_BYREF|VT_I4:
4924 memcpy(argpos, V_I4REF(arg), 4);
4928 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4935 tdesc = &(tattr->tdescAlias);
4936 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4939 case TKIND_INTERFACE:
4940 if (V_VT(arg) == VT_DISPATCH) {
4942 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4943 memcpy(argpos, &V_DISPATCH(arg), 4);
4947 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4948 &IID_IDispatch,(LPVOID*)&disp);
4949 if (SUCCEEDED(hres)) {
4950 memcpy(argpos,&disp,4);
4951 IUnknown_Release(V_DISPATCH(arg));
4955 FIXME("Failed to query IDispatch interface from %s while "
4956 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4960 if (V_VT(arg) == VT_UNKNOWN) {
4961 memcpy(argpos, &V_UNKNOWN(arg), 4);
4965 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4966 V_VT(arg),debugstr_guid(&(tattr->guid)));
4970 case TKIND_DISPATCH:
4971 if (V_VT(arg) == VT_DISPATCH) {
4972 memcpy(argpos, &V_DISPATCH(arg), 4);
4977 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4981 FIXME("TKIND_RECORD unhandled.\n");
4985 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4989 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4990 ITypeInfo_Release(tinfo2);
4995 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4996 memcpy(argpos,&V_I4(&va), arglen);
4997 FIXME("Should not use VariantChangeType here."
4998 " (conversion from 0x%x -> 0x%x) %08lx\n",
4999 V_VT(arg), vt, *argpos
5003 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
5007 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
5010 ITypeInfo *tinfo2 = NULL;
5011 TYPEATTR *tattr = NULL;
5013 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5016 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
5018 tdesc->u.hreftype, hr);
5021 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5024 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
5025 ITypeInfo_Release(tinfo2);
5029 switch (tattr->typekind)
5036 tdesc = &tattr->tdescAlias;
5037 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5040 case TKIND_INTERFACE:
5041 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5047 case TKIND_DISPATCH:
5052 FIXME("TKIND_RECORD unhandled.\n");
5057 FIXME("TKIND_RECORD unhandled.\n");
5062 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5066 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5067 ITypeInfo_Release(tinfo2);
5071 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
5075 /* enforce only one level of pointer indirection */
5076 if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
5078 tdesc = tdesc->u.lptdesc;
5080 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5081 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5082 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5083 if ((tdesc->vt == VT_USERDEFINED) ||
5084 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5086 VARTYPE vt_userdefined = 0;
5087 TYPEDESC *tdesc_userdefined = tdesc;
5088 if (tdesc->vt == VT_PTR)
5090 vt_userdefined = VT_BYREF;
5091 tdesc_userdefined = tdesc->u.lptdesc;
5093 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5095 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5096 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5098 *vt |= vt_userdefined;
5110 case VT_USERDEFINED:
5111 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5114 ERR("cannot convert VT_PTR into variant VT\n");
5124 /***********************************************************************
5125 * DispCallFunc (OLEAUT32.@)
5129 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5130 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5132 int i, argsize, argspos;
5136 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5137 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5138 pvargResult, V_VT(pvargResult));
5140 /* DispCallFunc is only used to invoke methods belonging to an
5141 * IDispatch-derived COM interface. So we need to add a first parameter
5142 * to the list of arguments, to supply the interface pointer */
5144 for (i=0;i<cActuals;i++)
5146 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5147 dump_Variant(prgpvarg[i]);
5148 argsize += _argsize(prgvt[i]);
5150 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5151 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
5153 for (i=0;i<cActuals;i++)
5155 VARIANT *arg = prgpvarg[i];
5156 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5157 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5158 argspos += _argsize(prgvt[i]);
5161 hres = _invoke((*(FARPROC**)pvInstance)[oVft/sizeof(void *)],cc,argsize,args);
5162 if (pvargResult && (vtReturn != VT_EMPTY))
5164 TRACE("Method returned 0x%08lx\n",hres);
5165 V_VT(pvargResult) = vtReturn;
5166 V_UI4(pvargResult) = hres;
5169 HeapFree(GetProcessHeap(),0,args);
5173 static HRESULT WINAPI ITypeInfo_fnInvoke(
5178 DISPPARAMS *pDispParams,
5179 VARIANT *pVarResult,
5180 EXCEPINFO *pExcepInfo,
5183 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5185 unsigned int func_index, var_index;
5189 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
5190 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5192 dump_DispParms(pDispParams);
5194 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
5195 if (SUCCEEDED(hres)) {
5196 FUNCDESC *func_desc;
5198 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
5199 if(FAILED(hres)) return hres;
5202 TRACE("invoking:\n");
5203 dump_FUNCDESC(func_desc);
5206 switch (func_desc->funckind) {
5207 case FUNC_PUREVIRTUAL:
5208 case FUNC_VIRTUAL: {
5210 int numargs, numargs2, argspos, args2pos;
5211 DWORD *args , *args2;
5212 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
5213 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
5216 numargs = 1; /* sizeof(thisptr) */
5218 for (i = 0; i < func_desc->cParams; i++) {
5219 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5221 numargs += _argsize(tdesc->vt);
5222 if (i>=pDispParams->cArgs) { /* arguments to return */
5223 if (tdesc->vt == VT_PTR) {
5224 numargs2 += _argsize(tdesc->u.lptdesc->vt);
5226 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
5227 numargs2 += _argsize(tdesc->vt);
5232 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
5233 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
5235 args[0] = (DWORD)pIUnk;
5236 argspos = 1; args2pos = 0;
5237 for (i = 0; i < func_desc->cParams; i++) {
5238 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
5239 TYPEDESC *tdesc = &(elemdesc->tdesc);
5240 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
5241 int arglen = _argsize(tdesc->vt);
5243 if (i<pDispParams->cArgs) {
5244 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
5246 if (paramFlags & PARAMFLAG_FOPT) {
5247 if(i < func_desc->cParams - func_desc->cParamsOpt)
5248 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5249 if(V_VT(arg) == VT_EMPTY
5250 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
5251 /* FIXME: Documentation says that we do this when parameter is left unspecified.
5252 How to determine it? */
5254 if(paramFlags & PARAMFLAG_FHASDEFAULT)
5255 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5256 V_VT(arg) = VT_ERROR;
5257 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5258 arglen = _argsize(VT_ERROR);
5261 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5262 if (FAILED(hres)) goto func_fail;
5264 } else if (paramFlags & PARAMFLAG_FOPT) {
5265 VARIANT *arg = &rgvarg[i];
5267 if (i < func_desc->cParams - func_desc->cParamsOpt)
5268 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5269 if (paramFlags & PARAMFLAG_FHASDEFAULT)
5270 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);
5275 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5276 if (FAILED(hres)) goto func_fail;
5279 if (tdesc->vt == VT_PTR)
5280 arglen = _argsize(tdesc->u.lptdesc->vt);
5282 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
5284 /* Supply pointers for the rest, so propertyget works*/
5285 args[argspos] = (DWORD)&args2[args2pos];
5287 /* If pointer to variant, pass reference it. */
5288 if ((tdesc->vt == VT_PTR) &&
5289 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
5292 args[argspos]= (DWORD)pVarResult;
5297 if (func_desc->cParamsOpt < 0)
5298 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
5300 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
5301 func_desc->callconv,
5307 for (i = 0; i < func_desc->cParams; i++) {
5308 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5309 if (wParamFlags & PARAMFLAG_FRETVAL) {
5310 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5311 TYPEDESC *tdesc = &elemdesc->tdesc;
5312 VARIANTARG varresult;
5313 V_VT(&varresult) = 0;
5314 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5317 /* FIXME: this is really messy - we should keep the
5318 * args in VARIANTARGs rather than a DWORD array */
5319 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5322 TRACE("varresult: ");
5323 dump_Variant(&varresult);
5325 hres = VariantCopyInd(pVarResult, &varresult);
5326 /* free data stored in varresult. Note that
5327 * VariantClear doesn't do what we want because we are
5328 * working with byref types. */
5329 /* FIXME: clear safearrays, bstrs, records and
5330 * variants here too */
5331 if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
5332 (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
5334 if(*V_UNKNOWNREF(&varresult))
5335 IUnknown_Release(*V_UNKNOWNREF(&varresult));
5342 if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
5343 WARN("invoked function failed with error 0x%08lx\n", res);
5344 hres = DISP_E_EXCEPTION;
5345 if (pExcepInfo) pExcepInfo->scode = res;
5348 HeapFree(GetProcessHeap(), 0, rgvarg);
5349 HeapFree(GetProcessHeap(),0,args2);
5350 HeapFree(GetProcessHeap(),0,args);
5353 case FUNC_DISPATCH: {
5356 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5357 if (SUCCEEDED(hres)) {
5358 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5359 hres = IDispatch_Invoke(
5360 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
5361 pVarResult,pExcepInfo,pArgErr
5364 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5365 IDispatch_Release(disp);
5367 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5371 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5376 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
5377 TRACE("-- 0x%08lx\n", hres);
5380 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5383 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5384 if(FAILED(hres)) return hres;
5386 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5387 dump_VARDESC(var_desc);
5388 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5392 /* not found, look for it in inherited interfaces */
5393 ITypeInfo2_GetTypeKind(iface, &type_kind);
5394 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5396 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5397 /* recursive search */
5399 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5400 if(SUCCEEDED(hres)){
5401 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5402 ITypeInfo_Release(pTInfo);
5405 WARN("Could not search inherited interface!\n");
5408 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
5409 return DISP_E_MEMBERNOTFOUND;
5412 /* ITypeInfo::GetDocumentation
5414 * Retrieves the documentation string, the complete Help file name and path,
5415 * and the context ID for the Help topic for a specified type description.
5417 * (Can be tested by the Visual Basic Editor in Word for instance.)
5419 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5420 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5421 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5423 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5424 TLBFuncDesc * pFDesc;
5425 TLBVarDesc * pVDesc;
5426 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5427 " HelpContext(%p) HelpFile(%p)\n",
5428 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5429 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5431 *pBstrName=SysAllocString(This->Name);
5433 *pBstrDocString=SysAllocString(This->DocString);
5435 *pdwHelpContext=This->dwHelpContext;
5437 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5439 }else {/* for a member */
5440 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5441 if(pFDesc->funcdesc.memid==memid){
5443 *pBstrName = SysAllocString(pFDesc->Name);
5445 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5447 *pdwHelpContext=pFDesc->helpcontext;
5450 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5451 if(pVDesc->vardesc.memid==memid){
5453 *pBstrName = SysAllocString(pVDesc->Name);
5455 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5457 *pdwHelpContext=pVDesc->HelpContext;
5461 WARN("member %ld not found\n", memid);
5462 return TYPE_E_ELEMENTNOTFOUND;
5465 /* ITypeInfo::GetDllEntry
5467 * Retrieves a description or specification of an entry point for a function
5470 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5471 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5474 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5475 TLBFuncDesc *pFDesc;
5477 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5479 if (pBstrDllName) *pBstrDllName = NULL;
5480 if (pBstrName) *pBstrName = NULL;
5481 if (pwOrdinal) *pwOrdinal = 0;
5483 if (This->TypeAttr.typekind != TKIND_MODULE)
5484 return TYPE_E_BADMODULEKIND;
5486 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5487 if(pFDesc->funcdesc.memid==memid){
5488 dump_TypeInfo(This);
5489 dump_TLBFuncDescOne(pFDesc);
5492 *pBstrDllName = SysAllocString(This->DllName);
5494 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5496 *pBstrName = SysAllocString(pFDesc->Entry);
5504 *pwOrdinal = (DWORD)pFDesc->Entry;
5507 return TYPE_E_ELEMENTNOTFOUND;
5510 /* ITypeInfo::GetRefTypeInfo
5512 * If a type description references other type descriptions, it retrieves
5513 * the referenced type descriptions.
5515 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5518 ITypeInfo **ppTInfo)
5520 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5521 HRESULT result = E_FAIL;
5523 if (hRefType == -1 &&
5524 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5525 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5527 /* when we meet a DUAL dispinterface, we must create the interface
5530 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5533 /* the interface version contains the same information as the dispinterface
5534 * copy the contents of the structs.
5536 *pTypeInfoImpl = *This;
5537 pTypeInfoImpl->ref = 1;
5539 /* change the type to interface */
5540 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5542 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5544 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5549 TLBRefType *pRefType;
5550 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5551 if(pRefType->reference == hRefType)
5555 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5556 if(pRefType && hRefType != -1) {
5557 ITypeLib *pTLib = NULL;
5559 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5561 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5563 if(pRefType->pImpTLInfo->pImpTypeLib) {
5564 TRACE("typeinfo in imported typelib that is already loaded\n");
5565 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5566 ITypeLib2_AddRef((ITypeLib*) pTLib);
5569 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5570 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5571 pRefType->pImpTLInfo->wVersionMajor,
5572 pRefType->pImpTLInfo->wVersionMinor,
5573 pRefType->pImpTLInfo->lcid,
5576 if(!SUCCEEDED(result)) {
5577 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5578 result=LoadTypeLib(libnam, &pTLib);
5579 SysFreeString(libnam);
5581 if(SUCCEEDED(result)) {
5582 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5583 ITypeLib2_AddRef(pTLib);
5587 if(SUCCEEDED(result)) {
5588 if(pRefType->index == TLB_REF_USE_GUID)
5589 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5593 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5597 ITypeLib2_Release(pTLib);
5601 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5602 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5606 /* ITypeInfo::AddressOfMember
5608 * Retrieves the addresses of static functions or variables, such as those
5611 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5612 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5614 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5615 FIXME("(%p) stub!\n", This);
5619 /* ITypeInfo::CreateInstance
5621 * Creates a new instance of a type that describes a component object class
5624 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5625 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5627 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5628 FIXME("(%p) stub!\n", This);
5632 /* ITypeInfo::GetMops
5634 * Retrieves marshalling information.
5636 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5639 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5640 FIXME("(%p) stub!\n", This);
5644 /* ITypeInfo::GetContainingTypeLib
5646 * Retrieves the containing type library and the index of the type description
5647 * within that type library.
5649 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5650 ITypeLib * *ppTLib, UINT *pIndex)
5652 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5654 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5656 *pIndex=This->index;
5657 TRACE("returning pIndex=%d\n", *pIndex);
5661 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5662 ITypeLib2_AddRef(*ppTLib);
5663 TRACE("returning ppTLib=%p\n", *ppTLib);
5669 /* ITypeInfo::ReleaseTypeAttr
5671 * Releases a TYPEATTR previously returned by GetTypeAttr.
5674 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5675 TYPEATTR* pTypeAttr)
5677 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5678 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5679 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5682 /* ITypeInfo::ReleaseFuncDesc
5684 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5686 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5688 FUNCDESC *pFuncDesc)
5690 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5693 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5695 for (i = 0; i < pFuncDesc->cParams; i++)
5696 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5697 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5699 SysFreeString((BSTR)pFuncDesc);
5702 /* ITypeInfo::ReleaseVarDesc
5704 * Releases a VARDESC previously returned by GetVarDesc.
5706 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5709 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5710 TRACE("(%p)->(%p)\n", This, pVarDesc);
5712 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5713 if (pVarDesc->varkind == VAR_CONST)
5714 VariantClear(pVarDesc->u.lpvarValue);
5715 SysFreeString((BSTR)pVarDesc);
5718 /* ITypeInfo2::GetTypeKind
5720 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5723 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5724 TYPEKIND *pTypeKind)
5726 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5727 *pTypeKind=This->TypeAttr.typekind;
5728 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5732 /* ITypeInfo2::GetTypeFlags
5734 * Returns the type flags without any allocations. This returns a DWORD type
5735 * flag, which expands the type flags without growing the TYPEATTR (type
5739 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5741 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5742 *pTypeFlags=This->TypeAttr.wTypeFlags;
5743 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5747 /* ITypeInfo2::GetFuncIndexOfMemId
5748 * Binds to a specific member based on a known DISPID, where the member name
5749 * is not known (for example, when binding to a default member).
5752 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5753 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5755 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5756 TLBFuncDesc *pFuncInfo;
5760 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5761 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5767 result = TYPE_E_ELEMENTNOTFOUND;
5769 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5770 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5774 /* TypeInfo2::GetVarIndexOfMemId
5776 * Binds to a specific member based on a known DISPID, where the member name
5777 * is not known (for example, when binding to a default member).
5780 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5781 MEMBERID memid, UINT *pVarIndex)
5783 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5784 TLBVarDesc *pVarInfo;
5787 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5788 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5794 result = TYPE_E_ELEMENTNOTFOUND;
5796 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5797 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5801 /* ITypeInfo2::GetCustData
5803 * Gets the custom data
5805 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5810 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5811 TLBCustData *pCData;
5813 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5814 if( IsEqualIID(guid, &pCData->guid)) break;
5816 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5820 VariantInit( pVarVal);
5821 VariantCopy( pVarVal, &pCData->data);
5824 return E_INVALIDARG; /* FIXME: correct? */
5827 /* ITypeInfo2::GetFuncCustData
5829 * Gets the custom data
5831 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5837 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5838 TLBCustData *pCData=NULL;
5839 TLBFuncDesc * pFDesc;
5841 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5842 pFDesc=pFDesc->next);
5845 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5846 if( IsEqualIID(guid, &pCData->guid)) break;
5848 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5851 VariantInit( pVarVal);
5852 VariantCopy( pVarVal, &pCData->data);
5855 return E_INVALIDARG; /* FIXME: correct? */
5858 /* ITypeInfo2::GetParamCustData
5860 * Gets the custom data
5862 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5869 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5870 TLBCustData *pCData=NULL;
5871 TLBFuncDesc * pFDesc;
5874 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5876 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5877 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5878 pCData = pCData->next)
5879 if( IsEqualIID(guid, &pCData->guid)) break;
5881 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5885 VariantInit( pVarVal);
5886 VariantCopy( pVarVal, &pCData->data);
5889 return E_INVALIDARG; /* FIXME: correct? */
5892 /* ITypeInfo2::GetVarCustData
5894 * Gets the custom data
5896 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5902 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5903 TLBCustData *pCData=NULL;
5904 TLBVarDesc * pVDesc;
5907 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5911 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5913 if( IsEqualIID(guid, &pCData->guid)) break;
5917 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5921 VariantInit( pVarVal);
5922 VariantCopy( pVarVal, &pCData->data);
5925 return E_INVALIDARG; /* FIXME: correct? */
5928 /* ITypeInfo2::GetImplCustData
5930 * Gets the custom data
5932 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5938 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5939 TLBCustData *pCData=NULL;
5940 TLBImplType * pRDesc;
5943 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5947 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5949 if( IsEqualIID(guid, &pCData->guid)) break;
5953 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5957 VariantInit( pVarVal);
5958 VariantCopy( pVarVal, &pCData->data);
5961 return E_INVALIDARG; /* FIXME: correct? */
5964 /* ITypeInfo2::GetDocumentation2
5966 * Retrieves the documentation string, the complete Help file name and path,
5967 * the localization context to use, and the context ID for the library Help
5968 * topic in the Help file.
5971 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5975 BSTR *pbstrHelpString,
5976 DWORD *pdwHelpStringContext,
5977 BSTR *pbstrHelpStringDll)
5979 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5980 TLBFuncDesc * pFDesc;
5981 TLBVarDesc * pVDesc;
5982 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5983 "HelpStringContext(%p) HelpStringDll(%p)\n",
5984 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5985 pbstrHelpStringDll );
5986 /* the help string should be obtained from the helpstringdll,
5987 * using the _DLLGetDocumentation function, based on the supplied
5988 * lcid. Nice to do sometime...
5990 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5992 *pbstrHelpString=SysAllocString(This->Name);
5993 if(pdwHelpStringContext)
5994 *pdwHelpStringContext=This->dwHelpStringContext;
5995 if(pbstrHelpStringDll)
5996 *pbstrHelpStringDll=
5997 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5999 }else {/* for a member */
6000 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6001 if(pFDesc->funcdesc.memid==memid){
6003 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6004 if(pdwHelpStringContext)
6005 *pdwHelpStringContext=pFDesc->HelpStringContext;
6006 if(pbstrHelpStringDll)
6007 *pbstrHelpStringDll=
6008 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6011 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6012 if(pVDesc->vardesc.memid==memid){
6014 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6015 if(pdwHelpStringContext)
6016 *pdwHelpStringContext=pVDesc->HelpStringContext;
6017 if(pbstrHelpStringDll)
6018 *pbstrHelpStringDll=
6019 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6023 return TYPE_E_ELEMENTNOTFOUND;
6026 /* ITypeInfo2::GetAllCustData
6028 * Gets all custom data items for the Type info.
6031 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6033 CUSTDATA *pCustData)
6035 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6036 TLBCustData *pCData;
6039 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6041 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6042 if(pCustData->prgCustData ){
6043 pCustData->cCustData=This->ctCustData;
6044 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6045 pCustData->prgCustData[i].guid=pCData->guid;
6046 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6049 ERR(" OUT OF MEMORY!\n");
6050 return E_OUTOFMEMORY;
6055 /* ITypeInfo2::GetAllFuncCustData
6057 * Gets all custom data items for the specified Function
6060 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6063 CUSTDATA *pCustData)
6065 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6066 TLBCustData *pCData;
6067 TLBFuncDesc * pFDesc;
6069 TRACE("(%p) index %d\n", This, index);
6070 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6071 pFDesc=pFDesc->next)
6074 pCustData->prgCustData =
6075 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6076 if(pCustData->prgCustData ){
6077 pCustData->cCustData=pFDesc->ctCustData;
6078 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6079 pCData = pCData->next){
6080 pCustData->prgCustData[i].guid=pCData->guid;
6081 VariantCopy(& pCustData->prgCustData[i].varValue,
6085 ERR(" OUT OF MEMORY!\n");
6086 return E_OUTOFMEMORY;
6090 return TYPE_E_ELEMENTNOTFOUND;
6093 /* ITypeInfo2::GetAllParamCustData
6095 * Gets all custom data items for the Functions
6098 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6099 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6101 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6102 TLBCustData *pCData=NULL;
6103 TLBFuncDesc * pFDesc;
6105 TRACE("(%p) index %d\n", This, indexFunc);
6106 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6107 pFDesc=pFDesc->next)
6109 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6110 pCustData->prgCustData =
6111 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6112 sizeof(CUSTDATAITEM));
6113 if(pCustData->prgCustData ){
6114 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6115 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6116 pCData; i++, pCData = pCData->next){
6117 pCustData->prgCustData[i].guid=pCData->guid;
6118 VariantCopy(& pCustData->prgCustData[i].varValue,
6122 ERR(" OUT OF MEMORY!\n");
6123 return E_OUTOFMEMORY;
6127 return TYPE_E_ELEMENTNOTFOUND;
6130 /* ITypeInfo2::GetAllVarCustData
6132 * Gets all custom data items for the specified Variable
6135 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6136 UINT index, CUSTDATA *pCustData)
6138 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6139 TLBCustData *pCData;
6140 TLBVarDesc * pVDesc;
6142 TRACE("(%p) index %d\n", This, index);
6143 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6144 pVDesc=pVDesc->next)
6147 pCustData->prgCustData =
6148 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6149 if(pCustData->prgCustData ){
6150 pCustData->cCustData=pVDesc->ctCustData;
6151 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6152 pCData = pCData->next){
6153 pCustData->prgCustData[i].guid=pCData->guid;
6154 VariantCopy(& pCustData->prgCustData[i].varValue,
6158 ERR(" OUT OF MEMORY!\n");
6159 return E_OUTOFMEMORY;
6163 return TYPE_E_ELEMENTNOTFOUND;
6166 /* ITypeInfo2::GetAllImplCustData
6168 * Gets all custom data items for the specified implementation type
6171 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6174 CUSTDATA *pCustData)
6176 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6177 TLBCustData *pCData;
6178 TLBImplType * pRDesc;
6180 TRACE("(%p) index %d\n", This, index);
6181 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6182 pRDesc=pRDesc->next)
6185 pCustData->prgCustData =
6186 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6187 if(pCustData->prgCustData ){
6188 pCustData->cCustData=pRDesc->ctCustData;
6189 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6190 pCData = pCData->next){
6191 pCustData->prgCustData[i].guid=pCData->guid;
6192 VariantCopy(& pCustData->prgCustData[i].varValue,
6196 ERR(" OUT OF MEMORY!\n");
6197 return E_OUTOFMEMORY;
6201 return TYPE_E_ELEMENTNOTFOUND;
6204 static const ITypeInfo2Vtbl tinfvt =
6207 ITypeInfo_fnQueryInterface,
6209 ITypeInfo_fnRelease,
6211 ITypeInfo_fnGetTypeAttr,
6212 ITypeInfo_fnGetTypeComp,
6213 ITypeInfo_fnGetFuncDesc,
6214 ITypeInfo_fnGetVarDesc,
6215 ITypeInfo_fnGetNames,
6216 ITypeInfo_fnGetRefTypeOfImplType,
6217 ITypeInfo_fnGetImplTypeFlags,
6218 ITypeInfo_fnGetIDsOfNames,
6220 ITypeInfo_fnGetDocumentation,
6221 ITypeInfo_fnGetDllEntry,
6222 ITypeInfo_fnGetRefTypeInfo,
6223 ITypeInfo_fnAddressOfMember,
6224 ITypeInfo_fnCreateInstance,
6225 ITypeInfo_fnGetMops,
6226 ITypeInfo_fnGetContainingTypeLib,
6227 ITypeInfo_fnReleaseTypeAttr,
6228 ITypeInfo_fnReleaseFuncDesc,
6229 ITypeInfo_fnReleaseVarDesc,
6231 ITypeInfo2_fnGetTypeKind,
6232 ITypeInfo2_fnGetTypeFlags,
6233 ITypeInfo2_fnGetFuncIndexOfMemId,
6234 ITypeInfo2_fnGetVarIndexOfMemId,
6235 ITypeInfo2_fnGetCustData,
6236 ITypeInfo2_fnGetFuncCustData,
6237 ITypeInfo2_fnGetParamCustData,
6238 ITypeInfo2_fnGetVarCustData,
6239 ITypeInfo2_fnGetImplTypeCustData,
6240 ITypeInfo2_fnGetDocumentation2,
6241 ITypeInfo2_fnGetAllCustData,
6242 ITypeInfo2_fnGetAllFuncCustData,
6243 ITypeInfo2_fnGetAllParamCustData,
6244 ITypeInfo2_fnGetAllVarCustData,
6245 ITypeInfo2_fnGetAllImplTypeCustData,
6248 /******************************************************************************
6249 * CreateDispTypeInfo [OLEAUT32.31]
6251 * Build type information for an object so it can be called through an
6252 * IDispatch interface.
6255 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6256 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6259 * This call allows an objects methods to be accessed through IDispatch, by
6260 * building an ITypeInfo object that IDispatch can use to call through.
6262 HRESULT WINAPI CreateDispTypeInfo(
6263 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6264 LCID lcid, /* [I] Locale Id */
6265 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6267 ITypeInfoImpl *pTIImpl;
6269 TLBFuncDesc **ppFuncDesc;
6271 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
6272 pTIImpl->pTypeLib = NULL;
6274 pTIImpl->Name = NULL;
6275 pTIImpl->dwHelpContext = -1;
6276 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
6277 pTIImpl->TypeAttr.lcid = lcid;
6278 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
6279 pTIImpl->TypeAttr.wMajorVerNum = 0;
6280 pTIImpl->TypeAttr.wMinorVerNum = 0;
6281 pTIImpl->TypeAttr.cbAlignment = 2;
6282 pTIImpl->TypeAttr.cbSizeInstance = -1;
6283 pTIImpl->TypeAttr.cbSizeVft = -1;
6284 pTIImpl->TypeAttr.cFuncs = 0;
6285 pTIImpl->TypeAttr.cImplTypes = 1;
6286 pTIImpl->TypeAttr.cVars = 0;
6287 pTIImpl->TypeAttr.wTypeFlags = 0;
6289 ppFuncDesc = &pTIImpl->funclist;
6290 for(func = 0; func < pidata->cMembers; func++) {
6291 METHODDATA *md = pidata->pmethdata + func;
6292 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6293 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6294 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6295 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6296 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6297 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6298 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6299 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
6300 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
6301 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6302 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6303 md->cArgs * sizeof(ELEMDESC));
6304 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6305 md->cArgs * sizeof(TLBParDesc));
6306 for(param = 0; param < md->cArgs; param++) {
6307 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6308 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6310 ppFuncDesc = &(*ppFuncDesc)->next;
6312 *pptinfo = (ITypeInfo*)pTIImpl;
6317 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6319 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6321 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6324 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6326 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6328 return ITypeInfo_AddRef((ITypeInfo *)This);
6331 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6333 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6335 return ITypeInfo_Release((ITypeInfo *)This);
6338 static HRESULT WINAPI ITypeComp_fnBind(
6343 ITypeInfo ** ppTInfo,
6344 DESCKIND * pDescKind,
6347 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6348 TLBFuncDesc * pFDesc;
6349 TLBVarDesc * pVDesc;
6351 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6353 *pDescKind = DESCKIND_NONE;
6354 pBindPtr->lpfuncdesc = NULL;
6357 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6358 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6359 if (!strcmpW(pFDesc->Name, szName)) {
6365 HRESULT hr = TLB_AllocAndInitFuncDesc(&pFDesc->funcdesc, &pBindPtr->lpfuncdesc);
6368 *pDescKind = DESCKIND_FUNCDESC;
6369 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6370 ITypeInfo_AddRef(*ppTInfo);
6373 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6374 if (!strcmpW(pVDesc->Name, szName)) {
6375 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6378 *pDescKind = DESCKIND_VARDESC;
6379 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6380 ITypeInfo_AddRef(*ppTInfo);
6385 /* FIXME: search each inherited interface, not just the first */
6386 if (This->TypeAttr.cImplTypes) {
6387 /* recursive search */
6391 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6394 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6395 ITypeInfo_Release(pTInfo);
6399 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6400 ITypeComp_Release(pTComp);
6403 WARN("Could not search inherited interface!\n");
6405 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6406 return DISP_E_MEMBERNOTFOUND;
6409 static HRESULT WINAPI ITypeComp_fnBindType(
6413 ITypeInfo ** ppTInfo,
6414 ITypeComp ** ppTComp)
6416 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6418 /* strange behaviour (does nothing) but like the
6421 if (!ppTInfo || !ppTComp)
6430 static const ITypeCompVtbl tcompvt =
6433 ITypeComp_fnQueryInterface,
6435 ITypeComp_fnRelease,
6438 ITypeComp_fnBindType