4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
44 * -. lousy fatal error handling
49 #include "wine/port.h"
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
69 #include "wine/unicode.h"
72 #include "wine/debug.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
102 /****************************************************************************
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
141 p_iSize /= sizeof(WORD);
144 *Val = FromLEWord(*Val);
151 static void FromLEDWords(void *p_Val, int p_iSize)
155 p_iSize /= sizeof(DWORD);
158 *Val = FromLEDWord(*Val);
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
177 INT best_maj = -1, best_min = -1;
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
186 len = sizeof(key_name);
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
229 if (*wMaj == best_maj && best_min >= 0)
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
266 static const WCHAR win16W[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W[] = {'w','i','n','3','2',0};
268 static const WCHAR win64W[] = {'w','i','n','6','4',0};
270 sprintfW( buffer, LcidFormatW, lcid );
273 case SYS_WIN16: strcatW( buffer, win16W ); break;
274 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 case SYS_WIN64: strcatW( buffer, win64W ); break;
277 TRACE("Typelib is for unsupported syskind %i\n", syskind);
283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
286 /****************************************************************************
287 * QueryPathOfRegTypeLib [OLEAUT32.164]
289 * Gets the path to a registered type library.
292 * guid [I] referenced guid
293 * wMaj [I] major version
294 * wMin [I] minor version
296 * path [O] path of typelib
300 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
301 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
304 HRESULT WINAPI QueryPathOfRegTypeLib(
311 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
315 WCHAR Path[MAX_PATH];
318 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
320 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
321 get_typelib_key( guid, wMaj, wMin, buffer );
323 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
324 if (res == ERROR_FILE_NOT_FOUND)
326 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
327 return TYPE_E_LIBNOTREGISTERED;
329 else if (res != ERROR_SUCCESS)
331 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
332 return TYPE_E_REGISTRYACCESS;
337 LONG dwPathLen = sizeof(Path);
339 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
341 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
345 else if (myLCID == lcid)
347 /* try with sub-langid */
348 myLCID = SUBLANGID(lcid);
350 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
352 /* try with system langid */
362 *path = SysAllocString( Path );
367 TRACE_(typelib)("-- 0x%08x\n", hr);
371 /******************************************************************************
372 * CreateTypeLib [OLEAUT32.160] creates a typelib
378 HRESULT WINAPI CreateTypeLib(
379 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
381 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
385 /******************************************************************************
386 * LoadTypeLib [OLEAUT32.161]
388 * Loads a type library
391 * szFile [I] Name of file to load from.
392 * pptLib [O] Pointer that receives ITypeLib object on success.
399 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
401 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
403 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
404 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
407 /******************************************************************************
408 * LoadTypeLibEx [OLEAUT32.183]
410 * Loads and optionally registers a type library
416 HRESULT WINAPI LoadTypeLibEx(
417 LPCOLESTR szFile, /* [in] Name of file to load from */
418 REGKIND regkind, /* [in] Specify kind of registration */
419 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
421 WCHAR szPath[MAX_PATH+1];
424 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
428 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
433 case REGKIND_DEFAULT:
434 /* don't register typelibs supplied with full path. Experimentation confirms the following */
435 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
436 (szFile[0] && (szFile[1] == ':'))) break;
437 /* else fall-through */
439 case REGKIND_REGISTER:
440 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
442 IUnknown_Release(*pptLib);
450 TRACE(" returns %08x\n",res);
454 /******************************************************************************
455 * LoadRegTypeLib [OLEAUT32.162]
457 * Loads a registered type library.
460 * rguid [I] GUID of the registered type library.
461 * wVerMajor [I] major version.
462 * wVerMinor [I] minor version.
463 * lcid [I] locale ID.
464 * ppTLib [O] pointer that receives an ITypeLib object on success.
468 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
471 HRESULT WINAPI LoadRegTypeLib(
483 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
487 res= LoadTypeLib(bstr, ppTLib);
491 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
497 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
498 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
499 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
500 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
501 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
502 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
504 /******************************************************************************
505 * RegisterTypeLib [OLEAUT32.163]
506 * Adds information about a type library to the System Registry
508 * Docs: ITypeLib FAR * ptlib
509 * Docs: OLECHAR FAR* szFullPath
510 * Docs: OLECHAR FAR* szHelpDir
516 HRESULT WINAPI RegisterTypeLib(
517 ITypeLib * ptlib, /* [in] Pointer to the library*/
518 OLECHAR * szFullPath, /* [in] full Path of the library*/
519 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
522 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
523 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
524 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
534 if (ptlib == NULL || szFullPath == NULL)
537 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
541 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
543 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
546 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
549 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
550 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
554 /* Set the human-readable name of the typelib */
555 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
557 if (RegSetValueExW(key, NULL, 0, REG_SZ,
558 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
566 /* Make up the name of the typelib path subkey */
567 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
569 /* Create the typelib path subkey */
570 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
571 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
573 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
574 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
582 /* Create the flags subkey */
583 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
584 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
586 /* FIXME: is %u correct? */
587 static const WCHAR formatW[] = {'%','u',0};
589 sprintfW(buf, formatW, attr->wLibFlags);
590 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
591 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
599 /* create the helpdir subkey */
600 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
601 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
603 BOOL freeHelpDir = FALSE;
606 /* if we created a new key, and helpDir was null, set the helpdir
607 to the directory which contains the typelib. However,
608 if we just opened an existing key, we leave the helpdir alone */
609 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
610 szHelpDir = SysAllocString(szFullPath);
611 pIndexStr = strrchrW(szHelpDir, '\\');
618 /* if we have an szHelpDir, set it! */
619 if (szHelpDir != NULL) {
620 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
621 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
627 if (freeHelpDir) SysFreeString(szHelpDir);
639 /* register OLE Automation-compatible interfaces for this typelib */
640 types = ITypeLib_GetTypeInfoCount(ptlib);
641 for (tidx=0; tidx<types; tidx++) {
642 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
643 LPOLESTR name = NULL;
644 ITypeInfo *tinfo = NULL;
646 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
649 case TKIND_INTERFACE:
650 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
651 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
655 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
656 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
660 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
665 TYPEATTR *tattr = NULL;
666 ITypeInfo_GetTypeAttr(tinfo, &tattr);
669 TRACE_(typelib)("guid=%s, flags=%04x (",
670 debugstr_guid(&tattr->guid),
673 if (TRACE_ON(typelib)) {
674 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
694 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
696 /* register interface<->typelib coupling */
697 get_interface_key( &tattr->guid, keyName );
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
699 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
702 RegSetValueExW(key, NULL, 0, REG_SZ,
703 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
705 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
706 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
707 RegSetValueExW(subKey, NULL, 0, REG_SZ,
708 (const BYTE *)PSOA, sizeof PSOA);
712 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
713 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
714 RegSetValueExW(subKey, NULL, 0, REG_SZ,
715 (const BYTE *)PSOA, sizeof PSOA);
719 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
720 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
723 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
724 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
726 StringFromGUID2(&attr->guid, buffer, 40);
727 RegSetValueExW(subKey, NULL, 0, REG_SZ,
728 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
729 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
730 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
731 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
739 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
742 ITypeInfo_Release(tinfo);
749 ITypeLib_ReleaseTLibAttr(ptlib, attr);
755 /******************************************************************************
756 * UnRegisterTypeLib [OLEAUT32.186]
757 * Removes information about a type library from the System Registry
764 HRESULT WINAPI UnRegisterTypeLib(
765 REFGUID libid, /* [in] Guid of the library */
766 WORD wVerMajor, /* [in] major version */
767 WORD wVerMinor, /* [in] minor version */
768 LCID lcid, /* [in] locale id */
771 BSTR tlibPath = NULL;
774 WCHAR subKeyName[50];
777 BOOL deleteOtherStuff;
780 TYPEATTR* typeAttr = NULL;
782 ITypeInfo* typeInfo = NULL;
783 ITypeLib* typeLib = NULL;
786 TRACE("(IID: %s)\n",debugstr_guid(libid));
788 /* Create the path to the key */
789 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
791 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
793 TRACE("Unsupported syskind %i\n", syskind);
794 result = E_INVALIDARG;
798 /* get the path to the typelib on disk */
799 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
800 result = E_INVALIDARG;
804 /* Try and open the key to the type library. */
805 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
806 result = E_INVALIDARG;
810 /* Try and load the type library */
811 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
812 result = TYPE_E_INVALIDSTATE;
816 /* remove any types registered with this typelib */
817 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
818 for (i=0; i<numTypes; i++) {
819 /* get the kind of type */
820 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
824 /* skip non-interfaces, and get type info for the type */
825 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
828 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
831 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
835 /* the path to the type */
836 get_interface_key( &typeAttr->guid, subKeyName );
838 /* Delete its bits */
839 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
842 RegDeleteKeyW(subKey, ProxyStubClsidW);
843 RegDeleteKeyW(subKey, ProxyStubClsid32W);
844 RegDeleteKeyW(subKey, TypeLibW);
847 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
850 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
852 if (typeInfo) ITypeInfo_Release(typeInfo);
856 /* Now, delete the type library path subkey */
857 get_lcid_subkey( lcid, syskind, subKeyName );
858 RegDeleteKeyW(key, subKeyName);
859 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
860 RegDeleteKeyW(key, subKeyName);
862 /* check if there is anything besides the FLAGS/HELPDIR keys.
863 If there is, we don't delete them */
864 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
865 deleteOtherStuff = TRUE;
867 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
868 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
870 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
871 if (!strcmpW(subKeyName, FLAGSW)) continue;
872 if (!strcmpW(subKeyName, HELPDIRW)) continue;
873 deleteOtherStuff = FALSE;
877 /* only delete the other parts of the key if we're absolutely sure */
878 if (deleteOtherStuff) {
879 RegDeleteKeyW(key, FLAGSW);
880 RegDeleteKeyW(key, HELPDIRW);
884 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
885 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
886 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
890 SysFreeString(tlibPath);
891 if (typeLib) ITypeLib_Release(typeLib);
892 if (subKey) RegCloseKey(subKey);
893 if (key) RegCloseKey(key);
897 /*======================= ITypeLib implementation =======================*/
899 typedef struct tagTLBCustData
903 struct tagTLBCustData* next;
906 /* data structure for import typelibs */
907 typedef struct tagTLBImpLib
909 int offset; /* offset in the file (MSFT)
910 offset in nametable (SLTG)
911 just used to identify library while reading
913 GUID guid; /* libid */
914 BSTR name; /* name */
916 LCID lcid; /* lcid of imported typelib */
918 WORD wVersionMajor; /* major version number */
919 WORD wVersionMinor; /* minor version number */
921 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
922 NULL if not yet loaded */
923 struct tagTLBImpLib * next;
926 /* internal ITypeLib data */
927 typedef struct tagITypeLibImpl
929 const ITypeLib2Vtbl *lpVtbl;
930 const ITypeCompVtbl *lpVtblTypeComp;
932 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
935 /* strings can be stored in tlb as multibyte strings BUT they are *always*
936 * exported to the application as a UNICODE string.
943 int TypeInfoCount; /* nr of typeinfo's in librarry */
944 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
945 int ctCustData; /* number of items in cust data list */
946 TLBCustData * pCustData; /* linked list to cust data */
947 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
948 int ctTypeDesc; /* number of items in type desc array */
949 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
950 library. Only used while reading MSFT
952 struct list ref_list; /* list of ref types in this typelib */
953 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
956 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
957 struct tagITypeLibImpl *next, *prev;
962 static const ITypeLib2Vtbl tlbvt;
963 static const ITypeCompVtbl tlbtcvt;
965 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
967 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
970 /* ITypeLib methods */
971 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
972 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
974 /*======================= ITypeInfo implementation =======================*/
976 /* data for referenced types */
977 typedef struct tagTLBRefType
979 INT index; /* Type index for internal ref or for external ref
980 it the format is SLTG. -2 indicates to
983 GUID guid; /* guid of the referenced type */
984 /* if index == TLB_REF_USE_GUID */
986 HREFTYPE reference; /* The href of this ref */
987 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
988 TLB_REF_INTERNAL for internal refs
989 TLB_REF_NOT_FOUND for broken refs */
994 #define TLB_REF_USE_GUID -2
996 #define TLB_REF_INTERNAL (void*)-2
997 #define TLB_REF_NOT_FOUND (void*)-1
999 /* internal Parameter data */
1000 typedef struct tagTLBParDesc
1004 TLBCustData * pCustData; /* linked list to cust data */
1007 /* internal Function data */
1008 typedef struct tagTLBFuncDesc
1010 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1011 BSTR Name; /* the name of this function */
1012 TLBParDesc *pParamDesc; /* array with param names and custom data */
1014 int HelpStringContext;
1016 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
1018 TLBCustData * pCustData; /* linked list to cust data; */
1019 struct tagTLBFuncDesc * next;
1022 /* internal Variable data */
1023 typedef struct tagTLBVarDesc
1025 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1026 BSTR Name; /* the name of this variable */
1028 int HelpStringContext; /* FIXME: where? */
1031 TLBCustData * pCustData;/* linked list to cust data; */
1032 struct tagTLBVarDesc * next;
1035 /* internal implemented interface data */
1036 typedef struct tagTLBImplType
1038 HREFTYPE hRef; /* hRef of interface */
1039 int implflags; /* IMPLFLAG_*s */
1041 TLBCustData * pCustData;/* linked list to custom data; */
1042 struct tagTLBImplType *next;
1045 /* internal TypeInfo data */
1046 typedef struct tagITypeInfoImpl
1048 const ITypeInfo2Vtbl *lpVtbl;
1049 const ITypeCompVtbl *lpVtblTypeComp;
1051 BOOL no_free_data; /* don't free data structures */
1052 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1053 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1054 int index; /* index in this typelib; */
1055 HREFTYPE hreftype; /* hreftype for app object binding */
1056 /* type libs seem to store the doc strings in ascii
1057 * so why should we do it in unicode?
1062 DWORD dwHelpContext;
1063 DWORD dwHelpStringContext;
1066 TLBFuncDesc * funclist; /* linked list with function descriptions */
1069 TLBVarDesc * varlist; /* linked list with variable descriptions */
1071 /* Implemented Interfaces */
1072 TLBImplType * impltypelist;
1075 TLBCustData * pCustData; /* linked list to cust data; */
1076 struct tagITypeInfoImpl * next;
1079 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1081 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1084 static const ITypeInfo2Vtbl tinfvt;
1085 static const ITypeCompVtbl tcompvt;
1087 static ITypeInfo2 * ITypeInfo_Constructor(void);
1089 typedef struct tagTLBContext
1091 unsigned int oStart; /* start of TLB in file */
1092 unsigned int pos; /* current pos */
1093 unsigned int length; /* total length */
1094 void *mapping; /* memory mapping */
1095 MSFT_SegDir * pTblDir;
1096 ITypeLibImpl* pLibInfo;
1100 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1105 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1106 if (pTD->vt & VT_RESERVED)
1107 szVarType += strlen(strcpy(szVarType, "reserved | "));
1108 if (pTD->vt & VT_BYREF)
1109 szVarType += strlen(strcpy(szVarType, "ref to "));
1110 if (pTD->vt & VT_ARRAY)
1111 szVarType += strlen(strcpy(szVarType, "array of "));
1112 if (pTD->vt & VT_VECTOR)
1113 szVarType += strlen(strcpy(szVarType, "vector of "));
1114 switch(pTD->vt & VT_TYPEMASK) {
1115 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1116 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1117 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1118 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1119 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1120 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1121 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1122 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1123 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1124 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1125 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1126 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1127 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1128 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1129 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1130 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1131 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1132 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1133 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1134 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1135 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1136 pTD->u.hreftype); break;
1137 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1138 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1139 case VT_PTR: sprintf(szVarType, "ptr to ");
1140 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1142 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1143 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1145 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1146 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1147 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1150 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1154 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1156 USHORT flags = edesc->u.paramdesc.wParamFlags;
1157 dump_TypeDesc(&edesc->tdesc,buf);
1158 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1159 MESSAGE("\t\tu.paramdesc.wParamFlags");
1160 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1161 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1162 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1163 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1164 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1165 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1166 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1167 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1168 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1170 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1172 MESSAGE("memid is %08x\n",funcdesc->memid);
1173 for (i=0;i<funcdesc->cParams;i++) {
1174 MESSAGE("Param %d:\n",i);
1175 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1177 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1178 switch (funcdesc->funckind) {
1179 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1180 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1181 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1182 case FUNC_STATIC: MESSAGE("static");break;
1183 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1184 default: MESSAGE("unknown");break;
1186 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1187 switch (funcdesc->invkind) {
1188 case INVOKE_FUNC: MESSAGE("func");break;
1189 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1190 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1191 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1193 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1194 switch (funcdesc->callconv) {
1195 case CC_CDECL: MESSAGE("cdecl");break;
1196 case CC_PASCAL: MESSAGE("pascal");break;
1197 case CC_STDCALL: MESSAGE("stdcall");break;
1198 case CC_SYSCALL: MESSAGE("syscall");break;
1201 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1202 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1203 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1205 MESSAGE("\telemdescFunc (return value type):\n");
1206 dump_ELEMDESC(&funcdesc->elemdescFunc);
1209 static const char * const typekind_desc[] =
1222 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1225 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1226 for (i=0;i<pfd->funcdesc.cParams;i++)
1227 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1230 dump_FUNCDESC(&(pfd->funcdesc));
1232 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1233 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1235 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1239 dump_TLBFuncDescOne(pfd);
1243 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1247 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1252 static void dump_TLBImpLib(const TLBImpLib *import)
1254 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1255 debugstr_w(import->name));
1256 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1257 import->wVersionMinor, import->lcid, import->offset);
1260 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1264 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1266 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1267 if(ref->index == -1)
1268 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1270 TRACE_(typelib)("type no: %d\n", ref->index);
1272 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1274 TRACE_(typelib)("in lib\n");
1275 dump_TLBImpLib(ref->pImpTLInfo);
1280 static void dump_TLBImplType(const TLBImplType * impl)
1284 "implementing/inheriting interface hRef = %x implflags %x\n",
1285 impl->hRef, impl->implflags);
1290 static void dump_Variant(const VARIANT * pvar)
1294 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1298 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1299 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1301 TRACE(",%p", V_BYREF(pvar));
1303 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1305 TRACE(",%p", V_ARRAY(pvar));
1307 else switch (V_TYPE(pvar))
1309 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1310 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1311 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1312 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1314 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1316 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1317 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1318 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1319 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1320 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1321 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1322 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1323 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1324 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1325 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1326 V_CY(pvar).s.Lo); break;
1328 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1329 TRACE(",<invalid>");
1331 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1332 st.wHour, st.wMinute, st.wSecond);
1336 case VT_USERDEFINED:
1338 case VT_NULL: break;
1339 default: TRACE(",?"); break;
1345 static void dump_DispParms(const DISPPARAMS * pdp)
1349 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1351 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1353 TRACE("named args:\n");
1354 for (index = 0; index < pdp->cNamedArgs; index++)
1355 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1358 if (pdp->cArgs && pdp->rgvarg)
1361 for (index = 0; index < pdp->cArgs; index++)
1362 dump_Variant( &pdp->rgvarg[index] );
1366 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1368 TRACE("%p ref=%u\n", pty, pty->ref);
1369 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1370 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1371 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1372 TRACE("fct:%u var:%u impl:%u\n",
1373 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1374 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1375 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1376 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1378 dump_TLBFuncDesc(pty->funclist);
1379 dump_TLBVarDesc(pty->varlist);
1380 dump_TLBImplType(pty->impltypelist);
1383 static void dump_VARDESC(const VARDESC *v)
1385 MESSAGE("memid %d\n",v->memid);
1386 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1387 MESSAGE("oInst %d\n",v->u.oInst);
1388 dump_ELEMDESC(&(v->elemdescVar));
1389 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1390 MESSAGE("varkind %d\n",v->varkind);
1393 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1395 /* VT_LPWSTR is largest type that */
1396 /* may appear in type description*/
1397 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1398 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1399 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1400 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1401 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1402 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1406 static void TLB_abort(void)
1411 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1412 static void * TLB_Alloc(unsigned size)
1415 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1417 ERR("cannot allocate memory\n");
1422 static void TLB_Free(void * ptr)
1424 HeapFree(GetProcessHeap(), 0, ptr);
1427 /* returns the size required for a deep copy of a typedesc into a
1429 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1433 if (alloc_initial_space)
1434 size += sizeof(TYPEDESC);
1440 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1443 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1444 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1450 /* deep copy a typedesc into a flat buffer */
1451 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1456 buffer = (char *)buffer + sizeof(TYPEDESC);
1465 dest->u.lptdesc = buffer;
1466 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1469 dest->u.lpadesc = buffer;
1470 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1471 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1472 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1478 /* free custom data allocated by MSFT_CustData */
1479 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1481 TLBCustData *pCustDataNext;
1482 for (; pCustData; pCustData = pCustDataNext)
1484 VariantClear(&pCustData->data);
1486 pCustDataNext = pCustData->next;
1487 TLB_Free(pCustData);
1491 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1496 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1497 ret = SysAllocStringLen(NULL, len - 1);
1498 if (!ret) return ret;
1499 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1503 /**********************************************************************
1505 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1507 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1512 static inline void MSFT_Seek(TLBContext *pcx, long where)
1514 if (where != DO_NOT_SEEK)
1516 where += pcx->oStart;
1517 if (where > pcx->length)
1520 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1528 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1530 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1531 pcx->pos, count, pcx->oStart, pcx->length, where);
1533 MSFT_Seek(pcx, where);
1534 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1535 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1540 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1545 ret = MSFT_Read(buffer, count, pcx, where);
1546 FromLEDWords(buffer, ret);
1551 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1556 ret = MSFT_Read(buffer, count, pcx, where);
1557 FromLEWords(buffer, ret);
1562 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1564 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1565 memset(pGuid,0, sizeof(GUID));
1568 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1569 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1570 pGuid->Data2 = FromLEWord(pGuid->Data2);
1571 pGuid->Data3 = FromLEWord(pGuid->Data3);
1572 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1575 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1577 MSFT_NameIntro niName;
1581 ERR_(typelib)("bad offset %d\n", offset);
1585 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1586 pcx->pTblDir->pNametab.offset+offset);
1588 return niName.hreftype;
1591 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1594 MSFT_NameIntro niName;
1596 BSTR bstrName = NULL;
1600 ERR_(typelib)("bad offset %d\n", offset);
1603 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1604 pcx->pTblDir->pNametab.offset+offset);
1605 niName.namelen &= 0xFF; /* FIXME: correct ? */
1606 name=TLB_Alloc((niName.namelen & 0xff) +1);
1607 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1608 name[niName.namelen & 0xff]='\0';
1610 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1613 /* no invalid characters in string */
1616 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1618 /* don't check for invalid character since this has been done previously */
1619 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1623 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1627 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1634 if(offset<0) return NULL;
1635 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1636 if(length <= 0) return 0;
1637 string=TLB_Alloc(length +1);
1638 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1639 string[length]='\0';
1641 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1642 string, -1, NULL, 0);
1644 /* no invalid characters in string */
1647 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1649 /* don't check for invalid character since this has been done previously */
1650 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1654 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1658 * read a value and fill a VARIANT structure
1660 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1664 TRACE_(typelib)("\n");
1666 if(offset <0) { /* data are packed in here */
1667 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1668 V_I4(pVar) = offset & 0x3ffffff;
1671 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1672 pcx->pTblDir->pCustData.offset + offset );
1673 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1674 switch (V_VT(pVar)){
1675 case VT_EMPTY: /* FIXME: is this right? */
1676 case VT_NULL: /* FIXME: is this right? */
1677 case VT_I2 : /* this should not happen */
1688 case VT_VOID : /* FIXME: is this right? */
1696 case VT_DECIMAL : /* FIXME: is this right? */
1699 /* pointer types with known behaviour */
1702 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1705 DWORD origPos = MSFT_Tell(pcx), nullPos;
1708 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1710 nullPos = MSFT_Tell(pcx);
1711 size = nullPos - origPos;
1712 MSFT_Seek(pcx, origPos);
1714 ptr=TLB_Alloc(size);/* allocate temp buffer */
1715 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1716 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1717 /* FIXME: do we need a AtoW conversion here? */
1718 V_UNION(pVar, bstrVal[size])='\0';
1719 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1723 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1730 case VT_USERDEFINED :
1736 case VT_STREAMED_OBJECT :
1737 case VT_STORED_OBJECT :
1738 case VT_BLOB_OBJECT :
1743 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1747 if(size>0) /* (big|small) endian correct? */
1748 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1752 * create a linked list with custom data
1754 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1760 TRACE_(typelib)("\n");
1764 pNew=TLB_Alloc(sizeof(TLBCustData));
1765 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1766 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1767 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1768 /* add new custom data at head of the list */
1769 pNew->next=*ppCustData;
1771 offset = entry.next;
1776 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1780 pTd->vt=type & VT_TYPEMASK;
1782 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1784 if(pTd->vt == VT_USERDEFINED)
1785 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1787 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1790 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1792 /* resolve referenced type if any */
1795 switch (lpTypeDesc->vt)
1798 lpTypeDesc = lpTypeDesc->u.lptdesc;
1802 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1805 case VT_USERDEFINED:
1806 MSFT_DoRefType(pcx, pTI->pTypeLib,
1807 lpTypeDesc->u.hreftype);
1819 MSFT_DoFuncs(TLBContext* pcx,
1824 TLBFuncDesc** pptfd)
1827 * member information is stored in a data structure at offset
1828 * indicated by the memoffset field of the typeinfo structure
1829 * There are several distinctive parts.
1830 * The first part starts with a field that holds the total length
1831 * of this (first) part excluding this field. Then follow the records,
1832 * for each member there is one record.
1834 * The first entry is always the length of the record (including this
1836 * The rest of the record depends on the type of the member. If there is
1837 * a field indicating the member type (function, variable, interface, etc)
1838 * I have not found it yet. At this time we depend on the information
1839 * in the type info and the usual order how things are stored.
1841 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1844 * Third is an equal sized array with file offsets to the name entry
1847 * The fourth and last (?) part is an array with offsets to the records
1848 * in the first part of this file segment.
1851 int infolen, nameoffset, reclength, nrattributes, i;
1852 int recoffset = offset + sizeof(INT);
1854 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1855 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1856 TLBFuncDesc *ptfd_prev = NULL;
1858 TRACE_(typelib)("\n");
1860 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1862 for ( i = 0; i < cFuncs ; i++ )
1864 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1866 /* name, eventually add to a hash table */
1867 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1868 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1870 /* nameoffset is sometimes -1 on the second half of a propget/propput
1871 * pair of functions */
1872 if ((nameoffset == -1) && (i > 0))
1873 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1875 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1877 /* read the function information record */
1878 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1880 reclength &= 0xffff;
1882 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1884 /* do the attributes */
1885 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1888 if ( nrattributes > 0 )
1890 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1892 if ( nrattributes > 1 )
1894 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1895 pFuncRec->OptAttr[1]) ;
1897 if ( nrattributes > 2 )
1899 if ( pFuncRec->FKCCIC & 0x2000 )
1901 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1902 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1903 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1907 (*pptfd)->Entry = MSFT_ReadString(pcx,
1908 pFuncRec->OptAttr[2]);
1910 if( nrattributes > 5 )
1912 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1914 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1917 pFuncRec->OptAttr[6],
1918 &(*pptfd)->pCustData);
1924 (*pptfd)->Entry = (BSTR)-1;
1929 /* fill the FuncDesc Structure */
1930 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1931 offset + infolen + ( i + 1) * sizeof(INT));
1933 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1934 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1935 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1936 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1937 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1938 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1939 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1943 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1945 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1947 /* do the parameters/arguments */
1948 if(pFuncRec->nrargs)
1951 MSFT_ParameterInfo paraminfo;
1953 (*pptfd)->funcdesc.lprgelemdescParam =
1954 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1956 (*pptfd)->pParamDesc =
1957 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1959 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1960 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1962 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1964 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1971 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1974 if (paraminfo.oName == -1)
1975 /* this occurs for [propput] or [propget] methods, so
1976 * we should just set the name of the parameter to the
1977 * name of the method. */
1978 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1980 (*pptfd)->pParamDesc[j].Name =
1981 MSFT_ReadName( pcx, paraminfo.oName );
1982 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1984 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1987 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1988 (pFuncRec->FKCCIC & 0x1000) )
1990 INT* pInt = (INT *)((char *)pFuncRec +
1992 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1994 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1996 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1997 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1999 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2003 elemdesc->u.paramdesc.pparamdescex = NULL;
2005 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2008 pFuncRec->OptAttr[7+j],
2009 &(*pptfd)->pParamDesc[j].pCustData);
2012 /* SEEK value = jump to offset,
2013 * from there jump to the end of record,
2014 * go back by (j-1) arguments
2016 MSFT_ReadLEDWords( ¶minfo ,
2017 sizeof(MSFT_ParameterInfo), pcx,
2018 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2019 * sizeof(MSFT_ParameterInfo)));
2023 /* scode is not used: archaic win16 stuff FIXME: right? */
2024 (*pptfd)->funcdesc.cScodes = 0 ;
2025 (*pptfd)->funcdesc.lprgscode = NULL ;
2028 pptfd = & ((*pptfd)->next);
2029 recoffset += reclength;
2031 HeapFree(GetProcessHeap(), 0, recbuf);
2034 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2035 int cVars, int offset, TLBVarDesc ** pptvd)
2037 int infolen, nameoffset, reclength;
2039 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2043 TRACE_(typelib)("\n");
2045 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2046 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2047 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2048 recoffset += offset+sizeof(INT);
2049 for(i=0;i<cVars;i++){
2050 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2051 /* name, eventually add to a hash table */
2052 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2053 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2054 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2055 /* read the variable information record */
2056 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2058 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2060 if(reclength >(6*sizeof(INT)) )
2061 (*pptvd)->HelpContext=pVarRec->HelpContext;
2062 if(reclength >(7*sizeof(INT)) )
2063 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2064 if(reclength >(8*sizeof(INT)) )
2065 if(reclength >(9*sizeof(INT)) )
2066 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2067 /* fill the VarDesc Structure */
2068 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2069 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2070 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2071 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2072 MSFT_GetTdesc(pcx, pVarRec->DataType,
2073 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2074 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2075 if(pVarRec->VarKind == VAR_CONST ){
2076 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2077 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2078 pVarRec->OffsValue, pcx);
2080 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2081 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2082 pptvd=&((*pptvd)->next);
2083 recoffset += reclength;
2086 /* fill in data for a hreftype (offset). When the referenced type is contained
2087 * in the typelib, it's just an (file) offset in the type info base dir.
2088 * If comes from import, it's an offset+1 in the ImpInfo table
2090 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2095 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2097 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2099 if(ref->reference == offset) return;
2102 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2103 list_add_tail(&pTL->ref_list, &ref->entry);
2105 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2106 /* external typelib */
2107 MSFT_ImpInfo impinfo;
2108 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2110 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2112 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2113 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2114 while (pImpLib){ /* search the known offsets of all import libraries */
2115 if(pImpLib->offset==impinfo.oImpFile) break;
2116 pImpLib=pImpLib->next;
2119 ref->reference = offset;
2120 ref->pImpTLInfo = pImpLib;
2121 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2122 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2123 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2124 ref->index = TLB_REF_USE_GUID;
2126 ref->index = impinfo.oGuid;
2128 ERR("Cannot find a reference\n");
2129 ref->reference = -1;
2130 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2133 /* in this typelib */
2134 ref->index = MSFT_HREFTYPE_INDEX(offset);
2135 ref->reference = offset;
2136 ref->pImpTLInfo = TLB_REF_INTERNAL;
2140 /* process Implemented Interfaces of a com class */
2141 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2145 MSFT_RefRecord refrec;
2146 TLBImplType **ppImpl = &pTI->impltypelist;
2148 TRACE_(typelib)("\n");
2150 for(i=0;i<count;i++){
2151 if(offset<0) break; /* paranoia */
2152 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2153 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2154 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2155 (*ppImpl)->hRef = refrec.reftype;
2156 (*ppImpl)->implflags=refrec.flags;
2157 (*ppImpl)->ctCustData=
2158 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2159 offset=refrec.onext;
2160 ppImpl=&((*ppImpl)->next);
2164 * process a typeinfo record
2166 static ITypeInfoImpl * MSFT_DoTypeInfo(
2169 ITypeLibImpl * pLibInfo)
2171 MSFT_TypeInfoBase tiBase;
2172 ITypeInfoImpl *ptiRet;
2174 TRACE_(typelib)("count=%u\n", count);
2176 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2177 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2178 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2180 /* this is where we are coming from */
2181 ptiRet->pTypeLib = pLibInfo;
2182 ptiRet->index=count;
2183 /* fill in the typeattr fields */
2185 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2186 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2187 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2188 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2189 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2190 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2191 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2192 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2193 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2194 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2195 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2196 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2197 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2198 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2199 MSFT_GetTdesc(pcx, tiBase.datatype1,
2200 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2203 /* IDLDESC idldescType; *//* never saw this one != zero */
2205 /* name, eventually add to a hash table */
2206 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2207 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2208 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2210 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2211 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2212 ptiRet->dwHelpContext=tiBase.helpcontext;
2214 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2215 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2217 /* note: InfoType's Help file and HelpStringDll come from the containing
2218 * library. Further HelpString and Docstring appear to be the same thing :(
2221 if(ptiRet->TypeAttr.cFuncs >0 )
2222 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2223 ptiRet->TypeAttr.cVars,
2224 tiBase.memoffset, & ptiRet->funclist);
2226 if(ptiRet->TypeAttr.cVars >0 )
2227 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2228 ptiRet->TypeAttr.cVars,
2229 tiBase.memoffset, & ptiRet->varlist);
2230 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2231 switch(ptiRet->TypeAttr.typekind)
2234 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2237 case TKIND_DISPATCH:
2238 /* This is not -1 when the interface is a non-base dual interface or
2239 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2240 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2244 if (tiBase.datatype1 != -1)
2246 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2247 ptiRet->impltypelist->hRef = tiBase.datatype1;
2248 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2252 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2253 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2254 ptiRet->impltypelist->hRef = tiBase.datatype1;
2259 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2261 TRACE_(typelib)("%s guid: %s kind:%s\n",
2262 debugstr_w(ptiRet->Name),
2263 debugstr_guid(&ptiRet->TypeAttr.guid),
2264 typekind_desc[ptiRet->TypeAttr.typekind]);
2265 if (TRACE_ON(typelib))
2266 dump_TypeInfo(ptiRet);
2271 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2272 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2273 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2276 static ITypeLibImpl *tlb_cache_first;
2277 static CRITICAL_SECTION cache_section;
2278 static CRITICAL_SECTION_DEBUG cache_section_debug =
2280 0, 0, &cache_section,
2281 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2282 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2284 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2287 typedef struct TLB_PEFile
2289 const IUnknownVtbl *lpvtbl;
2292 HRSRC typelib_resource;
2293 HGLOBAL typelib_global;
2294 LPVOID typelib_base;
2297 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2299 if (IsEqualIID(riid, &IID_IUnknown))
2302 IUnknown_AddRef(iface);
2306 return E_NOINTERFACE;
2309 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2311 TLB_PEFile *This = (TLB_PEFile *)iface;
2312 return InterlockedIncrement(&This->refs);
2315 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2317 TLB_PEFile *This = (TLB_PEFile *)iface;
2318 ULONG refs = InterlockedDecrement(&This->refs);
2321 if (This->typelib_global)
2322 FreeResource(This->typelib_global);
2324 FreeLibrary(This->dll);
2325 HeapFree(GetProcessHeap(), 0, This);
2330 static const IUnknownVtbl TLB_PEFile_Vtable =
2332 TLB_PEFile_QueryInterface,
2337 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2341 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2343 return E_OUTOFMEMORY;
2345 This->lpvtbl = &TLB_PEFile_Vtable;
2348 This->typelib_resource = NULL;
2349 This->typelib_global = NULL;
2350 This->typelib_base = NULL;
2352 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2353 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2357 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2358 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2359 if (This->typelib_resource)
2361 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2362 if (This->typelib_global)
2364 This->typelib_base = LockResource(This->typelib_global);
2366 if (This->typelib_base)
2368 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2369 *ppBase = This->typelib_base;
2370 *ppFile = (IUnknown *)&This->lpvtbl;
2377 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2378 return TYPE_E_CANTLOADLIBRARY;
2381 typedef struct TLB_NEFile
2383 const IUnknownVtbl *lpvtbl;
2385 LPVOID typelib_base;
2388 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2390 if (IsEqualIID(riid, &IID_IUnknown))
2393 IUnknown_AddRef(iface);
2397 return E_NOINTERFACE;
2400 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2402 TLB_NEFile *This = (TLB_NEFile *)iface;
2403 return InterlockedIncrement(&This->refs);
2406 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2408 TLB_NEFile *This = (TLB_NEFile *)iface;
2409 ULONG refs = InterlockedDecrement(&This->refs);
2412 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2413 HeapFree(GetProcessHeap(), 0, This);
2418 static const IUnknownVtbl TLB_NEFile_Vtable =
2420 TLB_NEFile_QueryInterface,
2425 /***********************************************************************
2426 * read_xx_header [internal]
2428 static int read_xx_header( HFILE lzfd )
2430 IMAGE_DOS_HEADER mzh;
2433 LZSeek( lzfd, 0, SEEK_SET );
2434 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2436 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2439 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2440 if ( 2 != LZRead( lzfd, magic, 2 ) )
2443 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2445 if ( magic[0] == 'N' && magic[1] == 'E' )
2446 return IMAGE_OS2_SIGNATURE;
2447 if ( magic[0] == 'P' && magic[1] == 'E' )
2448 return IMAGE_NT_SIGNATURE;
2451 WARN("Can't handle %s files.\n", magic );
2456 /***********************************************************************
2457 * find_ne_resource [internal]
2459 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2460 DWORD *resLen, DWORD *resOff )
2462 IMAGE_OS2_HEADER nehd;
2463 NE_TYPEINFO *typeInfo;
2464 NE_NAMEINFO *nameInfo;
2470 /* Read in NE header */
2471 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2472 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2474 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2477 TRACE("No resources in NE dll\n" );
2481 /* Read in resource table */
2482 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2483 if ( !resTab ) return FALSE;
2485 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2486 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2488 HeapFree( GetProcessHeap(), 0, resTab );
2493 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2495 if (HIWORD(typeid) != 0) /* named type */
2497 BYTE len = strlen( typeid );
2498 while (typeInfo->type_id)
2500 if (!(typeInfo->type_id & 0x8000))
2502 BYTE *p = resTab + typeInfo->type_id;
2503 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2505 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2506 typeInfo->count * sizeof(NE_NAMEINFO));
2509 else /* numeric type id */
2511 WORD id = LOWORD(typeid) | 0x8000;
2512 while (typeInfo->type_id)
2514 if (typeInfo->type_id == id) goto found_type;
2515 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2516 typeInfo->count * sizeof(NE_NAMEINFO));
2519 TRACE("No typeid entry found for %p\n", typeid );
2520 HeapFree( GetProcessHeap(), 0, resTab );
2524 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2526 if (HIWORD(resid) != 0) /* named resource */
2528 BYTE len = strlen( resid );
2529 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2531 BYTE *p = resTab + nameInfo->id;
2532 if (nameInfo->id & 0x8000) continue;
2533 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2536 else /* numeric resource id */
2538 WORD id = LOWORD(resid) | 0x8000;
2539 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2540 if (nameInfo->id == id) goto found_name;
2542 TRACE("No resid entry found for %p\n", typeid );
2543 HeapFree( GetProcessHeap(), 0, resTab );
2547 /* Return resource data */
2548 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2549 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2551 HeapFree( GetProcessHeap(), 0, resTab );
2555 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2559 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2560 TLB_NEFile *This = NULL;
2562 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2563 if (!This) return E_OUTOFMEMORY;
2565 This->lpvtbl = &TLB_NEFile_Vtable;
2567 This->typelib_base = NULL;
2569 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2570 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2572 DWORD reslen, offset;
2573 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2575 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2576 if( !This->typelib_base )
2580 LZSeek( lzfd, offset, SEEK_SET );
2581 reslen = LZRead( lzfd, This->typelib_base, reslen );
2583 *ppBase = This->typelib_base;
2584 *pdwTLBLength = reslen;
2585 *ppFile = (IUnknown *)&This->lpvtbl;
2591 if( lzfd >= 0) LZClose( lzfd );
2592 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2596 typedef struct TLB_Mapping
2598 const IUnknownVtbl *lpvtbl;
2602 LPVOID typelib_base;
2605 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2607 if (IsEqualIID(riid, &IID_IUnknown))
2610 IUnknown_AddRef(iface);
2614 return E_NOINTERFACE;
2617 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2619 TLB_Mapping *This = (TLB_Mapping *)iface;
2620 return InterlockedIncrement(&This->refs);
2623 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2625 TLB_Mapping *This = (TLB_Mapping *)iface;
2626 ULONG refs = InterlockedDecrement(&This->refs);
2629 if (This->typelib_base)
2630 UnmapViewOfFile(This->typelib_base);
2632 CloseHandle(This->mapping);
2633 if (This->file != INVALID_HANDLE_VALUE)
2634 CloseHandle(This->file);
2635 HeapFree(GetProcessHeap(), 0, This);
2640 static const IUnknownVtbl TLB_Mapping_Vtable =
2642 TLB_Mapping_QueryInterface,
2647 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2651 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2653 return E_OUTOFMEMORY;
2655 This->lpvtbl = &TLB_Mapping_Vtable;
2657 This->file = INVALID_HANDLE_VALUE;
2658 This->mapping = NULL;
2659 This->typelib_base = NULL;
2661 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2662 if (INVALID_HANDLE_VALUE != This->file)
2664 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2667 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2668 if(This->typelib_base)
2670 /* retrieve file size */
2671 *pdwTLBLength = GetFileSize(This->file, NULL);
2672 *ppBase = This->typelib_base;
2673 *ppFile = (IUnknown *)&This->lpvtbl;
2679 IUnknown_Release((IUnknown *)&This->lpvtbl);
2680 return TYPE_E_CANTLOADLIBRARY;
2683 /****************************************************************************
2686 * find the type of the typelib file and map the typelib resource into
2689 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2690 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2691 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2693 ITypeLibImpl *entry;
2696 LPWSTR index_str, file = (LPWSTR)pszFileName;
2697 LPVOID pBase = NULL;
2698 DWORD dwTLBLength = 0;
2699 IUnknown *pFile = NULL;
2703 index_str = strrchrW(pszFileName, '\\');
2704 if(index_str && *++index_str != '\0')
2707 long idx = strtolW(index_str, &end_ptr, 10);
2708 if(*end_ptr == '\0')
2710 int str_len = index_str - pszFileName - 1;
2712 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2713 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2718 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2720 if(strchrW(file, '\\'))
2722 lstrcpyW(pszPath, file);
2726 int len = GetSystemDirectoryW(pszPath, cchPath);
2727 pszPath[len] = '\\';
2728 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2732 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2734 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2736 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2737 EnterCriticalSection(&cache_section);
2738 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2740 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2742 TRACE("cache hit\n");
2743 *ppTypeLib = (ITypeLib2*)entry;
2744 ITypeLib_AddRef(*ppTypeLib);
2745 LeaveCriticalSection(&cache_section);
2749 LeaveCriticalSection(&cache_section);
2751 /* now actually load and parse the typelib */
2753 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2754 if (ret == TYPE_E_CANTLOADLIBRARY)
2755 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2756 if (ret == TYPE_E_CANTLOADLIBRARY)
2757 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2760 if (dwTLBLength >= 4)
2762 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2763 if (dwSignature == MSFT_SIGNATURE)
2764 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2765 else if (dwSignature == SLTG_SIGNATURE)
2766 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2769 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2770 ret = TYPE_E_CANTLOADLIBRARY;
2774 ret = TYPE_E_CANTLOADLIBRARY;
2775 IUnknown_Release(pFile);
2779 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2781 TRACE("adding to cache\n");
2782 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2783 lstrcpyW(impl->path, pszPath);
2784 /* We should really canonicalise the path here. */
2785 impl->index = index;
2787 /* FIXME: check if it has added already in the meantime */
2788 EnterCriticalSection(&cache_section);
2789 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2791 tlb_cache_first = impl;
2792 LeaveCriticalSection(&cache_section);
2795 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2800 /*================== ITypeLib(2) Methods ===================================*/
2802 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2804 ITypeLibImpl* pTypeLibImpl;
2806 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2807 if (!pTypeLibImpl) return NULL;
2809 pTypeLibImpl->lpVtbl = &tlbvt;
2810 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2811 pTypeLibImpl->ref = 1;
2813 list_init(&pTypeLibImpl->ref_list);
2814 pTypeLibImpl->dispatch_href = -1;
2816 return pTypeLibImpl;
2819 /****************************************************************************
2820 * ITypeLib2_Constructor_MSFT
2822 * loading an MSFT typelib from an in-memory image
2824 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2828 MSFT_Header tlbHeader;
2829 MSFT_SegDir tlbSegDir;
2830 ITypeLibImpl * pTypeLibImpl;
2832 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2834 pTypeLibImpl = TypeLibImpl_Constructor();
2835 if (!pTypeLibImpl) return NULL;
2837 /* get pointer to beginning of typelib data */
2841 cx.pLibInfo = pTypeLibImpl;
2842 cx.length = dwTLBLength;
2845 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2846 TRACE_(typelib)("header:\n");
2847 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2848 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2849 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2852 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2854 /* there is a small amount of information here until the next important
2856 * the segment directory . Try to calculate the amount of data */
2857 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2859 /* now read the segment directory */
2860 TRACE("read segment directory (at %ld)\n",lPSegDir);
2861 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2862 cx.pTblDir = &tlbSegDir;
2864 /* just check two entries */
2865 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2867 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2868 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2872 /* now fill our internal data */
2873 /* TLIBATTR fields */
2874 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2876 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2877 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2878 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2879 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2880 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2882 pTypeLibImpl->lcid = tlbHeader.lcid;
2884 /* name, eventually add to a hash table */
2885 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2888 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2889 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2891 if( tlbHeader.varflags & HELPDLLFLAG)
2894 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2895 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2898 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2901 if(tlbHeader.CustomDataOffset >= 0)
2903 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2906 /* fill in type descriptions */
2907 if(tlbSegDir.pTypdescTab.length > 0)
2909 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2911 pTypeLibImpl->ctTypeDesc = cTD;
2912 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2913 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2916 /* FIXME: add several sanity checks here */
2917 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2918 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2920 /* FIXME: check safearray */
2922 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2924 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2926 else if(td[0] == VT_CARRAY)
2928 /* array descr table here */
2929 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2931 else if(td[0] == VT_USERDEFINED)
2933 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2935 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2938 /* second time around to fill the array subscript info */
2941 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2942 if(tlbSegDir.pArrayDescriptions.offset>0)
2944 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2945 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2948 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2950 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2952 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2954 for(j = 0; j<td[2]; j++)
2956 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2957 sizeof(INT), &cx, DO_NOT_SEEK);
2958 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2959 sizeof(INT), &cx, DO_NOT_SEEK);
2964 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2965 ERR("didn't find array description data\n");
2970 /* imported type libs */
2971 if(tlbSegDir.pImpFiles.offset>0)
2973 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2974 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2977 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2981 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2982 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2983 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2985 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2986 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2987 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2988 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2991 name = TLB_Alloc(size+1);
2992 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2993 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2995 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2996 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2998 ppImpLib = &(*ppImpLib)->next;
3002 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3003 if(pTypeLibImpl->dispatch_href != -1)
3004 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3007 if(tlbHeader.nrtypeinfos >= 0 )
3009 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3010 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3013 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3015 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3017 ppTI = &((*ppTI)->next);
3018 (pTypeLibImpl->TypeInfoCount)++;
3022 TRACE("(%p)\n", pTypeLibImpl);
3023 return (ITypeLib2*) pTypeLibImpl;
3027 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3033 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3034 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3038 guid->Data4[0] = s >> 8;
3039 guid->Data4[1] = s & 0xff;
3042 for(i = 0; i < 6; i++) {
3043 memcpy(b, str + 24 + 2 * i, 2);
3044 guid->Data4[i + 2] = strtol(b, NULL, 16);
3049 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3055 bytelen = *(const WORD*)ptr;
3056 if(bytelen == 0xffff) return 2;
3057 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3058 *pBstr = SysAllocStringLen(NULL, len);
3060 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3064 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3069 bytelen = *(const WORD*)ptr;
3070 if(bytelen == 0xffff) return 2;
3071 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3072 memcpy(*str, ptr + 2, bytelen);
3073 (*str)[bytelen] = '\0';
3077 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3079 char *ptr = pLibBlk;
3082 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3083 FIXME("libblk magic = %04x\n", w);
3088 if((w = *(WORD*)ptr) != 0xffff) {
3089 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3094 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3096 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3098 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3101 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3104 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3105 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3107 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3110 ptr += 4; /* skip res12 */
3112 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3115 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3118 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3121 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3122 ptr += sizeof(GUID);
3124 return ptr - (char*)pLibBlk;
3127 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3132 } sltg_ref_lookup_t;
3134 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3135 HREFTYPE *typelib_ref)
3137 if(table && typeinfo_ref < table->num)
3139 *typelib_ref = table->refs[typeinfo_ref];
3143 ERR_(typelib)("Unable to find reference\n");
3148 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3153 if((*pType & 0xe00) == 0xe00) {
3155 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3157 pTD = pTD->u.lptdesc;
3159 switch(*pType & 0x3f) {
3162 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3164 pTD = pTD->u.lptdesc;
3167 case VT_USERDEFINED:
3168 pTD->vt = VT_USERDEFINED;
3169 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3175 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3178 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3180 pTD->vt = VT_CARRAY;
3181 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3183 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3184 pTD->u.lpadesc->cDims = pSA->cDims;
3185 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3186 pSA->cDims * sizeof(SAFEARRAYBOUND));
3188 pTD = &pTD->u.lpadesc->tdescElem;
3194 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3198 pTD->vt = VT_SAFEARRAY;
3199 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3201 pTD = pTD->u.lptdesc;
3205 pTD->vt = *pType & 0x3f;
3214 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3215 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3217 /* Handle [in/out] first */
3218 if((*pType & 0xc000) == 0xc000)
3219 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3220 else if(*pType & 0x8000)
3221 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3222 else if(*pType & 0x4000)
3223 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3225 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3228 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3231 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3233 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3237 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3242 TLBRefType *ref_type;
3243 sltg_ref_lookup_t *table;
3244 HREFTYPE typelib_ref;
3246 if(pRef->magic != SLTG_REF_MAGIC) {
3247 FIXME("Ref magic = %x\n", pRef->magic);
3250 name = ( (char*)pRef->names + pRef->number);
3252 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3253 table->num = pRef->number >> 3;
3255 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3257 /* We don't want the first href to be 0 */
3258 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3260 for(ref = 0; ref < pRef->number >> 3; ref++) {
3262 unsigned int lib_offs, type_num;
3264 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3266 name += SLTG_ReadStringA(name, &refname);
3267 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3268 FIXME_(typelib)("Can't sscanf ref\n");
3269 if(lib_offs != 0xffff) {
3270 TLBImpLib **import = &pTL->pImpLibs;
3273 if((*import)->offset == lib_offs)
3275 import = &(*import)->next;
3278 char fname[MAX_PATH+1];
3281 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3283 (*import)->offset = lib_offs;
3284 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3286 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3287 &(*import)->wVersionMajor,
3288 &(*import)->wVersionMinor,
3289 &(*import)->lcid, fname) != 4) {
3290 FIXME_(typelib)("can't sscanf ref %s\n",
3291 pNameTable + lib_offs + 40);
3293 len = strlen(fname);
3294 if(fname[len-1] != '#')
3295 FIXME("fname = %s\n", fname);
3296 fname[len-1] = '\0';
3297 (*import)->name = TLB_MultiByteToBSTR(fname);
3299 ref_type->pImpTLInfo = *import;
3301 /* Store a reference to IDispatch */
3302 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3303 pTL->dispatch_href = typelib_ref;
3305 } else { /* internal ref */
3306 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3308 ref_type->reference = typelib_ref;
3309 ref_type->index = type_num;
3311 HeapFree(GetProcessHeap(), 0, refname);
3312 list_add_tail(&pTL->ref_list, &ref_type->entry);
3314 table->refs[ref] = typelib_ref;
3317 if((BYTE)*name != SLTG_REF_MAGIC)
3318 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3319 dump_TLBRefType(pTL);
3323 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3324 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3326 SLTG_ImplInfo *info;
3327 TLBImplType **ppImplType = &pTI->impltypelist;
3328 /* I don't really get this structure, usually it's 0x16 bytes
3329 long, but iuser.tlb contains some that are 0x18 bytes long.
3330 That's ok because we can use the next ptr to jump to the next
3331 one. But how do we know the length of the last one? The WORD
3332 at offs 0x8 might be the clue. For now I'm just assuming that
3333 the last one is the regular 0x16 bytes. */
3335 info = (SLTG_ImplInfo*)pBlk;
3337 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3338 sizeof(**ppImplType));
3339 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3340 (*ppImplType)->implflags = info->impltypeflags;
3341 pTI->TypeAttr.cImplTypes++;
3342 ppImplType = &(*ppImplType)->next;
3344 if(info->next == 0xffff)
3347 FIXME_(typelib)("Interface inheriting more than one interface\n");
3348 info = (SLTG_ImplInfo*)(pBlk + info->next);
3350 info++; /* see comment at top of function */
3354 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3355 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3357 TLBVarDesc **ppVarDesc = &pTI->varlist;
3358 BSTR bstrPrevName = NULL;
3359 SLTG_Variable *pItem;
3363 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3364 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3366 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3367 sizeof(**ppVarDesc));
3368 (*ppVarDesc)->vardesc.memid = pItem->memid;
3370 if (pItem->magic != SLTG_VAR_MAGIC &&
3371 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3372 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3376 if (pItem->name == 0xfffe)
3377 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3379 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3381 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3382 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3383 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3385 if(pItem->flags & 0x02)
3386 pType = &pItem->type;
3388 pType = (WORD*)(pBlk + pItem->type);
3390 if (pItem->flags & ~0xda)
3391 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3393 SLTG_DoElem(pType, pBlk,
3394 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3396 if (TRACE_ON(typelib)) {
3398 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3399 TRACE_(typelib)("elemdescVar: %s\n", buf);
3402 if (pItem->flags & 0x40) {
3403 TRACE_(typelib)("VAR_DISPATCH\n");
3404 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3406 else if (pItem->flags & 0x10) {
3407 TRACE_(typelib)("VAR_CONST\n");
3408 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3409 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3411 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3412 if (pItem->flags & 0x08)
3413 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3415 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3421 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3423 TRACE_(typelib)("len = %u\n", len);
3424 if (len == 0xffff) {
3427 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3428 str = SysAllocStringLen(NULL, alloc_len);
3429 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3431 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3432 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3441 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3442 *(INT*)(pBlk + pItem->byte_offs);
3445 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3450 TRACE_(typelib)("VAR_PERINSTANCE\n");
3451 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3452 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3455 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3456 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3458 if (pItem->flags & 0x80)
3459 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3461 bstrPrevName = (*ppVarDesc)->Name;
3462 ppVarDesc = &((*ppVarDesc)->next);
3464 pTI->TypeAttr.cVars = cVars;
3467 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3468 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3470 SLTG_Function *pFunc;
3472 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3474 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3475 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3480 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3481 sizeof(**ppFuncDesc));
3483 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3484 case SLTG_FUNCTION_MAGIC:
3485 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3487 case SLTG_DISPATCH_FUNCTION_MAGIC:
3488 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3490 case SLTG_STATIC_FUNCTION_MAGIC:
3491 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3494 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3495 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3499 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3501 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3502 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3503 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3504 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3505 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3506 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3508 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3509 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3511 if(pFunc->retnextopt & 0x80)
3512 pType = &pFunc->rettype;
3514 pType = (WORD*)(pBlk + pFunc->rettype);
3516 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3518 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3519 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3520 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3521 (*ppFuncDesc)->pParamDesc =
3522 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3523 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3525 pArg = (WORD*)(pBlk + pFunc->arg_off);
3527 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3528 char *paramName = pNameTable + *pArg;
3530 /* If arg type follows then paramName points to the 2nd
3531 letter of the name, else the next WORD is an offset to
3532 the arg type and paramName points to the first letter.
3533 So let's take one char off paramName and see if we're
3534 pointing at an alpha-numeric char. However if *pArg is
3535 0xffff or 0xfffe then the param has no name, the former
3536 meaning that the next WORD is the type, the latter
3537 meaning that the next WORD is an offset to the type. */
3542 else if(*pArg == 0xfffe) {
3546 else if(paramName[-1] && !isalnum(paramName[-1]))
3551 if(HaveOffs) { /* the next word is an offset to type */
3552 pType = (WORD*)(pBlk + *pArg);
3553 SLTG_DoElem(pType, pBlk,
3554 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3559 pArg = SLTG_DoElem(pArg, pBlk,
3560 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3563 /* Are we an optional param ? */
3564 if((*ppFuncDesc)->funcdesc.cParams - param <=
3565 (*ppFuncDesc)->funcdesc.cParamsOpt)
3566 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3569 (*ppFuncDesc)->pParamDesc[param].Name =
3570 TLB_MultiByteToBSTR(paramName);
3572 (*ppFuncDesc)->pParamDesc[param].Name =
3573 SysAllocString((*ppFuncDesc)->Name);
3577 ppFuncDesc = &((*ppFuncDesc)->next);
3578 if(pFunc->next == 0xffff) break;
3580 pTI->TypeAttr.cFuncs = cFuncs;
3583 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3584 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3585 SLTG_TypeInfoTail *pTITail)
3588 sltg_ref_lookup_t *ref_lookup = NULL;
3590 if(pTIHeader->href_table != 0xffffffff) {
3591 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3597 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3598 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3600 HeapFree(GetProcessHeap(), 0, ref_lookup);
3604 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3605 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3606 const SLTG_TypeInfoTail *pTITail)
3609 sltg_ref_lookup_t *ref_lookup = NULL;
3611 if(pTIHeader->href_table != 0xffffffff) {
3612 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3618 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3619 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3622 if (pTITail->funcs_off != 0xffff)
3623 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3625 HeapFree(GetProcessHeap(), 0, ref_lookup);
3627 if (TRACE_ON(typelib))
3628 dump_TLBFuncDesc(pTI->funclist);
3631 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3632 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3633 const SLTG_TypeInfoTail *pTITail)
3635 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3638 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3639 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3640 const SLTG_TypeInfoTail *pTITail)
3643 sltg_ref_lookup_t *ref_lookup = NULL;
3645 if (pTITail->simple_alias) {
3646 /* if simple alias, no more processing required */
3647 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3651 if(pTIHeader->href_table != 0xffffffff) {
3652 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3656 /* otherwise it is an offset to a type */
3657 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3659 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3661 HeapFree(GetProcessHeap(), 0, ref_lookup);
3664 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3665 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3666 const SLTG_TypeInfoTail *pTITail)
3668 sltg_ref_lookup_t *ref_lookup = NULL;
3669 if (pTIHeader->href_table != 0xffffffff)
3670 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3673 if (pTITail->vars_off != 0xffff)
3674 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3676 if (pTITail->funcs_off != 0xffff)
3677 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3679 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3680 * of dispinterface functions including the IDispatch ones, so
3681 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3682 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3684 HeapFree(GetProcessHeap(), 0, ref_lookup);
3685 if (TRACE_ON(typelib))
3686 dump_TLBFuncDesc(pTI->funclist);
3689 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3690 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3691 const SLTG_TypeInfoTail *pTITail)
3693 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3696 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3697 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3698 const SLTG_TypeInfoTail *pTITail)
3700 sltg_ref_lookup_t *ref_lookup = NULL;
3701 if (pTIHeader->href_table != 0xffffffff)
3702 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3705 if (pTITail->vars_off != 0xffff)
3706 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3708 if (pTITail->funcs_off != 0xffff)
3709 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3710 HeapFree(GetProcessHeap(), 0, ref_lookup);
3711 if (TRACE_ON(typelib))
3715 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3716 managable copy of it into this */
3729 } SLTG_InternalOtherTypeInfo;
3731 /****************************************************************************
3732 * ITypeLib2_Constructor_SLTG
3734 * loading a SLTG typelib from an in-memory image
3736 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3738 ITypeLibImpl *pTypeLibImpl;
3739 SLTG_Header *pHeader;
3740 SLTG_BlkEntry *pBlkEntry;
3744 LPVOID pBlk, pFirstBlk;
3745 SLTG_LibBlk *pLibBlk;
3746 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3747 char *pAfterOTIBlks = NULL;
3748 char *pNameTable, *ptr;
3751 ITypeInfoImpl **ppTypeInfoImpl;
3753 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3756 pTypeLibImpl = TypeLibImpl_Constructor();
3757 if (!pTypeLibImpl) return NULL;
3761 TRACE_(typelib)("header:\n");
3762 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3763 pHeader->nrOfFileBlks );
3764 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3765 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3766 pHeader->SLTG_magic);
3770 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3771 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3773 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3774 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3776 /* Next we have a magic block */
3777 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3779 /* Let's see if we're still in sync */
3780 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3781 sizeof(SLTG_COMPOBJ_MAGIC))) {
3782 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3785 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3786 sizeof(SLTG_DIR_MAGIC))) {
3787 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3791 pIndex = (SLTG_Index*)(pMagic+1);
3793 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3795 pFirstBlk = pPad9 + 1;
3797 /* We'll set up a ptr to the main library block, which is the last one. */
3799 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3800 pBlkEntry[order].next != 0;
3801 order = pBlkEntry[order].next - 1, i++) {
3802 pBlk = (char*)pBlk + pBlkEntry[order].len;
3806 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3808 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3813 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3815 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3816 sizeof(*pOtherTypeInfoBlks) *
3817 pTypeLibImpl->TypeInfoCount);
3820 ptr = (char*)pLibBlk + len;
3822 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3826 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3828 w = *(WORD*)(ptr + 2);
3831 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3833 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3834 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3836 w = *(WORD*)(ptr + 4 + len);
3838 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3840 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3842 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3843 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3845 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3846 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3847 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3849 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3851 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3854 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3855 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3856 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3857 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3858 len += sizeof(SLTG_OtherTypeInfo);
3862 pAfterOTIBlks = ptr;
3864 /* Skip this WORD and get the next DWORD */
3865 len = *(DWORD*)(pAfterOTIBlks + 2);
3867 /* Now add this to pLibBLk look at what we're pointing at and
3868 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3869 dust and we should be pointing at the beginning of the name
3872 pNameTable = (char*)pLibBlk + len;
3874 switch(*(WORD*)pNameTable) {
3881 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3885 pNameTable += 0x216;
3889 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3891 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3894 /* Hopefully we now have enough ptrs set up to actually read in
3895 some TypeInfos. It's not clear which order to do them in, so
3896 I'll just follow the links along the BlkEntry chain and read
3897 them in the order in which they are in the file */
3899 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3901 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3902 pBlkEntry[order].next != 0;
3903 order = pBlkEntry[order].next - 1, i++) {
3905 SLTG_TypeInfoHeader *pTIHeader;
3906 SLTG_TypeInfoTail *pTITail;
3907 SLTG_MemberHeader *pMemHeader;
3909 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3910 pOtherTypeInfoBlks[i].index_name)) {
3911 FIXME_(typelib)("Index strings don't match\n");
3916 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3917 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3920 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3921 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3922 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3924 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3925 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3926 (*ppTypeInfoImpl)->index = i;
3927 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3928 pOtherTypeInfoBlks[i].name_offs +
3930 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3931 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3932 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3933 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3934 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3935 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3936 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3938 if((pTIHeader->typeflags1 & 7) != 2)
3939 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3940 if(pTIHeader->typeflags3 != 2)
3941 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3943 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3944 debugstr_w((*ppTypeInfoImpl)->Name),
3945 typekind_desc[pTIHeader->typekind],
3946 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3947 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3949 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3951 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3953 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3954 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3955 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3957 switch(pTIHeader->typekind) {
3959 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3960 pTIHeader, pTITail);
3964 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3965 pTIHeader, pTITail);
3968 case TKIND_INTERFACE:
3969 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3970 pTIHeader, pTITail);
3974 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3975 pTIHeader, pTITail);
3979 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3980 pTIHeader, pTITail);
3983 case TKIND_DISPATCH:
3984 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3985 pTIHeader, pTITail);
3989 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3990 pTIHeader, pTITail);
3994 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3999 /* could get cFuncs, cVars and cImplTypes from here
4000 but we've already set those */
4001 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4016 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4017 pBlk = (char*)pBlk + pBlkEntry[order].len;
4020 if(i != pTypeLibImpl->TypeInfoCount) {
4021 FIXME("Somehow processed %d TypeInfos\n", i);
4025 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4026 return (ITypeLib2*)pTypeLibImpl;
4029 /* ITypeLib::QueryInterface
4031 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4036 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4038 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4041 if(IsEqualIID(riid, &IID_IUnknown) ||
4042 IsEqualIID(riid,&IID_ITypeLib)||
4043 IsEqualIID(riid,&IID_ITypeLib2))
4050 ITypeLib2_AddRef(iface);
4051 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4054 TRACE("-- Interface: E_NOINTERFACE\n");
4055 return E_NOINTERFACE;
4060 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4062 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4063 ULONG ref = InterlockedIncrement(&This->ref);
4065 TRACE("(%p)->ref was %u\n",This, ref - 1);
4070 /* ITypeLib::Release
4072 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4074 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4075 ULONG ref = InterlockedDecrement(&This->ref);
4077 TRACE("(%p)->(%u)\n",This, ref);
4081 TLBImpLib *pImpLib, *pImpLibNext;
4082 TLBCustData *pCustData, *pCustDataNext;
4083 TLBRefType *ref_type;
4087 /* remove cache entry */
4090 TRACE("removing from cache list\n");
4091 EnterCriticalSection(&cache_section);
4092 if (This->next) This->next->prev = This->prev;
4093 if (This->prev) This->prev->next = This->next;
4094 else tlb_cache_first = This->next;
4095 LeaveCriticalSection(&cache_section);
4096 HeapFree(GetProcessHeap(), 0, This->path);
4098 TRACE(" destroying ITypeLib(%p)\n",This);
4100 SysFreeString(This->Name);
4103 SysFreeString(This->DocString);
4104 This->DocString = NULL;
4106 SysFreeString(This->HelpFile);
4107 This->HelpFile = NULL;
4109 SysFreeString(This->HelpStringDll);
4110 This->HelpStringDll = NULL;
4112 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4114 VariantClear(&pCustData->data);
4116 pCustDataNext = pCustData->next;
4117 TLB_Free(pCustData);
4120 for (i = 0; i < This->ctTypeDesc; i++)
4121 if (This->pTypeDesc[i].vt == VT_CARRAY)
4122 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4124 TLB_Free(This->pTypeDesc);
4126 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4128 if (pImpLib->pImpTypeLib)
4129 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4130 SysFreeString(pImpLib->name);
4132 pImpLibNext = pImpLib->next;
4136 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4138 list_remove(&ref_type->entry);
4142 if (This->pTypeInfo) /* can be NULL */
4143 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4144 HeapFree(GetProcessHeap(),0,This);
4151 /* ITypeLib::GetTypeInfoCount
4153 * Returns the number of type descriptions in the type library
4155 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4157 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4158 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4159 return This->TypeInfoCount;
4162 /* ITypeLib::GetTypeInfo
4164 * retrieves the specified type description in the library.
4166 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4169 ITypeInfo **ppTInfo)
4173 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4174 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4176 TRACE("(%p)->(index=%d)\n", This, index);
4178 if (!ppTInfo) return E_INVALIDARG;
4180 /* search element n in list */
4181 for(i=0; i < index; i++)
4183 pTypeInfo = pTypeInfo->next;
4186 TRACE("-- element not found\n");
4187 return TYPE_E_ELEMENTNOTFOUND;
4191 *ppTInfo = (ITypeInfo *) pTypeInfo;
4193 ITypeInfo_AddRef(*ppTInfo);
4194 TRACE("-- found (%p)\n",*ppTInfo);
4199 /* ITypeLibs::GetTypeInfoType
4201 * Retrieves the type of a type description.
4203 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4208 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4210 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4212 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4213 return TYPE_E_ELEMENTNOTFOUND;
4215 TRACE("(%p) index %d\n", This, index);
4217 if(!pTKind) return E_INVALIDARG;
4219 /* search element n in list */
4220 for(i=0; i < index; i++)
4224 TRACE("-- element not found\n");
4225 return TYPE_E_ELEMENTNOTFOUND;
4227 pTInfo = pTInfo->next;
4230 *pTKind = pTInfo->TypeAttr.typekind;
4231 TRACE("-- found Type (%d)\n", *pTKind);
4235 /* ITypeLib::GetTypeInfoOfGuid
4237 * Retrieves the type description that corresponds to the specified GUID.
4240 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4243 ITypeInfo **ppTInfo)
4245 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4246 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4248 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4252 WARN("-- element not found\n");
4253 return TYPE_E_ELEMENTNOTFOUND;
4256 /* search linked list for guid */
4257 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4259 pTypeInfo = pTypeInfo->next;
4263 /* end of list reached */
4264 WARN("-- element not found\n");
4265 return TYPE_E_ELEMENTNOTFOUND;
4269 TRACE("-- found (%p, %s)\n",
4271 debugstr_w(pTypeInfo->Name));
4273 *ppTInfo = (ITypeInfo*)pTypeInfo;
4274 ITypeInfo_AddRef(*ppTInfo);
4278 /* ITypeLib::GetLibAttr
4280 * Retrieves the structure that contains the library's attributes.
4283 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4285 LPTLIBATTR *ppTLibAttr)
4287 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4288 TRACE("(%p)\n",This);
4289 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4290 **ppTLibAttr = This->LibAttr;
4294 /* ITypeLib::GetTypeComp
4296 * Enables a client compiler to bind to a library's types, variables,
4297 * constants, and global functions.
4300 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4302 ITypeComp **ppTComp)
4304 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4306 TRACE("(%p)->(%p)\n",This,ppTComp);
4307 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4308 ITypeComp_AddRef(*ppTComp);
4313 /* ITypeLib::GetDocumentation
4315 * Retrieves the library's documentation string, the complete Help file name
4316 * and path, and the context identifier for the library Help topic in the Help
4319 * On a successful return all non-null BSTR pointers will have been set,
4322 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4326 BSTR *pBstrDocString,
4327 DWORD *pdwHelpContext,
4328 BSTR *pBstrHelpFile)
4330 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4332 HRESULT result = E_INVALIDARG;
4337 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4339 pBstrName, pBstrDocString,
4340 pdwHelpContext, pBstrHelpFile);
4344 /* documentation for the typelib */
4349 if(!(*pBstrName = SysAllocString(This->Name)))
4357 if (This->DocString)
4359 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4362 else if (This->Name)
4364 if(!(*pBstrDocString = SysAllocString(This->Name)))
4368 *pBstrDocString = NULL;
4372 *pdwHelpContext = This->dwHelpContext;
4378 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4382 *pBstrHelpFile = NULL;
4389 /* for a typeinfo */
4390 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4392 if(SUCCEEDED(result))
4394 result = ITypeInfo_GetDocumentation(pTInfo,
4398 pdwHelpContext, pBstrHelpFile);
4400 ITypeInfo_Release(pTInfo);
4405 if (pBstrDocString) SysFreeString (*pBstrDocString);
4407 if (pBstrName) SysFreeString (*pBstrName);
4409 return STG_E_INSUFFICIENTMEMORY;
4414 * Indicates whether a passed-in string contains the name of a type or member
4415 * described in the library.
4418 static HRESULT WINAPI ITypeLib2_fnIsName(
4424 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4425 ITypeInfoImpl *pTInfo;
4426 TLBFuncDesc *pFInfo;
4429 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4431 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4435 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4436 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4437 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4438 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4439 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4440 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4441 goto ITypeLib2_fnIsName_exit;
4443 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4444 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4449 ITypeLib2_fnIsName_exit:
4450 TRACE("(%p)slow! search for %s: %s found!\n", This,
4451 debugstr_w(szNameBuf), *pfName?"NOT":"");
4456 /* ITypeLib::FindName
4458 * Finds occurrences of a type description in a type library. This may be used
4459 * to quickly verify that a name exists in a type library.
4462 static HRESULT WINAPI ITypeLib2_fnFindName(
4466 ITypeInfo **ppTInfo,
4470 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4471 ITypeInfoImpl *pTInfo;
4472 TLBFuncDesc *pFInfo;
4475 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4477 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4478 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4479 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4480 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4481 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4482 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4483 goto ITypeLib2_fnFindName_exit;
4486 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4487 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4489 ITypeLib2_fnFindName_exit:
4490 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4491 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4494 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4495 This, *pcFound, debugstr_w(szNameBuf), j);
4502 /* ITypeLib::ReleaseTLibAttr
4504 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4507 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4509 TLIBATTR *pTLibAttr)
4511 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4512 TRACE("freeing (%p)\n",This);
4513 HeapFree(GetProcessHeap(),0,pTLibAttr);
4517 /* ITypeLib2::GetCustData
4519 * gets the custom data
4521 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4526 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4527 TLBCustData *pCData;
4529 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4531 if( IsEqualIID(guid, &pCData->guid)) break;
4534 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4538 VariantInit( pVarVal);
4539 VariantCopy( pVarVal, &pCData->data);
4542 return E_INVALIDARG; /* FIXME: correct? */
4545 /* ITypeLib2::GetLibStatistics
4547 * Returns statistics about a type library that are required for efficient
4548 * sizing of hash tables.
4551 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4553 ULONG *pcUniqueNames,
4554 ULONG *pcchUniqueNames)
4556 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4558 FIXME("(%p): stub!\n", This);
4560 if(pcUniqueNames) *pcUniqueNames=1;
4561 if(pcchUniqueNames) *pcchUniqueNames=1;
4565 /* ITypeLib2::GetDocumentation2
4567 * Retrieves the library's documentation string, the complete Help file name
4568 * and path, the localization context to use, and the context ID for the
4569 * library Help topic in the Help file.
4572 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4576 BSTR *pbstrHelpString,
4577 DWORD *pdwHelpStringContext,
4578 BSTR *pbstrHelpStringDll)
4580 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4584 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4586 /* the help string should be obtained from the helpstringdll,
4587 * using the _DLLGetDocumentation function, based on the supplied
4588 * lcid. Nice to do sometime...
4592 /* documentation for the typelib */
4594 *pbstrHelpString=SysAllocString(This->DocString);
4595 if(pdwHelpStringContext)
4596 *pdwHelpStringContext=This->dwHelpContext;
4597 if(pbstrHelpStringDll)
4598 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4604 /* for a typeinfo */
4605 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4607 if(SUCCEEDED(result))
4609 ITypeInfo2 * pTInfo2;
4610 result = ITypeInfo_QueryInterface(pTInfo,
4612 (LPVOID*) &pTInfo2);
4614 if(SUCCEEDED(result))
4616 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4620 pdwHelpStringContext,
4621 pbstrHelpStringDll);
4623 ITypeInfo2_Release(pTInfo2);
4626 ITypeInfo_Release(pTInfo);
4632 /* ITypeLib2::GetAllCustData
4634 * Gets all custom data items for the library.
4637 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4639 CUSTDATA *pCustData)
4641 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4642 TLBCustData *pCData;
4644 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4645 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4646 if(pCustData->prgCustData ){
4647 pCustData->cCustData=This->ctCustData;
4648 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4649 pCustData->prgCustData[i].guid=pCData->guid;
4650 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4653 ERR(" OUT OF MEMORY!\n");
4654 return E_OUTOFMEMORY;
4659 static const ITypeLib2Vtbl tlbvt = {
4660 ITypeLib2_fnQueryInterface,
4662 ITypeLib2_fnRelease,
4663 ITypeLib2_fnGetTypeInfoCount,
4664 ITypeLib2_fnGetTypeInfo,
4665 ITypeLib2_fnGetTypeInfoType,
4666 ITypeLib2_fnGetTypeInfoOfGuid,
4667 ITypeLib2_fnGetLibAttr,
4668 ITypeLib2_fnGetTypeComp,
4669 ITypeLib2_fnGetDocumentation,
4671 ITypeLib2_fnFindName,
4672 ITypeLib2_fnReleaseTLibAttr,
4674 ITypeLib2_fnGetCustData,
4675 ITypeLib2_fnGetLibStatistics,
4676 ITypeLib2_fnGetDocumentation2,
4677 ITypeLib2_fnGetAllCustData
4681 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4683 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4685 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4688 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4690 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4692 return ITypeLib2_AddRef((ITypeLib2 *)This);
4695 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4697 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4699 return ITypeLib2_Release((ITypeLib2 *)This);
4702 static HRESULT WINAPI ITypeLibComp_fnBind(
4707 ITypeInfo ** ppTInfo,
4708 DESCKIND * pDescKind,
4711 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4712 ITypeInfoImpl *pTypeInfo;
4714 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4716 *pDescKind = DESCKIND_NONE;
4717 pBindPtr->lptcomp = NULL;
4720 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4722 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4724 /* FIXME: check wFlags here? */
4725 /* FIXME: we should use a hash table to look this info up using lHash
4726 * instead of an O(n) search */
4727 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4728 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4730 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4732 *pDescKind = DESCKIND_TYPECOMP;
4733 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4734 ITypeComp_AddRef(pBindPtr->lptcomp);
4735 TRACE("module or enum: %s\n", debugstr_w(szName));
4740 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4741 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4743 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4746 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4747 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4749 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4754 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4755 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4757 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4759 ITypeInfo *subtypeinfo;
4761 DESCKIND subdesckind;
4763 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4764 &subtypeinfo, &subdesckind, &subbindptr);
4765 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4767 TYPEDESC tdesc_appobject =
4770 (TYPEDESC *)pTypeInfo->hreftype
4774 const VARDESC vardesc_appobject =
4777 NULL, /* lpstrSchema */
4792 VAR_STATIC /* varkind */
4795 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4797 /* cleanup things filled in by Bind call so we can put our
4798 * application object data in there instead */
4799 switch (subdesckind)
4801 case DESCKIND_FUNCDESC:
4802 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4804 case DESCKIND_VARDESC:
4805 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4810 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4812 if (pTypeInfo->hreftype == -1)
4813 FIXME("no hreftype for interface %p\n", pTypeInfo);
4815 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4819 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4820 *ppTInfo = (ITypeInfo *)pTypeInfo;
4821 ITypeInfo_AddRef(*ppTInfo);
4827 TRACE("name not found %s\n", debugstr_w(szName));
4831 static HRESULT WINAPI ITypeLibComp_fnBindType(
4835 ITypeInfo ** ppTInfo,
4836 ITypeComp ** ppTComp)
4838 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4839 ITypeInfoImpl *pTypeInfo;
4841 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4843 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4845 /* FIXME: should use lHash to do the search */
4846 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4848 TRACE("returning %p\n", pTypeInfo);
4849 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4850 ITypeInfo_AddRef(*ppTInfo);
4851 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4852 ITypeComp_AddRef(*ppTComp);
4857 TRACE("not found\n");
4863 static const ITypeCompVtbl tlbtcvt =
4866 ITypeLibComp_fnQueryInterface,
4867 ITypeLibComp_fnAddRef,
4868 ITypeLibComp_fnRelease,
4870 ITypeLibComp_fnBind,
4871 ITypeLibComp_fnBindType
4874 /*================== ITypeInfo(2) Methods ===================================*/
4875 static ITypeInfo2 * ITypeInfo_Constructor(void)
4877 ITypeInfoImpl * pTypeInfoImpl;
4879 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4882 pTypeInfoImpl->lpVtbl = &tinfvt;
4883 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4884 pTypeInfoImpl->ref=1;
4885 pTypeInfoImpl->hreftype = -1;
4886 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4887 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4889 TRACE("(%p)\n", pTypeInfoImpl);
4890 return (ITypeInfo2*) pTypeInfoImpl;
4893 /* ITypeInfo::QueryInterface
4895 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4900 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4902 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4905 if(IsEqualIID(riid, &IID_IUnknown) ||
4906 IsEqualIID(riid,&IID_ITypeInfo)||
4907 IsEqualIID(riid,&IID_ITypeInfo2))
4911 ITypeInfo_AddRef(iface);
4912 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4915 TRACE("-- Interface: E_NOINTERFACE\n");
4916 return E_NOINTERFACE;
4919 /* ITypeInfo::AddRef
4921 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4923 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4924 ULONG ref = InterlockedIncrement(&This->ref);
4926 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4928 TRACE("(%p)->ref is %u\n",This, ref);
4932 /* ITypeInfo::Release
4934 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4936 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4937 ULONG ref = InterlockedDecrement(&This->ref);
4939 TRACE("(%p)->(%u)\n",This, ref);
4942 /* We don't release ITypeLib when ref=0 because
4943 it means that function is called by ITypeLib2_Release */
4944 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4946 TLBFuncDesc *pFInfo, *pFInfoNext;
4947 TLBVarDesc *pVInfo, *pVInfoNext;
4948 TLBImplType *pImpl, *pImplNext;
4950 TRACE("destroying ITypeInfo(%p)\n",This);
4952 if (This->no_free_data)
4955 SysFreeString(This->Name);
4958 SysFreeString(This->DocString);
4959 This->DocString = NULL;
4961 SysFreeString(This->DllName);
4962 This->DllName = NULL;
4964 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4967 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4969 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4970 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4972 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4973 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4975 SysFreeString(pFInfo->pParamDesc[i].Name);
4977 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4978 TLB_Free(pFInfo->pParamDesc);
4979 TLB_FreeCustData(pFInfo->pCustData);
4980 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4981 SysFreeString(pFInfo->Entry);
4982 SysFreeString(pFInfo->HelpString);
4983 SysFreeString(pFInfo->Name);
4985 pFInfoNext = pFInfo->next;
4988 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4990 if (pVInfo->vardesc.varkind == VAR_CONST)
4992 VariantClear(pVInfo->vardesc.u.lpvarValue);
4993 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4995 TLB_FreeCustData(pVInfo->pCustData);
4996 SysFreeString(pVInfo->Name);
4997 pVInfoNext = pVInfo->next;
5000 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5002 TLB_FreeCustData(pImpl->pCustData);
5003 pImplNext = pImpl->next;
5006 TLB_FreeCustData(This->pCustData);
5011 ITypeInfo_Release((ITypeInfo*)This->next);
5014 HeapFree(GetProcessHeap(),0,This);
5020 /* ITypeInfo::GetTypeAttr
5022 * Retrieves a TYPEATTR structure that contains the attributes of the type
5026 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5027 LPTYPEATTR *ppTypeAttr)
5029 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5032 TRACE("(%p)\n",This);
5034 size = sizeof(**ppTypeAttr);
5035 if (This->TypeAttr.typekind == TKIND_ALIAS)
5036 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5038 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5040 return E_OUTOFMEMORY;
5042 **ppTypeAttr = This->TypeAttr;
5044 if (This->TypeAttr.typekind == TKIND_ALIAS)
5045 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5046 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5048 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5049 /* This should include all the inherited funcs */
5050 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5051 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5052 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5057 /* ITypeInfo::GetTypeComp
5059 * Retrieves the ITypeComp interface for the type description, which enables a
5060 * client compiler to bind to the type description's members.
5063 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5064 ITypeComp * *ppTComp)
5066 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5068 TRACE("(%p)->(%p)\n", This, ppTComp);
5070 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5071 ITypeComp_AddRef(*ppTComp);
5075 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5077 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5078 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5079 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5083 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5086 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5087 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5089 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5090 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5091 *buffer += sizeof(PARAMDESCEX);
5092 *pparamdescex_dest = *pparamdescex_src;
5093 VariantInit(&pparamdescex_dest->varDefaultValue);
5094 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5095 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5098 dest->u.paramdesc.pparamdescex = NULL;
5102 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5104 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5105 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5108 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5112 SIZE_T size = sizeof(*src);
5116 size += sizeof(*src->lprgscode) * src->cScodes;
5117 size += TLB_SizeElemDesc(&src->elemdescFunc);
5118 for (i = 0; i < src->cParams; i++)
5120 size += sizeof(ELEMDESC);
5121 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5124 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5125 if (!dest) return E_OUTOFMEMORY;
5128 if (dispinterface) /* overwrite funckind */
5129 dest->funckind = FUNC_DISPATCH;
5130 buffer = (char *)(dest + 1);
5132 dest->lprgscode = (SCODE *)buffer;
5133 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5134 buffer += sizeof(*src->lprgscode) * src->cScodes;
5136 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5139 SysFreeString((BSTR)dest);
5143 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5144 buffer += sizeof(ELEMDESC) * src->cParams;
5145 for (i = 0; i < src->cParams; i++)
5147 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5153 /* undo the above actions */
5154 for (i = i - 1; i >= 0; i--)
5155 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5156 TLB_FreeElemDesc(&dest->elemdescFunc);
5157 SysFreeString((BSTR)dest);
5161 /* special treatment for dispinterfaces: this makes functions appear
5162 * to return their [retval] value when it is really returning an
5164 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5166 if (dest->cParams &&
5167 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5169 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5170 if (elemdesc->tdesc.vt != VT_PTR)
5172 ERR("elemdesc should have started with VT_PTR instead of:\n");
5174 dump_ELEMDESC(elemdesc);
5175 return E_UNEXPECTED;
5178 /* copy last parameter to the return value. we are using a flat
5179 * buffer so there is no danger of leaking memory in
5181 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5183 /* remove the last parameter */
5187 /* otherwise this function is made to appear to have no return
5189 dest->elemdescFunc.tdesc.vt = VT_VOID;
5197 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5199 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5200 const TLBFuncDesc *pFDesc;
5203 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5208 *ppFuncDesc = &pFDesc->funcdesc;
5212 return TYPE_E_ELEMENTNOTFOUND;
5215 /* internal function to make the inherited interfaces' methods appear
5216 * part of the interface */
5217 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5218 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5220 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5222 UINT implemented_funcs = 0;
5227 *hrefoffset = DISPATCH_HREF_OFFSET;
5229 if(This->impltypelist)
5231 ITypeInfo *pSubTypeInfo;
5234 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5238 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5241 &sub_funcs, hrefoffset);
5242 implemented_funcs += sub_funcs;
5243 ITypeInfo_Release(pSubTypeInfo);
5246 *hrefoffset += DISPATCH_HREF_OFFSET;
5250 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5254 if (index < implemented_funcs)
5255 return E_INVALIDARG;
5256 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5260 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5262 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5265 switch (pTypeDesc->vt)
5267 case VT_USERDEFINED:
5268 pTypeDesc->u.hreftype += hrefoffset;
5272 pTypeDesc = pTypeDesc->u.lptdesc;
5275 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5283 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5286 for (i = 0; i < pFuncDesc->cParams; i++)
5287 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5288 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5291 /* ITypeInfo::GetFuncDesc
5293 * Retrieves the FUNCDESC structure that contains information about a
5294 * specified function.
5297 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5298 LPFUNCDESC *ppFuncDesc)
5300 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5301 const FUNCDESC *internal_funcdesc;
5303 UINT hrefoffset = 0;
5305 TRACE("(%p) index %d\n", This, index);
5307 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5308 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5309 &internal_funcdesc, NULL,
5312 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5313 &internal_funcdesc);
5316 WARN("description for function %d not found\n", index);
5320 hr = TLB_AllocAndInitFuncDesc(
5323 This->TypeAttr.typekind == TKIND_DISPATCH);
5325 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5326 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5328 TRACE("-- 0x%08x\n", hr);
5332 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5336 SIZE_T size = sizeof(*src);
5339 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5340 if (src->varkind == VAR_CONST)
5341 size += sizeof(VARIANT);
5342 size += TLB_SizeElemDesc(&src->elemdescVar);
5344 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5345 if (!dest) return E_OUTOFMEMORY;
5348 buffer = (char *)(dest + 1);
5349 if (src->lpstrSchema)
5352 dest->lpstrSchema = (LPOLESTR)buffer;
5353 len = strlenW(src->lpstrSchema);
5354 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5355 buffer += (len + 1) * sizeof(WCHAR);
5358 if (src->varkind == VAR_CONST)
5362 dest->u.lpvarValue = (VARIANT *)buffer;
5363 *dest->u.lpvarValue = *src->u.lpvarValue;
5364 buffer += sizeof(VARIANT);
5365 VariantInit(dest->u.lpvarValue);
5366 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5369 SysFreeString((BSTR)dest_ptr);
5373 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5376 if (src->varkind == VAR_CONST)
5377 VariantClear(dest->u.lpvarValue);
5378 SysFreeString((BSTR)dest);
5385 /* ITypeInfo::GetVarDesc
5387 * Retrieves a VARDESC structure that describes the specified variable.
5390 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5391 LPVARDESC *ppVarDesc)
5393 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5395 const TLBVarDesc *pVDesc;
5397 TRACE("(%p) index %d\n", This, index);
5399 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5403 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5405 return E_INVALIDARG;
5408 /* ITypeInfo_GetNames
5410 * Retrieves the variable with the specified member ID (or the name of the
5411 * property or method and its parameters) that correspond to the specified
5414 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5415 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5417 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5418 const TLBFuncDesc *pFDesc;
5419 const TLBVarDesc *pVDesc;
5421 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5422 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5425 /* function found, now return function and parameter names */
5426 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5429 *rgBstrNames=SysAllocString(pFDesc->Name);
5431 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5437 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5440 *rgBstrNames=SysAllocString(pVDesc->Name);
5445 if(This->impltypelist &&
5446 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5447 /* recursive search */
5450 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5452 if(SUCCEEDED(result))
5454 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5455 ITypeInfo_Release(pTInfo);
5458 WARN("Could not search inherited interface!\n");
5462 WARN("no names found\n");
5465 return TYPE_E_ELEMENTNOTFOUND;
5472 /* ITypeInfo::GetRefTypeOfImplType
5474 * If a type description describes a COM class, it retrieves the type
5475 * description of the implemented interface types. For an interface,
5476 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5480 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5485 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5488 const TLBImplType *pImpl = This->impltypelist;
5490 TRACE("(%p) index %d\n", This, index);
5491 if (TRACE_ON(ole)) dump_TypeInfo(This);
5495 /* only valid on dual interfaces;
5496 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5498 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5500 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5501 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5507 hr = TYPE_E_ELEMENTNOTFOUND;
5510 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5512 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5513 *pRefType = This->pTypeLib->dispatch_href;
5517 /* get element n from linked list */
5518 for(i=0; pImpl && i<index; i++)
5520 pImpl = pImpl->next;
5524 *pRefType = pImpl->hRef;
5526 hr = TYPE_E_ELEMENTNOTFOUND;
5532 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5534 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5540 /* ITypeInfo::GetImplTypeFlags
5542 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5543 * or base interface in a type description.
5545 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5546 UINT index, INT *pImplTypeFlags)
5548 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5552 TRACE("(%p) index %d\n", This, index);
5553 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5554 i++, pImpl=pImpl->next)
5556 if(i==index && pImpl){
5557 *pImplTypeFlags=pImpl->implflags;
5561 return TYPE_E_ELEMENTNOTFOUND;
5565 * Maps between member names and member IDs, and parameter names and
5568 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5569 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5571 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5572 const TLBFuncDesc *pFDesc;
5573 const TLBVarDesc *pVDesc;
5577 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5580 /* init out parameters in case of failure */
5581 for (i = 0; i < cNames; i++)
5582 pMemId[i] = MEMBERID_NIL;
5584 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5586 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5587 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5588 for(i=1; i < cNames; i++){
5589 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5590 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5592 if( j<pFDesc->funcdesc.cParams)
5595 ret=DISP_E_UNKNOWNNAME;
5597 TRACE("-- 0x%08x\n", ret);
5601 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5602 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5603 if(cNames) *pMemId=pVDesc->vardesc.memid;
5607 /* not found, see if it can be found in an inherited interface */
5608 if(This->impltypelist) {
5609 /* recursive search */
5611 ret=ITypeInfo_GetRefTypeInfo(iface,
5612 This->impltypelist->hRef, &pTInfo);
5614 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5615 ITypeInfo_Release(pTInfo);
5618 WARN("Could not search inherited interface!\n");
5620 WARN("no names found\n");
5621 return DISP_E_UNKNOWNNAME;
5624 /* ITypeInfo::Invoke
5626 * Invokes a method, or accesses a property of an object, that implements the
5627 * interface described by the type description.
5630 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5633 if (TRACE_ON(ole)) {
5635 TRACE("Calling %p(",func);
5636 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5648 res = func(args[0]);
5651 res = func(args[0],args[1]);
5654 res = func(args[0],args[1],args[2]);
5657 res = func(args[0],args[1],args[2],args[3]);
5660 res = func(args[0],args[1],args[2],args[3],args[4]);
5663 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5666 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5669 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5672 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5675 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5678 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5681 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]);
5684 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]);
5687 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]);
5690 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5693 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5696 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5699 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5702 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5705 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5708 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5711 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5714 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5717 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23]);
5720 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24]);
5723 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25]);
5726 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26]);
5729 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27]);
5732 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28]);
5735 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5738 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5744 FIXME("unsupported calling convention %d\n",callconv);
5748 TRACE("returns %08x\n",res);
5752 /* The size of the argument on the stack in DWORD units (in all x86 call
5753 * convetions the arguments on the stack are DWORD-aligned)
5755 static int _dispargsize(VARTYPE vt)
5760 return 8/sizeof(DWORD);
5762 return sizeof(double)/sizeof(DWORD);
5764 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5766 return sizeof(CY)/sizeof(DWORD);
5768 return sizeof(DATE)/sizeof(DWORD);
5770 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5772 FIXME("VT_RECORD not implemented\n");
5779 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5782 ITypeInfo *tinfo2 = NULL;
5783 TYPEATTR *tattr = NULL;
5785 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5788 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5790 tdesc->u.hreftype, hr);
5793 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5796 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5797 ITypeInfo_Release(tinfo2);
5801 switch (tattr->typekind)
5808 tdesc = &tattr->tdescAlias;
5809 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5812 case TKIND_INTERFACE:
5813 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5819 case TKIND_DISPATCH:
5828 FIXME("TKIND_RECORD unhandled.\n");
5833 FIXME("TKIND_UNION unhandled.\n");
5838 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5842 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5843 ITypeInfo_Release(tinfo2);
5847 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5851 /* enforce only one level of pointer indirection */
5852 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5854 tdesc = tdesc->u.lptdesc;
5856 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5857 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5858 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5859 if ((tdesc->vt == VT_USERDEFINED) ||
5860 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5862 VARTYPE vt_userdefined = 0;
5863 const TYPEDESC *tdesc_userdefined = tdesc;
5864 if (tdesc->vt == VT_PTR)
5866 vt_userdefined = VT_BYREF;
5867 tdesc_userdefined = tdesc->u.lptdesc;
5869 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5871 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5872 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5874 *vt |= vt_userdefined;
5886 case VT_USERDEFINED:
5887 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5894 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5895 hr = DISP_E_BADVARTYPE;
5899 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5914 /***********************************************************************
5915 * DispCallFunc (OLEAUT32.@)
5917 * Invokes a function of the specified calling convention, passing the
5918 * specified arguments and returns the result.
5921 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5922 * oVft [I] The offset in the vtable. See notes.
5923 * cc [I] Calling convention of the function to call.
5924 * vtReturn [I] The return type of the function.
5925 * cActuals [I] Number of parameters.
5926 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5927 * prgpvarg [I] The arguments to pass.
5928 * pvargResult [O] The return value of the function. Can be NULL.
5932 * Failure: HRESULT code.
5935 * The HRESULT return value of this function is not affected by the return
5936 * value of the user supplied function, which is returned in pvargResult.
5938 * If pvInstance is NULL then a non-object function is to be called and oVft
5939 * is the address of the function to call.
5941 * The cc parameter can be one of the following values:
5954 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5955 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5957 int argsize, argspos;
5962 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5963 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5964 pvargResult, V_VT(pvargResult));
5968 argsize++; /* for This pointer */
5970 for (i=0;i<cActuals;i++)
5972 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5973 dump_Variant(prgpvarg[i]);
5974 argsize += _dispargsize(prgvt[i]);
5976 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5981 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5985 for (i=0;i<cActuals;i++)
5987 VARIANT *arg = prgpvarg[i];
5988 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5989 if (prgvt[i] == VT_VARIANT)
5990 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5992 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5993 argspos += _dispargsize(prgvt[i]);
5998 FARPROC *vtable = *(FARPROC**)pvInstance;
5999 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
6002 /* if we aren't invoking an object then the function pointer is stored
6004 hres = _invoke((FARPROC)oVft, cc, argsize, args);
6006 if (pvargResult && (vtReturn != VT_EMPTY))
6008 TRACE("Method returned 0x%08x\n",hres);
6009 V_VT(pvargResult) = vtReturn;
6010 V_UI4(pvargResult) = hres;
6013 HeapFree(GetProcessHeap(),0,args);
6017 #define INVBUF_ELEMENT_SIZE \
6018 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6019 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6020 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6021 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6022 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6023 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6024 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6025 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6027 static HRESULT WINAPI ITypeInfo_fnInvoke(
6032 DISPPARAMS *pDispParams,
6033 VARIANT *pVarResult,
6034 EXCEPINFO *pExcepInfo,
6037 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6039 unsigned int var_index;
6042 const TLBFuncDesc *pFuncInfo;
6044 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6045 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6050 ERR("NULL pDispParams not allowed\n");
6051 return E_INVALIDARG;
6054 dump_DispParms(pDispParams);
6056 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6058 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6059 pDispParams->cNamedArgs, pDispParams->cArgs);
6060 return E_INVALIDARG;
6063 /* we do this instead of using GetFuncDesc since it will return a fake
6064 * FUNCDESC for dispinterfaces and we want the real function description */
6065 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6066 if ((memid == pFuncInfo->funcdesc.memid) &&
6067 (wFlags & pFuncInfo->funcdesc.invkind))
6071 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6075 TRACE("invoking:\n");
6076 dump_TLBFuncDescOne(pFuncInfo);
6079 switch (func_desc->funckind) {
6080 case FUNC_PUREVIRTUAL:
6081 case FUNC_VIRTUAL: {
6082 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6084 VARIANT retval; /* pointer for storing byref retvals in */
6085 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6086 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6087 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6088 UINT cNamedArgs = pDispParams->cNamedArgs;
6089 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6090 UINT vargs_converted=0;
6094 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6096 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6098 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6099 hres = DISP_E_PARAMNOTFOUND;
6102 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6104 rgdispidNamedArgs++;
6107 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6109 ERR("functions with the vararg attribute do not support named arguments\n");
6110 hres = DISP_E_NONAMEDARGS;
6114 for (i = 0; i < func_desc->cParams; i++)
6116 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6117 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6122 TRACE("changing args\n");
6123 for (i = 0; i < func_desc->cParams; i++)
6125 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6126 VARIANTARG *src_arg;
6128 if (wParamFlags & PARAMFLAG_FLCID)
6131 arg = prgpvarg[i] = &rgvarg[i];
6133 V_I4(arg) = This->pTypeLib->lcid;
6141 for (j = 0; j < cNamedArgs; j++)
6142 if (rgdispidNamedArgs[j] == i)
6144 src_arg = &pDispParams->rgvarg[j];
6150 src_arg = vargs_converted < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted] : NULL;
6154 if (wParamFlags & PARAMFLAG_FRETVAL)
6156 /* under most conditions the caller is not allowed to
6157 * pass in a dispparam arg in the index of what would be
6158 * the retval parameter. however, there is an exception
6159 * where the extra parameter is used in an extra
6160 * IDispatch::Invoke below */
6161 if ((i < pDispParams->cArgs) &&
6162 ((func_desc->cParams != 1) || !pVarResult ||
6163 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6165 hres = DISP_E_BADPARAMCOUNT;
6169 /* note: this check is placed so that if the caller passes
6170 * in a VARIANTARG for the retval we just ignore it, like
6172 if (i == func_desc->cParams - 1)
6175 arg = prgpvarg[i] = &rgvarg[i];
6176 memset(arg, 0, sizeof(*arg));
6177 V_VT(arg) = rgvt[i];
6178 memset(&retval, 0, sizeof(retval));
6179 V_BYREF(arg) = &retval;
6183 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6184 hres = E_UNEXPECTED;
6190 dump_Variant(src_arg);
6192 if (rgvt[i] == VT_VARIANT)
6193 hres = VariantCopy(&rgvarg[i], src_arg);
6194 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6196 if (rgvt[i] == V_VT(src_arg))
6197 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6200 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6201 hres = VariantCopy(&missing_arg[i], src_arg);
6202 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6204 V_VT(&rgvarg[i]) = rgvt[i];
6206 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6209 SAFEARRAYBOUND bound;
6213 bound.cElements = pDispParams->cArgs-i;
6214 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6216 ERR("SafeArrayCreate failed\n");
6219 hres = SafeArrayAccessData(a, (LPVOID)&v);
6222 ERR("SafeArrayAccessData failed with %x\n", hres);
6225 for (j = 0; j < bound.cElements; j++)
6226 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6227 hres = SafeArrayUnaccessData(a);
6230 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6233 V_ARRAY(&rgvarg[i]) = a;
6234 V_VT(&rgvarg[i]) = rgvt[i];
6236 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6238 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6239 V_VT(&missing_arg[i]) = V_VT(src_arg);
6240 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6241 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6242 V_VT(&rgvarg[i]) = rgvt[i];
6244 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6246 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6247 V_VT(&rgvarg[i]) = rgvt[i];
6251 /* FIXME: this doesn't work for VT_BYREF arguments if
6252 * they are not the same type as in the paramdesc */
6253 V_VT(&rgvarg[i]) = V_VT(src_arg);
6254 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6255 V_VT(&rgvarg[i]) = rgvt[i];
6260 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6261 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6262 debugstr_VT(src_arg), debugstr_VF(src_arg));
6265 prgpvarg[i] = &rgvarg[i];
6267 else if (wParamFlags & PARAMFLAG_FOPT)
6270 arg = prgpvarg[i] = &rgvarg[i];
6271 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6273 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6279 VARIANTARG *missing_arg;
6280 /* if the function wants a pointer to a variant then
6281 * set that up, otherwise just pass the VT_ERROR in
6282 * the argument by value */
6283 if (rgvt[i] & VT_BYREF)
6285 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6286 V_VT(arg) = VT_VARIANT | VT_BYREF;
6287 V_VARIANTREF(arg) = missing_arg;
6291 V_VT(missing_arg) = VT_ERROR;
6292 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6297 hres = DISP_E_BADPARAMCOUNT;
6301 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6303 /* VT_VOID is a special case for return types, so it is not
6304 * handled in the general function */
6305 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6306 V_VT(&varresult) = VT_EMPTY;
6309 V_VT(&varresult) = 0;
6310 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6311 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6314 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6315 V_VT(&varresult), func_desc->cParams, rgvt,
6316 prgpvarg, &varresult);
6318 vargs_converted = 0;
6320 for (i = 0; i < func_desc->cParams; i++)
6322 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6324 if (wParamFlags & PARAMFLAG_FLCID)
6326 else if (wParamFlags & PARAMFLAG_FRETVAL)
6330 TRACE("[retval] value: ");
6331 dump_Variant(prgpvarg[i]);
6336 VariantInit(pVarResult);
6337 /* deref return value */
6338 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6341 /* free data stored in varresult. Note that
6342 * VariantClear doesn't do what we want because we are
6343 * working with byref types. */
6344 /* FIXME: clear safearrays, bstrs, records and
6345 * variants here too */
6346 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6347 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6349 if(*V_UNKNOWNREF(prgpvarg[i]))
6350 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6354 else if (vargs_converted < pDispParams->cArgs)
6356 if (wParamFlags & PARAMFLAG_FOUT)
6358 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6360 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6361 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6365 ERR("failed to convert param %d to vt %d\n", i,
6366 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6370 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6371 func_desc->cParamsOpt < 0 &&
6372 i == func_desc->cParams-1)
6374 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6377 hres = SafeArrayGetUBound(a, 1, &ubound);
6380 ERR("SafeArrayGetUBound failed with %x\n", hres);
6383 hres = SafeArrayAccessData(a, (LPVOID)&v);
6386 ERR("SafeArrayAccessData failed with %x\n", hres);
6389 for (j = 0; j <= ubound; j++)
6390 VariantClear(&v[j]);
6391 hres = SafeArrayUnaccessData(a);
6394 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6398 VariantClear(&rgvarg[i]);
6401 else if (wParamFlags & PARAMFLAG_FOPT)
6403 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6404 VariantClear(&rgvarg[i]);
6408 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6410 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6411 hres = DISP_E_EXCEPTION;
6414 IErrorInfo *pErrorInfo;
6415 pExcepInfo->scode = V_ERROR(&varresult);
6416 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6418 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6419 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6420 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6421 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6423 IErrorInfo_Release(pErrorInfo);
6427 if (V_VT(&varresult) != VT_ERROR)
6429 TRACE("varresult value: ");
6430 dump_Variant(&varresult);
6434 VariantClear(pVarResult);
6435 *pVarResult = varresult;
6438 VariantClear(&varresult);
6441 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6442 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6443 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6444 (pDispParams->cArgs != 0))
6446 if (V_VT(pVarResult) == VT_DISPATCH)
6448 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6449 /* Note: not VariantClear; we still need the dispatch
6450 * pointer to be valid */
6451 VariantInit(pVarResult);
6452 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6453 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6454 pDispParams, pVarResult, pExcepInfo, pArgErr);
6455 IDispatch_Release(pDispatch);
6459 VariantClear(pVarResult);
6460 hres = DISP_E_NOTACOLLECTION;
6465 HeapFree(GetProcessHeap(), 0, buffer);
6468 case FUNC_DISPATCH: {
6471 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6472 if (SUCCEEDED(hres)) {
6473 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6474 hres = IDispatch_Invoke(
6475 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6476 pVarResult,pExcepInfo,pArgErr
6479 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6480 IDispatch_Release(disp);
6482 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6486 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6491 TRACE("-- 0x%08x\n", hres);
6494 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6497 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6498 if(FAILED(hres)) return hres;
6500 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6501 dump_VARDESC(var_desc);
6502 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6506 /* not found, look for it in inherited interfaces */
6507 ITypeInfo2_GetTypeKind(iface, &type_kind);
6508 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6509 if(This->impltypelist) {
6510 /* recursive search */
6512 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6513 if(SUCCEEDED(hres)){
6514 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6515 ITypeInfo_Release(pTInfo);
6518 WARN("Could not search inherited interface!\n");
6521 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6522 return DISP_E_MEMBERNOTFOUND;
6525 /* ITypeInfo::GetDocumentation
6527 * Retrieves the documentation string, the complete Help file name and path,
6528 * and the context ID for the Help topic for a specified type description.
6530 * (Can be tested by the Visual Basic Editor in Word for instance.)
6532 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6533 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6534 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6536 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6537 const TLBFuncDesc *pFDesc;
6538 const TLBVarDesc *pVDesc;
6539 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6540 " HelpContext(%p) HelpFile(%p)\n",
6541 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6542 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6544 *pBstrName=SysAllocString(This->Name);
6546 *pBstrDocString=SysAllocString(This->DocString);
6548 *pdwHelpContext=This->dwHelpContext;
6550 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6552 }else {/* for a member */
6553 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6554 if(pFDesc->funcdesc.memid==memid){
6556 *pBstrName = SysAllocString(pFDesc->Name);
6558 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6560 *pdwHelpContext=pFDesc->helpcontext;
6563 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6564 if(pVDesc->vardesc.memid==memid){
6566 *pBstrName = SysAllocString(pVDesc->Name);
6568 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6570 *pdwHelpContext=pVDesc->HelpContext;
6575 if(This->impltypelist &&
6576 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6577 /* recursive search */
6580 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6582 if(SUCCEEDED(result)) {
6583 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6584 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6585 ITypeInfo_Release(pTInfo);
6588 WARN("Could not search inherited interface!\n");
6591 WARN("member %d not found\n", memid);
6592 return TYPE_E_ELEMENTNOTFOUND;
6595 /* ITypeInfo::GetDllEntry
6597 * Retrieves a description or specification of an entry point for a function
6600 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6601 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6604 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6605 const TLBFuncDesc *pFDesc;
6607 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6609 if (pBstrDllName) *pBstrDllName = NULL;
6610 if (pBstrName) *pBstrName = NULL;
6611 if (pwOrdinal) *pwOrdinal = 0;
6613 if (This->TypeAttr.typekind != TKIND_MODULE)
6614 return TYPE_E_BADMODULEKIND;
6616 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6617 if(pFDesc->funcdesc.memid==memid){
6618 dump_TypeInfo(This);
6620 dump_TLBFuncDescOne(pFDesc);
6623 *pBstrDllName = SysAllocString(This->DllName);
6625 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6627 *pBstrName = SysAllocString(pFDesc->Entry);
6635 *pwOrdinal = (DWORD)pFDesc->Entry;
6638 return TYPE_E_ELEMENTNOTFOUND;
6641 /* internal function to make the inherited interfaces' methods appear
6642 * part of the interface */
6643 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6644 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6646 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6649 TRACE("%p, 0x%x\n", iface, *hRefType);
6651 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6653 ITypeInfo *pSubTypeInfo;
6655 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6659 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6661 ITypeInfo_Release(pSubTypeInfo);
6665 *hRefType -= DISPATCH_HREF_OFFSET;
6667 if (!(*hRefType & DISPATCH_HREF_MASK))
6668 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6673 /* ITypeInfo::GetRefTypeInfo
6675 * If a type description references other type descriptions, it retrieves
6676 * the referenced type descriptions.
6678 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6681 ITypeInfo **ppTInfo)
6683 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6684 HRESULT result = E_FAIL;
6686 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6688 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6689 ITypeInfo_AddRef(*ppTInfo);
6692 else if (hRefType == -1 &&
6693 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6694 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6696 /* when we meet a DUAL dispinterface, we must create the interface
6699 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6702 /* the interface version contains the same information as the dispinterface
6703 * copy the contents of the structs.
6705 *pTypeInfoImpl = *This;
6706 pTypeInfoImpl->ref = 0;
6708 /* change the type to interface */
6709 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6711 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6713 /* we use data structures from This, so we need to keep a reference
6714 * to it to stop it being destroyed and signal to the new instance to
6715 * not free its data structures when it is destroyed */
6716 pTypeInfoImpl->no_free_data = TRUE;
6717 pTypeInfoImpl->next = This;
6718 ITypeInfo_AddRef((ITypeInfo*) This);
6720 ITypeInfo_AddRef(*ppTInfo);
6724 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6725 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6726 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6728 HREFTYPE href_dispatch = hRefType;
6729 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6731 TLBRefType *ref_type;
6732 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6734 if(ref_type->reference == hRefType)
6737 if(&ref_type->entry == &This->pTypeLib->ref_list)
6739 FIXME("Can't find pRefType for ref %x\n", hRefType);
6742 if(hRefType != -1) {
6743 ITypeLib *pTLib = NULL;
6745 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6747 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6749 if(ref_type->pImpTLInfo->pImpTypeLib) {
6750 TRACE("typeinfo in imported typelib that is already loaded\n");
6751 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6752 ITypeLib2_AddRef(pTLib);
6755 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6756 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6757 ref_type->pImpTLInfo->wVersionMajor,
6758 ref_type->pImpTLInfo->wVersionMinor,
6759 ref_type->pImpTLInfo->lcid,
6762 if(FAILED(result)) {
6763 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6764 result=LoadTypeLib(libnam, &pTLib);
6765 SysFreeString(libnam);
6767 if(SUCCEEDED(result)) {
6768 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6769 ITypeLib2_AddRef(pTLib);
6773 if(SUCCEEDED(result)) {
6774 if(ref_type->index == TLB_REF_USE_GUID)
6775 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6779 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6783 ITypeLib2_Release(pTLib);
6788 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6789 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6793 /* ITypeInfo::AddressOfMember
6795 * Retrieves the addresses of static functions or variables, such as those
6798 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6799 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6801 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6807 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6809 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6813 module = LoadLibraryW(dll);
6816 ERR("couldn't load %s\n", debugstr_w(dll));
6818 SysFreeString(entry);
6819 return STG_E_FILENOTFOUND;
6821 /* FIXME: store library somewhere where we can free it */
6826 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6827 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6828 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6830 *ppv = GetProcAddress(module, entryA);
6832 ERR("function not found %s\n", debugstr_a(entryA));
6834 HeapFree(GetProcessHeap(), 0, entryA);
6838 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6840 ERR("function not found %d\n", ordinal);
6844 SysFreeString(entry);
6847 return TYPE_E_DLLFUNCTIONNOTFOUND;
6852 /* ITypeInfo::CreateInstance
6854 * Creates a new instance of a type that describes a component object class
6857 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6858 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6860 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6864 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6870 WARN("Not able to aggregate\n");
6871 return CLASS_E_NOAGGREGATION;
6874 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6875 if(FAILED(hr)) return hr;
6877 if(pTA->typekind != TKIND_COCLASS)
6879 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6885 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6888 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6889 TRACE("GetActiveObject rets %08x\n", hr);
6892 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6893 IUnknown_Release(pUnk);
6898 hr = CoCreateInstance(&pTA->guid, NULL,
6899 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6903 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6907 /* ITypeInfo::GetMops
6909 * Retrieves marshalling information.
6911 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6914 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6915 FIXME("(%p) stub!\n", This);
6919 /* ITypeInfo::GetContainingTypeLib
6921 * Retrieves the containing type library and the index of the type description
6922 * within that type library.
6924 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6925 ITypeLib * *ppTLib, UINT *pIndex)
6927 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6929 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6931 *pIndex=This->index;
6932 TRACE("returning pIndex=%d\n", *pIndex);
6936 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6937 ITypeLib2_AddRef(*ppTLib);
6938 TRACE("returning ppTLib=%p\n", *ppTLib);
6944 /* ITypeInfo::ReleaseTypeAttr
6946 * Releases a TYPEATTR previously returned by GetTypeAttr.
6949 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6950 TYPEATTR* pTypeAttr)
6952 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6953 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6954 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6957 /* ITypeInfo::ReleaseFuncDesc
6959 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6961 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6963 FUNCDESC *pFuncDesc)
6965 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6968 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6970 for (i = 0; i < pFuncDesc->cParams; i++)
6971 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6972 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6974 SysFreeString((BSTR)pFuncDesc);
6977 /* ITypeInfo::ReleaseVarDesc
6979 * Releases a VARDESC previously returned by GetVarDesc.
6981 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6984 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6985 TRACE("(%p)->(%p)\n", This, pVarDesc);
6987 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6988 if (pVarDesc->varkind == VAR_CONST)
6989 VariantClear(pVarDesc->u.lpvarValue);
6990 SysFreeString((BSTR)pVarDesc);
6993 /* ITypeInfo2::GetTypeKind
6995 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6998 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6999 TYPEKIND *pTypeKind)
7001 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7002 *pTypeKind=This->TypeAttr.typekind;
7003 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7007 /* ITypeInfo2::GetTypeFlags
7009 * Returns the type flags without any allocations. This returns a DWORD type
7010 * flag, which expands the type flags without growing the TYPEATTR (type
7014 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7016 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7017 *pTypeFlags=This->TypeAttr.wTypeFlags;
7018 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7022 /* ITypeInfo2::GetFuncIndexOfMemId
7023 * Binds to a specific member based on a known DISPID, where the member name
7024 * is not known (for example, when binding to a default member).
7027 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7028 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7030 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7031 const TLBFuncDesc *pFuncInfo;
7035 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7036 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7042 result = TYPE_E_ELEMENTNOTFOUND;
7044 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7045 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7049 /* TypeInfo2::GetVarIndexOfMemId
7051 * Binds to a specific member based on a known DISPID, where the member name
7052 * is not known (for example, when binding to a default member).
7055 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7056 MEMBERID memid, UINT *pVarIndex)
7058 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7059 TLBVarDesc *pVarInfo;
7062 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7063 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7069 result = TYPE_E_ELEMENTNOTFOUND;
7071 TRACE("(%p) memid 0x%08x -> %s\n", This,
7072 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7076 /* ITypeInfo2::GetCustData
7078 * Gets the custom data
7080 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7085 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7086 TLBCustData *pCData;
7088 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7089 if( IsEqualIID(guid, &pCData->guid)) break;
7091 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7093 VariantInit( pVarVal);
7095 VariantCopy( pVarVal, &pCData->data);
7097 VariantClear( pVarVal );
7101 /* ITypeInfo2::GetFuncCustData
7103 * Gets the custom data
7105 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7111 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7112 TLBCustData *pCData=NULL;
7113 TLBFuncDesc * pFDesc;
7115 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7116 pFDesc=pFDesc->next);
7119 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7120 if( IsEqualIID(guid, &pCData->guid)) break;
7122 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7125 VariantInit( pVarVal);
7126 VariantCopy( pVarVal, &pCData->data);
7129 return E_INVALIDARG; /* FIXME: correct? */
7132 /* ITypeInfo2::GetParamCustData
7134 * Gets the custom data
7136 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7143 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7144 TLBCustData *pCData=NULL;
7145 TLBFuncDesc * pFDesc;
7148 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7150 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7151 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7152 pCData = pCData->next)
7153 if( IsEqualIID(guid, &pCData->guid)) break;
7155 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7159 VariantInit( pVarVal);
7160 VariantCopy( pVarVal, &pCData->data);
7163 return E_INVALIDARG; /* FIXME: correct? */
7166 /* ITypeInfo2::GetVarCustData
7168 * Gets the custom data
7170 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7176 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7177 TLBCustData *pCData=NULL;
7178 TLBVarDesc * pVDesc;
7181 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7185 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7187 if( IsEqualIID(guid, &pCData->guid)) break;
7191 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7195 VariantInit( pVarVal);
7196 VariantCopy( pVarVal, &pCData->data);
7199 return E_INVALIDARG; /* FIXME: correct? */
7202 /* ITypeInfo2::GetImplCustData
7204 * Gets the custom data
7206 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7212 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7213 TLBCustData *pCData=NULL;
7214 TLBImplType * pRDesc;
7217 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7221 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7223 if( IsEqualIID(guid, &pCData->guid)) break;
7227 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7231 VariantInit( pVarVal);
7232 VariantCopy( pVarVal, &pCData->data);
7235 return E_INVALIDARG; /* FIXME: correct? */
7238 /* ITypeInfo2::GetDocumentation2
7240 * Retrieves the documentation string, the complete Help file name and path,
7241 * the localization context to use, and the context ID for the library Help
7242 * topic in the Help file.
7245 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7249 BSTR *pbstrHelpString,
7250 DWORD *pdwHelpStringContext,
7251 BSTR *pbstrHelpStringDll)
7253 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7254 const TLBFuncDesc *pFDesc;
7255 const TLBVarDesc *pVDesc;
7256 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7257 "HelpStringContext(%p) HelpStringDll(%p)\n",
7258 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7259 pbstrHelpStringDll );
7260 /* the help string should be obtained from the helpstringdll,
7261 * using the _DLLGetDocumentation function, based on the supplied
7262 * lcid. Nice to do sometime...
7264 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7266 *pbstrHelpString=SysAllocString(This->Name);
7267 if(pdwHelpStringContext)
7268 *pdwHelpStringContext=This->dwHelpStringContext;
7269 if(pbstrHelpStringDll)
7270 *pbstrHelpStringDll=
7271 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7273 }else {/* for a member */
7274 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7275 if(pFDesc->funcdesc.memid==memid){
7277 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7278 if(pdwHelpStringContext)
7279 *pdwHelpStringContext=pFDesc->HelpStringContext;
7280 if(pbstrHelpStringDll)
7281 *pbstrHelpStringDll=
7282 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7285 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7286 if(pVDesc->vardesc.memid==memid){
7288 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7289 if(pdwHelpStringContext)
7290 *pdwHelpStringContext=pVDesc->HelpStringContext;
7291 if(pbstrHelpStringDll)
7292 *pbstrHelpStringDll=
7293 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7297 return TYPE_E_ELEMENTNOTFOUND;
7300 /* ITypeInfo2::GetAllCustData
7302 * Gets all custom data items for the Type info.
7305 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7307 CUSTDATA *pCustData)
7309 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7310 TLBCustData *pCData;
7313 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7315 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7316 if(pCustData->prgCustData ){
7317 pCustData->cCustData=This->ctCustData;
7318 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7319 pCustData->prgCustData[i].guid=pCData->guid;
7320 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7323 ERR(" OUT OF MEMORY!\n");
7324 return E_OUTOFMEMORY;
7329 /* ITypeInfo2::GetAllFuncCustData
7331 * Gets all custom data items for the specified Function
7334 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7337 CUSTDATA *pCustData)
7339 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7340 TLBCustData *pCData;
7341 TLBFuncDesc * pFDesc;
7343 TRACE("(%p) index %d\n", This, index);
7344 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7345 pFDesc=pFDesc->next)
7348 pCustData->prgCustData =
7349 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7350 if(pCustData->prgCustData ){
7351 pCustData->cCustData=pFDesc->ctCustData;
7352 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7353 pCData = pCData->next){
7354 pCustData->prgCustData[i].guid=pCData->guid;
7355 VariantCopy(& pCustData->prgCustData[i].varValue,
7359 ERR(" OUT OF MEMORY!\n");
7360 return E_OUTOFMEMORY;
7364 return TYPE_E_ELEMENTNOTFOUND;
7367 /* ITypeInfo2::GetAllParamCustData
7369 * Gets all custom data items for the Functions
7372 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7373 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7375 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7376 TLBCustData *pCData=NULL;
7377 TLBFuncDesc * pFDesc;
7379 TRACE("(%p) index %d\n", This, indexFunc);
7380 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7381 pFDesc=pFDesc->next)
7383 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7384 pCustData->prgCustData =
7385 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7386 sizeof(CUSTDATAITEM));
7387 if(pCustData->prgCustData ){
7388 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7389 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7390 pCData; i++, pCData = pCData->next){
7391 pCustData->prgCustData[i].guid=pCData->guid;
7392 VariantCopy(& pCustData->prgCustData[i].varValue,
7396 ERR(" OUT OF MEMORY!\n");
7397 return E_OUTOFMEMORY;
7401 return TYPE_E_ELEMENTNOTFOUND;
7404 /* ITypeInfo2::GetAllVarCustData
7406 * Gets all custom data items for the specified Variable
7409 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7410 UINT index, CUSTDATA *pCustData)
7412 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7413 TLBCustData *pCData;
7414 TLBVarDesc * pVDesc;
7416 TRACE("(%p) index %d\n", This, index);
7417 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7418 pVDesc=pVDesc->next)
7421 pCustData->prgCustData =
7422 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7423 if(pCustData->prgCustData ){
7424 pCustData->cCustData=pVDesc->ctCustData;
7425 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7426 pCData = pCData->next){
7427 pCustData->prgCustData[i].guid=pCData->guid;
7428 VariantCopy(& pCustData->prgCustData[i].varValue,
7432 ERR(" OUT OF MEMORY!\n");
7433 return E_OUTOFMEMORY;
7437 return TYPE_E_ELEMENTNOTFOUND;
7440 /* ITypeInfo2::GetAllImplCustData
7442 * Gets all custom data items for the specified implementation type
7445 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7448 CUSTDATA *pCustData)
7450 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7451 TLBCustData *pCData;
7452 TLBImplType * pRDesc;
7454 TRACE("(%p) index %d\n", This, index);
7455 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7456 pRDesc=pRDesc->next)
7459 pCustData->prgCustData =
7460 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7461 if(pCustData->prgCustData ){
7462 pCustData->cCustData=pRDesc->ctCustData;
7463 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7464 pCData = pCData->next){
7465 pCustData->prgCustData[i].guid=pCData->guid;
7466 VariantCopy(& pCustData->prgCustData[i].varValue,
7470 ERR(" OUT OF MEMORY!\n");
7471 return E_OUTOFMEMORY;
7475 return TYPE_E_ELEMENTNOTFOUND;
7478 static const ITypeInfo2Vtbl tinfvt =
7481 ITypeInfo_fnQueryInterface,
7483 ITypeInfo_fnRelease,
7485 ITypeInfo_fnGetTypeAttr,
7486 ITypeInfo_fnGetTypeComp,
7487 ITypeInfo_fnGetFuncDesc,
7488 ITypeInfo_fnGetVarDesc,
7489 ITypeInfo_fnGetNames,
7490 ITypeInfo_fnGetRefTypeOfImplType,
7491 ITypeInfo_fnGetImplTypeFlags,
7492 ITypeInfo_fnGetIDsOfNames,
7494 ITypeInfo_fnGetDocumentation,
7495 ITypeInfo_fnGetDllEntry,
7496 ITypeInfo_fnGetRefTypeInfo,
7497 ITypeInfo_fnAddressOfMember,
7498 ITypeInfo_fnCreateInstance,
7499 ITypeInfo_fnGetMops,
7500 ITypeInfo_fnGetContainingTypeLib,
7501 ITypeInfo_fnReleaseTypeAttr,
7502 ITypeInfo_fnReleaseFuncDesc,
7503 ITypeInfo_fnReleaseVarDesc,
7505 ITypeInfo2_fnGetTypeKind,
7506 ITypeInfo2_fnGetTypeFlags,
7507 ITypeInfo2_fnGetFuncIndexOfMemId,
7508 ITypeInfo2_fnGetVarIndexOfMemId,
7509 ITypeInfo2_fnGetCustData,
7510 ITypeInfo2_fnGetFuncCustData,
7511 ITypeInfo2_fnGetParamCustData,
7512 ITypeInfo2_fnGetVarCustData,
7513 ITypeInfo2_fnGetImplTypeCustData,
7514 ITypeInfo2_fnGetDocumentation2,
7515 ITypeInfo2_fnGetAllCustData,
7516 ITypeInfo2_fnGetAllFuncCustData,
7517 ITypeInfo2_fnGetAllParamCustData,
7518 ITypeInfo2_fnGetAllVarCustData,
7519 ITypeInfo2_fnGetAllImplTypeCustData,
7522 /******************************************************************************
7523 * CreateDispTypeInfo [OLEAUT32.31]
7525 * Build type information for an object so it can be called through an
7526 * IDispatch interface.
7529 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7530 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7533 * This call allows an objects methods to be accessed through IDispatch, by
7534 * building an ITypeInfo object that IDispatch can use to call through.
7536 HRESULT WINAPI CreateDispTypeInfo(
7537 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7538 LCID lcid, /* [I] Locale Id */
7539 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7541 ITypeInfoImpl *pTIClass, *pTIIface;
7542 ITypeLibImpl *pTypeLibImpl;
7543 unsigned int param, func;
7544 TLBFuncDesc **ppFuncDesc;
7548 pTypeLibImpl = TypeLibImpl_Constructor();
7549 if (!pTypeLibImpl) return E_FAIL;
7551 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7552 pTIIface->pTypeLib = pTypeLibImpl;
7553 pTIIface->index = 0;
7554 pTIIface->Name = NULL;
7555 pTIIface->dwHelpContext = -1;
7556 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7557 pTIIface->TypeAttr.lcid = lcid;
7558 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7559 pTIIface->TypeAttr.wMajorVerNum = 0;
7560 pTIIface->TypeAttr.wMinorVerNum = 0;
7561 pTIIface->TypeAttr.cbAlignment = 2;
7562 pTIIface->TypeAttr.cbSizeInstance = -1;
7563 pTIIface->TypeAttr.cbSizeVft = -1;
7564 pTIIface->TypeAttr.cFuncs = 0;
7565 pTIIface->TypeAttr.cImplTypes = 0;
7566 pTIIface->TypeAttr.cVars = 0;
7567 pTIIface->TypeAttr.wTypeFlags = 0;
7569 ppFuncDesc = &pTIIface->funclist;
7570 for(func = 0; func < pidata->cMembers; func++) {
7571 METHODDATA *md = pidata->pmethdata + func;
7572 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7573 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7574 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7575 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7576 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7577 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7578 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7579 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7580 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7581 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7582 (*ppFuncDesc)->funcdesc.cScodes = 0;
7583 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7584 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7585 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7586 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7587 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7588 md->cArgs * sizeof(ELEMDESC));
7589 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7590 md->cArgs * sizeof(TLBParDesc));
7591 for(param = 0; param < md->cArgs; param++) {
7592 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7593 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7595 (*ppFuncDesc)->helpcontext = 0;
7596 (*ppFuncDesc)->HelpStringContext = 0;
7597 (*ppFuncDesc)->HelpString = NULL;
7598 (*ppFuncDesc)->Entry = NULL;
7599 (*ppFuncDesc)->ctCustData = 0;
7600 (*ppFuncDesc)->pCustData = NULL;
7601 (*ppFuncDesc)->next = NULL;
7602 pTIIface->TypeAttr.cFuncs++;
7603 ppFuncDesc = &(*ppFuncDesc)->next;
7606 dump_TypeInfo(pTIIface);
7608 pTypeLibImpl->pTypeInfo = pTIIface;
7609 pTypeLibImpl->TypeInfoCount++;
7611 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7612 pTIClass->pTypeLib = pTypeLibImpl;
7613 pTIClass->index = 1;
7614 pTIClass->Name = NULL;
7615 pTIClass->dwHelpContext = -1;
7616 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7617 pTIClass->TypeAttr.lcid = lcid;
7618 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7619 pTIClass->TypeAttr.wMajorVerNum = 0;
7620 pTIClass->TypeAttr.wMinorVerNum = 0;
7621 pTIClass->TypeAttr.cbAlignment = 2;
7622 pTIClass->TypeAttr.cbSizeInstance = -1;
7623 pTIClass->TypeAttr.cbSizeVft = -1;
7624 pTIClass->TypeAttr.cFuncs = 0;
7625 pTIClass->TypeAttr.cImplTypes = 1;
7626 pTIClass->TypeAttr.cVars = 0;
7627 pTIClass->TypeAttr.wTypeFlags = 0;
7629 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7630 pTIClass->impltypelist->hRef = 0;
7632 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7635 ref->pImpTLInfo = TLB_REF_INTERNAL;
7636 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7638 dump_TypeInfo(pTIClass);
7640 pTIIface->next = pTIClass;
7641 pTypeLibImpl->TypeInfoCount++;
7643 *pptinfo = (ITypeInfo*)pTIClass;
7645 ITypeInfo_AddRef(*pptinfo);
7646 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7652 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7654 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7656 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7659 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7661 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7663 return ITypeInfo_AddRef((ITypeInfo *)This);
7666 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7668 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7670 return ITypeInfo_Release((ITypeInfo *)This);
7673 static HRESULT WINAPI ITypeComp_fnBind(
7678 ITypeInfo ** ppTInfo,
7679 DESCKIND * pDescKind,
7682 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7683 const TLBFuncDesc *pFDesc;
7684 const TLBVarDesc *pVDesc;
7685 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7687 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7689 *pDescKind = DESCKIND_NONE;
7690 pBindPtr->lpfuncdesc = NULL;
7693 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7694 if (!strcmpiW(pFDesc->Name, szName)) {
7695 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7698 /* name found, but wrong flags */
7699 hr = TYPE_E_TYPEMISMATCH;
7704 HRESULT hr = TLB_AllocAndInitFuncDesc(
7706 &pBindPtr->lpfuncdesc,
7707 This->TypeAttr.typekind == TKIND_DISPATCH);
7710 *pDescKind = DESCKIND_FUNCDESC;
7711 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7712 ITypeInfo_AddRef(*ppTInfo);
7715 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7716 if (!strcmpiW(pVDesc->Name, szName)) {
7717 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7720 *pDescKind = DESCKIND_VARDESC;
7721 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7722 ITypeInfo_AddRef(*ppTInfo);
7727 /* FIXME: search each inherited interface, not just the first */
7728 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7729 /* recursive search */
7733 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7736 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7737 ITypeInfo_Release(pTInfo);
7741 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7742 ITypeComp_Release(pTComp);
7745 WARN("Could not search inherited interface!\n");
7747 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7751 static HRESULT WINAPI ITypeComp_fnBindType(
7755 ITypeInfo ** ppTInfo,
7756 ITypeComp ** ppTComp)
7758 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7760 /* strange behaviour (does nothing) but like the
7763 if (!ppTInfo || !ppTComp)
7772 static const ITypeCompVtbl tcompvt =
7775 ITypeComp_fnQueryInterface,
7777 ITypeComp_fnRelease,
7780 ITypeComp_fnBindType