4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
56 #include "wine/port.h"
65 #define NONAMELESSUNION
66 #define NONAMELESSSTRUCT
75 #include "wine/unicode.h"
78 #include "wine/debug.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(ole);
82 WINE_DECLARE_DEBUG_CHANNEL(typelib);
84 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
85 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
87 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt);
89 /****************************************************************************
92 * Takes p_iVal (which is in little endian) and returns it
93 * in the host machine's byte order.
95 #ifdef WORDS_BIGENDIAN
96 static WORD FromLEWord(WORD p_iVal)
98 return (((p_iVal & 0x00FF) << 8) |
99 ((p_iVal & 0xFF00) >> 8));
103 static DWORD FromLEDWord(DWORD p_iVal)
105 return (((p_iVal & 0x000000FF) << 24) |
106 ((p_iVal & 0x0000FF00) << 8) |
107 ((p_iVal & 0x00FF0000) >> 8) |
108 ((p_iVal & 0xFF000000) >> 24));
111 #define FromLEWord(X) (X)
112 #define FromLEDWord(X) (X)
116 /****************************************************************************
119 * Fix byte order in any structure if necessary
121 #ifdef WORDS_BIGENDIAN
122 static void FromLEWords(void *p_Val, int p_iSize)
126 p_iSize /= sizeof(WORD);
129 *Val = FromLEWord(*Val);
136 static void FromLEDWords(void *p_Val, int p_iSize)
140 p_iSize /= sizeof(DWORD);
143 *Val = FromLEDWord(*Val);
149 #define FromLEWords(X,Y) /*nothing*/
150 #define FromLEDWords(X,Y) /*nothing*/
153 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
154 /* buffer must be at least 60 characters long */
155 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
157 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
158 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
160 memcpy( buffer, TypelibW, sizeof(TypelibW) );
161 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
162 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
166 /* get the path of an interface key, in the form "Interface\\<guid>" */
167 /* buffer must be at least 50 characters long */
168 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
170 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
172 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
173 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
177 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
178 /* buffer must be at least 16 characters long */
179 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
181 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
182 static const WCHAR win16W[] = {'w','i','n','1','6',0};
183 static const WCHAR win32W[] = {'w','i','n','3','2',0};
185 sprintfW( buffer, LcidFormatW, lcid );
188 case SYS_WIN16: strcatW( buffer, win16W ); break;
189 case SYS_WIN32: strcatW( buffer, win32W ); break;
191 TRACE("Typelib is for unsupported syskind %i\n", syskind);
197 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
200 /****************************************************************************
201 * QueryPathOfRegTypeLib [OLEAUT32.164]
203 * Gets the path to a registered type library.
206 * guid [I] referenced guid
207 * wMaj [I] major version
208 * wMin [I] minor version
210 * path [O] path of typelib
214 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
215 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
218 HRESULT WINAPI QueryPathOfRegTypeLib(
225 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
229 WCHAR Path[MAX_PATH];
232 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
234 get_typelib_key( guid, wMaj, wMin, buffer );
236 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
237 if (res == ERROR_FILE_NOT_FOUND)
239 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
240 return TYPE_E_LIBNOTREGISTERED;
242 else if (res != ERROR_SUCCESS)
244 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
245 return TYPE_E_REGISTRYACCESS;
250 LONG dwPathLen = sizeof(Path);
252 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
254 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
258 else if (myLCID == lcid)
260 /* try with sub-langid */
261 myLCID = SUBLANGID(lcid);
263 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
265 /* try with system langid */
275 *path = SysAllocString( Path );
280 TRACE_(typelib)("-- 0x%08lx\n", hr);
284 /******************************************************************************
285 * CreateTypeLib [OLEAUT32.160] creates a typelib
291 HRESULT WINAPI CreateTypeLib(
292 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
294 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
298 /******************************************************************************
299 * LoadTypeLib [OLEAUT32.161]
301 * Loads a type library
304 * szFile [I] Name of file to load from.
305 * pptLib [O] Pointer that receives ITypeLib object on success.
312 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
314 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
316 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
317 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
320 /******************************************************************************
321 * LoadTypeLibEx [OLEAUT32.183]
323 * Loads and optionally registers a type library
329 HRESULT WINAPI LoadTypeLibEx(
330 LPCOLESTR szFile, /* [in] Name of file to load from */
331 REGKIND regkind, /* [in] Specify kind of registration */
332 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
334 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
339 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
341 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
342 memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));
345 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
348 /* Look for a trailing '\\' followed by an index */
349 pIndexStr = strrchrW(szFile, '\\');
350 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
351 index = atoiW(pIndexStr);
352 memcpy(szFileCopy, szFile,
353 (pIndexStr - szFile - 1) * sizeof(WCHAR));
354 szFileCopy[pIndexStr - szFile - 1] = '\0';
355 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
357 return TYPE_E_CANTLOADLIBRARY;
358 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
359 return TYPE_E_CANTLOADLIBRARY;
363 TRACE("File %s index %d\n", debugstr_w(szPath), index);
365 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
370 case REGKIND_DEFAULT:
371 /* don't register typelibs supplied with full path. Experimentation confirms the following */
373 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
374 (szFile[0] && (szFile[1] == ':'))) break;
375 /* else fall-through */
377 case REGKIND_REGISTER:
378 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
380 IUnknown_Release(*pptLib);
388 TRACE(" returns %08lx\n",res);
392 /******************************************************************************
393 * LoadRegTypeLib [OLEAUT32.162]
395 * Loads a registered type library.
398 * rguid [I] GUID of the registered type library.
399 * wVerMajor [I] major version.
400 * wVerMinor [I] minor version.
401 * lcid [I] locale ID.
402 * ppTLib [O] pointer that receives an ITypeLib object on success.
406 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
409 HRESULT WINAPI LoadRegTypeLib(
417 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
421 res= LoadTypeLib(bstr, ppTLib);
425 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
431 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
432 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
433 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
434 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
435 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
436 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
438 /******************************************************************************
439 * RegisterTypeLib [OLEAUT32.163]
440 * Adds information about a type library to the System Registry
442 * Docs: ITypeLib FAR * ptlib
443 * Docs: OLECHAR FAR* szFullPath
444 * Docs: OLECHAR FAR* szHelpDir
450 HRESULT WINAPI RegisterTypeLib(
451 ITypeLib * ptlib, /* [in] Pointer to the library*/
452 OLECHAR * szFullPath, /* [in] full Path of the library*/
453 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
456 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
457 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
458 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
468 if (ptlib == NULL || szFullPath == NULL)
471 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
474 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
477 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
478 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
482 /* Set the human-readable name of the typelib */
483 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
485 if (RegSetValueExW(key, NULL, 0, REG_SZ,
486 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
494 /* Make up the name of the typelib path subkey */
495 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
497 /* Create the typelib path subkey */
498 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
499 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
501 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
502 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
510 /* Create the flags subkey */
511 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
512 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
514 /* FIXME: is %u correct? */
515 static const WCHAR formatW[] = {'%','u',0};
517 sprintfW(buf, formatW, attr->wLibFlags);
518 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
519 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
527 /* create the helpdir subkey */
528 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
529 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
531 BOOL freeHelpDir = FALSE;
534 /* if we created a new key, and helpDir was null, set the helpdir
535 to the directory which contains the typelib. However,
536 if we just opened an existing key, we leave the helpdir alone */
537 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
538 szHelpDir = SysAllocString(szFullPath);
539 pIndexStr = strrchrW(szHelpDir, '\\');
546 /* if we have an szHelpDir, set it! */
547 if (szHelpDir != NULL) {
548 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
549 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
555 if (freeHelpDir) SysFreeString(szHelpDir);
567 /* register OLE Automation-compatible interfaces for this typelib */
568 types = ITypeLib_GetTypeInfoCount(ptlib);
569 for (tidx=0; tidx<types; tidx++) {
570 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
571 LPOLESTR name = NULL;
572 ITypeInfo *tinfo = NULL;
574 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
577 case TKIND_INTERFACE:
578 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
579 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
583 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
584 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
588 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
593 TYPEATTR *tattr = NULL;
594 ITypeInfo_GetTypeAttr(tinfo, &tattr);
597 TRACE_(typelib)("guid=%s, flags=%04x (",
598 debugstr_guid(&tattr->guid),
601 if (TRACE_ON(typelib)) {
602 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
622 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
624 /* register interface<->typelib coupling */
625 get_interface_key( &tattr->guid, keyName );
626 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
627 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
630 RegSetValueExW(key, NULL, 0, REG_SZ,
631 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
633 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
634 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
635 RegSetValueExW(subKey, NULL, 0, REG_SZ,
636 (BYTE*)PSOA, sizeof PSOA);
640 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
641 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
642 RegSetValueExW(subKey, NULL, 0, REG_SZ,
643 (BYTE*)PSOA, sizeof PSOA);
647 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
648 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
651 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
652 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
654 StringFromGUID2(&attr->guid, buffer, 40);
655 RegSetValueExW(subKey, NULL, 0, REG_SZ,
656 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
657 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
658 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
659 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
667 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
670 ITypeInfo_Release(tinfo);
677 ITypeLib_ReleaseTLibAttr(ptlib, attr);
683 /******************************************************************************
684 * UnRegisterTypeLib [OLEAUT32.186]
685 * Removes information about a type library from the System Registry
692 HRESULT WINAPI UnRegisterTypeLib(
693 REFGUID libid, /* [in] Guid of the library */
694 WORD wVerMajor, /* [in] major version */
695 WORD wVerMinor, /* [in] minor version */
696 LCID lcid, /* [in] locale id */
699 BSTR tlibPath = NULL;
702 WCHAR subKeyName[50];
705 BOOL deleteOtherStuff;
708 TYPEATTR* typeAttr = NULL;
710 ITypeInfo* typeInfo = NULL;
711 ITypeLib* typeLib = NULL;
714 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
716 /* Create the path to the key */
717 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
719 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
721 TRACE("Unsupported syskind %i\n", syskind);
722 result = E_INVALIDARG;
726 /* get the path to the typelib on disk */
727 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
728 result = E_INVALIDARG;
732 /* Try and open the key to the type library. */
733 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
734 result = E_INVALIDARG;
738 /* Try and load the type library */
739 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
740 result = TYPE_E_INVALIDSTATE;
744 /* remove any types registered with this typelib */
745 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
746 for (i=0; i<numTypes; i++) {
747 /* get the kind of type */
748 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
752 /* skip non-interfaces, and get type info for the type */
753 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
756 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
759 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
763 /* the path to the type */
764 get_interface_key( &typeAttr->guid, subKeyName );
766 /* Delete its bits */
767 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
770 RegDeleteKeyW(subKey, ProxyStubClsidW);
771 RegDeleteKeyW(subKey, ProxyStubClsid32W);
772 RegDeleteKeyW(subKey, TypeLibW);
775 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
778 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
780 if (typeInfo) ITypeInfo_Release(typeInfo);
784 /* Now, delete the type library path subkey */
785 get_lcid_subkey( lcid, syskind, subKeyName );
786 RegDeleteKeyW(key, subKeyName);
787 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
788 RegDeleteKeyW(key, subKeyName);
790 /* check if there is anything besides the FLAGS/HELPDIR keys.
791 If there is, we don't delete them */
792 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
793 deleteOtherStuff = TRUE;
795 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
796 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
798 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
799 if (!strcmpW(subKeyName, FLAGSW)) continue;
800 if (!strcmpW(subKeyName, HELPDIRW)) continue;
801 deleteOtherStuff = FALSE;
805 /* only delete the other parts of the key if we're absolutely sure */
806 if (deleteOtherStuff) {
807 RegDeleteKeyW(key, FLAGSW);
808 RegDeleteKeyW(key, HELPDIRW);
812 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
813 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
814 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
818 if (tlibPath) SysFreeString(tlibPath);
819 if (typeLib) ITypeLib_Release(typeLib);
820 if (subKey) RegCloseKey(subKey);
821 if (key) RegCloseKey(key);
825 /*======================= ITypeLib implementation =======================*/
827 typedef struct tagTLBCustData
831 struct tagTLBCustData* next;
834 /* data structure for import typelibs */
835 typedef struct tagTLBImpLib
837 int offset; /* offset in the file (MSFT)
838 offset in nametable (SLTG)
839 just used to identify library while reading
841 GUID guid; /* libid */
842 BSTR name; /* name */
844 LCID lcid; /* lcid of imported typelib */
846 WORD wVersionMajor; /* major version number */
847 WORD wVersionMinor; /* minor version number */
849 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
850 NULL if not yet loaded */
851 struct tagTLBImpLib * next;
854 /* internal ITypeLib data */
855 typedef struct tagITypeLibImpl
857 const ITypeLib2Vtbl *lpVtbl;
858 const ITypeCompVtbl *lpVtblTypeComp;
860 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
862 /* strings can be stored in tlb as multibyte strings BUT they are *always*
863 * exported to the application as a UNICODE string.
869 unsigned long dwHelpContext;
870 int TypeInfoCount; /* nr of typeinfo's in librarry */
871 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
872 int ctCustData; /* number of items in cust data list */
873 TLBCustData * pCustData; /* linked list to cust data */
874 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
875 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
876 libary. Only used while read MSFT
879 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
880 struct tagITypeLibImpl *next, *prev;
885 static const ITypeLib2Vtbl tlbvt;
886 static const ITypeCompVtbl tlbtcvt;
888 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
890 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
893 /* ITypeLib methods */
894 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
895 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
897 /*======================= ITypeInfo implementation =======================*/
899 /* data for referenced types */
900 typedef struct tagTLBRefType
902 INT index; /* Type index for internal ref or for external ref
903 it the format is SLTG. -2 indicates to
906 GUID guid; /* guid of the referenced type */
907 /* if index == TLB_REF_USE_GUID */
909 HREFTYPE reference; /* The href of this ref */
910 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
911 TLB_REF_INTERNAL for internal refs
912 TLB_REF_NOT_FOUND for broken refs */
914 struct tagTLBRefType * next;
917 #define TLB_REF_USE_GUID -2
919 #define TLB_REF_INTERNAL (void*)-2
920 #define TLB_REF_NOT_FOUND (void*)-1
922 /* internal Parameter data */
923 typedef struct tagTLBParDesc
927 TLBCustData * pCustData; /* linked list to cust data */
930 /* internal Function data */
931 typedef struct tagTLBFuncDesc
933 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
934 BSTR Name; /* the name of this function */
935 TLBParDesc *pParamDesc; /* array with param names and custom data */
937 int HelpStringContext;
939 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
941 TLBCustData * pCustData; /* linked list to cust data; */
942 struct tagTLBFuncDesc * next;
945 /* internal Variable data */
946 typedef struct tagTLBVarDesc
948 VARDESC vardesc; /* lots of info on the variable and its attributes. */
949 BSTR Name; /* the name of this variable */
951 int HelpStringContext; /* FIXME: where? */
954 TLBCustData * pCustData;/* linked list to cust data; */
955 struct tagTLBVarDesc * next;
958 /* internal implemented interface data */
959 typedef struct tagTLBImplType
961 HREFTYPE hRef; /* hRef of interface */
962 int implflags; /* IMPLFLAG_*s */
964 TLBCustData * pCustData;/* linked list to custom data; */
965 struct tagTLBImplType *next;
968 /* internal TypeInfo data */
969 typedef struct tagITypeInfoImpl
971 const ITypeInfo2Vtbl *lpVtbl;
972 const ITypeCompVtbl *lpVtblTypeComp;
974 TYPEATTR TypeAttr ; /* _lots_ of type information. */
975 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
976 int index; /* index in this typelib; */
977 /* type libs seem to store the doc strings in ascii
978 * so why should we do it in unicode?
983 unsigned long dwHelpContext;
984 unsigned long dwHelpStringContext;
987 TLBFuncDesc * funclist; /* linked list with function descriptions */
990 TLBVarDesc * varlist; /* linked list with variable descriptions */
992 /* Implemented Interfaces */
993 TLBImplType * impltypelist;
995 TLBRefType * reflist;
997 TLBCustData * pCustData; /* linked list to cust data; */
998 struct tagITypeInfoImpl * next;
1001 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1003 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1006 static const ITypeInfo2Vtbl tinfvt;
1007 static const ITypeCompVtbl tcompvt;
1009 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1011 typedef struct tagTLBContext
1013 unsigned int oStart; /* start of TLB in file */
1014 unsigned int pos; /* current pos */
1015 unsigned int length; /* total length */
1016 void *mapping; /* memory mapping */
1017 MSFT_SegDir * pTblDir;
1018 ITypeLibImpl* pLibInfo;
1022 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1027 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1028 if (pTD->vt & VT_RESERVED)
1029 szVarType += strlen(strcpy(szVarType, "reserved | "));
1030 if (pTD->vt & VT_BYREF)
1031 szVarType += strlen(strcpy(szVarType, "ref to "));
1032 if (pTD->vt & VT_ARRAY)
1033 szVarType += strlen(strcpy(szVarType, "array of "));
1034 if (pTD->vt & VT_VECTOR)
1035 szVarType += strlen(strcpy(szVarType, "vector of "));
1036 switch(pTD->vt & VT_TYPEMASK) {
1037 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1038 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1039 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1040 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1041 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1042 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1043 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1044 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1045 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1046 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1047 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1048 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1049 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1050 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1051 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1052 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1053 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1054 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1055 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1056 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1057 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1058 pTD->u.hreftype); break;
1059 case VT_PTR: sprintf(szVarType, "ptr to ");
1060 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1062 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1063 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1065 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1066 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1067 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1070 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1074 static void dump_ELEMDESC(ELEMDESC *edesc) {
1076 dump_TypeDesc(&edesc->tdesc,buf);
1077 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1078 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1079 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1081 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
1083 MESSAGE("memid is %08lx\n",funcdesc->memid);
1084 for (i=0;i<funcdesc->cParams;i++) {
1085 MESSAGE("Param %d:\n",i);
1086 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1088 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1089 switch (funcdesc->funckind) {
1090 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1091 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1092 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1093 case FUNC_STATIC: MESSAGE("static");break;
1094 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1095 default: MESSAGE("unknown");break;
1097 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1098 switch (funcdesc->invkind) {
1099 case INVOKE_FUNC: MESSAGE("func");break;
1100 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1101 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1102 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1104 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1105 switch (funcdesc->callconv) {
1106 case CC_CDECL: MESSAGE("cdecl");break;
1107 case CC_PASCAL: MESSAGE("pascal");break;
1108 case CC_STDCALL: MESSAGE("stdcall");break;
1109 case CC_SYSCALL: MESSAGE("syscall");break;
1112 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1113 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1114 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1116 MESSAGE("\telemdescFunc (return value type):\n");
1117 dump_ELEMDESC(&funcdesc->elemdescFunc);
1120 static const char * typekind_desc[] =
1133 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1136 if (!TRACE_ON(typelib))
1138 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1139 for (i=0;i<pfd->funcdesc.cParams;i++)
1140 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1143 dump_FUNCDESC(&(pfd->funcdesc));
1145 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1146 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1148 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1152 dump_TLBFuncDescOne(pfd);
1156 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1160 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1165 static void dump_TLBImpLib(TLBImpLib *import)
1167 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1168 debugstr_w(import->name));
1169 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1170 import->wVersionMinor, import->lcid, import->offset);
1173 static void dump_TLBRefType(TLBRefType * prt)
1177 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1178 if(prt->index == -1)
1179 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1181 TRACE_(typelib)("type no: %d\n", prt->index);
1183 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1184 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1185 TRACE_(typelib)("in lib\n");
1186 dump_TLBImpLib(prt->pImpTLInfo);
1192 static void dump_TLBImplType(TLBImplType * impl)
1196 "implementing/inheriting interface hRef = %lx implflags %x\n",
1197 impl->hRef, impl->implflags);
1202 void dump_Variant(VARIANT * pvar)
1206 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1210 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1211 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1213 TRACE(",%p", V_BYREF(pvar));
1215 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1219 else switch (V_TYPE(pvar))
1221 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1222 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1223 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1224 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1226 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1228 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1229 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1230 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1231 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1232 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1233 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1234 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1235 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1236 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1237 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1238 V_CY(pvar).s.Lo); break;
1240 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1241 TRACE(",<invalid>");
1243 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1244 st.wHour, st.wMinute, st.wSecond);
1248 case VT_USERDEFINED:
1250 case VT_NULL: break;
1251 default: TRACE(",?"); break;
1257 static void dump_DispParms(DISPPARAMS * pdp)
1261 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1263 while (index < pdp->cArgs)
1265 dump_Variant( &pdp->rgvarg[index] );
1270 static void dump_TypeInfo(ITypeInfoImpl * pty)
1272 TRACE("%p ref=%lu\n", pty, pty->ref);
1273 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1274 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1275 TRACE("fct:%u var:%u impl:%u\n",
1276 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1277 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1278 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1279 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1280 dump_TLBFuncDesc(pty->funclist);
1281 dump_TLBVarDesc(pty->varlist);
1282 dump_TLBImplType(pty->impltypelist);
1285 static void dump_VARDESC(VARDESC *v)
1287 MESSAGE("memid %ld\n",v->memid);
1288 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1289 MESSAGE("oInst %ld\n",v->u.oInst);
1290 dump_ELEMDESC(&(v->elemdescVar));
1291 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1292 MESSAGE("varkind %d\n",v->varkind);
1295 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1297 /* VT_LPWSTR is largest type that */
1298 /* may appear in type description*/
1299 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1300 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1301 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1302 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1303 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1304 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1308 static void TLB_abort(void)
1312 static void * TLB_Alloc(unsigned size)
1315 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1317 ERR("cannot allocate memory\n");
1322 static void TLB_Free(void * ptr)
1324 HeapFree(GetProcessHeap(), 0, ptr);
1327 /* deep copy a typedesc */
1328 static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in)
1333 out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC));
1334 copy_typedesc(out->u.lptdesc, in->u.lptdesc);
1336 case VT_USERDEFINED:
1337 out->u.hreftype = in->u.hreftype;
1340 out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) +
1341 (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND));
1342 copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem);
1343 out->u.lpadesc->cDims = in->u.lpadesc->cDims;
1344 memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND));
1351 /* free()s any allocated memory pointed to by the tdesc. NB does not
1352 free the tdesc itself - this is because the tdesc is typically part
1353 of a larger structure */
1354 static void free_deep_typedesc(TYPEDESC *tdesc)
1358 free_deep_typedesc(tdesc->u.lptdesc);
1359 HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);
1360 tdesc->u.lptdesc = NULL;
1363 free_deep_typedesc(&tdesc->u.lpadesc->tdescElem);
1364 HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);
1365 tdesc->u.lpadesc = NULL;
1372 /**********************************************************************
1374 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1377 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1379 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1380 pcx->pos, count, pcx->oStart, pcx->length, where);
1382 if (where != DO_NOT_SEEK)
1384 where += pcx->oStart;
1385 if (where > pcx->length)
1388 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1393 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1394 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1399 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1404 ret = MSFT_Read(buffer, count, pcx, where);
1405 FromLEDWords(buffer, ret);
1410 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1415 ret = MSFT_Read(buffer, count, pcx, where);
1416 FromLEWords(buffer, ret);
1421 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1423 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1424 memset(pGuid,0, sizeof(GUID));
1427 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1428 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1429 pGuid->Data2 = FromLEWord(pGuid->Data2);
1430 pGuid->Data3 = FromLEWord(pGuid->Data3);
1431 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1434 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1437 MSFT_NameIntro niName;
1439 WCHAR* pwstring = NULL;
1440 BSTR bstrName = NULL;
1444 ERR_(typelib)("bad offset %d\n", offset);
1447 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1448 pcx->pTblDir->pNametab.offset+offset);
1449 niName.namelen &= 0xFF; /* FIXME: correct ? */
1450 name=TLB_Alloc((niName.namelen & 0xff) +1);
1451 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1452 name[niName.namelen & 0xff]='\0';
1454 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1457 /* no invalid characters in string */
1460 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1462 /* don't check for invalid character since this has been done previously */
1463 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1465 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1466 lengthInChars = SysStringLen(bstrName);
1467 HeapFree(GetProcessHeap(), 0, pwstring);
1470 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1474 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1481 if(offset<0) return NULL;
1482 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1483 if(length <= 0) return 0;
1484 string=TLB_Alloc(length +1);
1485 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1486 string[length]='\0';
1488 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1489 string, -1, NULL, 0);
1491 /* no invalid characters in string */
1494 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1496 /* don't check for invalid character since this has been done previously */
1497 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1499 bstr = SysAllocStringLen(pwstring, lengthInChars);
1500 lengthInChars = SysStringLen(bstr);
1501 HeapFree(GetProcessHeap(), 0, pwstring);
1504 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1508 * read a value and fill a VARIANT structure
1510 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1514 TRACE_(typelib)("\n");
1516 if(offset <0) { /* data are packed in here */
1517 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1518 V_I2(pVar) = offset & 0x3ffffff;
1521 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1522 pcx->pTblDir->pCustData.offset + offset );
1523 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1524 switch (V_VT(pVar)){
1525 case VT_EMPTY: /* FIXME: is this right? */
1526 case VT_NULL: /* FIXME: is this right? */
1527 case VT_I2 : /* this should not happen */
1538 case VT_VOID : /* FIXME: is this right? */
1546 case VT_DECIMAL : /* FIXME: is this right? */
1549 /* pointer types with known behaviour */
1552 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1554 FIXME("BSTR length = %d?\n", size);
1556 ptr=TLB_Alloc(size);/* allocate temp buffer */
1557 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1558 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1559 /* FIXME: do we need a AtoW conversion here? */
1560 V_UNION(pVar, bstrVal[size])=L'\0';
1561 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1566 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1573 case VT_USERDEFINED :
1579 case VT_STREAMED_OBJECT :
1580 case VT_STORED_OBJECT :
1581 case VT_BLOB_OBJECT :
1586 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1590 if(size>0) /* (big|small) endian correct? */
1591 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1595 * create a linked list with custom data
1597 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1603 TRACE_(typelib)("\n");
1607 pNew=TLB_Alloc(sizeof(TLBCustData));
1608 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1609 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1610 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1611 /* add new custom data at head of the list */
1612 pNew->next=*ppCustData;
1614 offset = entry.next;
1619 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1623 pTd->vt=type & VT_TYPEMASK;
1625 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1627 if(pTd->vt == VT_USERDEFINED)
1628 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1630 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1634 MSFT_DoFuncs(TLBContext* pcx,
1639 TLBFuncDesc** pptfd)
1642 * member information is stored in a data structure at offset
1643 * indicated by the memoffset field of the typeinfo structure
1644 * There are several distinctive parts.
1645 * The first part starts with a field that holds the total length
1646 * of this (first) part excluding this field. Then follow the records,
1647 * for each member there is one record.
1649 * The first entry is always the length of the record (including this
1651 * The rest of the record depends on the type of the member. If there is
1652 * a field indicating the member type (function, variable, interface, etc)
1653 * I have not found it yet. At this time we depend on the information
1654 * in the type info and the usual order how things are stored.
1656 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1659 * Third is an equal sized array with file offsets to the name entry
1662 * The fourth and last (?) part is an array with offsets to the records
1663 * in the first part of this file segment.
1666 int infolen, nameoffset, reclength, nrattributes, i;
1667 int recoffset = offset + sizeof(INT);
1670 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1672 TRACE_(typelib)("\n");
1674 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1676 for ( i = 0; i < cFuncs ; i++ )
1678 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1680 /* name, eventually add to a hash table */
1681 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1682 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1684 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1686 /* read the function information record */
1687 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1691 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1693 /* do the attributes */
1694 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1697 if ( nrattributes > 0 )
1699 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1701 if ( nrattributes > 1 )
1703 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1704 pFuncRec->OptAttr[1]) ;
1706 if ( nrattributes > 2 )
1708 if ( pFuncRec->FKCCIC & 0x2000 )
1710 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1714 (*pptfd)->Entry = MSFT_ReadString(pcx,
1715 pFuncRec->OptAttr[2]);
1717 if( nrattributes > 5 )
1719 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1721 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1724 pFuncRec->OptAttr[6],
1725 &(*pptfd)->pCustData);
1732 /* fill the FuncDesc Structure */
1733 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1734 offset + infolen + ( i + 1) * sizeof(INT));
1736 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1737 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1738 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1739 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1740 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1741 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1742 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1746 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1749 /* do the parameters/arguments */
1750 if(pFuncRec->nrargs)
1753 MSFT_ParameterInfo paraminfo;
1755 (*pptfd)->funcdesc.lprgelemdescParam =
1756 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1758 (*pptfd)->pParamDesc =
1759 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1761 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1762 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1764 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1766 TYPEDESC* lpArgTypeDesc = 0;
1770 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1773 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1776 if (paraminfo.oName == -1)
1777 /* this occurs for [propput] or [propget] methods, so
1778 * we should just set the name of the parameter to the
1779 * name of the method. */
1780 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1782 (*pptfd)->pParamDesc[j].Name =
1783 MSFT_ReadName( pcx, paraminfo.oName );
1784 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1786 /* SEEK value = jump to offset,
1787 * from there jump to the end of record,
1788 * go back by (j-1) arguments
1790 MSFT_ReadLEDWords( ¶minfo ,
1791 sizeof(MSFT_ParameterInfo), pcx,
1792 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1793 * sizeof(MSFT_ParameterInfo)));
1795 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1797 while ( lpArgTypeDesc != NULL )
1799 switch ( lpArgTypeDesc->vt )
1802 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1806 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1809 case VT_USERDEFINED:
1810 MSFT_DoRefType(pcx, pTI,
1811 lpArgTypeDesc->u.hreftype);
1813 lpArgTypeDesc = NULL;
1817 lpArgTypeDesc = NULL;
1823 /* parameter is the return value! */
1824 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1826 TYPEDESC* lpArgTypeDesc;
1828 (*pptfd)->funcdesc.elemdescFunc =
1829 (*pptfd)->funcdesc.lprgelemdescParam[j];
1831 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1833 while ( lpArgTypeDesc != NULL )
1835 switch ( lpArgTypeDesc->vt )
1838 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1842 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1846 case VT_USERDEFINED:
1849 lpArgTypeDesc->u.hreftype);
1851 lpArgTypeDesc = NULL;
1855 lpArgTypeDesc = NULL;
1860 /* second time around */
1861 for(j=0;j<pFuncRec->nrargs;j++)
1864 if ( (PARAMFLAG_FHASDEFAULT &
1865 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1866 ((pFuncRec->FKCCIC) & 0x1000) )
1868 INT* pInt = (INT *)((char *)pFuncRec +
1870 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1872 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1874 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1875 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1877 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1881 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1884 pFuncRec->OptAttr[7+j],
1885 &(*pptfd)->pParamDesc[j].pCustData);
1890 /* scode is not used: archaic win16 stuff FIXME: right? */
1891 (*pptfd)->funcdesc.cScodes = 0 ;
1892 (*pptfd)->funcdesc.lprgscode = NULL ;
1894 pptfd = & ((*pptfd)->next);
1895 recoffset += reclength;
1899 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1900 int cVars, int offset, TLBVarDesc ** pptvd)
1902 int infolen, nameoffset, reclength;
1904 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1908 TRACE_(typelib)("\n");
1910 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1911 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1912 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1913 recoffset += offset+sizeof(INT);
1914 for(i=0;i<cVars;i++){
1915 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1916 /* name, eventually add to a hash table */
1917 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1918 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1919 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1920 /* read the variable information record */
1921 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1923 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1925 if(reclength >(6*sizeof(INT)) )
1926 (*pptvd)->HelpContext=pVarRec->HelpContext;
1927 if(reclength >(7*sizeof(INT)) )
1928 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1929 if(reclength >(8*sizeof(INT)) )
1930 if(reclength >(9*sizeof(INT)) )
1931 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1932 /* fill the VarDesc Structure */
1933 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1934 offset + infolen + ( i + 1) * sizeof(INT));
1935 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1936 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1937 MSFT_GetTdesc(pcx, pVarRec->DataType,
1938 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1939 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1940 if(pVarRec->VarKind == VAR_CONST ){
1941 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1942 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1943 pVarRec->OffsValue, pcx);
1945 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1946 pptvd=&((*pptvd)->next);
1947 recoffset += reclength;
1950 /* fill in data for a hreftype (offset). When the referenced type is contained
1951 * in the typelib, it's just an (file) offset in the type info base dir.
1952 * If comes from import, it's an offset+1 in the ImpInfo table
1954 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1958 TLBRefType **ppRefType = &pTI->reflist;
1960 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1963 if((*ppRefType)->reference == offset)
1965 ppRefType = &(*ppRefType)->next;
1968 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1969 sizeof(**ppRefType));
1971 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1972 /* external typelib */
1973 MSFT_ImpInfo impinfo;
1974 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1976 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1978 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1979 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1980 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1981 if(pImpLib->offset==impinfo.oImpFile) break;
1982 pImpLib=pImpLib->next;
1985 (*ppRefType)->reference=offset;
1986 (*ppRefType)->pImpTLInfo = pImpLib;
1987 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1988 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1989 (*ppRefType)->index = TLB_REF_USE_GUID;
1991 (*ppRefType)->index = impinfo.oGuid;
1993 ERR("Cannot find a reference\n");
1994 (*ppRefType)->reference=-1;
1995 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1998 /* in this typelib */
1999 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2000 (*ppRefType)->reference=offset;
2001 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2005 /* process Implemented Interfaces of a com class */
2006 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2010 MSFT_RefRecord refrec;
2011 TLBImplType **ppImpl = &pTI->impltypelist;
2013 TRACE_(typelib)("\n");
2015 for(i=0;i<count;i++){
2016 if(offset<0) break; /* paranoia */
2017 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2018 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2019 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2020 (*ppImpl)->hRef = refrec.reftype;
2021 (*ppImpl)->implflags=refrec.flags;
2022 (*ppImpl)->ctCustData=
2023 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2024 offset=refrec.onext;
2025 ppImpl=&((*ppImpl)->next);
2029 * process a typeinfo record
2031 static ITypeInfoImpl * MSFT_DoTypeInfo(
2034 ITypeLibImpl * pLibInfo)
2036 MSFT_TypeInfoBase tiBase;
2037 ITypeInfoImpl *ptiRet;
2039 TRACE_(typelib)("count=%u\n", count);
2041 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2042 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2043 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2045 /* this is where we are coming from */
2046 ptiRet->pTypeLib = pLibInfo;
2047 ptiRet->index=count;
2048 /* fill in the typeattr fields */
2049 WARN("Assign constructor/destructor memid\n");
2051 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2052 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2053 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2054 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2055 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2056 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2057 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2058 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2059 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2060 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2061 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2062 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2063 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2064 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2065 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2066 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2067 MSFT_GetTdesc(pcx, tiBase.datatype1,
2068 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2071 /* IDLDESC idldescType; *//* never saw this one != zero */
2073 /* name, eventually add to a hash table */
2074 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2075 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2077 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2078 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2079 ptiRet->dwHelpContext=tiBase.helpcontext;
2081 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2082 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2084 /* note: InfoType's Help file and HelpStringDll come from the containing
2085 * library. Further HelpString and Docstring appear to be the same thing :(
2088 if(ptiRet->TypeAttr.cFuncs >0 )
2089 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2090 ptiRet->TypeAttr.cVars,
2091 tiBase.memoffset, & ptiRet->funclist);
2093 if(ptiRet->TypeAttr.cVars >0 )
2094 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2095 ptiRet->TypeAttr.cVars,
2096 tiBase.memoffset, & ptiRet->varlist);
2097 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2098 switch(ptiRet->TypeAttr.typekind)
2101 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2104 case TKIND_DISPATCH:
2105 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2107 if (tiBase.datatype1 != -1)
2109 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2110 ptiRet->impltypelist->hRef = tiBase.datatype1;
2113 { /* FIXME: This is a really bad hack to add IDispatch */
2114 const char* szStdOle = "stdole2.tlb\0";
2115 int nStdOleLen = strlen(szStdOle);
2116 TLBRefType **ppRef = &ptiRet->reflist;
2119 if((*ppRef)->reference == -1)
2121 ppRef = &(*ppRef)->next;
2124 *ppRef = TLB_Alloc(sizeof(**ppRef));
2125 (*ppRef)->guid = IID_IDispatch;
2126 (*ppRef)->reference = -1;
2127 (*ppRef)->index = TLB_REF_USE_GUID;
2128 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2129 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2130 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2133 MultiByteToWideChar(CP_ACP,
2137 (*ppRef)->pImpTLInfo->name,
2138 SysStringLen((*ppRef)->pImpTLInfo->name));
2140 (*ppRef)->pImpTLInfo->lcid = 0;
2141 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2142 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2147 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2148 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2149 ptiRet->impltypelist->hRef = tiBase.datatype1;
2154 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2156 TRACE_(typelib)("%s guid: %s kind:%s\n",
2157 debugstr_w(ptiRet->Name),
2158 debugstr_guid(&ptiRet->TypeAttr.guid),
2159 typekind_desc[ptiRet->TypeAttr.typekind]);
2164 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2165 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2166 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2169 static ITypeLibImpl *tlb_cache_first;
2170 static CRITICAL_SECTION cache_section;
2171 static CRITICAL_SECTION_DEBUG cache_section_debug =
2173 0, 0, &cache_section,
2174 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2175 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2177 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2180 /****************************************************************************
2183 * find the type of the typelib file and map the typelib resource into
2186 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2187 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2188 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2190 ITypeLibImpl *entry;
2191 int ret = TYPE_E_CANTLOADLIBRARY;
2192 DWORD dwSignature = 0;
2195 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2199 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2200 EnterCriticalSection(&cache_section);
2201 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2203 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2205 TRACE("cache hit\n");
2206 *ppTypeLib = (ITypeLib2*)entry;
2207 ITypeLib_AddRef(*ppTypeLib);
2208 LeaveCriticalSection(&cache_section);
2212 LeaveCriticalSection(&cache_section);
2214 /* check the signature of the file */
2215 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2216 if (INVALID_HANDLE_VALUE != hFile)
2218 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2221 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2224 /* retrieve file size */
2225 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2227 /* first try to load as *.tlb */
2228 dwSignature = FromLEDWord(*((DWORD*) pBase));
2229 if ( dwSignature == MSFT_SIGNATURE)
2231 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2233 else if ( dwSignature == SLTG_SIGNATURE)
2235 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2237 UnmapViewOfFile(pBase);
2239 CloseHandle(hMapping);
2245 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2248 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2249 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2251 /* find the typelibrary resource*/
2252 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2253 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2256 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2257 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2260 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2263 LPVOID pBase = LockResource(hGlobal);
2264 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2268 /* try to load as incore resource */
2269 dwSignature = FromLEDWord(*((DWORD*) pBase));
2270 if ( dwSignature == MSFT_SIGNATURE)
2272 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2274 else if ( dwSignature == SLTG_SIGNATURE)
2276 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2280 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2283 FreeResource( hGlobal );
2286 FreeLibrary(hinstDLL);
2291 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2293 TRACE("adding to cache\n");
2294 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2295 lstrcpyW(impl->path, pszFileName);
2296 /* We should really canonicalise the path here. */
2297 impl->index = index;
2299 /* FIXME: check if it has added already in the meantime */
2300 EnterCriticalSection(&cache_section);
2301 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2303 tlb_cache_first = impl;
2304 LeaveCriticalSection(&cache_section);
2307 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2312 /*================== ITypeLib(2) Methods ===================================*/
2314 /****************************************************************************
2315 * ITypeLib2_Constructor_MSFT
2317 * loading an MSFT typelib from an in-memory image
2319 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2323 MSFT_Header tlbHeader;
2324 MSFT_SegDir tlbSegDir;
2325 ITypeLibImpl * pTypeLibImpl;
2327 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2329 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2330 if (!pTypeLibImpl) return NULL;
2332 pTypeLibImpl->lpVtbl = &tlbvt;
2333 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2334 pTypeLibImpl->ref = 1;
2336 /* get pointer to beginning of typelib data */
2340 cx.pLibInfo = pTypeLibImpl;
2341 cx.length = dwTLBLength;
2344 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2346 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2347 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2348 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2351 /* there is a small amount of information here until the next important
2353 * the segment directory . Try to calculate the amount of data */
2354 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2356 /* now read the segment directory */
2357 TRACE("read segment directory (at %ld)\n",lPSegDir);
2358 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2359 cx.pTblDir = &tlbSegDir;
2361 /* just check two entries */
2362 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2364 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2365 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2369 /* now fill our internal data */
2370 /* TLIBATTR fields */
2371 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2373 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2374 /* Windows seems to have zero here, is this correct? */
2375 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2376 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2378 pTypeLibImpl->LibAttr.lcid = 0;
2380 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2381 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2382 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2383 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2385 /* name, eventually add to a hash table */
2386 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2389 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2390 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2392 if( tlbHeader.varflags & HELPDLLFLAG)
2395 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2396 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2399 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2402 if(tlbHeader.CustomDataOffset >= 0)
2404 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2407 /* fill in typedescriptions */
2408 if(tlbSegDir.pTypdescTab.length > 0)
2410 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2412 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2413 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2416 /* FIXME: add several sanity checks here */
2417 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2418 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2420 /* FIXME: check safearray */
2422 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2424 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2426 else if(td[0] == VT_CARRAY)
2428 /* array descr table here */
2429 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2431 else if(td[0] == VT_USERDEFINED)
2433 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2435 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2438 /* second time around to fill the array subscript info */
2441 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2442 if(tlbSegDir.pArrayDescriptions.offset>0)
2444 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2445 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2448 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2450 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2452 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2454 for(j = 0; j<td[2]; j++)
2456 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2457 sizeof(INT), &cx, DO_NOT_SEEK);
2458 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2459 sizeof(INT), &cx, DO_NOT_SEEK);
2464 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2465 ERR("didn't find array description data\n");
2470 /* imported type libs */
2471 if(tlbSegDir.pImpFiles.offset>0)
2473 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2474 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2477 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2482 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2483 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2484 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2486 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2487 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2488 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2489 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2492 name = TLB_Alloc(size+1);
2493 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2494 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2495 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2496 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2499 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2500 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2502 ppImpLib = &(*ppImpLib)->next;
2507 if(tlbHeader.nrtypeinfos >= 0 )
2509 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2510 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2513 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2515 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2517 ppTI = &((*ppTI)->next);
2518 (pTypeLibImpl->TypeInfoCount)++;
2522 TRACE("(%p)\n", pTypeLibImpl);
2523 return (ITypeLib2*) pTypeLibImpl;
2527 static BSTR TLB_MultiByteToBSTR(char *ptr)
2533 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2534 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2535 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2536 ret = SysAllocString(nameW);
2537 HeapFree(GetProcessHeap(), 0, nameW);
2541 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2547 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2548 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2552 guid->Data4[0] = s >> 8;
2553 guid->Data4[1] = s & 0xff;
2556 for(i = 0; i < 6; i++) {
2557 memcpy(b, str + 24 + 2 * i, 2);
2558 guid->Data4[i + 2] = strtol(b, NULL, 16);
2563 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2570 bytelen = *(WORD*)ptr;
2571 if(bytelen == 0xffff) return 2;
2572 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2573 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2574 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2575 *pBstr = SysAllocStringLen(nameW, len);
2576 HeapFree(GetProcessHeap(), 0, nameW);
2580 static WORD SLTG_ReadStringA(char *ptr, char **str)
2585 bytelen = *(WORD*)ptr;
2586 if(bytelen == 0xffff) return 2;
2587 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2588 memcpy(*str, ptr + 2, bytelen);
2589 (*str)[bytelen] = '\0';
2593 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2595 char *ptr = pLibBlk;
2598 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2599 FIXME("libblk magic = %04x\n", w);
2604 if((w = *(WORD*)ptr) != 0xffff) {
2605 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2610 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2612 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2614 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2617 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2620 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2621 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2623 pTypeLibImpl->LibAttr.lcid = 0;
2626 ptr += 4; /* skip res12 */
2628 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2631 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2634 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2637 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2638 ptr += sizeof(GUID);
2640 return ptr - (char*)pLibBlk;
2643 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2646 TYPEDESC *pTD = &pElem->tdesc;
2648 /* Handle [in/out] first */
2649 if((*pType & 0xc000) == 0xc000)
2650 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2651 else if(*pType & 0x8000)
2652 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2653 else if(*pType & 0x4000)
2654 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2656 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2659 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2662 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2665 if((*pType & 0xe00) == 0xe00) {
2667 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2669 pTD = pTD->u.lptdesc;
2671 switch(*pType & 0x7f) {
2674 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2676 pTD = pTD->u.lptdesc;
2679 case VT_USERDEFINED:
2680 pTD->vt = VT_USERDEFINED;
2681 pTD->u.hreftype = *(++pType) / 4;
2687 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2690 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2692 pTD->vt = VT_CARRAY;
2693 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2695 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2696 pTD->u.lpadesc->cDims = pSA->cDims;
2697 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2698 pSA->cDims * sizeof(SAFEARRAYBOUND));
2700 pTD = &pTD->u.lpadesc->tdescElem;
2706 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2710 pTD->vt = VT_SAFEARRAY;
2711 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2713 pTD = pTD->u.lptdesc;
2717 pTD->vt = *pType & 0x7f;
2727 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2732 TLBRefType **ppRefType;
2734 if(pRef->magic != SLTG_REF_MAGIC) {
2735 FIXME("Ref magic = %x\n", pRef->magic);
2738 name = ( (char*)(&pRef->names) + pRef->number);
2740 ppRefType = &pTI->reflist;
2741 for(ref = 0; ref < pRef->number >> 3; ref++) {
2743 unsigned int lib_offs, type_num;
2745 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2746 sizeof(**ppRefType));
2748 name += SLTG_ReadStringA(name, &refname);
2749 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2750 FIXME("Can't sscanf ref\n");
2751 if(lib_offs != 0xffff) {
2752 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2755 if((*import)->offset == lib_offs)
2757 import = &(*import)->next;
2760 char fname[MAX_PATH+1];
2763 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2765 (*import)->offset = lib_offs;
2766 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2768 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2769 &(*import)->wVersionMajor,
2770 &(*import)->wVersionMinor,
2771 &(*import)->lcid, fname) != 4) {
2772 FIXME("can't sscanf ref %s\n",
2773 pNameTable + lib_offs + 40);
2775 len = strlen(fname);
2776 if(fname[len-1] != '#')
2777 FIXME("fname = %s\n", fname);
2778 fname[len-1] = '\0';
2779 (*import)->name = TLB_MultiByteToBSTR(fname);
2781 (*ppRefType)->pImpTLInfo = *import;
2782 } else { /* internal ref */
2783 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2785 (*ppRefType)->reference = ref;
2786 (*ppRefType)->index = type_num;
2788 HeapFree(GetProcessHeap(), 0, refname);
2789 ppRefType = &(*ppRefType)->next;
2791 if((BYTE)*name != SLTG_REF_MAGIC)
2792 FIXME("End of ref block magic = %x\n", *name);
2793 dump_TLBRefType(pTI->reflist);
2796 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2799 SLTG_ImplInfo *info;
2800 TLBImplType **ppImplType = &pTI->impltypelist;
2801 /* I don't really get this structure, usually it's 0x16 bytes
2802 long, but iuser.tlb contains some that are 0x18 bytes long.
2803 That's ok because we can use the next ptr to jump to the next
2804 one. But how do we know the length of the last one? The WORD
2805 at offs 0x8 might be the clue. For now I'm just assuming that
2806 the last one is the regular 0x16 bytes. */
2808 info = (SLTG_ImplInfo*)pBlk;
2810 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2811 sizeof(**ppImplType));
2812 (*ppImplType)->hRef = info->ref;
2813 (*ppImplType)->implflags = info->impltypeflags;
2814 pTI->TypeAttr.cImplTypes++;
2815 ppImplType = &(*ppImplType)->next;
2817 if(info->next == 0xffff)
2820 FIXME("Interface inheriting more than one interface\n");
2821 info = (SLTG_ImplInfo*)(pBlk + info->next);
2823 info++; /* see comment at top of function */
2827 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2830 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2831 SLTG_MemberHeader *pMemHeader;
2832 char *pFirstItem, *pNextItem;
2834 if(pTIHeader->href_table != 0xffffffff) {
2835 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2840 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2842 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2844 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2845 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2848 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2852 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2855 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2856 SLTG_MemberHeader *pMemHeader;
2857 SLTG_Function *pFunc;
2858 char *pFirstItem, *pNextItem;
2859 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2862 if(pTIHeader->href_table != 0xffffffff) {
2863 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2867 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2869 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2871 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2872 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2875 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2876 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2881 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2882 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2883 FIXME("func magic = %02x\n", pFunc->magic);
2886 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2887 sizeof(**ppFuncDesc));
2888 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2890 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2891 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2892 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2893 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2894 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2895 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2897 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2898 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2900 if(pFunc->retnextopt & 0x80)
2901 pType = &pFunc->rettype;
2903 pType = (WORD*)(pFirstItem + pFunc->rettype);
2906 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2908 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2909 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2910 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2911 (*ppFuncDesc)->pParamDesc =
2912 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2913 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2915 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2917 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2918 char *paramName = pNameTable + *pArg;
2920 /* If arg type follows then paramName points to the 2nd
2921 letter of the name, else the next WORD is an offset to
2922 the arg type and paramName points to the first letter.
2923 So let's take one char off paramName and see if we're
2924 pointing at an alpha-numeric char. However if *pArg is
2925 0xffff or 0xfffe then the param has no name, the former
2926 meaning that the next WORD is the type, the latter
2927 meaning the the next WORD is an offset to the type. */
2932 else if(*pArg == 0xfffe) {
2936 else if(paramName[-1] && !isalnum(paramName[-1]))
2941 if(HaveOffs) { /* the next word is an offset to type */
2942 pType = (WORD*)(pFirstItem + *pArg);
2943 SLTG_DoType(pType, pFirstItem,
2944 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2949 pArg = SLTG_DoType(pArg, pFirstItem,
2950 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2953 /* Are we an optional param ? */
2954 if((*ppFuncDesc)->funcdesc.cParams - param <=
2955 (*ppFuncDesc)->funcdesc.cParamsOpt)
2956 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2959 (*ppFuncDesc)->pParamDesc[param].Name =
2960 TLB_MultiByteToBSTR(paramName);
2964 ppFuncDesc = &((*ppFuncDesc)->next);
2965 if(pFunc->next == 0xffff) break;
2967 pTI->TypeAttr.cFuncs = num;
2968 dump_TLBFuncDesc(pTI->funclist);
2969 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2972 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2975 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2976 SLTG_MemberHeader *pMemHeader;
2977 SLTG_RecordItem *pItem;
2979 TLBVarDesc **ppVarDesc = &pTI->varlist;
2984 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2986 pFirstItem = (char*)(pMemHeader + 1);
2987 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2988 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2989 if(pItem->magic != SLTG_RECORD_MAGIC) {
2990 FIXME("record magic = %02x\n", pItem->magic);
2993 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2994 sizeof(**ppVarDesc));
2995 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2996 (*ppVarDesc)->vardesc.memid = pItem->memid;
2997 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2998 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3000 if(pItem->typepos == 0x02)
3001 pType = &pItem->type;
3002 else if(pItem->typepos == 0x00)
3003 pType = (WORD*)(pFirstItem + pItem->type);
3005 FIXME("typepos = %02x\n", pItem->typepos);
3009 SLTG_DoType(pType, pFirstItem,
3010 &(*ppVarDesc)->vardesc.elemdescVar);
3012 /* FIXME("helpcontext, helpstring\n"); */
3014 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3016 ppVarDesc = &((*ppVarDesc)->next);
3017 if(pItem->next == 0xffff) break;
3019 pTI->TypeAttr.cVars = num;
3020 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3023 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3026 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3027 SLTG_MemberHeader *pMemHeader;
3028 SLTG_AliasItem *pItem;
3031 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3032 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3035 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3036 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3037 if (pItem->vt == 0xffff) {
3038 if (i<(pMemHeader->cbExtra/4-1))
3039 FIXME("Endmarker too early in process alias data!\n");
3043 FIXME("Chain extends over last entry?\n");
3046 if (pItem->vt == VT_USERDEFINED) {
3047 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3048 /* guessing here ... */
3049 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3050 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3053 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3054 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3058 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3061 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3064 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3065 SLTG_MemberHeader *pMemHeader;
3066 SLTG_AliasItem *pItem;
3068 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3069 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3070 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3071 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3072 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3075 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3078 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3079 SLTG_MemberHeader *pMemHeader;
3080 SLTG_EnumItem *pItem;
3082 TLBVarDesc **ppVarDesc = &pTI->varlist;
3085 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3087 pFirstItem = (char*)(pMemHeader + 1);
3088 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3089 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3090 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3091 FIXME("enumitem magic = %04x\n", pItem->magic);
3094 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3095 sizeof(**ppVarDesc));
3096 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3097 (*ppVarDesc)->vardesc.memid = pItem->memid;
3098 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3100 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3101 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3102 *(INT*)(pItem->value + pFirstItem);
3103 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3104 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3105 /* FIXME("helpcontext, helpstring\n"); */
3107 ppVarDesc = &((*ppVarDesc)->next);
3108 if(pItem->next == 0xffff) break;
3110 pTI->TypeAttr.cVars = num;
3111 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3114 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3115 managable copy of it into this */
3128 } SLTG_InternalOtherTypeInfo;
3130 /****************************************************************************
3131 * ITypeLib2_Constructor_SLTG
3133 * loading a SLTG typelib from an in-memory image
3135 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3137 ITypeLibImpl *pTypeLibImpl;
3138 SLTG_Header *pHeader;
3139 SLTG_BlkEntry *pBlkEntry;
3143 LPVOID pBlk, pFirstBlk;
3144 SLTG_LibBlk *pLibBlk;
3145 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3146 char *pAfterOTIBlks = NULL;
3147 char *pNameTable, *ptr;
3150 ITypeInfoImpl **ppTypeInfoImpl;
3152 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3154 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3155 if (!pTypeLibImpl) return NULL;
3157 pTypeLibImpl->lpVtbl = &tlbvt;
3158 pTypeLibImpl->ref = 1;
3162 TRACE_(typelib)("header:\n");
3163 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3164 pHeader->nrOfFileBlks );
3165 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3166 FIXME("Header type magic 0x%08lx not supported.\n",
3167 pHeader->SLTG_magic);
3171 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3172 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3174 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3175 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3177 /* Next we have a magic block */
3178 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3180 /* Let's see if we're still in sync */
3181 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3182 sizeof(SLTG_COMPOBJ_MAGIC))) {
3183 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3186 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3187 sizeof(SLTG_DIR_MAGIC))) {
3188 FIXME("dir magic = %s\n", pMagic->dir_magic);
3192 pIndex = (SLTG_Index*)(pMagic+1);
3194 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3196 pFirstBlk = (LPVOID)(pPad9 + 1);
3198 /* We'll set up a ptr to the main library block, which is the last one. */
3200 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3201 pBlkEntry[order].next != 0;
3202 order = pBlkEntry[order].next - 1, i++) {
3203 pBlk = (char*)pBlk + pBlkEntry[order].len;
3207 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3209 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3214 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3216 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3217 sizeof(*pOtherTypeInfoBlks) *
3218 pTypeLibImpl->TypeInfoCount);
3221 ptr = (char*)pLibBlk + len;
3223 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3227 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3229 w = *(WORD*)(ptr + 2);
3232 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3234 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3235 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3237 w = *(WORD*)(ptr + 4 + len);
3239 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3241 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3243 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3244 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3246 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3247 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3248 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3250 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3252 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3255 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3256 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3257 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3258 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3259 len += sizeof(SLTG_OtherTypeInfo);
3263 pAfterOTIBlks = ptr;
3265 /* Skip this WORD and get the next DWORD */
3266 len = *(DWORD*)(pAfterOTIBlks + 2);
3268 /* Now add this to pLibBLk look at what we're pointing at and
3269 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3270 dust and we should be pointing at the beginning of the name
3273 pNameTable = (char*)pLibBlk + len;
3275 switch(*(WORD*)pNameTable) {
3282 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3286 pNameTable += 0x216;
3290 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3292 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3295 /* Hopefully we now have enough ptrs set up to actually read in
3296 some TypeInfos. It's not clear which order to do them in, so
3297 I'll just follow the links along the BlkEntry chain and read
3298 them in in the order in which they're in the file */
3300 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3302 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3303 pBlkEntry[order].next != 0;
3304 order = pBlkEntry[order].next - 1, i++) {
3306 SLTG_TypeInfoHeader *pTIHeader;
3307 SLTG_TypeInfoTail *pTITail;
3309 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3310 pOtherTypeInfoBlks[i].index_name)) {
3311 FIXME("Index strings don't match\n");
3316 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3317 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3320 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3321 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3322 (*ppTypeInfoImpl)->index = i;
3323 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3324 pOtherTypeInfoBlks[i].name_offs +
3326 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3327 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3329 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3330 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3331 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3332 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3333 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3335 if((pTIHeader->typeflags1 & 7) != 2)
3336 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3337 if(pTIHeader->typeflags3 != 2)
3338 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3340 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3341 debugstr_w((*ppTypeInfoImpl)->Name),
3342 typekind_desc[pTIHeader->typekind],
3343 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3344 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3346 switch(pTIHeader->typekind) {
3348 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3352 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3355 case TKIND_INTERFACE:
3356 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3360 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3364 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3365 if (pTITail->tdescalias_vt)
3366 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3369 case TKIND_DISPATCH:
3370 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3374 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3380 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3381 but we've already set those */
3382 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3383 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3384 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3386 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3408 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3409 pBlk = (char*)pBlk + pBlkEntry[order].len;
3412 if(i != pTypeLibImpl->TypeInfoCount) {
3413 FIXME("Somehow processed %d TypeInfos\n", i);
3417 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3418 return (ITypeLib2*)pTypeLibImpl;
3421 /* ITypeLib::QueryInterface
3423 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3428 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3430 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3433 if(IsEqualIID(riid, &IID_IUnknown) ||
3434 IsEqualIID(riid,&IID_ITypeLib)||
3435 IsEqualIID(riid,&IID_ITypeLib2))
3442 ITypeLib2_AddRef(iface);
3443 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3446 TRACE("-- Interface: E_NOINTERFACE\n");
3447 return E_NOINTERFACE;
3452 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3454 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3455 ULONG ref = InterlockedIncrement(&This->ref);
3457 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3462 /* ITypeLib::Release
3464 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3466 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3467 ULONG ref = InterlockedDecrement(&This->ref);
3469 TRACE("(%p)->(%lu)\n",This, ref);
3473 /* remove cache entry */
3474 TRACE("removing from cache list\n");
3475 EnterCriticalSection(&cache_section);
3476 if (This->next) This->next->prev = This->prev;
3477 if (This->prev) This->prev->next = This->next;
3478 else tlb_cache_first = This->next;
3479 LeaveCriticalSection(&cache_section);
3481 /* FIXME destroy child objects */
3482 TRACE(" destroying ITypeLib(%p)\n",This);
3486 SysFreeString(This->Name);
3490 if (This->DocString)
3492 SysFreeString(This->DocString);
3493 This->DocString = NULL;
3498 SysFreeString(This->HelpFile);
3499 This->HelpFile = NULL;
3502 if (This->HelpStringDll)
3504 SysFreeString(This->HelpStringDll);
3505 This->HelpStringDll = NULL;
3508 if (This->pTypeInfo) /* can be NULL */
3509 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3510 HeapFree(GetProcessHeap(),0,This);
3517 /* ITypeLib::GetTypeInfoCount
3519 * Returns the number of type descriptions in the type library
3521 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3523 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3524 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3525 return This->TypeInfoCount;
3528 /* ITypeLib::GetTypeInfo
3530 * retrieves the specified type description in the library.
3532 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3535 ITypeInfo **ppTInfo)
3539 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3540 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3542 TRACE("(%p)->(index=%d) \n", This, index);
3544 if (!ppTInfo) return E_INVALIDARG;
3546 /* search element n in list */
3547 for(i=0; i < index; i++)
3549 pTypeInfo = pTypeInfo->next;
3552 TRACE("-- element not found\n");
3553 return TYPE_E_ELEMENTNOTFOUND;
3557 *ppTInfo = (ITypeInfo *) pTypeInfo;
3559 ITypeInfo_AddRef(*ppTInfo);
3560 TRACE("-- found (%p)\n",*ppTInfo);
3565 /* ITypeLibs::GetTypeInfoType
3567 * Retrieves the type of a type description.
3569 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3574 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3576 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3578 TRACE("(%p) index %d \n",This, index);
3580 if(!pTKind) return E_INVALIDARG;
3582 /* search element n in list */
3583 for(i=0; i < index; i++)
3587 TRACE("-- element not found\n");
3588 return TYPE_E_ELEMENTNOTFOUND;
3590 pTInfo = pTInfo->next;
3593 *pTKind = pTInfo->TypeAttr.typekind;
3594 TRACE("-- found Type (%d)\n", *pTKind);
3598 /* ITypeLib::GetTypeInfoOfGuid
3600 * Retrieves the type description that corresponds to the specified GUID.
3603 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3606 ITypeInfo **ppTInfo)
3608 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3609 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3611 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3613 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3615 /* search linked list for guid */
3616 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3618 pTypeInfo = pTypeInfo->next;
3622 /* end of list reached */
3623 TRACE("-- element not found\n");
3624 return TYPE_E_ELEMENTNOTFOUND;
3628 TRACE("-- found (%p, %s)\n",
3630 debugstr_w(pTypeInfo->Name));
3632 *ppTInfo = (ITypeInfo*)pTypeInfo;
3633 ITypeInfo_AddRef(*ppTInfo);
3637 /* ITypeLib::GetLibAttr
3639 * Retrieves the structure that contains the library's attributes.
3642 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3644 LPTLIBATTR *ppTLibAttr)
3646 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3647 TRACE("(%p)\n",This);
3648 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3649 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3653 /* ITypeLib::GetTypeComp
3655 * Enables a client compiler to bind to a library's types, variables,
3656 * constants, and global functions.
3659 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3661 ITypeComp **ppTComp)
3663 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3665 TRACE("(%p)->(%p)\n",This,ppTComp);
3666 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3667 ITypeComp_AddRef(*ppTComp);
3672 /* ITypeLib::GetDocumentation
3674 * Retrieves the library's documentation string, the complete Help file name
3675 * and path, and the context identifier for the library Help topic in the Help
3678 * On a successful return all non-null BSTR pointers will have been set,
3681 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3685 BSTR *pBstrDocString,
3686 DWORD *pdwHelpContext,
3687 BSTR *pBstrHelpFile)
3689 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3691 HRESULT result = E_INVALIDARG;
3696 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3698 pBstrName, pBstrDocString,
3699 pdwHelpContext, pBstrHelpFile);
3703 /* documentation for the typelib */
3708 if(!(*pBstrName = SysAllocString(This->Name)))
3716 if (This->DocString)
3718 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3721 else if (This->Name)
3723 if(!(*pBstrDocString = SysAllocString(This->Name)))
3727 *pBstrDocString = NULL;
3731 *pdwHelpContext = This->dwHelpContext;
3737 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3741 *pBstrHelpFile = NULL;
3748 /* for a typeinfo */
3749 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3751 if(SUCCEEDED(result))
3753 result = ITypeInfo_GetDocumentation(pTInfo,
3757 pdwHelpContext, pBstrHelpFile);
3759 ITypeInfo_Release(pTInfo);
3764 if (pBstrDocString) SysFreeString (*pBstrDocString);
3766 if (pBstrName) SysFreeString (*pBstrName);
3768 return STG_E_INSUFFICIENTMEMORY;
3773 * Indicates whether a passed-in string contains the name of a type or member
3774 * described in the library.
3777 static HRESULT WINAPI ITypeLib2_fnIsName(
3783 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3784 ITypeInfoImpl *pTInfo;
3785 TLBFuncDesc *pFInfo;
3788 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3790 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3794 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3795 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3796 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3797 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3798 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3799 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3800 goto ITypeLib2_fnIsName_exit;
3802 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3803 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3808 ITypeLib2_fnIsName_exit:
3809 TRACE("(%p)slow! search for %s: %s found!\n", This,
3810 debugstr_w(szNameBuf), *pfName?"NOT":"");
3815 /* ITypeLib::FindName
3817 * Finds occurrences of a type description in a type library. This may be used
3818 * to quickly verify that a name exists in a type library.
3821 static HRESULT WINAPI ITypeLib2_fnFindName(
3825 ITypeInfo **ppTInfo,
3829 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3830 ITypeInfoImpl *pTInfo;
3831 TLBFuncDesc *pFInfo;
3834 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3836 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3837 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3838 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3839 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3840 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3841 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3842 goto ITypeLib2_fnFindName_exit;
3845 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3846 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3848 ITypeLib2_fnFindName_exit:
3849 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3850 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3853 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3854 This, *pcFound, debugstr_w(szNameBuf), j);
3861 /* ITypeLib::ReleaseTLibAttr
3863 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3866 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3868 TLIBATTR *pTLibAttr)
3870 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3871 TRACE("freeing (%p)\n",This);
3872 HeapFree(GetProcessHeap(),0,pTLibAttr);
3876 /* ITypeLib2::GetCustData
3878 * gets the custom data
3880 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3885 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3886 TLBCustData *pCData;
3888 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3890 if( IsEqualIID(guid, &pCData->guid)) break;
3893 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3897 VariantInit( pVarVal);
3898 VariantCopy( pVarVal, &pCData->data);
3901 return E_INVALIDARG; /* FIXME: correct? */
3904 /* ITypeLib2::GetLibStatistics
3906 * Returns statistics about a type library that are required for efficient
3907 * sizing of hash tables.
3910 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3912 ULONG *pcUniqueNames,
3913 ULONG *pcchUniqueNames)
3915 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3917 FIXME("(%p): stub!\n", This);
3919 if(pcUniqueNames) *pcUniqueNames=1;
3920 if(pcchUniqueNames) *pcchUniqueNames=1;
3924 /* ITypeLib2::GetDocumentation2
3926 * Retrieves the library's documentation string, the complete Help file name
3927 * and path, the localization context to use, and the context ID for the
3928 * library Help topic in the Help file.
3931 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3935 BSTR *pbstrHelpString,
3936 DWORD *pdwHelpStringContext,
3937 BSTR *pbstrHelpStringDll)
3939 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3943 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3945 /* the help string should be obtained from the helpstringdll,
3946 * using the _DLLGetDocumentation function, based on the supplied
3947 * lcid. Nice to do sometime...
3951 /* documentation for the typelib */
3953 *pbstrHelpString=SysAllocString(This->DocString);
3954 if(pdwHelpStringContext)
3955 *pdwHelpStringContext=This->dwHelpContext;
3956 if(pbstrHelpStringDll)
3957 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3963 /* for a typeinfo */
3964 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3966 if(SUCCEEDED(result))
3968 ITypeInfo2 * pTInfo2;
3969 result = ITypeInfo_QueryInterface(pTInfo,
3971 (LPVOID*) &pTInfo2);
3973 if(SUCCEEDED(result))
3975 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3979 pdwHelpStringContext,
3980 pbstrHelpStringDll);
3982 ITypeInfo2_Release(pTInfo2);
3985 ITypeInfo_Release(pTInfo);
3991 /* ITypeLib2::GetAllCustData
3993 * Gets all custom data items for the library.
3996 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3998 CUSTDATA *pCustData)
4000 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4001 TLBCustData *pCData;
4003 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4004 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4005 if(pCustData->prgCustData ){
4006 pCustData->cCustData=This->ctCustData;
4007 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4008 pCustData->prgCustData[i].guid=pCData->guid;
4009 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4012 ERR(" OUT OF MEMORY! \n");
4013 return E_OUTOFMEMORY;
4018 static const ITypeLib2Vtbl tlbvt = {
4019 ITypeLib2_fnQueryInterface,
4021 ITypeLib2_fnRelease,
4022 ITypeLib2_fnGetTypeInfoCount,
4023 ITypeLib2_fnGetTypeInfo,
4024 ITypeLib2_fnGetTypeInfoType,
4025 ITypeLib2_fnGetTypeInfoOfGuid,
4026 ITypeLib2_fnGetLibAttr,
4027 ITypeLib2_fnGetTypeComp,
4028 ITypeLib2_fnGetDocumentation,
4030 ITypeLib2_fnFindName,
4031 ITypeLib2_fnReleaseTLibAttr,
4033 ITypeLib2_fnGetCustData,
4034 ITypeLib2_fnGetLibStatistics,
4035 ITypeLib2_fnGetDocumentation2,
4036 ITypeLib2_fnGetAllCustData
4040 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4042 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4044 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4047 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4049 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4051 return ITypeLib2_AddRef((ITypeLib2 *)This);
4054 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4056 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4058 return ITypeLib2_Release((ITypeLib2 *)This);
4061 static HRESULT WINAPI ITypeLibComp_fnBind(
4066 ITypeInfo ** ppTInfo,
4067 DESCKIND * pDescKind,
4070 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4074 static HRESULT WINAPI ITypeLibComp_fnBindType(
4078 ITypeInfo ** ppTInfo,
4079 ITypeComp ** ppTComp)
4081 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4085 static const ITypeCompVtbl tlbtcvt =
4088 ITypeLibComp_fnQueryInterface,
4089 ITypeLibComp_fnAddRef,
4090 ITypeLibComp_fnRelease,
4092 ITypeLibComp_fnBind,
4093 ITypeLibComp_fnBindType
4096 /*================== ITypeInfo(2) Methods ===================================*/
4097 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4099 ITypeInfoImpl * pTypeInfoImpl;
4101 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4104 pTypeInfoImpl->lpVtbl = &tinfvt;
4105 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4106 pTypeInfoImpl->ref=1;
4108 TRACE("(%p)\n", pTypeInfoImpl);
4109 return (ITypeInfo2*) pTypeInfoImpl;
4112 /* ITypeInfo::QueryInterface
4114 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4119 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4121 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4124 if(IsEqualIID(riid, &IID_IUnknown) ||
4125 IsEqualIID(riid,&IID_ITypeInfo)||
4126 IsEqualIID(riid,&IID_ITypeInfo2))
4130 ITypeInfo_AddRef(iface);
4131 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4134 TRACE("-- Interface: E_NOINTERFACE\n");
4135 return E_NOINTERFACE;
4138 /* ITypeInfo::AddRef
4140 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4142 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4143 ULONG ref = InterlockedIncrement(&This->ref);
4145 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4147 TRACE("(%p)->ref is %lu\n",This, ref);
4151 /* ITypeInfo::Release
4153 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4155 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4156 ULONG ref = InterlockedDecrement(&This->ref);
4158 TRACE("(%p)->(%lu)\n",This, ref);
4161 /* We don't release ITypeLib when ref=0 because
4162 it means that function is called by ITypeLib2_Release */
4163 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4165 FIXME("destroy child objects\n");
4167 TRACE("destroying ITypeInfo(%p)\n",This);
4170 SysFreeString(This->Name);
4174 if (This->DocString)
4176 SysFreeString(This->DocString);
4177 This->DocString = 0;
4182 SysFreeString(This->DllName);
4188 ITypeInfo_Release((ITypeInfo*)This->next);
4191 HeapFree(GetProcessHeap(),0,This);
4197 /* ITypeInfo::GetTypeAttr
4199 * Retrieves a TYPEATTR structure that contains the attributes of the type
4203 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4204 LPTYPEATTR *ppTypeAttr)
4206 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4207 TRACE("(%p)\n",This);
4208 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr));
4209 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4211 if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */
4212 copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias);
4214 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4215 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4217 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4218 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4223 /* ITypeInfo::GetTypeComp
4225 * Retrieves the ITypeComp interface for the type description, which enables a
4226 * client compiler to bind to the type description's members.
4229 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4230 ITypeComp * *ppTComp)
4232 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4234 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4236 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4237 ITypeComp_AddRef(*ppTComp);
4241 /* ITypeInfo::GetFuncDesc
4243 * Retrieves the FUNCDESC structure that contains information about a
4244 * specified function.
4247 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4248 LPFUNCDESC *ppFuncDesc)
4250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4252 TLBFuncDesc * pFDesc;
4253 TRACE("(%p) index %d\n", This, index);
4254 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4257 /* FIXME: must do a copy here */
4258 *ppFuncDesc=&pFDesc->funcdesc;
4261 return E_INVALIDARG;
4264 /* ITypeInfo::GetVarDesc
4266 * Retrieves a VARDESC structure that describes the specified variable.
4269 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4270 LPVARDESC *ppVarDesc)
4272 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4274 TLBVarDesc * pVDesc;
4275 TRACE("(%p) index %d\n", This, index);
4276 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4279 /* FIXME: must do a copy here */
4280 *ppVarDesc=&pVDesc->vardesc;
4283 return E_INVALIDARG;
4286 /* ITypeInfo_GetNames
4288 * Retrieves the variable with the specified member ID (or the name of the
4289 * property or method and its parameters) that correspond to the specified
4292 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4293 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4295 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4296 TLBFuncDesc * pFDesc;
4297 TLBVarDesc * pVDesc;
4299 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4300 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4303 /* function found, now return function and parameter names */
4304 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4307 *rgBstrNames=SysAllocString(pFDesc->Name);
4309 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4315 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4318 *rgBstrNames=SysAllocString(pVDesc->Name);
4323 if(This->TypeAttr.cImplTypes &&
4324 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4325 /* recursive search */
4328 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4330 if(SUCCEEDED(result))
4332 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4333 ITypeInfo_Release(pTInfo);
4336 WARN("Could not search inherited interface!\n");
4340 WARN("no names found\n");
4343 return TYPE_E_ELEMENTNOTFOUND;
4350 /* ITypeInfo::GetRefTypeOfImplType
4352 * If a type description describes a COM class, it retrieves the type
4353 * description of the implemented interface types. For an interface,
4354 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4358 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4363 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4366 TLBImplType *pImpl = This->impltypelist;
4368 TRACE("(%p) index %d\n", This, index);
4369 if (TRACE_ON(ole)) dump_TypeInfo(This);
4373 /* only valid on dual interfaces;
4374 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4376 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4378 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4379 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4385 hr = TYPE_E_ELEMENTNOTFOUND;
4390 /* get element n from linked list */
4391 for(i=0; pImpl && i<index; i++)
4393 pImpl = pImpl->next;
4397 *pRefType = pImpl->hRef;
4399 hr = TYPE_E_ELEMENTNOTFOUND;
4405 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4407 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4413 /* ITypeInfo::GetImplTypeFlags
4415 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4416 * or base interface in a type description.
4418 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4419 UINT index, INT *pImplTypeFlags)
4421 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4425 TRACE("(%p) index %d\n", This, index);
4426 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4427 i++, pImpl=pImpl->next)
4429 if(i==index && pImpl){
4430 *pImplTypeFlags=pImpl->implflags;
4434 return TYPE_E_ELEMENTNOTFOUND;
4438 * Maps between member names and member IDs, and parameter names and
4441 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4442 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4444 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4445 TLBFuncDesc * pFDesc;
4446 TLBVarDesc * pVDesc;
4449 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4451 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4453 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4454 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4455 for(i=1; i < cNames; i++){
4456 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4457 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4459 if( j<pFDesc->funcdesc.cParams)
4462 ret=DISP_E_UNKNOWNNAME;
4467 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4468 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4469 if(cNames) *pMemId=pVDesc->vardesc.memid;
4473 /* not found, see if this is and interface with an inheritance */
4474 if(This->TypeAttr.cImplTypes &&
4475 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4476 /* recursive search */
4478 ret=ITypeInfo_GetRefTypeInfo(iface,
4479 This->impltypelist->hRef, &pTInfo);
4481 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4482 ITypeInfo_Release(pTInfo);
4485 WARN("Could not search inherited interface!\n");
4487 WARN("no names found\n");
4488 return DISP_E_UNKNOWNNAME;
4491 /* ITypeInfo::Invoke
4493 * Invokes a method, or accesses a property of an object, that implements the
4494 * interface described by the type description.
4497 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4500 if (TRACE_ON(ole)) {
4502 TRACE("Calling %p(",func);
4503 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4515 res = func(args[0]);
4518 res = func(args[0],args[1]);
4521 res = func(args[0],args[1],args[2]);
4524 res = func(args[0],args[1],args[2],args[3]);
4527 res = func(args[0],args[1],args[2],args[3],args[4]);
4530 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4533 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4536 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4539 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4542 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4545 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4548 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]);
4551 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]);
4554 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]);
4557 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4563 FIXME("unsupported calling convention %d\n",callconv);
4567 TRACE("returns %08lx\n",res);
4571 extern int _argsize(DWORD vt);
4573 /****************************************************************************
4574 * Helper functions for Dispcall / Invoke, which copies one variant
4575 * with target type onto the argument stack.
4578 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4579 DWORD *argpos, VARIANT *arg, VARTYPE vt
4581 UINT arglen = _argsize(vt)*sizeof(DWORD);
4584 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4585 memcpy(argpos,&arg,sizeof(void*));
4589 if (V_VT(arg) == vt) {
4590 memcpy(argpos, &V_I4(arg), arglen);
4594 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4595 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4599 if (vt == VT_VARIANT) {
4600 memcpy(argpos, arg, arglen);
4603 /* Deref BYREF vars if there is need */
4604 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4605 memcpy(argpos,(void*)V_I4(arg), arglen);
4608 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4609 /* in this context, if the type lib specifies IUnknown*, giving an
4610 IDispatch* is correct; so, don't invoke VariantChangeType */
4611 memcpy(argpos,&V_I4(arg), arglen);
4614 if ((vt == VT_PTR) && tdesc)
4615 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4617 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4618 ITypeInfo *tinfo2 = NULL;
4619 TYPEATTR *tattr = NULL;
4622 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4624 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4625 "while coercing from vt 0x%x. Copying 4 byte.\n",
4626 tdesc->u.hreftype,V_VT(arg));
4627 memcpy(argpos, &V_I4(arg), 4);
4630 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4633 ERR("GetTypeAttr failed\n");
4634 ITypeInfo_Release(tinfo2);
4637 switch (tattr->typekind) {
4639 switch ( V_VT( arg ) ) {
4641 *argpos = V_I2(arg);
4645 memcpy(argpos, &V_I4(arg), 4);
4648 case VT_BYREF|VT_I4:
4649 memcpy(argpos, V_I4REF(arg), 4);
4653 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4660 tdesc = &(tattr->tdescAlias);
4661 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4664 case TKIND_INTERFACE:
4665 if (V_VT(arg) == VT_DISPATCH) {
4667 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4668 memcpy(argpos, &V_DISPATCH(arg), 4);
4672 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4673 &IID_IDispatch,(LPVOID*)&disp);
4674 if (SUCCEEDED(hres)) {
4675 memcpy(argpos,&disp,4);
4676 IUnknown_Release(V_DISPATCH(arg));
4680 FIXME("Failed to query IDispatch interface from %s while "
4681 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4685 if (V_VT(arg) == VT_UNKNOWN) {
4686 memcpy(argpos, &V_UNKNOWN(arg), 4);
4690 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4691 V_VT(arg),debugstr_guid(&(tattr->guid)));
4695 case TKIND_DISPATCH:
4696 if (V_VT(arg) == VT_DISPATCH) {
4697 memcpy(argpos, &V_DISPATCH(arg), 4);
4702 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4706 FIXME("TKIND_RECORD unhandled.\n");
4710 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4714 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4715 ITypeInfo_Release(tinfo2);
4720 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4721 memcpy(argpos,&V_I4(&va), arglen);
4722 FIXME("Should not use VariantChangeType here."
4723 " (conversion from 0x%x -> 0x%x) %08lx\n",
4724 V_VT(arg), vt, *argpos
4728 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4732 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4735 ITypeInfo *tinfo2 = NULL;
4736 TYPEATTR *tattr = NULL;
4738 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4741 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4743 tdesc->u.hreftype, hr);
4746 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4749 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4750 ITypeInfo_Release(tinfo2);
4754 switch (tattr->typekind)
4761 tdesc = &tattr->tdescAlias;
4762 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4765 case TKIND_INTERFACE:
4766 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4772 case TKIND_DISPATCH:
4777 FIXME("TKIND_RECORD unhandled.\n");
4782 FIXME("TKIND_RECORD unhandled.\n");
4787 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4791 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4792 ITypeInfo_Release(tinfo2);
4796 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4800 /* enforce only one level of pointer indirection */
4801 if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
4803 tdesc = tdesc->u.lptdesc;
4805 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4806 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4807 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4808 if ((tdesc->vt == VT_USERDEFINED) ||
4809 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4811 VARTYPE vt_userdefined = 0;
4812 TYPEDESC *tdesc_userdefined = tdesc;
4813 if (tdesc->vt == VT_PTR)
4815 vt_userdefined = VT_BYREF;
4816 tdesc_userdefined = tdesc->u.lptdesc;
4818 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
4820 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
4821 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
4823 *vt |= vt_userdefined;
4835 case VT_USERDEFINED:
4836 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
4839 ERR("cannot convert VT_PTR into variant VT\n");
4849 /***********************************************************************
4850 * DispCallFunc (OLEAUT32.@)
4854 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4855 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4857 int i, argsize, argspos;
4861 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4862 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4864 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4865 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4867 for (i=0;i<cActuals;i++) {
4868 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4869 dump_Variant(prgpvarg[i]);
4870 argsize += _argsize(prgvt[i]);
4872 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4873 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4875 for (i=0;i<cActuals;i++) {
4876 VARIANT *arg = prgpvarg[i];
4877 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4878 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4879 argspos += _argsize(prgvt[i]);
4882 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4884 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4889 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4890 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4891 FIXME("Method returned %lx\n",hres);
4893 HeapFree(GetProcessHeap(),0,args);
4897 static HRESULT WINAPI ITypeInfo_fnInvoke(
4902 DISPPARAMS *pDispParams,
4903 VARIANT *pVarResult,
4904 EXCEPINFO *pExcepInfo,
4907 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4909 unsigned int func_index, var_index;
4913 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4914 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4916 dump_DispParms(pDispParams);
4918 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4919 if (SUCCEEDED(hres)) {
4920 FUNCDESC *func_desc;
4922 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4923 if(FAILED(hres)) return hres;
4926 TRACE("invoking:\n");
4927 dump_FUNCDESC(func_desc);
4930 switch (func_desc->funckind) {
4931 case FUNC_PUREVIRTUAL:
4932 case FUNC_VIRTUAL: {
4934 int numargs, numargs2, argspos, args2pos;
4935 DWORD *args , *args2;
4936 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4937 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4940 numargs = 1; /* sizeof(thisptr) */
4942 for (i = 0; i < func_desc->cParams; i++) {
4943 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4945 numargs += _argsize(tdesc->vt);
4946 if (i>=pDispParams->cArgs) { /* arguments to return */
4947 if (tdesc->vt == VT_PTR) {
4948 numargs2 += _argsize(tdesc->u.lptdesc->vt);
4950 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
4951 numargs2 += _argsize(tdesc->vt);
4956 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4957 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
4959 args[0] = (DWORD)pIUnk;
4960 argspos = 1; args2pos = 0;
4961 for (i = 0; i < func_desc->cParams; i++) {
4962 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
4963 TYPEDESC *tdesc = &(elemdesc->tdesc);
4964 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
4965 int arglen = _argsize(tdesc->vt);
4967 if (i<pDispParams->cArgs) {
4968 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4970 if (paramFlags & PARAMFLAG_FOPT) {
4971 if(i < func_desc->cParams - func_desc->cParamsOpt)
4972 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4973 if(V_VT(arg) == VT_EMPTY
4974 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
4975 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4976 How to determine it? */
4978 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4979 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4980 V_VT(arg) = VT_ERROR;
4981 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4982 arglen = _argsize(VT_ERROR);
4985 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4986 if (FAILED(hres)) goto func_fail;
4988 } else if (paramFlags & PARAMFLAG_FOPT) {
4989 VARIANT *arg = &rgvarg[i];
4991 if (i < func_desc->cParams - func_desc->cParamsOpt)
4992 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4993 if (paramFlags & PARAMFLAG_FHASDEFAULT)
4994 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4996 V_VT(arg) = VT_ERROR;
4997 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4998 arglen = _argsize(VT_ERROR);
4999 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5000 if (FAILED(hres)) goto func_fail;
5003 if (tdesc->vt == VT_PTR)
5004 arglen = _argsize(tdesc->u.lptdesc->vt);
5006 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
5008 /* Supply pointers for the rest, so propertyget works*/
5009 args[argspos] = (DWORD)&args2[args2pos];
5011 /* If pointer to variant, pass reference it. */
5012 if ((tdesc->vt == VT_PTR) &&
5013 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
5016 args[argspos]= (DWORD)pVarResult;
5021 if (func_desc->cParamsOpt < 0)
5022 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
5024 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
5025 func_desc->callconv,
5031 for (i = 0; i < func_desc->cParams; i++) {
5032 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5033 if (wParamFlags & PARAMFLAG_FRETVAL) {
5034 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5035 TYPEDESC *tdesc = &elemdesc->tdesc;
5036 VARIANTARG varresult;
5037 V_VT(&varresult) = 0;
5038 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5041 /* FIXME: this is really messy - we should keep the
5042 * args in VARIANTARGs rather than a DWORD array */
5043 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5046 TRACE("varresult: ");
5047 dump_Variant(&varresult);
5049 hres = VariantCopyInd(pVarResult, &varresult);
5050 /* free data stored in varresult. Note that
5051 * VariantClear doesn't do what we want because we are
5052 * working with byref types. */
5053 /* FIXME: clear safearrays, bstrs, records and
5054 * variants here too */
5055 if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
5056 (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
5057 IUnknown_Release(*V_UNKNOWNREF(&varresult));
5063 if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
5064 WARN("invoked function failed with error 0x%08lx\n", res);
5065 hres = DISP_E_EXCEPTION;
5066 if (pExcepInfo) pExcepInfo->scode = res;
5069 HeapFree(GetProcessHeap(), 0, rgvarg);
5070 HeapFree(GetProcessHeap(),0,args2);
5071 HeapFree(GetProcessHeap(),0,args);
5074 case FUNC_DISPATCH: {
5077 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5078 if (SUCCEEDED(hres)) {
5079 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5080 hres = IDispatch_Invoke(
5081 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
5082 pVarResult,pExcepInfo,pArgErr
5085 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5086 IDispatch_Release(disp);
5088 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5092 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5097 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
5100 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5103 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5104 if(FAILED(hres)) return hres;
5106 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5107 dump_VARDESC(var_desc);
5108 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5112 /* not found, look for it in inherited interfaces */
5113 ITypeInfo2_GetTypeKind(iface, &type_kind);
5114 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5116 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5117 /* recursive search */
5119 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5120 if(SUCCEEDED(hres)){
5121 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5122 ITypeInfo_Release(pTInfo);
5125 WARN("Could not search inherited interface!\n");
5128 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
5129 return DISP_E_MEMBERNOTFOUND;
5132 /* ITypeInfo::GetDocumentation
5134 * Retrieves the documentation string, the complete Help file name and path,
5135 * and the context ID for the Help topic for a specified type description.
5137 * (Can be tested by the Visual Basic Editor in Word for instance.)
5139 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5140 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5141 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5143 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5144 TLBFuncDesc * pFDesc;
5145 TLBVarDesc * pVDesc;
5146 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5147 " HelpContext(%p) HelpFile(%p)\n",
5148 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5149 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5151 *pBstrName=SysAllocString(This->Name);
5153 *pBstrDocString=SysAllocString(This->DocString);
5155 *pdwHelpContext=This->dwHelpContext;
5157 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5159 }else {/* for a member */
5160 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5161 if(pFDesc->funcdesc.memid==memid){
5163 *pBstrName = SysAllocString(pFDesc->Name);
5165 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5167 *pdwHelpContext=pFDesc->helpcontext;
5170 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5171 if(pVDesc->vardesc.memid==memid){
5173 *pBstrName = SysAllocString(pVDesc->Name);
5175 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5177 *pdwHelpContext=pVDesc->HelpContext;
5181 WARN("member %ld not found\n", memid);
5182 return TYPE_E_ELEMENTNOTFOUND;
5185 /* ITypeInfo::GetDllEntry
5187 * Retrieves a description or specification of an entry point for a function
5190 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5191 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5194 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5195 TLBFuncDesc *pFDesc;
5197 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5199 if (pBstrDllName) *pBstrDllName = NULL;
5200 if (pBstrName) *pBstrName = NULL;
5201 if (pwOrdinal) *pwOrdinal = 0;
5203 if (This->TypeAttr.typekind != TKIND_MODULE)
5204 return TYPE_E_BADMODULEKIND;
5206 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5207 if(pFDesc->funcdesc.memid==memid){
5208 dump_TypeInfo(This);
5209 dump_TLBFuncDescOne(pFDesc);
5212 *pBstrDllName = SysAllocString(This->DllName);
5214 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5216 *pBstrName = SysAllocString(pFDesc->Entry);
5224 *pwOrdinal = (DWORD)pFDesc->Entry;
5227 return TYPE_E_ELEMENTNOTFOUND;
5230 /* ITypeInfo::GetRefTypeInfo
5232 * If a type description references other type descriptions, it retrieves
5233 * the referenced type descriptions.
5235 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5238 ITypeInfo **ppTInfo)
5240 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5241 HRESULT result = E_FAIL;
5243 if (hRefType == -1 &&
5244 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5245 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5247 /* when we meet a DUAL dispinterface, we must create the interface
5250 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5253 /* the interface version contains the same information as the dispinterface
5254 * copy the contents of the structs.
5256 *pTypeInfoImpl = *This;
5257 pTypeInfoImpl->ref = 1;
5259 /* change the type to interface */
5260 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5262 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5264 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5269 TLBRefType *pRefType;
5270 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5271 if(pRefType->reference == hRefType)
5275 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5276 if(pRefType && hRefType != -1) {
5277 ITypeLib *pTLib = NULL;
5279 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5281 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5283 if(pRefType->pImpTLInfo->pImpTypeLib) {
5284 TRACE("typeinfo in imported typelib that is already loaded\n");
5285 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5286 ITypeLib2_AddRef((ITypeLib*) pTLib);
5289 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5290 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5291 pRefType->pImpTLInfo->wVersionMajor,
5292 pRefType->pImpTLInfo->wVersionMinor,
5293 pRefType->pImpTLInfo->lcid,
5296 if(!SUCCEEDED(result)) {
5297 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5298 result=LoadTypeLib(libnam, &pTLib);
5299 SysFreeString(libnam);
5301 if(SUCCEEDED(result)) {
5302 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5303 ITypeLib2_AddRef(pTLib);
5307 if(SUCCEEDED(result)) {
5308 if(pRefType->index == TLB_REF_USE_GUID)
5309 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5313 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5317 ITypeLib2_Release(pTLib);
5321 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5322 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5326 /* ITypeInfo::AddressOfMember
5328 * Retrieves the addresses of static functions or variables, such as those
5331 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5332 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5334 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5335 FIXME("(%p) stub!\n", This);
5339 /* ITypeInfo::CreateInstance
5341 * Creates a new instance of a type that describes a component object class
5344 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5345 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5347 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5348 FIXME("(%p) stub!\n", This);
5352 /* ITypeInfo::GetMops
5354 * Retrieves marshalling information.
5356 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5359 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5360 FIXME("(%p) stub!\n", This);
5364 /* ITypeInfo::GetContainingTypeLib
5366 * Retrieves the containing type library and the index of the type description
5367 * within that type library.
5369 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5370 ITypeLib * *ppTLib, UINT *pIndex)
5372 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5374 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5376 *pIndex=This->index;
5377 TRACE("returning pIndex=%d\n", *pIndex);
5381 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5382 ITypeLib2_AddRef(*ppTLib);
5383 TRACE("returning ppTLib=%p\n", *ppTLib);
5389 /* ITypeInfo::ReleaseTypeAttr
5391 * Releases a TYPEATTR previously returned by GetTypeAttr.
5394 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5395 TYPEATTR* pTypeAttr)
5397 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5398 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5399 if(This->TypeAttr.typekind == TKIND_ALIAS)
5400 free_deep_typedesc(&pTypeAttr->tdescAlias);
5401 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5404 /* ITypeInfo::ReleaseFuncDesc
5406 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5408 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5410 FUNCDESC *pFuncDesc)
5412 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5413 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5416 /* ITypeInfo::ReleaseVarDesc
5418 * Releases a VARDESC previously returned by GetVarDesc.
5420 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5423 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5424 TRACE("(%p)->(%p)\n", This, pVarDesc);
5427 /* ITypeInfo2::GetTypeKind
5429 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5432 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5433 TYPEKIND *pTypeKind)
5435 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5436 *pTypeKind=This->TypeAttr.typekind;
5437 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5441 /* ITypeInfo2::GetTypeFlags
5443 * Returns the type flags without any allocations. This returns a DWORD type
5444 * flag, which expands the type flags without growing the TYPEATTR (type
5448 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5450 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5451 *pTypeFlags=This->TypeAttr.wTypeFlags;
5452 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5456 /* ITypeInfo2::GetFuncIndexOfMemId
5457 * Binds to a specific member based on a known DISPID, where the member name
5458 * is not known (for example, when binding to a default member).
5461 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5462 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5464 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5465 TLBFuncDesc *pFuncInfo;
5469 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5470 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5476 result = TYPE_E_ELEMENTNOTFOUND;
5478 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5479 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5483 /* TypeInfo2::GetVarIndexOfMemId
5485 * Binds to a specific member based on a known DISPID, where the member name
5486 * is not known (for example, when binding to a default member).
5489 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5490 MEMBERID memid, UINT *pVarIndex)
5492 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5493 TLBVarDesc *pVarInfo;
5496 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5497 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5503 result = TYPE_E_ELEMENTNOTFOUND;
5505 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5506 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5510 /* ITypeInfo2::GetCustData
5512 * Gets the custom data
5514 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5519 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5520 TLBCustData *pCData;
5522 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5523 if( IsEqualIID(guid, &pCData->guid)) break;
5525 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5529 VariantInit( pVarVal);
5530 VariantCopy( pVarVal, &pCData->data);
5533 return E_INVALIDARG; /* FIXME: correct? */
5536 /* ITypeInfo2::GetFuncCustData
5538 * Gets the custom data
5540 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5546 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5547 TLBCustData *pCData=NULL;
5548 TLBFuncDesc * pFDesc;
5550 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5551 pFDesc=pFDesc->next);
5554 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5555 if( IsEqualIID(guid, &pCData->guid)) break;
5557 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5560 VariantInit( pVarVal);
5561 VariantCopy( pVarVal, &pCData->data);
5564 return E_INVALIDARG; /* FIXME: correct? */
5567 /* ITypeInfo2::GetParamCustData
5569 * Gets the custom data
5571 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5578 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5579 TLBCustData *pCData=NULL;
5580 TLBFuncDesc * pFDesc;
5583 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5585 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5586 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5587 pCData = pCData->next)
5588 if( IsEqualIID(guid, &pCData->guid)) break;
5590 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5594 VariantInit( pVarVal);
5595 VariantCopy( pVarVal, &pCData->data);
5598 return E_INVALIDARG; /* FIXME: correct? */
5601 /* ITypeInfo2::GetVarCustData
5603 * Gets the custom data
5605 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5611 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5612 TLBCustData *pCData=NULL;
5613 TLBVarDesc * pVDesc;
5616 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5620 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5622 if( IsEqualIID(guid, &pCData->guid)) break;
5626 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5630 VariantInit( pVarVal);
5631 VariantCopy( pVarVal, &pCData->data);
5634 return E_INVALIDARG; /* FIXME: correct? */
5637 /* ITypeInfo2::GetImplCustData
5639 * Gets the custom data
5641 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5647 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5648 TLBCustData *pCData=NULL;
5649 TLBImplType * pRDesc;
5652 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5656 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5658 if( IsEqualIID(guid, &pCData->guid)) break;
5662 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5666 VariantInit( pVarVal);
5667 VariantCopy( pVarVal, &pCData->data);
5670 return E_INVALIDARG; /* FIXME: correct? */
5673 /* ITypeInfo2::GetDocumentation2
5675 * Retrieves the documentation string, the complete Help file name and path,
5676 * the localization context to use, and the context ID for the library Help
5677 * topic in the Help file.
5680 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5684 BSTR *pbstrHelpString,
5685 DWORD *pdwHelpStringContext,
5686 BSTR *pbstrHelpStringDll)
5688 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5689 TLBFuncDesc * pFDesc;
5690 TLBVarDesc * pVDesc;
5691 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5692 "HelpStringContext(%p) HelpStringDll(%p)\n",
5693 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5694 pbstrHelpStringDll );
5695 /* the help string should be obtained from the helpstringdll,
5696 * using the _DLLGetDocumentation function, based on the supplied
5697 * lcid. Nice to do sometime...
5699 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5701 *pbstrHelpString=SysAllocString(This->Name);
5702 if(pdwHelpStringContext)
5703 *pdwHelpStringContext=This->dwHelpStringContext;
5704 if(pbstrHelpStringDll)
5705 *pbstrHelpStringDll=
5706 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5708 }else {/* for a member */
5709 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5710 if(pFDesc->funcdesc.memid==memid){
5712 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5713 if(pdwHelpStringContext)
5714 *pdwHelpStringContext=pFDesc->HelpStringContext;
5715 if(pbstrHelpStringDll)
5716 *pbstrHelpStringDll=
5717 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5720 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5721 if(pVDesc->vardesc.memid==memid){
5723 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5724 if(pdwHelpStringContext)
5725 *pdwHelpStringContext=pVDesc->HelpStringContext;
5726 if(pbstrHelpStringDll)
5727 *pbstrHelpStringDll=
5728 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5732 return TYPE_E_ELEMENTNOTFOUND;
5735 /* ITypeInfo2::GetAllCustData
5737 * Gets all custom data items for the Type info.
5740 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5742 CUSTDATA *pCustData)
5744 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5745 TLBCustData *pCData;
5748 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5750 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5751 if(pCustData->prgCustData ){
5752 pCustData->cCustData=This->ctCustData;
5753 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5754 pCustData->prgCustData[i].guid=pCData->guid;
5755 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5758 ERR(" OUT OF MEMORY! \n");
5759 return E_OUTOFMEMORY;
5764 /* ITypeInfo2::GetAllFuncCustData
5766 * Gets all custom data items for the specified Function
5769 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5772 CUSTDATA *pCustData)
5774 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5775 TLBCustData *pCData;
5776 TLBFuncDesc * pFDesc;
5778 TRACE("(%p) index %d\n", This, index);
5779 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5780 pFDesc=pFDesc->next)
5783 pCustData->prgCustData =
5784 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5785 if(pCustData->prgCustData ){
5786 pCustData->cCustData=pFDesc->ctCustData;
5787 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5788 pCData = pCData->next){
5789 pCustData->prgCustData[i].guid=pCData->guid;
5790 VariantCopy(& pCustData->prgCustData[i].varValue,
5794 ERR(" OUT OF MEMORY! \n");
5795 return E_OUTOFMEMORY;
5799 return TYPE_E_ELEMENTNOTFOUND;
5802 /* ITypeInfo2::GetAllParamCustData
5804 * Gets all custom data items for the Functions
5807 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5808 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5810 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5811 TLBCustData *pCData=NULL;
5812 TLBFuncDesc * pFDesc;
5814 TRACE("(%p) index %d\n", This, indexFunc);
5815 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5816 pFDesc=pFDesc->next)
5818 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5819 pCustData->prgCustData =
5820 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5821 sizeof(CUSTDATAITEM));
5822 if(pCustData->prgCustData ){
5823 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5824 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5825 pCData; i++, pCData = pCData->next){
5826 pCustData->prgCustData[i].guid=pCData->guid;
5827 VariantCopy(& pCustData->prgCustData[i].varValue,
5831 ERR(" OUT OF MEMORY! \n");
5832 return E_OUTOFMEMORY;
5836 return TYPE_E_ELEMENTNOTFOUND;
5839 /* ITypeInfo2::GetAllVarCustData
5841 * Gets all custom data items for the specified Variable
5844 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5845 UINT index, CUSTDATA *pCustData)
5847 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5848 TLBCustData *pCData;
5849 TLBVarDesc * pVDesc;
5851 TRACE("(%p) index %d\n", This, index);
5852 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5853 pVDesc=pVDesc->next)
5856 pCustData->prgCustData =
5857 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5858 if(pCustData->prgCustData ){
5859 pCustData->cCustData=pVDesc->ctCustData;
5860 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5861 pCData = pCData->next){
5862 pCustData->prgCustData[i].guid=pCData->guid;
5863 VariantCopy(& pCustData->prgCustData[i].varValue,
5867 ERR(" OUT OF MEMORY! \n");
5868 return E_OUTOFMEMORY;
5872 return TYPE_E_ELEMENTNOTFOUND;
5875 /* ITypeInfo2::GetAllImplCustData
5877 * Gets all custom data items for the specified implementation type
5880 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5883 CUSTDATA *pCustData)
5885 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5886 TLBCustData *pCData;
5887 TLBImplType * pRDesc;
5889 TRACE("(%p) index %d\n", This, index);
5890 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5891 pRDesc=pRDesc->next)
5894 pCustData->prgCustData =
5895 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5896 if(pCustData->prgCustData ){
5897 pCustData->cCustData=pRDesc->ctCustData;
5898 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5899 pCData = pCData->next){
5900 pCustData->prgCustData[i].guid=pCData->guid;
5901 VariantCopy(& pCustData->prgCustData[i].varValue,
5905 ERR(" OUT OF MEMORY! \n");
5906 return E_OUTOFMEMORY;
5910 return TYPE_E_ELEMENTNOTFOUND;
5913 static const ITypeInfo2Vtbl tinfvt =
5916 ITypeInfo_fnQueryInterface,
5918 ITypeInfo_fnRelease,
5920 ITypeInfo_fnGetTypeAttr,
5921 ITypeInfo_fnGetTypeComp,
5922 ITypeInfo_fnGetFuncDesc,
5923 ITypeInfo_fnGetVarDesc,
5924 ITypeInfo_fnGetNames,
5925 ITypeInfo_fnGetRefTypeOfImplType,
5926 ITypeInfo_fnGetImplTypeFlags,
5927 ITypeInfo_fnGetIDsOfNames,
5929 ITypeInfo_fnGetDocumentation,
5930 ITypeInfo_fnGetDllEntry,
5931 ITypeInfo_fnGetRefTypeInfo,
5932 ITypeInfo_fnAddressOfMember,
5933 ITypeInfo_fnCreateInstance,
5934 ITypeInfo_fnGetMops,
5935 ITypeInfo_fnGetContainingTypeLib,
5936 ITypeInfo_fnReleaseTypeAttr,
5937 ITypeInfo_fnReleaseFuncDesc,
5938 ITypeInfo_fnReleaseVarDesc,
5940 ITypeInfo2_fnGetTypeKind,
5941 ITypeInfo2_fnGetTypeFlags,
5942 ITypeInfo2_fnGetFuncIndexOfMemId,
5943 ITypeInfo2_fnGetVarIndexOfMemId,
5944 ITypeInfo2_fnGetCustData,
5945 ITypeInfo2_fnGetFuncCustData,
5946 ITypeInfo2_fnGetParamCustData,
5947 ITypeInfo2_fnGetVarCustData,
5948 ITypeInfo2_fnGetImplTypeCustData,
5949 ITypeInfo2_fnGetDocumentation2,
5950 ITypeInfo2_fnGetAllCustData,
5951 ITypeInfo2_fnGetAllFuncCustData,
5952 ITypeInfo2_fnGetAllParamCustData,
5953 ITypeInfo2_fnGetAllVarCustData,
5954 ITypeInfo2_fnGetAllImplTypeCustData,
5957 /******************************************************************************
5958 * CreateDispTypeInfo [OLEAUT32.31]
5960 * Build type information for an object so it can be called through an
5961 * IDispatch interface.
5964 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5965 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5968 * This call allows an objects methods to be accessed through IDispatch, by
5969 * building an ITypeInfo object that IDispatch can use to call through.
5971 HRESULT WINAPI CreateDispTypeInfo(
5972 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5973 LCID lcid, /* [I] Locale Id */
5974 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5976 ITypeInfoImpl *pTIImpl;
5978 TLBFuncDesc **ppFuncDesc;
5980 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5981 pTIImpl->pTypeLib = NULL;
5983 pTIImpl->Name = NULL;
5984 pTIImpl->dwHelpContext = -1;
5985 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
5986 pTIImpl->TypeAttr.lcid = lcid;
5987 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
5988 pTIImpl->TypeAttr.wMajorVerNum = 0;
5989 pTIImpl->TypeAttr.wMinorVerNum = 0;
5990 pTIImpl->TypeAttr.cbAlignment = 2;
5991 pTIImpl->TypeAttr.cbSizeInstance = -1;
5992 pTIImpl->TypeAttr.cbSizeVft = -1;
5993 pTIImpl->TypeAttr.cFuncs = 0;
5994 pTIImpl->TypeAttr.cImplTypes = 1;
5995 pTIImpl->TypeAttr.cVars = 0;
5996 pTIImpl->TypeAttr.wTypeFlags = 0;
5998 ppFuncDesc = &pTIImpl->funclist;
5999 for(func = 0; func < pidata->cMembers; func++) {
6000 METHODDATA *md = pidata->pmethdata + func;
6001 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6002 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6003 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6004 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6005 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6006 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6007 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6008 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
6009 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
6010 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6011 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6012 md->cArgs * sizeof(ELEMDESC));
6013 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6014 md->cArgs * sizeof(TLBParDesc));
6015 for(param = 0; param < md->cArgs; param++) {
6016 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6017 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6019 ppFuncDesc = &(*ppFuncDesc)->next;
6021 *pptinfo = (ITypeInfo*)pTIImpl;
6026 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6028 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6030 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6033 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6035 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6037 return ITypeInfo_AddRef((ITypeInfo *)This);
6040 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6042 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6044 return ITypeInfo_Release((ITypeInfo *)This);
6047 static HRESULT WINAPI ITypeComp_fnBind(
6052 ITypeInfo ** ppTInfo,
6053 DESCKIND * pDescKind,
6056 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6057 TLBFuncDesc * pFDesc;
6058 TLBVarDesc * pVDesc;
6060 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6062 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6063 if (pFDesc->funcdesc.invkind & wFlags)
6064 if (!strcmpW(pFDesc->Name, szName)) {
6070 *pDescKind = DESCKIND_FUNCDESC;
6071 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
6072 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6075 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
6077 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6078 if (!strcmpW(pVDesc->Name, szName)) {
6079 *pDescKind = DESCKIND_VARDESC;
6080 pBindPtr->lpvardesc = &pVDesc->vardesc;
6081 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6087 /* not found, look for it in inherited interfaces */
6088 if (This->TypeAttr.cImplTypes &&
6089 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
6090 /* recursive search */
6094 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6097 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6098 ITypeInfo_Release(pTInfo);
6102 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6103 ITypeComp_Release(pTComp);
6106 WARN("Could not search inherited interface!\n");
6108 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6109 *pDescKind = DESCKIND_NONE;
6110 pBindPtr->lpfuncdesc = NULL;
6112 return DISP_E_MEMBERNOTFOUND;
6115 static HRESULT WINAPI ITypeComp_fnBindType(
6119 ITypeInfo ** ppTInfo,
6120 ITypeComp ** ppTComp)
6122 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6124 /* strange behaviour (does nothing) but like the
6127 if (!ppTInfo || !ppTComp)
6136 static const ITypeCompVtbl tcompvt =
6139 ITypeComp_fnQueryInterface,
6141 ITypeComp_fnRelease,
6144 ITypeComp_fnBindType