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 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
287 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
288 SYSKIND syskind, LCID lcid, LPBSTR path )
290 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
294 WCHAR Path[MAX_PATH];
297 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
299 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
300 get_typelib_key( guid, wMaj, wMin, buffer );
302 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
303 if (res == ERROR_FILE_NOT_FOUND)
305 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
306 return TYPE_E_LIBNOTREGISTERED;
308 else if (res != ERROR_SUCCESS)
310 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
311 return TYPE_E_REGISTRYACCESS;
316 LONG dwPathLen = sizeof(Path);
318 get_lcid_subkey( myLCID, syskind, buffer );
320 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
324 else if (myLCID == lcid)
326 /* try with sub-langid */
327 myLCID = SUBLANGID(lcid);
329 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
331 /* try with system langid */
341 *path = SysAllocString( Path );
346 TRACE_(typelib)("-- 0x%08x\n", hr);
350 /****************************************************************************
351 * QueryPathOfRegTypeLib [OLEAUT32.164]
353 * Gets the path to a registered type library.
356 * guid [I] referenced guid
357 * wMaj [I] major version
358 * wMin [I] minor version
360 * path [O] path of typelib
364 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
365 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
368 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
370 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
373 /******************************************************************************
374 * CreateTypeLib [OLEAUT32.160] creates a typelib
380 HRESULT WINAPI CreateTypeLib(
381 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
383 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
387 /******************************************************************************
388 * LoadTypeLib [OLEAUT32.161]
390 * Loads a type library
393 * szFile [I] Name of file to load from.
394 * pptLib [O] Pointer that receives ITypeLib object on success.
401 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
403 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
405 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
406 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
409 /******************************************************************************
410 * LoadTypeLibEx [OLEAUT32.183]
412 * Loads and optionally registers a type library
418 HRESULT WINAPI LoadTypeLibEx(
419 LPCOLESTR szFile, /* [in] Name of file to load from */
420 REGKIND regkind, /* [in] Specify kind of registration */
421 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
423 WCHAR szPath[MAX_PATH+1];
426 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
430 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
435 case REGKIND_DEFAULT:
436 /* don't register typelibs supplied with full path. Experimentation confirms the following */
437 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
438 (szFile[0] && (szFile[1] == ':'))) break;
439 /* else fall-through */
441 case REGKIND_REGISTER:
442 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
444 IUnknown_Release(*pptLib);
452 TRACE(" returns %08x\n",res);
456 /******************************************************************************
457 * LoadRegTypeLib [OLEAUT32.162]
459 * Loads a registered type library.
462 * rguid [I] GUID of the registered type library.
463 * wVerMajor [I] major version.
464 * wVerMinor [I] minor version.
465 * lcid [I] locale ID.
466 * ppTLib [O] pointer that receives an ITypeLib object on success.
470 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
473 HRESULT WINAPI LoadRegTypeLib(
485 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
489 res= LoadTypeLib(bstr, ppTLib);
493 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
499 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
500 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
501 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
502 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
503 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
504 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
506 /******************************************************************************
507 * RegisterTypeLib [OLEAUT32.163]
508 * Adds information about a type library to the System Registry
510 * Docs: ITypeLib FAR * ptlib
511 * Docs: OLECHAR FAR* szFullPath
512 * Docs: OLECHAR FAR* szHelpDir
518 HRESULT WINAPI RegisterTypeLib(
519 ITypeLib * ptlib, /* [in] Pointer to the library*/
520 OLECHAR * szFullPath, /* [in] full Path of the library*/
521 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
524 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
525 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
526 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
536 if (ptlib == NULL || szFullPath == NULL)
539 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
543 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
545 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
548 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
551 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
552 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
556 /* Set the human-readable name of the typelib */
557 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
561 if (RegSetValueExW(key, NULL, 0, REG_SZ,
562 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
568 /* Make up the name of the typelib path subkey */
569 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
571 /* Create the typelib path subkey */
572 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
573 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
575 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
576 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
584 /* Create the flags subkey */
585 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
586 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
588 /* FIXME: is %u correct? */
589 static const WCHAR formatW[] = {'%','u',0};
591 sprintfW(buf, formatW, attr->wLibFlags);
592 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
593 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
601 /* create the helpdir subkey */
602 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
603 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
605 BOOL freeHelpDir = FALSE;
608 /* if we created a new key, and helpDir was null, set the helpdir
609 to the directory which contains the typelib. However,
610 if we just opened an existing key, we leave the helpdir alone */
611 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
612 szHelpDir = SysAllocString(szFullPath);
613 pIndexStr = strrchrW(szHelpDir, '\\');
620 /* if we have an szHelpDir, set it! */
621 if (szHelpDir != NULL) {
622 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
623 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
629 if (freeHelpDir) SysFreeString(szHelpDir);
641 /* register OLE Automation-compatible interfaces for this typelib */
642 types = ITypeLib_GetTypeInfoCount(ptlib);
643 for (tidx=0; tidx<types; tidx++) {
644 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
645 LPOLESTR name = NULL;
646 ITypeInfo *tinfo = NULL;
648 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
651 case TKIND_INTERFACE:
652 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
653 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
657 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
658 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
662 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
667 TYPEATTR *tattr = NULL;
668 ITypeInfo_GetTypeAttr(tinfo, &tattr);
671 TRACE_(typelib)("guid=%s, flags=%04x (",
672 debugstr_guid(&tattr->guid),
675 if (TRACE_ON(typelib)) {
676 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
696 /* Register all dispinterfaces (which includes dual interfaces) and
697 oleautomation interfaces */
698 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
699 kind == TKIND_DISPATCH)
701 /* register interface<->typelib coupling */
702 get_interface_key( &tattr->guid, keyName );
703 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
704 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
707 RegSetValueExW(key, NULL, 0, REG_SZ,
708 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
710 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
711 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
712 RegSetValueExW(subKey, NULL, 0, REG_SZ,
713 (const BYTE *)PSOA, sizeof PSOA);
717 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
718 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
719 RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (const BYTE *)PSOA, sizeof PSOA);
724 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
725 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
728 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
729 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
731 StringFromGUID2(&attr->guid, buffer, 40);
732 RegSetValueExW(subKey, NULL, 0, REG_SZ,
733 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
734 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
735 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
736 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
744 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
747 ITypeInfo_Release(tinfo);
754 ITypeLib_ReleaseTLibAttr(ptlib, attr);
760 /******************************************************************************
761 * UnRegisterTypeLib [OLEAUT32.186]
762 * Removes information about a type library from the System Registry
769 HRESULT WINAPI UnRegisterTypeLib(
770 REFGUID libid, /* [in] Guid of the library */
771 WORD wVerMajor, /* [in] major version */
772 WORD wVerMinor, /* [in] minor version */
773 LCID lcid, /* [in] locale id */
776 BSTR tlibPath = NULL;
779 WCHAR subKeyName[50];
782 BOOL deleteOtherStuff;
785 TYPEATTR* typeAttr = NULL;
787 ITypeInfo* typeInfo = NULL;
788 ITypeLib* typeLib = NULL;
791 TRACE("(IID: %s)\n",debugstr_guid(libid));
793 /* Create the path to the key */
794 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
796 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
798 TRACE("Unsupported syskind %i\n", syskind);
799 result = E_INVALIDARG;
803 /* get the path to the typelib on disk */
804 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
805 result = E_INVALIDARG;
809 /* Try and open the key to the type library. */
810 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
811 result = E_INVALIDARG;
815 /* Try and load the type library */
816 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
817 result = TYPE_E_INVALIDSTATE;
821 /* remove any types registered with this typelib */
822 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
823 for (i=0; i<numTypes; i++) {
824 /* get the kind of type */
825 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
829 /* skip non-interfaces, and get type info for the type */
830 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
833 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
836 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
840 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
841 kind == TKIND_DISPATCH)
843 /* the path to the type */
844 get_interface_key( &typeAttr->guid, subKeyName );
846 /* Delete its bits */
847 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
850 RegDeleteKeyW(subKey, ProxyStubClsidW);
851 RegDeleteKeyW(subKey, ProxyStubClsid32W);
852 RegDeleteKeyW(subKey, TypeLibW);
855 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
859 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
861 if (typeInfo) ITypeInfo_Release(typeInfo);
865 /* Now, delete the type library path subkey */
866 get_lcid_subkey( lcid, syskind, subKeyName );
867 RegDeleteKeyW(key, subKeyName);
868 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
869 RegDeleteKeyW(key, subKeyName);
871 /* check if there is anything besides the FLAGS/HELPDIR keys.
872 If there is, we don't delete them */
873 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
874 deleteOtherStuff = TRUE;
876 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
877 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
879 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
880 if (!strcmpW(subKeyName, FLAGSW)) continue;
881 if (!strcmpW(subKeyName, HELPDIRW)) continue;
882 deleteOtherStuff = FALSE;
886 /* only delete the other parts of the key if we're absolutely sure */
887 if (deleteOtherStuff) {
888 RegDeleteKeyW(key, FLAGSW);
889 RegDeleteKeyW(key, HELPDIRW);
893 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
894 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
895 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
899 SysFreeString(tlibPath);
900 if (typeLib) ITypeLib_Release(typeLib);
901 if (subKey) RegCloseKey(subKey);
902 if (key) RegCloseKey(key);
906 /******************************************************************************
907 * RegisterTypeLibForUser [OLEAUT32.442]
908 * Adds information about a type library to the user registry
910 * Docs: ITypeLib FAR * ptlib
911 * Docs: OLECHAR FAR* szFullPath
912 * Docs: OLECHAR FAR* szHelpDir
918 HRESULT WINAPI RegisterTypeLibForUser(
919 ITypeLib * ptlib, /* [in] Pointer to the library*/
920 OLECHAR * szFullPath, /* [in] full Path of the library*/
921 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
924 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib,
925 debugstr_w(szFullPath), debugstr_w(szHelpDir));
926 return RegisterTypeLib(ptlib, szFullPath, szHelpDir);
929 /******************************************************************************
930 * UnRegisterTypeLibForUser [OLEAUT32.443]
931 * Removes information about a type library from the user registry
937 HRESULT WINAPI UnRegisterTypeLibForUser(
938 REFGUID libid, /* [in] GUID of the library */
939 WORD wVerMajor, /* [in] major version */
940 WORD wVerMinor, /* [in] minor version */
941 LCID lcid, /* [in] locale id */
944 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
945 debugstr_guid(libid), wVerMajor, wVerMinor, lcid, syskind);
946 return UnRegisterTypeLib(libid, wVerMajor, wVerMinor, lcid, syskind);
949 /*======================= ITypeLib implementation =======================*/
951 typedef struct tagTLBCustData
955 struct tagTLBCustData* next;
958 /* data structure for import typelibs */
959 typedef struct tagTLBImpLib
961 int offset; /* offset in the file (MSFT)
962 offset in nametable (SLTG)
963 just used to identify library while reading
965 GUID guid; /* libid */
966 BSTR name; /* name */
968 LCID lcid; /* lcid of imported typelib */
970 WORD wVersionMajor; /* major version number */
971 WORD wVersionMinor; /* minor version number */
973 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
974 NULL if not yet loaded */
975 struct tagTLBImpLib * next;
978 /* internal ITypeLib data */
979 typedef struct tagITypeLibImpl
981 const ITypeLib2Vtbl *lpVtbl;
982 const ITypeCompVtbl *lpVtblTypeComp;
984 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
987 /* strings can be stored in tlb as multibyte strings BUT they are *always*
988 * exported to the application as a UNICODE string.
995 int TypeInfoCount; /* nr of typeinfo's in librarry */
996 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
997 int ctCustData; /* number of items in cust data list */
998 TLBCustData * pCustData; /* linked list to cust data */
999 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
1000 int ctTypeDesc; /* number of items in type desc array */
1001 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
1002 library. Only used while reading MSFT
1004 struct list ref_list; /* list of ref types in this typelib */
1005 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
1008 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1009 struct tagITypeLibImpl *next, *prev;
1014 static const ITypeLib2Vtbl tlbvt;
1015 static const ITypeCompVtbl tlbtcvt;
1017 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
1019 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
1022 /* ITypeLib methods */
1023 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
1024 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
1026 /*======================= ITypeInfo implementation =======================*/
1028 /* data for referenced types */
1029 typedef struct tagTLBRefType
1031 INT index; /* Type index for internal ref or for external ref
1032 it the format is SLTG. -2 indicates to
1035 GUID guid; /* guid of the referenced type */
1036 /* if index == TLB_REF_USE_GUID */
1038 HREFTYPE reference; /* The href of this ref */
1039 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
1040 TLB_REF_INTERNAL for internal refs
1041 TLB_REF_NOT_FOUND for broken refs */
1046 #define TLB_REF_USE_GUID -2
1048 #define TLB_REF_INTERNAL (void*)-2
1049 #define TLB_REF_NOT_FOUND (void*)-1
1051 /* internal Parameter data */
1052 typedef struct tagTLBParDesc
1056 TLBCustData * pCustData; /* linked list to cust data */
1059 /* internal Function data */
1060 typedef struct tagTLBFuncDesc
1062 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1063 BSTR Name; /* the name of this function */
1064 TLBParDesc *pParamDesc; /* array with param names and custom data */
1066 int HelpStringContext;
1068 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1070 TLBCustData * pCustData; /* linked list to cust data; */
1071 struct tagTLBFuncDesc * next;
1074 /* internal Variable data */
1075 typedef struct tagTLBVarDesc
1077 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1078 BSTR Name; /* the name of this variable */
1080 int HelpStringContext; /* FIXME: where? */
1083 TLBCustData * pCustData;/* linked list to cust data; */
1084 struct tagTLBVarDesc * next;
1087 /* internal implemented interface data */
1088 typedef struct tagTLBImplType
1090 HREFTYPE hRef; /* hRef of interface */
1091 int implflags; /* IMPLFLAG_*s */
1093 TLBCustData * pCustData;/* linked list to custom data; */
1094 struct tagTLBImplType *next;
1097 /* internal TypeInfo data */
1098 typedef struct tagITypeInfoImpl
1100 const ITypeInfo2Vtbl *lpVtbl;
1101 const ITypeCompVtbl *lpVtblTypeComp;
1103 BOOL not_attached_to_typelib;
1104 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1105 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1106 int index; /* index in this typelib; */
1107 HREFTYPE hreftype; /* hreftype for app object binding */
1108 /* type libs seem to store the doc strings in ascii
1109 * so why should we do it in unicode?
1114 DWORD dwHelpContext;
1115 DWORD dwHelpStringContext;
1118 TLBFuncDesc * funclist; /* linked list with function descriptions */
1121 TLBVarDesc * varlist; /* linked list with variable descriptions */
1123 /* Implemented Interfaces */
1124 TLBImplType * impltypelist;
1127 TLBCustData * pCustData; /* linked list to cust data; */
1128 struct tagITypeInfoImpl * next;
1131 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1133 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1136 static const ITypeInfo2Vtbl tinfvt;
1137 static const ITypeCompVtbl tcompvt;
1139 static ITypeInfo2 * ITypeInfo_Constructor(void);
1140 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This);
1142 typedef struct tagTLBContext
1144 unsigned int oStart; /* start of TLB in file */
1145 unsigned int pos; /* current pos */
1146 unsigned int length; /* total length */
1147 void *mapping; /* memory mapping */
1148 MSFT_SegDir * pTblDir;
1149 ITypeLibImpl* pLibInfo;
1153 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1158 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1159 if (pTD->vt & VT_RESERVED)
1160 szVarType += strlen(strcpy(szVarType, "reserved | "));
1161 if (pTD->vt & VT_BYREF)
1162 szVarType += strlen(strcpy(szVarType, "ref to "));
1163 if (pTD->vt & VT_ARRAY)
1164 szVarType += strlen(strcpy(szVarType, "array of "));
1165 if (pTD->vt & VT_VECTOR)
1166 szVarType += strlen(strcpy(szVarType, "vector of "));
1167 switch(pTD->vt & VT_TYPEMASK) {
1168 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1169 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1170 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1171 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1172 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1173 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1174 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1175 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1176 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1177 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1178 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1179 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1180 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1181 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1182 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1183 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1184 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1185 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1186 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1187 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1188 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1189 pTD->u.hreftype); break;
1190 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1191 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1192 case VT_PTR: sprintf(szVarType, "ptr to ");
1193 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1195 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1196 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1198 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1199 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1200 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1203 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1207 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1209 USHORT flags = edesc->u.paramdesc.wParamFlags;
1210 dump_TypeDesc(&edesc->tdesc,buf);
1211 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1212 MESSAGE("\t\tu.paramdesc.wParamFlags");
1213 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1214 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1215 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1216 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1217 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1218 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1219 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1220 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1221 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1223 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1225 MESSAGE("memid is %08x\n",funcdesc->memid);
1226 for (i=0;i<funcdesc->cParams;i++) {
1227 MESSAGE("Param %d:\n",i);
1228 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1230 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1231 switch (funcdesc->funckind) {
1232 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1233 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1234 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1235 case FUNC_STATIC: MESSAGE("static");break;
1236 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1237 default: MESSAGE("unknown");break;
1239 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1240 switch (funcdesc->invkind) {
1241 case INVOKE_FUNC: MESSAGE("func");break;
1242 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1243 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1244 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1246 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1247 switch (funcdesc->callconv) {
1248 case CC_CDECL: MESSAGE("cdecl");break;
1249 case CC_PASCAL: MESSAGE("pascal");break;
1250 case CC_STDCALL: MESSAGE("stdcall");break;
1251 case CC_SYSCALL: MESSAGE("syscall");break;
1254 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1255 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1256 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1258 MESSAGE("\telemdescFunc (return value type):\n");
1259 dump_ELEMDESC(&funcdesc->elemdescFunc);
1262 static const char * const typekind_desc[] =
1275 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1278 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1279 for (i=0;i<pfd->funcdesc.cParams;i++)
1280 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1283 dump_FUNCDESC(&(pfd->funcdesc));
1285 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1286 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1288 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1292 dump_TLBFuncDescOne(pfd);
1296 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1300 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1305 static void dump_TLBImpLib(const TLBImpLib *import)
1307 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1308 debugstr_w(import->name));
1309 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1310 import->wVersionMinor, import->lcid, import->offset);
1313 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1317 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1319 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1320 if(ref->index == -1)
1321 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1323 TRACE_(typelib)("type no: %d\n", ref->index);
1325 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1327 TRACE_(typelib)("in lib\n");
1328 dump_TLBImpLib(ref->pImpTLInfo);
1333 static void dump_TLBImplType(const TLBImplType * impl)
1337 "implementing/inheriting interface hRef = %x implflags %x\n",
1338 impl->hRef, impl->implflags);
1343 static void dump_Variant(const VARIANT * pvar)
1347 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1351 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1352 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1354 TRACE(",%p", V_BYREF(pvar));
1356 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1358 TRACE(",%p", V_ARRAY(pvar));
1360 else switch (V_TYPE(pvar))
1362 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1363 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1364 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1365 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1367 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1369 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1370 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1371 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1372 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1373 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1374 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1375 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1376 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1377 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1378 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1379 V_CY(pvar).s.Lo); break;
1381 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1382 TRACE(",<invalid>");
1384 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1385 st.wHour, st.wMinute, st.wSecond);
1389 case VT_USERDEFINED:
1391 case VT_NULL: break;
1392 default: TRACE(",?"); break;
1398 static void dump_DispParms(const DISPPARAMS * pdp)
1402 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1404 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1406 TRACE("named args:\n");
1407 for (index = 0; index < pdp->cNamedArgs; index++)
1408 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1411 if (pdp->cArgs && pdp->rgvarg)
1414 for (index = 0; index < pdp->cArgs; index++)
1415 dump_Variant( &pdp->rgvarg[index] );
1419 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1421 TRACE("%p ref=%u\n", pty, pty->ref);
1422 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1423 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1424 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1425 TRACE("fct:%u var:%u impl:%u\n",
1426 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1427 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1428 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1429 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1431 dump_TLBFuncDesc(pty->funclist);
1432 dump_TLBVarDesc(pty->varlist);
1433 dump_TLBImplType(pty->impltypelist);
1436 static void dump_VARDESC(const VARDESC *v)
1438 MESSAGE("memid %d\n",v->memid);
1439 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1440 MESSAGE("oInst %d\n",v->u.oInst);
1441 dump_ELEMDESC(&(v->elemdescVar));
1442 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1443 MESSAGE("varkind %d\n",v->varkind);
1446 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1448 /* VT_LPWSTR is largest type that */
1449 /* may appear in type description*/
1450 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1451 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1452 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1453 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1454 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1455 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1459 static void TLB_abort(void)
1464 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1465 static void * TLB_Alloc(unsigned size)
1468 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1470 ERR("cannot allocate memory\n");
1475 static void TLB_Free(void * ptr)
1477 HeapFree(GetProcessHeap(), 0, ptr);
1480 /* returns the size required for a deep copy of a typedesc into a
1482 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1486 if (alloc_initial_space)
1487 size += sizeof(TYPEDESC);
1493 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1496 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1497 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1503 /* deep copy a typedesc into a flat buffer */
1504 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1509 buffer = (char *)buffer + sizeof(TYPEDESC);
1518 dest->u.lptdesc = buffer;
1519 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1522 dest->u.lpadesc = buffer;
1523 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1524 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1525 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1531 /* free custom data allocated by MSFT_CustData */
1532 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1534 TLBCustData *pCustDataNext;
1535 for (; pCustData; pCustData = pCustDataNext)
1537 VariantClear(&pCustData->data);
1539 pCustDataNext = pCustData->next;
1540 TLB_Free(pCustData);
1544 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1549 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1550 ret = SysAllocStringLen(NULL, len - 1);
1551 if (!ret) return ret;
1552 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1556 /**********************************************************************
1558 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1560 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1565 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1567 if (where != DO_NOT_SEEK)
1569 where += pcx->oStart;
1570 if (where > pcx->length)
1573 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1581 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1583 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1584 pcx->pos, count, pcx->oStart, pcx->length, where);
1586 MSFT_Seek(pcx, where);
1587 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1588 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1593 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1598 ret = MSFT_Read(buffer, count, pcx, where);
1599 FromLEDWords(buffer, ret);
1604 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1609 ret = MSFT_Read(buffer, count, pcx, where);
1610 FromLEWords(buffer, ret);
1615 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1617 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1618 memset(pGuid,0, sizeof(GUID));
1621 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1622 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1623 pGuid->Data2 = FromLEWord(pGuid->Data2);
1624 pGuid->Data3 = FromLEWord(pGuid->Data3);
1625 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1628 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1630 MSFT_NameIntro niName;
1634 ERR_(typelib)("bad offset %d\n", offset);
1638 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1639 pcx->pTblDir->pNametab.offset+offset);
1641 return niName.hreftype;
1644 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1647 MSFT_NameIntro niName;
1649 BSTR bstrName = NULL;
1653 ERR_(typelib)("bad offset %d\n", offset);
1656 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1657 pcx->pTblDir->pNametab.offset+offset);
1658 niName.namelen &= 0xFF; /* FIXME: correct ? */
1659 name=TLB_Alloc((niName.namelen & 0xff) +1);
1660 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1661 name[niName.namelen & 0xff]='\0';
1663 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1666 /* no invalid characters in string */
1669 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1671 /* don't check for invalid character since this has been done previously */
1672 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1676 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1680 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1687 if(offset<0) return NULL;
1688 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1689 if(length <= 0) return 0;
1690 string=TLB_Alloc(length +1);
1691 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1692 string[length]='\0';
1694 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1695 string, -1, NULL, 0);
1697 /* no invalid characters in string */
1700 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1702 /* don't check for invalid character since this has been done previously */
1703 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1707 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1711 * read a value and fill a VARIANT structure
1713 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1717 TRACE_(typelib)("\n");
1719 if(offset <0) { /* data are packed in here */
1720 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1721 V_I4(pVar) = offset & 0x3ffffff;
1724 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1725 pcx->pTblDir->pCustData.offset + offset );
1726 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1727 switch (V_VT(pVar)){
1728 case VT_EMPTY: /* FIXME: is this right? */
1729 case VT_NULL: /* FIXME: is this right? */
1730 case VT_I2 : /* this should not happen */
1741 case VT_VOID : /* FIXME: is this right? */
1749 case VT_DECIMAL : /* FIXME: is this right? */
1752 /* pointer types with known behaviour */
1755 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1758 DWORD origPos = MSFT_Tell(pcx), nullPos;
1761 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1763 nullPos = MSFT_Tell(pcx);
1764 size = nullPos - origPos;
1765 MSFT_Seek(pcx, origPos);
1767 ptr=TLB_Alloc(size);/* allocate temp buffer */
1768 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1769 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1770 /* FIXME: do we need a AtoW conversion here? */
1771 V_UNION(pVar, bstrVal[size])='\0';
1772 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1776 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1783 case VT_USERDEFINED :
1789 case VT_STREAMED_OBJECT :
1790 case VT_STORED_OBJECT :
1791 case VT_BLOB_OBJECT :
1796 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1800 if(size>0) /* (big|small) endian correct? */
1801 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1805 * create a linked list with custom data
1807 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1813 TRACE_(typelib)("\n");
1817 pNew=TLB_Alloc(sizeof(TLBCustData));
1818 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1819 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1820 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1821 /* add new custom data at head of the list */
1822 pNew->next=*ppCustData;
1824 offset = entry.next;
1829 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1833 pTd->vt=type & VT_TYPEMASK;
1835 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1837 if(pTd->vt == VT_USERDEFINED)
1838 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1840 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1843 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1845 /* resolve referenced type if any */
1848 switch (lpTypeDesc->vt)
1851 lpTypeDesc = lpTypeDesc->u.lptdesc;
1855 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1858 case VT_USERDEFINED:
1859 MSFT_DoRefType(pcx, pTI->pTypeLib,
1860 lpTypeDesc->u.hreftype);
1872 MSFT_DoFuncs(TLBContext* pcx,
1877 TLBFuncDesc** pptfd)
1880 * member information is stored in a data structure at offset
1881 * indicated by the memoffset field of the typeinfo structure
1882 * There are several distinctive parts.
1883 * The first part starts with a field that holds the total length
1884 * of this (first) part excluding this field. Then follow the records,
1885 * for each member there is one record.
1887 * The first entry is always the length of the record (including this
1889 * The rest of the record depends on the type of the member. If there is
1890 * a field indicating the member type (function, variable, interface, etc)
1891 * I have not found it yet. At this time we depend on the information
1892 * in the type info and the usual order how things are stored.
1894 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1897 * Third is an equal sized array with file offsets to the name entry
1900 * The fourth and last (?) part is an array with offsets to the records
1901 * in the first part of this file segment.
1904 int infolen, nameoffset, reclength, nrattributes, i;
1905 int recoffset = offset + sizeof(INT);
1907 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1908 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1909 TLBFuncDesc *ptfd_prev = NULL;
1911 TRACE_(typelib)("\n");
1913 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1915 for ( i = 0; i < cFuncs ; i++ )
1917 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1919 /* name, eventually add to a hash table */
1920 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1921 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1923 /* nameoffset is sometimes -1 on the second half of a propget/propput
1924 * pair of functions */
1925 if ((nameoffset == -1) && (i > 0))
1926 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1928 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1930 /* read the function information record */
1931 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1933 reclength &= 0xffff;
1935 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1937 /* do the attributes */
1938 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1941 if ( nrattributes > 0 )
1943 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1945 if ( nrattributes > 1 )
1947 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1948 pFuncRec->OptAttr[1]) ;
1950 if ( nrattributes > 2 )
1952 if ( pFuncRec->FKCCIC & 0x2000 )
1954 if (!IS_INTRESOURCE(pFuncRec->OptAttr[2]))
1955 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->OptAttr[2]);
1956 (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->OptAttr[2]);
1960 (*pptfd)->Entry = MSFT_ReadString(pcx,
1961 pFuncRec->OptAttr[2]);
1963 if( nrattributes > 5 )
1965 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1967 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1970 pFuncRec->OptAttr[6],
1971 &(*pptfd)->pCustData);
1977 (*pptfd)->Entry = (BSTR)-1;
1982 /* fill the FuncDesc Structure */
1983 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1984 offset + infolen + ( i + 1) * sizeof(INT));
1986 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1987 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1988 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1989 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1990 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1991 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1992 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1996 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1998 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
2000 /* do the parameters/arguments */
2001 if(pFuncRec->nrargs)
2004 MSFT_ParameterInfo paraminfo;
2006 (*pptfd)->funcdesc.lprgelemdescParam =
2007 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
2009 (*pptfd)->pParamDesc =
2010 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
2012 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
2013 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
2015 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
2017 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
2024 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
2027 if (paraminfo.oName == -1)
2028 /* this occurs for [propput] or [propget] methods, so
2029 * we should just set the name of the parameter to the
2030 * name of the method. */
2031 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
2033 (*pptfd)->pParamDesc[j].Name =
2034 MSFT_ReadName( pcx, paraminfo.oName );
2035 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
2037 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
2040 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
2041 (pFuncRec->FKCCIC & 0x1000) )
2043 INT* pInt = (INT *)((char *)pFuncRec +
2045 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
2047 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2049 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
2050 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2052 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2056 elemdesc->u.paramdesc.pparamdescex = NULL;
2058 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2061 pFuncRec->OptAttr[7+j],
2062 &(*pptfd)->pParamDesc[j].pCustData);
2065 /* SEEK value = jump to offset,
2066 * from there jump to the end of record,
2067 * go back by (j-1) arguments
2069 MSFT_ReadLEDWords( ¶minfo ,
2070 sizeof(MSFT_ParameterInfo), pcx,
2071 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2072 * sizeof(MSFT_ParameterInfo)));
2076 /* scode is not used: archaic win16 stuff FIXME: right? */
2077 (*pptfd)->funcdesc.cScodes = 0 ;
2078 (*pptfd)->funcdesc.lprgscode = NULL ;
2081 pptfd = & ((*pptfd)->next);
2082 recoffset += reclength;
2084 HeapFree(GetProcessHeap(), 0, recbuf);
2087 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2088 int cVars, int offset, TLBVarDesc ** pptvd)
2090 int infolen, nameoffset, reclength;
2092 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2096 TRACE_(typelib)("\n");
2098 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2099 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2100 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2101 recoffset += offset+sizeof(INT);
2102 for(i=0;i<cVars;i++){
2103 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2104 /* name, eventually add to a hash table */
2105 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2106 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2107 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2108 /* read the variable information record */
2109 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2111 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2113 if(reclength >(6*sizeof(INT)) )
2114 (*pptvd)->HelpContext=pVarRec->HelpContext;
2115 if(reclength >(7*sizeof(INT)) )
2116 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2117 if(reclength >(8*sizeof(INT)) )
2118 if(reclength >(9*sizeof(INT)) )
2119 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2120 /* fill the VarDesc Structure */
2121 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2122 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2123 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2124 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2125 MSFT_GetTdesc(pcx, pVarRec->DataType,
2126 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2127 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2128 if(pVarRec->VarKind == VAR_CONST ){
2129 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2130 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2131 pVarRec->OffsValue, pcx);
2133 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2134 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2135 pptvd=&((*pptvd)->next);
2136 recoffset += reclength;
2139 /* fill in data for a hreftype (offset). When the referenced type is contained
2140 * in the typelib, it's just an (file) offset in the type info base dir.
2141 * If comes from import, it's an offset+1 in the ImpInfo table
2143 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2148 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2150 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2152 if(ref->reference == offset) return;
2155 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2156 list_add_tail(&pTL->ref_list, &ref->entry);
2158 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2159 /* external typelib */
2160 MSFT_ImpInfo impinfo;
2161 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2163 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2165 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2166 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2167 while (pImpLib){ /* search the known offsets of all import libraries */
2168 if(pImpLib->offset==impinfo.oImpFile) break;
2169 pImpLib=pImpLib->next;
2172 ref->reference = offset;
2173 ref->pImpTLInfo = pImpLib;
2174 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2175 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2176 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2177 ref->index = TLB_REF_USE_GUID;
2179 ref->index = impinfo.oGuid;
2181 ERR("Cannot find a reference\n");
2182 ref->reference = -1;
2183 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2186 /* in this typelib */
2187 ref->index = MSFT_HREFTYPE_INDEX(offset);
2188 ref->reference = offset;
2189 ref->pImpTLInfo = TLB_REF_INTERNAL;
2193 /* process Implemented Interfaces of a com class */
2194 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2198 MSFT_RefRecord refrec;
2199 TLBImplType **ppImpl = &pTI->impltypelist;
2201 TRACE_(typelib)("\n");
2203 for(i=0;i<count;i++){
2204 if(offset<0) break; /* paranoia */
2205 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2206 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2207 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2208 (*ppImpl)->hRef = refrec.reftype;
2209 (*ppImpl)->implflags=refrec.flags;
2210 (*ppImpl)->ctCustData=
2211 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2212 offset=refrec.onext;
2213 ppImpl=&((*ppImpl)->next);
2217 * process a typeinfo record
2219 static ITypeInfoImpl * MSFT_DoTypeInfo(
2222 ITypeLibImpl * pLibInfo)
2224 MSFT_TypeInfoBase tiBase;
2225 ITypeInfoImpl *ptiRet;
2227 TRACE_(typelib)("count=%u\n", count);
2229 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2230 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2231 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2233 /* this is where we are coming from */
2234 ptiRet->pTypeLib = pLibInfo;
2235 ptiRet->index=count;
2236 /* fill in the typeattr fields */
2238 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2239 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2240 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2241 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2242 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2243 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2244 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2245 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2246 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2247 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2248 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2249 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2250 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2251 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2252 MSFT_GetTdesc(pcx, tiBase.datatype1,
2253 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2256 /* IDLDESC idldescType; *//* never saw this one != zero */
2258 /* name, eventually add to a hash table */
2259 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2260 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2261 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2263 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2264 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2265 ptiRet->dwHelpContext=tiBase.helpcontext;
2267 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2268 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2270 /* note: InfoType's Help file and HelpStringDll come from the containing
2271 * library. Further HelpString and Docstring appear to be the same thing :(
2274 if(ptiRet->TypeAttr.cFuncs >0 )
2275 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2276 ptiRet->TypeAttr.cVars,
2277 tiBase.memoffset, & ptiRet->funclist);
2279 if(ptiRet->TypeAttr.cVars >0 )
2280 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2281 ptiRet->TypeAttr.cVars,
2282 tiBase.memoffset, & ptiRet->varlist);
2283 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2284 switch(ptiRet->TypeAttr.typekind)
2287 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2290 case TKIND_DISPATCH:
2291 /* This is not -1 when the interface is a non-base dual interface or
2292 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2293 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2297 if (tiBase.datatype1 != -1)
2299 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2300 ptiRet->impltypelist->hRef = tiBase.datatype1;
2301 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2305 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2306 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2307 ptiRet->impltypelist->hRef = tiBase.datatype1;
2312 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2314 TRACE_(typelib)("%s guid: %s kind:%s\n",
2315 debugstr_w(ptiRet->Name),
2316 debugstr_guid(&ptiRet->TypeAttr.guid),
2317 typekind_desc[ptiRet->TypeAttr.typekind]);
2318 if (TRACE_ON(typelib))
2319 dump_TypeInfo(ptiRet);
2324 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2325 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2326 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2329 static ITypeLibImpl *tlb_cache_first;
2330 static CRITICAL_SECTION cache_section;
2331 static CRITICAL_SECTION_DEBUG cache_section_debug =
2333 0, 0, &cache_section,
2334 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2335 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2337 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2340 typedef struct TLB_PEFile
2342 const IUnknownVtbl *lpvtbl;
2345 HRSRC typelib_resource;
2346 HGLOBAL typelib_global;
2347 LPVOID typelib_base;
2350 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2352 if (IsEqualIID(riid, &IID_IUnknown))
2355 IUnknown_AddRef(iface);
2359 return E_NOINTERFACE;
2362 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2364 TLB_PEFile *This = (TLB_PEFile *)iface;
2365 return InterlockedIncrement(&This->refs);
2368 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2370 TLB_PEFile *This = (TLB_PEFile *)iface;
2371 ULONG refs = InterlockedDecrement(&This->refs);
2374 if (This->typelib_global)
2375 FreeResource(This->typelib_global);
2377 FreeLibrary(This->dll);
2378 HeapFree(GetProcessHeap(), 0, This);
2383 static const IUnknownVtbl TLB_PEFile_Vtable =
2385 TLB_PEFile_QueryInterface,
2390 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2394 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2396 return E_OUTOFMEMORY;
2398 This->lpvtbl = &TLB_PEFile_Vtable;
2401 This->typelib_resource = NULL;
2402 This->typelib_global = NULL;
2403 This->typelib_base = NULL;
2405 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2406 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2410 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2411 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2412 if (This->typelib_resource)
2414 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2415 if (This->typelib_global)
2417 This->typelib_base = LockResource(This->typelib_global);
2419 if (This->typelib_base)
2421 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2422 *ppBase = This->typelib_base;
2423 *ppFile = (IUnknown *)&This->lpvtbl;
2430 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2431 return TYPE_E_CANTLOADLIBRARY;
2434 typedef struct TLB_NEFile
2436 const IUnknownVtbl *lpvtbl;
2438 LPVOID typelib_base;
2441 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2443 if (IsEqualIID(riid, &IID_IUnknown))
2446 IUnknown_AddRef(iface);
2450 return E_NOINTERFACE;
2453 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2455 TLB_NEFile *This = (TLB_NEFile *)iface;
2456 return InterlockedIncrement(&This->refs);
2459 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2461 TLB_NEFile *This = (TLB_NEFile *)iface;
2462 ULONG refs = InterlockedDecrement(&This->refs);
2465 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2466 HeapFree(GetProcessHeap(), 0, This);
2471 static const IUnknownVtbl TLB_NEFile_Vtable =
2473 TLB_NEFile_QueryInterface,
2478 /***********************************************************************
2479 * read_xx_header [internal]
2481 static int read_xx_header( HFILE lzfd )
2483 IMAGE_DOS_HEADER mzh;
2486 LZSeek( lzfd, 0, SEEK_SET );
2487 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2489 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2492 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2493 if ( 2 != LZRead( lzfd, magic, 2 ) )
2496 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2498 if ( magic[0] == 'N' && magic[1] == 'E' )
2499 return IMAGE_OS2_SIGNATURE;
2500 if ( magic[0] == 'P' && magic[1] == 'E' )
2501 return IMAGE_NT_SIGNATURE;
2504 WARN("Can't handle %s files.\n", magic );
2509 /***********************************************************************
2510 * find_ne_resource [internal]
2512 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2513 DWORD *resLen, DWORD *resOff )
2515 IMAGE_OS2_HEADER nehd;
2516 NE_TYPEINFO *typeInfo;
2517 NE_NAMEINFO *nameInfo;
2523 /* Read in NE header */
2524 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2525 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2527 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2530 TRACE("No resources in NE dll\n" );
2534 /* Read in resource table */
2535 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2536 if ( !resTab ) return FALSE;
2538 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2539 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2541 HeapFree( GetProcessHeap(), 0, resTab );
2546 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2548 if (!IS_INTRESOURCE(typeid)) /* named type */
2550 BYTE len = strlen( typeid );
2551 while (typeInfo->type_id)
2553 if (!(typeInfo->type_id & 0x8000))
2555 BYTE *p = resTab + typeInfo->type_id;
2556 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2558 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2559 typeInfo->count * sizeof(NE_NAMEINFO));
2562 else /* numeric type id */
2564 WORD id = LOWORD(typeid) | 0x8000;
2565 while (typeInfo->type_id)
2567 if (typeInfo->type_id == id) goto found_type;
2568 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2569 typeInfo->count * sizeof(NE_NAMEINFO));
2572 TRACE("No typeid entry found for %p\n", typeid );
2573 HeapFree( GetProcessHeap(), 0, resTab );
2577 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2579 if (!IS_INTRESOURCE(resid)) /* named resource */
2581 BYTE len = strlen( resid );
2582 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2584 BYTE *p = resTab + nameInfo->id;
2585 if (nameInfo->id & 0x8000) continue;
2586 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2589 else /* numeric resource id */
2591 WORD id = LOWORD(resid) | 0x8000;
2592 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2593 if (nameInfo->id == id) goto found_name;
2595 TRACE("No resid entry found for %p\n", typeid );
2596 HeapFree( GetProcessHeap(), 0, resTab );
2600 /* Return resource data */
2601 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2602 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2604 HeapFree( GetProcessHeap(), 0, resTab );
2608 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2612 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2613 TLB_NEFile *This = NULL;
2615 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2616 if (!This) return E_OUTOFMEMORY;
2618 This->lpvtbl = &TLB_NEFile_Vtable;
2620 This->typelib_base = NULL;
2622 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2623 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2625 DWORD reslen, offset;
2626 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2628 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2629 if( !This->typelib_base )
2633 LZSeek( lzfd, offset, SEEK_SET );
2634 reslen = LZRead( lzfd, This->typelib_base, reslen );
2636 *ppBase = This->typelib_base;
2637 *pdwTLBLength = reslen;
2638 *ppFile = (IUnknown *)&This->lpvtbl;
2644 if( lzfd >= 0) LZClose( lzfd );
2645 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2649 typedef struct TLB_Mapping
2651 const IUnknownVtbl *lpvtbl;
2655 LPVOID typelib_base;
2658 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2660 if (IsEqualIID(riid, &IID_IUnknown))
2663 IUnknown_AddRef(iface);
2667 return E_NOINTERFACE;
2670 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2672 TLB_Mapping *This = (TLB_Mapping *)iface;
2673 return InterlockedIncrement(&This->refs);
2676 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2678 TLB_Mapping *This = (TLB_Mapping *)iface;
2679 ULONG refs = InterlockedDecrement(&This->refs);
2682 if (This->typelib_base)
2683 UnmapViewOfFile(This->typelib_base);
2685 CloseHandle(This->mapping);
2686 if (This->file != INVALID_HANDLE_VALUE)
2687 CloseHandle(This->file);
2688 HeapFree(GetProcessHeap(), 0, This);
2693 static const IUnknownVtbl TLB_Mapping_Vtable =
2695 TLB_Mapping_QueryInterface,
2700 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2704 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2706 return E_OUTOFMEMORY;
2708 This->lpvtbl = &TLB_Mapping_Vtable;
2710 This->file = INVALID_HANDLE_VALUE;
2711 This->mapping = NULL;
2712 This->typelib_base = NULL;
2714 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2715 if (INVALID_HANDLE_VALUE != This->file)
2717 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2720 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2721 if(This->typelib_base)
2723 /* retrieve file size */
2724 *pdwTLBLength = GetFileSize(This->file, NULL);
2725 *ppBase = This->typelib_base;
2726 *ppFile = (IUnknown *)&This->lpvtbl;
2732 IUnknown_Release((IUnknown *)&This->lpvtbl);
2733 return TYPE_E_CANTLOADLIBRARY;
2736 /****************************************************************************
2739 * find the type of the typelib file and map the typelib resource into
2742 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2743 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2744 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2746 ITypeLibImpl *entry;
2749 LPWSTR index_str, file = (LPWSTR)pszFileName;
2750 LPVOID pBase = NULL;
2751 DWORD dwTLBLength = 0;
2752 IUnknown *pFile = NULL;
2756 index_str = strrchrW(pszFileName, '\\');
2757 if(index_str && *++index_str != '\0')
2760 LONG idx = strtolW(index_str, &end_ptr, 10);
2761 if(*end_ptr == '\0')
2763 int str_len = index_str - pszFileName - 1;
2765 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2766 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2771 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2773 if(strchrW(file, '\\'))
2775 lstrcpyW(pszPath, file);
2779 int len = GetSystemDirectoryW(pszPath, cchPath);
2780 pszPath[len] = '\\';
2781 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2785 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2787 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2789 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2790 EnterCriticalSection(&cache_section);
2791 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2793 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2795 TRACE("cache hit\n");
2796 *ppTypeLib = (ITypeLib2*)entry;
2797 ITypeLib_AddRef(*ppTypeLib);
2798 LeaveCriticalSection(&cache_section);
2802 LeaveCriticalSection(&cache_section);
2804 /* now actually load and parse the typelib */
2806 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2807 if (ret == TYPE_E_CANTLOADLIBRARY)
2808 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2809 if (ret == TYPE_E_CANTLOADLIBRARY)
2810 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2813 if (dwTLBLength >= 4)
2815 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2816 if (dwSignature == MSFT_SIGNATURE)
2817 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2818 else if (dwSignature == SLTG_SIGNATURE)
2819 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2822 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2823 ret = TYPE_E_CANTLOADLIBRARY;
2827 ret = TYPE_E_CANTLOADLIBRARY;
2828 IUnknown_Release(pFile);
2832 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2834 TRACE("adding to cache\n");
2835 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2836 lstrcpyW(impl->path, pszPath);
2837 /* We should really canonicalise the path here. */
2838 impl->index = index;
2840 /* FIXME: check if it has added already in the meantime */
2841 EnterCriticalSection(&cache_section);
2842 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2844 tlb_cache_first = impl;
2845 LeaveCriticalSection(&cache_section);
2848 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2853 /*================== ITypeLib(2) Methods ===================================*/
2855 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2857 ITypeLibImpl* pTypeLibImpl;
2859 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2860 if (!pTypeLibImpl) return NULL;
2862 pTypeLibImpl->lpVtbl = &tlbvt;
2863 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2864 pTypeLibImpl->ref = 1;
2866 list_init(&pTypeLibImpl->ref_list);
2867 pTypeLibImpl->dispatch_href = -1;
2869 return pTypeLibImpl;
2872 /****************************************************************************
2873 * ITypeLib2_Constructor_MSFT
2875 * loading an MSFT typelib from an in-memory image
2877 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2881 MSFT_Header tlbHeader;
2882 MSFT_SegDir tlbSegDir;
2883 ITypeLibImpl * pTypeLibImpl;
2885 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2887 pTypeLibImpl = TypeLibImpl_Constructor();
2888 if (!pTypeLibImpl) return NULL;
2890 /* get pointer to beginning of typelib data */
2894 cx.pLibInfo = pTypeLibImpl;
2895 cx.length = dwTLBLength;
2898 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2899 TRACE_(typelib)("header:\n");
2900 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2901 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2902 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2905 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2907 /* there is a small amount of information here until the next important
2909 * the segment directory . Try to calculate the amount of data */
2910 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2912 /* now read the segment directory */
2913 TRACE("read segment directory (at %d)\n",lPSegDir);
2914 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2915 cx.pTblDir = &tlbSegDir;
2917 /* just check two entries */
2918 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2920 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
2921 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2925 /* now fill our internal data */
2926 /* TLIBATTR fields */
2927 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2929 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2930 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2931 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2932 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2933 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2935 pTypeLibImpl->lcid = tlbHeader.lcid;
2937 /* name, eventually add to a hash table */
2938 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2941 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2942 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2944 if( tlbHeader.varflags & HELPDLLFLAG)
2947 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2948 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2951 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2954 if(tlbHeader.CustomDataOffset >= 0)
2956 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2959 /* fill in type descriptions */
2960 if(tlbSegDir.pTypdescTab.length > 0)
2962 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2964 pTypeLibImpl->ctTypeDesc = cTD;
2965 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2966 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2969 /* FIXME: add several sanity checks here */
2970 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2971 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2973 /* FIXME: check safearray */
2975 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2977 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2979 else if(td[0] == VT_CARRAY)
2981 /* array descr table here */
2982 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
2984 else if(td[0] == VT_USERDEFINED)
2986 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2988 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2991 /* second time around to fill the array subscript info */
2994 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2995 if(tlbSegDir.pArrayDescriptions.offset>0)
2997 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2998 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
3001 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
3003 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
3005 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
3007 for(j = 0; j<td[2]; j++)
3009 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
3010 sizeof(INT), &cx, DO_NOT_SEEK);
3011 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
3012 sizeof(INT), &cx, DO_NOT_SEEK);
3017 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
3018 ERR("didn't find array description data\n");
3023 /* imported type libs */
3024 if(tlbSegDir.pImpFiles.offset>0)
3026 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
3027 int oGuid, offset = tlbSegDir.pImpFiles.offset;
3030 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
3034 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
3035 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
3036 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
3038 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
3039 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
3040 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
3041 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3044 name = TLB_Alloc(size+1);
3045 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3046 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3049 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3050 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3052 ppImpLib = &(*ppImpLib)->next;
3056 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3057 if(pTypeLibImpl->dispatch_href != -1)
3058 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3061 if(tlbHeader.nrtypeinfos >= 0 )
3063 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3064 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3067 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3069 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3071 ppTI = &((*ppTI)->next);
3072 (pTypeLibImpl->TypeInfoCount)++;
3076 TRACE("(%p)\n", pTypeLibImpl);
3077 return (ITypeLib2*) pTypeLibImpl;
3081 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3087 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3088 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3092 guid->Data4[0] = s >> 8;
3093 guid->Data4[1] = s & 0xff;
3096 for(i = 0; i < 6; i++) {
3097 memcpy(b, str + 24 + 2 * i, 2);
3098 guid->Data4[i + 2] = strtol(b, NULL, 16);
3103 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3109 bytelen = *(const WORD*)ptr;
3110 if(bytelen == 0xffff) return 2;
3111 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3112 *pBstr = SysAllocStringLen(NULL, len);
3114 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3118 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3123 bytelen = *(const WORD*)ptr;
3124 if(bytelen == 0xffff) return 2;
3125 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3126 memcpy(*str, ptr + 2, bytelen);
3127 (*str)[bytelen] = '\0';
3131 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3133 char *ptr = pLibBlk;
3136 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3137 FIXME("libblk magic = %04x\n", w);
3142 if((w = *(WORD*)ptr) != 0xffff) {
3143 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3148 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3150 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3152 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3155 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3158 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3159 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3161 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3164 ptr += 4; /* skip res12 */
3166 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3169 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3172 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3175 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3176 ptr += sizeof(GUID);
3178 return ptr - (char*)pLibBlk;
3181 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3186 } sltg_ref_lookup_t;
3188 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3189 HREFTYPE *typelib_ref)
3191 if(table && typeinfo_ref < table->num)
3193 *typelib_ref = table->refs[typeinfo_ref];
3197 ERR_(typelib)("Unable to find reference\n");
3202 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3207 if((*pType & 0xe00) == 0xe00) {
3209 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3211 pTD = pTD->u.lptdesc;
3213 switch(*pType & 0x3f) {
3216 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3218 pTD = pTD->u.lptdesc;
3221 case VT_USERDEFINED:
3222 pTD->vt = VT_USERDEFINED;
3223 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3229 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3232 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3234 pTD->vt = VT_CARRAY;
3235 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3237 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3238 pTD->u.lpadesc->cDims = pSA->cDims;
3239 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3240 pSA->cDims * sizeof(SAFEARRAYBOUND));
3242 pTD = &pTD->u.lpadesc->tdescElem;
3248 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3252 pTD->vt = VT_SAFEARRAY;
3253 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3255 pTD = pTD->u.lptdesc;
3259 pTD->vt = *pType & 0x3f;
3268 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3269 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3271 /* Handle [in/out] first */
3272 if((*pType & 0xc000) == 0xc000)
3273 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3274 else if(*pType & 0x8000)
3275 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3276 else if(*pType & 0x4000)
3277 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3279 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3282 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3285 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3287 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3291 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3296 TLBRefType *ref_type;
3297 sltg_ref_lookup_t *table;
3298 HREFTYPE typelib_ref;
3300 if(pRef->magic != SLTG_REF_MAGIC) {
3301 FIXME("Ref magic = %x\n", pRef->magic);
3304 name = ( (char*)pRef->names + pRef->number);
3306 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3307 table->num = pRef->number >> 3;
3309 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3311 /* We don't want the first href to be 0 */
3312 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3314 for(ref = 0; ref < pRef->number >> 3; ref++) {
3316 unsigned int lib_offs, type_num;
3318 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3320 name += SLTG_ReadStringA(name, &refname);
3321 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3322 FIXME_(typelib)("Can't sscanf ref\n");
3323 if(lib_offs != 0xffff) {
3324 TLBImpLib **import = &pTL->pImpLibs;
3327 if((*import)->offset == lib_offs)
3329 import = &(*import)->next;
3332 char fname[MAX_PATH+1];
3335 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3337 (*import)->offset = lib_offs;
3338 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3340 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3341 &(*import)->wVersionMajor,
3342 &(*import)->wVersionMinor,
3343 &(*import)->lcid, fname) != 4) {
3344 FIXME_(typelib)("can't sscanf ref %s\n",
3345 pNameTable + lib_offs + 40);
3347 len = strlen(fname);
3348 if(fname[len-1] != '#')
3349 FIXME("fname = %s\n", fname);
3350 fname[len-1] = '\0';
3351 (*import)->name = TLB_MultiByteToBSTR(fname);
3353 ref_type->pImpTLInfo = *import;
3355 /* Store a reference to IDispatch */
3356 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3357 pTL->dispatch_href = typelib_ref;
3359 } else { /* internal ref */
3360 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3362 ref_type->reference = typelib_ref;
3363 ref_type->index = type_num;
3365 HeapFree(GetProcessHeap(), 0, refname);
3366 list_add_tail(&pTL->ref_list, &ref_type->entry);
3368 table->refs[ref] = typelib_ref;
3371 if((BYTE)*name != SLTG_REF_MAGIC)
3372 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3373 dump_TLBRefType(pTL);
3377 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3378 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3380 SLTG_ImplInfo *info;
3381 TLBImplType **ppImplType = &pTI->impltypelist;
3382 /* I don't really get this structure, usually it's 0x16 bytes
3383 long, but iuser.tlb contains some that are 0x18 bytes long.
3384 That's ok because we can use the next ptr to jump to the next
3385 one. But how do we know the length of the last one? The WORD
3386 at offs 0x8 might be the clue. For now I'm just assuming that
3387 the last one is the regular 0x16 bytes. */
3389 info = (SLTG_ImplInfo*)pBlk;
3391 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3392 sizeof(**ppImplType));
3393 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3394 (*ppImplType)->implflags = info->impltypeflags;
3395 pTI->TypeAttr.cImplTypes++;
3396 ppImplType = &(*ppImplType)->next;
3398 if(info->next == 0xffff)
3401 FIXME_(typelib)("Interface inheriting more than one interface\n");
3402 info = (SLTG_ImplInfo*)(pBlk + info->next);
3404 info++; /* see comment at top of function */
3408 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3409 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3411 TLBVarDesc **ppVarDesc = &pTI->varlist;
3412 BSTR bstrPrevName = NULL;
3413 SLTG_Variable *pItem;
3417 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3418 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3420 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3421 sizeof(**ppVarDesc));
3422 (*ppVarDesc)->vardesc.memid = pItem->memid;
3424 if (pItem->magic != SLTG_VAR_MAGIC &&
3425 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3426 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3430 if (pItem->name == 0xfffe)
3431 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3433 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3435 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3436 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3437 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3439 if(pItem->flags & 0x02)
3440 pType = &pItem->type;
3442 pType = (WORD*)(pBlk + pItem->type);
3444 if (pItem->flags & ~0xda)
3445 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3447 SLTG_DoElem(pType, pBlk,
3448 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3450 if (TRACE_ON(typelib)) {
3452 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3453 TRACE_(typelib)("elemdescVar: %s\n", buf);
3456 if (pItem->flags & 0x40) {
3457 TRACE_(typelib)("VAR_DISPATCH\n");
3458 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3460 else if (pItem->flags & 0x10) {
3461 TRACE_(typelib)("VAR_CONST\n");
3462 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3463 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3465 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3466 if (pItem->flags & 0x08)
3467 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3469 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3475 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3477 TRACE_(typelib)("len = %u\n", len);
3478 if (len == 0xffff) {
3481 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3482 str = SysAllocStringLen(NULL, alloc_len);
3483 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3485 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3486 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3495 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3496 *(INT*)(pBlk + pItem->byte_offs);
3499 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3504 TRACE_(typelib)("VAR_PERINSTANCE\n");
3505 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3506 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3509 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3510 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3512 if (pItem->flags & 0x80)
3513 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3515 bstrPrevName = (*ppVarDesc)->Name;
3516 ppVarDesc = &((*ppVarDesc)->next);
3518 pTI->TypeAttr.cVars = cVars;
3521 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3522 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3524 SLTG_Function *pFunc;
3526 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3528 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3529 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3534 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3535 sizeof(**ppFuncDesc));
3537 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3538 case SLTG_FUNCTION_MAGIC:
3539 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3541 case SLTG_DISPATCH_FUNCTION_MAGIC:
3542 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3544 case SLTG_STATIC_FUNCTION_MAGIC:
3545 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3548 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3549 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3553 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3555 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3556 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3557 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3558 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3559 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3560 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3562 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3563 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3565 if(pFunc->retnextopt & 0x80)
3566 pType = &pFunc->rettype;
3568 pType = (WORD*)(pBlk + pFunc->rettype);
3570 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3572 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3573 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3574 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3575 (*ppFuncDesc)->pParamDesc =
3576 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3577 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3579 pArg = (WORD*)(pBlk + pFunc->arg_off);
3581 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3582 char *paramName = pNameTable + *pArg;
3584 /* If arg type follows then paramName points to the 2nd
3585 letter of the name, else the next WORD is an offset to
3586 the arg type and paramName points to the first letter.
3587 So let's take one char off paramName and see if we're
3588 pointing at an alpha-numeric char. However if *pArg is
3589 0xffff or 0xfffe then the param has no name, the former
3590 meaning that the next WORD is the type, the latter
3591 meaning that the next WORD is an offset to the type. */
3596 else if(*pArg == 0xfffe) {
3600 else if(paramName[-1] && !isalnum(paramName[-1]))
3605 if(HaveOffs) { /* the next word is an offset to type */
3606 pType = (WORD*)(pBlk + *pArg);
3607 SLTG_DoElem(pType, pBlk,
3608 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3613 pArg = SLTG_DoElem(pArg, pBlk,
3614 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3617 /* Are we an optional param ? */
3618 if((*ppFuncDesc)->funcdesc.cParams - param <=
3619 (*ppFuncDesc)->funcdesc.cParamsOpt)
3620 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3623 (*ppFuncDesc)->pParamDesc[param].Name =
3624 TLB_MultiByteToBSTR(paramName);
3626 (*ppFuncDesc)->pParamDesc[param].Name =
3627 SysAllocString((*ppFuncDesc)->Name);
3631 ppFuncDesc = &((*ppFuncDesc)->next);
3632 if(pFunc->next == 0xffff) break;
3634 pTI->TypeAttr.cFuncs = cFuncs;
3637 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3638 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3639 SLTG_TypeInfoTail *pTITail)
3642 sltg_ref_lookup_t *ref_lookup = NULL;
3644 if(pTIHeader->href_table != 0xffffffff) {
3645 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3651 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3652 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3654 HeapFree(GetProcessHeap(), 0, ref_lookup);
3658 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3659 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3660 const SLTG_TypeInfoTail *pTITail)
3663 sltg_ref_lookup_t *ref_lookup = NULL;
3665 if(pTIHeader->href_table != 0xffffffff) {
3666 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3672 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3673 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3676 if (pTITail->funcs_off != 0xffff)
3677 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3679 HeapFree(GetProcessHeap(), 0, ref_lookup);
3681 if (TRACE_ON(typelib))
3682 dump_TLBFuncDesc(pTI->funclist);
3685 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3686 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3687 const SLTG_TypeInfoTail *pTITail)
3689 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3692 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3693 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3694 const SLTG_TypeInfoTail *pTITail)
3697 sltg_ref_lookup_t *ref_lookup = NULL;
3699 if (pTITail->simple_alias) {
3700 /* if simple alias, no more processing required */
3701 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3705 if(pTIHeader->href_table != 0xffffffff) {
3706 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3710 /* otherwise it is an offset to a type */
3711 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3713 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3715 HeapFree(GetProcessHeap(), 0, ref_lookup);
3718 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3719 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3720 const SLTG_TypeInfoTail *pTITail)
3722 sltg_ref_lookup_t *ref_lookup = NULL;
3723 if (pTIHeader->href_table != 0xffffffff)
3724 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3727 if (pTITail->vars_off != 0xffff)
3728 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3730 if (pTITail->funcs_off != 0xffff)
3731 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3733 if (pTITail->impls_off != 0xffff)
3734 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3736 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3737 * of dispinterface functions including the IDispatch ones, so
3738 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3739 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3741 HeapFree(GetProcessHeap(), 0, ref_lookup);
3742 if (TRACE_ON(typelib))
3743 dump_TLBFuncDesc(pTI->funclist);
3746 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3747 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3748 const SLTG_TypeInfoTail *pTITail)
3750 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3753 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3754 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3755 const SLTG_TypeInfoTail *pTITail)
3757 sltg_ref_lookup_t *ref_lookup = NULL;
3758 if (pTIHeader->href_table != 0xffffffff)
3759 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3762 if (pTITail->vars_off != 0xffff)
3763 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3765 if (pTITail->funcs_off != 0xffff)
3766 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3767 HeapFree(GetProcessHeap(), 0, ref_lookup);
3768 if (TRACE_ON(typelib))
3772 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3773 managable copy of it into this */
3786 } SLTG_InternalOtherTypeInfo;
3788 /****************************************************************************
3789 * ITypeLib2_Constructor_SLTG
3791 * loading a SLTG typelib from an in-memory image
3793 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3795 ITypeLibImpl *pTypeLibImpl;
3796 SLTG_Header *pHeader;
3797 SLTG_BlkEntry *pBlkEntry;
3801 LPVOID pBlk, pFirstBlk;
3802 SLTG_LibBlk *pLibBlk;
3803 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3804 char *pAfterOTIBlks = NULL;
3805 char *pNameTable, *ptr;
3808 ITypeInfoImpl **ppTypeInfoImpl;
3810 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3813 pTypeLibImpl = TypeLibImpl_Constructor();
3814 if (!pTypeLibImpl) return NULL;
3818 TRACE_(typelib)("header:\n");
3819 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3820 pHeader->nrOfFileBlks );
3821 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3822 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3823 pHeader->SLTG_magic);
3827 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3828 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3830 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3831 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3833 /* Next we have a magic block */
3834 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3836 /* Let's see if we're still in sync */
3837 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3838 sizeof(SLTG_COMPOBJ_MAGIC))) {
3839 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3842 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3843 sizeof(SLTG_DIR_MAGIC))) {
3844 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3848 pIndex = (SLTG_Index*)(pMagic+1);
3850 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3852 pFirstBlk = pPad9 + 1;
3854 /* We'll set up a ptr to the main library block, which is the last one. */
3856 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3857 pBlkEntry[order].next != 0;
3858 order = pBlkEntry[order].next - 1, i++) {
3859 pBlk = (char*)pBlk + pBlkEntry[order].len;
3863 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3865 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3870 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3872 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3873 sizeof(*pOtherTypeInfoBlks) *
3874 pTypeLibImpl->TypeInfoCount);
3877 ptr = (char*)pLibBlk + len;
3879 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3883 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3885 w = *(WORD*)(ptr + 2);
3888 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3890 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3891 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3893 w = *(WORD*)(ptr + 4 + len);
3895 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3897 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3899 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3900 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3902 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3903 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3904 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3906 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3908 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3911 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3912 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3913 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3914 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3915 len += sizeof(SLTG_OtherTypeInfo);
3919 pAfterOTIBlks = ptr;
3921 /* Skip this WORD and get the next DWORD */
3922 len = *(DWORD*)(pAfterOTIBlks + 2);
3924 /* Now add this to pLibBLk look at what we're pointing at and
3925 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3926 dust and we should be pointing at the beginning of the name
3929 pNameTable = (char*)pLibBlk + len;
3931 switch(*(WORD*)pNameTable) {
3938 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3942 pNameTable += 0x216;
3946 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3948 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3951 /* Hopefully we now have enough ptrs set up to actually read in
3952 some TypeInfos. It's not clear which order to do them in, so
3953 I'll just follow the links along the BlkEntry chain and read
3954 them in the order in which they are in the file */
3956 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3958 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3959 pBlkEntry[order].next != 0;
3960 order = pBlkEntry[order].next - 1, i++) {
3962 SLTG_TypeInfoHeader *pTIHeader;
3963 SLTG_TypeInfoTail *pTITail;
3964 SLTG_MemberHeader *pMemHeader;
3966 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3967 pOtherTypeInfoBlks[i].index_name)) {
3968 FIXME_(typelib)("Index strings don't match\n");
3973 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3974 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3977 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3978 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3979 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3981 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3982 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3983 (*ppTypeInfoImpl)->index = i;
3984 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3985 pOtherTypeInfoBlks[i].name_offs +
3987 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3988 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3989 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3990 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3991 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3992 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3993 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3995 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3996 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3998 if((pTIHeader->typeflags1 & 7) != 2)
3999 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
4000 if(pTIHeader->typeflags3 != 2)
4001 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
4003 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4004 debugstr_w((*ppTypeInfoImpl)->Name),
4005 typekind_desc[pTIHeader->typekind],
4006 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
4007 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
4009 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
4011 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
4013 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
4014 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
4015 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
4017 switch(pTIHeader->typekind) {
4019 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4020 pTIHeader, pTITail);
4024 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4025 pTIHeader, pTITail);
4028 case TKIND_INTERFACE:
4029 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4030 pTIHeader, pTITail);
4034 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4035 pTIHeader, pTITail);
4039 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4040 pTIHeader, pTITail);
4043 case TKIND_DISPATCH:
4044 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4045 pTIHeader, pTITail);
4049 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4050 pTIHeader, pTITail);
4054 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4059 /* could get cFuncs, cVars and cImplTypes from here
4060 but we've already set those */
4061 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4076 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4077 pBlk = (char*)pBlk + pBlkEntry[order].len;
4080 if(i != pTypeLibImpl->TypeInfoCount) {
4081 FIXME("Somehow processed %d TypeInfos\n", i);
4085 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4086 return (ITypeLib2*)pTypeLibImpl;
4089 /* ITypeLib::QueryInterface
4091 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4096 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4098 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4101 if(IsEqualIID(riid, &IID_IUnknown) ||
4102 IsEqualIID(riid,&IID_ITypeLib)||
4103 IsEqualIID(riid,&IID_ITypeLib2))
4110 ITypeLib2_AddRef(iface);
4111 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4114 TRACE("-- Interface: E_NOINTERFACE\n");
4115 return E_NOINTERFACE;
4120 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4122 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4123 ULONG ref = InterlockedIncrement(&This->ref);
4125 TRACE("(%p)->ref was %u\n",This, ref - 1);
4130 /* ITypeLib::Release
4132 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4134 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4135 ULONG ref = InterlockedDecrement(&This->ref);
4137 TRACE("(%p)->(%u)\n",This, ref);
4141 TLBImpLib *pImpLib, *pImpLibNext;
4142 TLBCustData *pCustData, *pCustDataNext;
4143 TLBRefType *ref_type;
4146 ITypeInfoImpl *pTI, *pTINext;
4148 /* remove cache entry */
4151 TRACE("removing from cache list\n");
4152 EnterCriticalSection(&cache_section);
4153 if (This->next) This->next->prev = This->prev;
4154 if (This->prev) This->prev->next = This->next;
4155 else tlb_cache_first = This->next;
4156 LeaveCriticalSection(&cache_section);
4157 HeapFree(GetProcessHeap(), 0, This->path);
4159 TRACE(" destroying ITypeLib(%p)\n",This);
4161 SysFreeString(This->Name);
4164 SysFreeString(This->DocString);
4165 This->DocString = NULL;
4167 SysFreeString(This->HelpFile);
4168 This->HelpFile = NULL;
4170 SysFreeString(This->HelpStringDll);
4171 This->HelpStringDll = NULL;
4173 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4175 VariantClear(&pCustData->data);
4177 pCustDataNext = pCustData->next;
4178 TLB_Free(pCustData);
4181 for (i = 0; i < This->ctTypeDesc; i++)
4182 if (This->pTypeDesc[i].vt == VT_CARRAY)
4183 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4185 TLB_Free(This->pTypeDesc);
4187 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4189 if (pImpLib->pImpTypeLib)
4190 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4191 SysFreeString(pImpLib->name);
4193 pImpLibNext = pImpLib->next;
4197 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4199 list_remove(&ref_type->entry);
4203 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4205 pTINext = pTI->next;
4206 ITypeInfo_fnDestroy(pTI);
4208 HeapFree(GetProcessHeap(),0,This);
4215 /* ITypeLib::GetTypeInfoCount
4217 * Returns the number of type descriptions in the type library
4219 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4221 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4222 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4223 return This->TypeInfoCount;
4226 /* ITypeLib::GetTypeInfo
4228 * retrieves the specified type description in the library.
4230 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4233 ITypeInfo **ppTInfo)
4237 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4238 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4240 TRACE("(%p)->(index=%d)\n", This, index);
4242 if (!ppTInfo) return E_INVALIDARG;
4244 /* search element n in list */
4245 for(i=0; i < index; i++)
4247 pTypeInfo = pTypeInfo->next;
4250 TRACE("-- element not found\n");
4251 return TYPE_E_ELEMENTNOTFOUND;
4255 *ppTInfo = (ITypeInfo *) pTypeInfo;
4257 ITypeInfo_AddRef(*ppTInfo);
4258 TRACE("-- found (%p)\n",*ppTInfo);
4263 /* ITypeLibs::GetTypeInfoType
4265 * Retrieves the type of a type description.
4267 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4272 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4274 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4276 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4277 return TYPE_E_ELEMENTNOTFOUND;
4279 TRACE("(%p) index %d\n", This, index);
4281 if(!pTKind) return E_INVALIDARG;
4283 /* search element n in list */
4284 for(i=0; i < index; i++)
4288 TRACE("-- element not found\n");
4289 return TYPE_E_ELEMENTNOTFOUND;
4291 pTInfo = pTInfo->next;
4294 *pTKind = pTInfo->TypeAttr.typekind;
4295 TRACE("-- found Type (%d)\n", *pTKind);
4299 /* ITypeLib::GetTypeInfoOfGuid
4301 * Retrieves the type description that corresponds to the specified GUID.
4304 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4307 ITypeInfo **ppTInfo)
4309 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4310 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4312 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4316 WARN("-- element not found\n");
4317 return TYPE_E_ELEMENTNOTFOUND;
4320 /* search linked list for guid */
4321 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4323 pTypeInfo = pTypeInfo->next;
4327 /* end of list reached */
4328 WARN("-- element not found\n");
4329 return TYPE_E_ELEMENTNOTFOUND;
4333 TRACE("-- found (%p, %s)\n",
4335 debugstr_w(pTypeInfo->Name));
4337 *ppTInfo = (ITypeInfo*)pTypeInfo;
4338 ITypeInfo_AddRef(*ppTInfo);
4342 /* ITypeLib::GetLibAttr
4344 * Retrieves the structure that contains the library's attributes.
4347 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4349 LPTLIBATTR *ppTLibAttr)
4351 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4352 TRACE("(%p)\n",This);
4353 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4354 **ppTLibAttr = This->LibAttr;
4358 /* ITypeLib::GetTypeComp
4360 * Enables a client compiler to bind to a library's types, variables,
4361 * constants, and global functions.
4364 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4366 ITypeComp **ppTComp)
4368 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4370 TRACE("(%p)->(%p)\n",This,ppTComp);
4371 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4372 ITypeComp_AddRef(*ppTComp);
4377 /* ITypeLib::GetDocumentation
4379 * Retrieves the library's documentation string, the complete Help file name
4380 * and path, and the context identifier for the library Help topic in the Help
4383 * On a successful return all non-null BSTR pointers will have been set,
4386 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4390 BSTR *pBstrDocString,
4391 DWORD *pdwHelpContext,
4392 BSTR *pBstrHelpFile)
4394 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4396 HRESULT result = E_INVALIDARG;
4401 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4403 pBstrName, pBstrDocString,
4404 pdwHelpContext, pBstrHelpFile);
4408 /* documentation for the typelib */
4413 if(!(*pBstrName = SysAllocString(This->Name)))
4421 if (This->DocString)
4423 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4426 else if (This->Name)
4428 if(!(*pBstrDocString = SysAllocString(This->Name)))
4432 *pBstrDocString = NULL;
4436 *pdwHelpContext = This->dwHelpContext;
4442 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4446 *pBstrHelpFile = NULL;
4453 /* for a typeinfo */
4454 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4456 if(SUCCEEDED(result))
4458 result = ITypeInfo_GetDocumentation(pTInfo,
4462 pdwHelpContext, pBstrHelpFile);
4464 ITypeInfo_Release(pTInfo);
4469 if (pBstrDocString) SysFreeString (*pBstrDocString);
4471 if (pBstrName) SysFreeString (*pBstrName);
4473 return STG_E_INSUFFICIENTMEMORY;
4478 * Indicates whether a passed-in string contains the name of a type or member
4479 * described in the library.
4482 static HRESULT WINAPI ITypeLib2_fnIsName(
4488 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4489 ITypeInfoImpl *pTInfo;
4490 TLBFuncDesc *pFInfo;
4493 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4495 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4499 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4500 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4501 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4502 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4503 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4504 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4505 goto ITypeLib2_fnIsName_exit;
4507 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4508 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4513 ITypeLib2_fnIsName_exit:
4514 TRACE("(%p)slow! search for %s: %s found!\n", This,
4515 debugstr_w(szNameBuf), *pfName?"NOT":"");
4520 /* ITypeLib::FindName
4522 * Finds occurrences of a type description in a type library. This may be used
4523 * to quickly verify that a name exists in a type library.
4526 static HRESULT WINAPI ITypeLib2_fnFindName(
4530 ITypeInfo **ppTInfo,
4534 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4535 ITypeInfoImpl *pTInfo;
4536 TLBFuncDesc *pFInfo;
4539 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4541 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4542 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4543 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4544 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4545 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4546 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4547 goto ITypeLib2_fnFindName_exit;
4550 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4551 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4553 ITypeLib2_fnFindName_exit:
4554 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4555 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4558 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4559 This, *pcFound, debugstr_w(szNameBuf), j);
4566 /* ITypeLib::ReleaseTLibAttr
4568 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4571 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4573 TLIBATTR *pTLibAttr)
4575 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4576 TRACE("freeing (%p)\n",This);
4577 HeapFree(GetProcessHeap(),0,pTLibAttr);
4581 /* ITypeLib2::GetCustData
4583 * gets the custom data
4585 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4590 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4591 TLBCustData *pCData;
4593 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4595 if( IsEqualIID(guid, &pCData->guid)) break;
4598 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4602 VariantInit( pVarVal);
4603 VariantCopy( pVarVal, &pCData->data);
4606 return E_INVALIDARG; /* FIXME: correct? */
4609 /* ITypeLib2::GetLibStatistics
4611 * Returns statistics about a type library that are required for efficient
4612 * sizing of hash tables.
4615 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4617 ULONG *pcUniqueNames,
4618 ULONG *pcchUniqueNames)
4620 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4622 FIXME("(%p): stub!\n", This);
4624 if(pcUniqueNames) *pcUniqueNames=1;
4625 if(pcchUniqueNames) *pcchUniqueNames=1;
4629 /* ITypeLib2::GetDocumentation2
4631 * Retrieves the library's documentation string, the complete Help file name
4632 * and path, the localization context to use, and the context ID for the
4633 * library Help topic in the Help file.
4636 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4640 BSTR *pbstrHelpString,
4641 DWORD *pdwHelpStringContext,
4642 BSTR *pbstrHelpStringDll)
4644 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4648 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4650 /* the help string should be obtained from the helpstringdll,
4651 * using the _DLLGetDocumentation function, based on the supplied
4652 * lcid. Nice to do sometime...
4656 /* documentation for the typelib */
4658 *pbstrHelpString=SysAllocString(This->DocString);
4659 if(pdwHelpStringContext)
4660 *pdwHelpStringContext=This->dwHelpContext;
4661 if(pbstrHelpStringDll)
4662 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4668 /* for a typeinfo */
4669 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4671 if(SUCCEEDED(result))
4673 ITypeInfo2 * pTInfo2;
4674 result = ITypeInfo_QueryInterface(pTInfo,
4676 (LPVOID*) &pTInfo2);
4678 if(SUCCEEDED(result))
4680 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4684 pdwHelpStringContext,
4685 pbstrHelpStringDll);
4687 ITypeInfo2_Release(pTInfo2);
4690 ITypeInfo_Release(pTInfo);
4696 /* ITypeLib2::GetAllCustData
4698 * Gets all custom data items for the library.
4701 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4703 CUSTDATA *pCustData)
4705 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4706 TLBCustData *pCData;
4708 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4709 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4710 if(pCustData->prgCustData ){
4711 pCustData->cCustData=This->ctCustData;
4712 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4713 pCustData->prgCustData[i].guid=pCData->guid;
4714 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4717 ERR(" OUT OF MEMORY!\n");
4718 return E_OUTOFMEMORY;
4723 static const ITypeLib2Vtbl tlbvt = {
4724 ITypeLib2_fnQueryInterface,
4726 ITypeLib2_fnRelease,
4727 ITypeLib2_fnGetTypeInfoCount,
4728 ITypeLib2_fnGetTypeInfo,
4729 ITypeLib2_fnGetTypeInfoType,
4730 ITypeLib2_fnGetTypeInfoOfGuid,
4731 ITypeLib2_fnGetLibAttr,
4732 ITypeLib2_fnGetTypeComp,
4733 ITypeLib2_fnGetDocumentation,
4735 ITypeLib2_fnFindName,
4736 ITypeLib2_fnReleaseTLibAttr,
4738 ITypeLib2_fnGetCustData,
4739 ITypeLib2_fnGetLibStatistics,
4740 ITypeLib2_fnGetDocumentation2,
4741 ITypeLib2_fnGetAllCustData
4745 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4747 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4749 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4752 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4754 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4756 return ITypeLib2_AddRef((ITypeLib2 *)This);
4759 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4761 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4763 return ITypeLib2_Release((ITypeLib2 *)This);
4766 static HRESULT WINAPI ITypeLibComp_fnBind(
4771 ITypeInfo ** ppTInfo,
4772 DESCKIND * pDescKind,
4775 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4776 ITypeInfoImpl *pTypeInfo;
4779 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4781 *pDescKind = DESCKIND_NONE;
4782 pBindPtr->lptcomp = NULL;
4785 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4787 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4789 /* FIXME: check wFlags here? */
4790 /* FIXME: we should use a hash table to look this info up using lHash
4791 * instead of an O(n) search */
4792 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4793 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4795 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4797 *pDescKind = DESCKIND_TYPECOMP;
4798 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4799 ITypeComp_AddRef(pBindPtr->lptcomp);
4800 TRACE("module or enum: %s\n", debugstr_w(szName));
4805 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4806 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4808 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4811 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4812 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4814 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4817 else if (hr == TYPE_E_TYPEMISMATCH)
4821 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4822 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4824 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4826 ITypeInfo *subtypeinfo;
4828 DESCKIND subdesckind;
4830 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4831 &subtypeinfo, &subdesckind, &subbindptr);
4832 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4834 TYPEDESC tdesc_appobject;
4835 const VARDESC vardesc_appobject =
4838 NULL, /* lpstrSchema */
4853 VAR_STATIC /* varkind */
4856 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4857 tdesc_appobject.vt = VT_USERDEFINED;
4859 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4861 /* cleanup things filled in by Bind call so we can put our
4862 * application object data in there instead */
4863 switch (subdesckind)
4865 case DESCKIND_FUNCDESC:
4866 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4868 case DESCKIND_VARDESC:
4869 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4874 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4876 if (pTypeInfo->hreftype == -1)
4877 FIXME("no hreftype for interface %p\n", pTypeInfo);
4879 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4883 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4884 *ppTInfo = (ITypeInfo *)pTypeInfo;
4885 ITypeInfo_AddRef(*ppTInfo);
4888 else if (hr == TYPE_E_TYPEMISMATCH)
4895 TRACE("type mismatch %s\n", debugstr_w(szName));
4896 return TYPE_E_TYPEMISMATCH;
4900 TRACE("name not found %s\n", debugstr_w(szName));
4905 static HRESULT WINAPI ITypeLibComp_fnBindType(
4909 ITypeInfo ** ppTInfo,
4910 ITypeComp ** ppTComp)
4912 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4913 ITypeInfoImpl *pTypeInfo;
4915 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4917 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4919 /* FIXME: should use lHash to do the search */
4920 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4922 TRACE("returning %p\n", pTypeInfo);
4923 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4924 ITypeInfo_AddRef(*ppTInfo);
4925 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4926 ITypeComp_AddRef(*ppTComp);
4931 TRACE("not found\n");
4937 static const ITypeCompVtbl tlbtcvt =
4940 ITypeLibComp_fnQueryInterface,
4941 ITypeLibComp_fnAddRef,
4942 ITypeLibComp_fnRelease,
4944 ITypeLibComp_fnBind,
4945 ITypeLibComp_fnBindType
4948 /*================== ITypeInfo(2) Methods ===================================*/
4949 static ITypeInfo2 * ITypeInfo_Constructor(void)
4951 ITypeInfoImpl * pTypeInfoImpl;
4953 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4956 pTypeInfoImpl->lpVtbl = &tinfvt;
4957 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4958 pTypeInfoImpl->ref = 0;
4959 pTypeInfoImpl->hreftype = -1;
4960 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4961 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4963 TRACE("(%p)\n", pTypeInfoImpl);
4964 return (ITypeInfo2*) pTypeInfoImpl;
4967 /* ITypeInfo::QueryInterface
4969 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4974 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4976 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4979 if(IsEqualIID(riid, &IID_IUnknown) ||
4980 IsEqualIID(riid,&IID_ITypeInfo)||
4981 IsEqualIID(riid,&IID_ITypeInfo2))
4985 ITypeInfo_AddRef(iface);
4986 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4989 TRACE("-- Interface: E_NOINTERFACE\n");
4990 return E_NOINTERFACE;
4993 /* ITypeInfo::AddRef
4995 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4997 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4998 ULONG ref = InterlockedIncrement(&This->ref);
5000 TRACE("(%p)->ref is %u\n",This, ref);
5002 if (ref == 1 /* incremented from 0 */)
5003 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
5008 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This)
5010 TLBFuncDesc *pFInfo, *pFInfoNext;
5011 TLBVarDesc *pVInfo, *pVInfoNext;
5012 TLBImplType *pImpl, *pImplNext;
5014 TRACE("destroying ITypeInfo(%p)\n",This);
5016 SysFreeString(This->Name);
5019 SysFreeString(This->DocString);
5020 This->DocString = NULL;
5022 SysFreeString(This->DllName);
5023 This->DllName = NULL;
5025 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
5028 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
5030 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
5031 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5033 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5034 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
5036 SysFreeString(pFInfo->pParamDesc[i].Name);
5038 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
5039 TLB_Free(pFInfo->pParamDesc);
5040 TLB_FreeCustData(pFInfo->pCustData);
5041 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
5042 SysFreeString(pFInfo->Entry);
5043 SysFreeString(pFInfo->HelpString);
5044 SysFreeString(pFInfo->Name);
5046 pFInfoNext = pFInfo->next;
5049 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5051 if (pVInfo->vardesc.varkind == VAR_CONST)
5053 VariantClear(pVInfo->vardesc.u.lpvarValue);
5054 TLB_Free(pVInfo->vardesc.u.lpvarValue);
5056 TLB_FreeCustData(pVInfo->pCustData);
5057 SysFreeString(pVInfo->Name);
5058 pVInfoNext = pVInfo->next;
5061 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5063 TLB_FreeCustData(pImpl->pCustData);
5064 pImplNext = pImpl->next;
5067 TLB_FreeCustData(This->pCustData);
5069 HeapFree(GetProcessHeap(), 0, This);
5072 /* ITypeInfo::Release
5074 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5076 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5077 ULONG ref = InterlockedDecrement(&This->ref);
5079 TRACE("(%p)->(%u)\n",This, ref);
5083 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5084 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5085 if (not_attached_to_typelib)
5086 HeapFree(GetProcessHeap(), 0, This);
5087 /* otherwise This will be freed when typelib is freed */
5093 /* ITypeInfo::GetTypeAttr
5095 * Retrieves a TYPEATTR structure that contains the attributes of the type
5099 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5100 LPTYPEATTR *ppTypeAttr)
5102 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5105 TRACE("(%p)\n",This);
5107 size = sizeof(**ppTypeAttr);
5108 if (This->TypeAttr.typekind == TKIND_ALIAS)
5109 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5111 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5113 return E_OUTOFMEMORY;
5115 **ppTypeAttr = This->TypeAttr;
5117 if (This->TypeAttr.typekind == TKIND_ALIAS)
5118 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5119 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5121 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5122 /* This should include all the inherited funcs */
5123 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5124 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5125 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5130 /* ITypeInfo::GetTypeComp
5132 * Retrieves the ITypeComp interface for the type description, which enables a
5133 * client compiler to bind to the type description's members.
5136 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5137 ITypeComp * *ppTComp)
5139 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5141 TRACE("(%p)->(%p)\n", This, ppTComp);
5143 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5144 ITypeComp_AddRef(*ppTComp);
5148 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5150 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5151 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5152 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5156 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5159 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5160 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5162 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5163 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5164 *buffer += sizeof(PARAMDESCEX);
5165 *pparamdescex_dest = *pparamdescex_src;
5166 VariantInit(&pparamdescex_dest->varDefaultValue);
5167 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5168 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5171 dest->u.paramdesc.pparamdescex = NULL;
5175 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5177 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5178 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5181 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5185 SIZE_T size = sizeof(*src);
5189 size += sizeof(*src->lprgscode) * src->cScodes;
5190 size += TLB_SizeElemDesc(&src->elemdescFunc);
5191 for (i = 0; i < src->cParams; i++)
5193 size += sizeof(ELEMDESC);
5194 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5197 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5198 if (!dest) return E_OUTOFMEMORY;
5201 if (dispinterface) /* overwrite funckind */
5202 dest->funckind = FUNC_DISPATCH;
5203 buffer = (char *)(dest + 1);
5205 dest->lprgscode = (SCODE *)buffer;
5206 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5207 buffer += sizeof(*src->lprgscode) * src->cScodes;
5209 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5212 SysFreeString((BSTR)dest);
5216 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5217 buffer += sizeof(ELEMDESC) * src->cParams;
5218 for (i = 0; i < src->cParams; i++)
5220 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5226 /* undo the above actions */
5227 for (i = i - 1; i >= 0; i--)
5228 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5229 TLB_FreeElemDesc(&dest->elemdescFunc);
5230 SysFreeString((BSTR)dest);
5234 /* special treatment for dispinterfaces: this makes functions appear
5235 * to return their [retval] value when it is really returning an
5237 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5239 if (dest->cParams &&
5240 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5242 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5243 if (elemdesc->tdesc.vt != VT_PTR)
5245 ERR("elemdesc should have started with VT_PTR instead of:\n");
5247 dump_ELEMDESC(elemdesc);
5248 return E_UNEXPECTED;
5251 /* copy last parameter to the return value. we are using a flat
5252 * buffer so there is no danger of leaking memory in
5254 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5256 /* remove the last parameter */
5260 /* otherwise this function is made to appear to have no return
5262 dest->elemdescFunc.tdesc.vt = VT_VOID;
5270 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5272 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5273 const TLBFuncDesc *pFDesc;
5276 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5281 *ppFuncDesc = &pFDesc->funcdesc;
5285 return TYPE_E_ELEMENTNOTFOUND;
5288 /* internal function to make the inherited interfaces' methods appear
5289 * part of the interface */
5290 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5291 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5293 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5295 UINT implemented_funcs = 0;
5300 *hrefoffset = DISPATCH_HREF_OFFSET;
5302 if(This->impltypelist)
5304 ITypeInfo *pSubTypeInfo;
5307 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5311 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5314 &sub_funcs, hrefoffset);
5315 implemented_funcs += sub_funcs;
5316 ITypeInfo_Release(pSubTypeInfo);
5319 *hrefoffset += DISPATCH_HREF_OFFSET;
5323 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5327 if (index < implemented_funcs)
5328 return E_INVALIDARG;
5329 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5333 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5335 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5338 switch (pTypeDesc->vt)
5340 case VT_USERDEFINED:
5341 pTypeDesc->u.hreftype += hrefoffset;
5345 pTypeDesc = pTypeDesc->u.lptdesc;
5348 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5356 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5359 for (i = 0; i < pFuncDesc->cParams; i++)
5360 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5361 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5364 /* ITypeInfo::GetFuncDesc
5366 * Retrieves the FUNCDESC structure that contains information about a
5367 * specified function.
5370 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5371 LPFUNCDESC *ppFuncDesc)
5373 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5374 const FUNCDESC *internal_funcdesc;
5376 UINT hrefoffset = 0;
5378 TRACE("(%p) index %d\n", This, index);
5380 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5381 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5382 &internal_funcdesc, NULL,
5385 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5386 &internal_funcdesc);
5389 WARN("description for function %d not found\n", index);
5393 hr = TLB_AllocAndInitFuncDesc(
5396 This->TypeAttr.typekind == TKIND_DISPATCH);
5398 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5399 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5401 TRACE("-- 0x%08x\n", hr);
5405 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5409 SIZE_T size = sizeof(*src);
5412 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5413 if (src->varkind == VAR_CONST)
5414 size += sizeof(VARIANT);
5415 size += TLB_SizeElemDesc(&src->elemdescVar);
5417 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5418 if (!dest) return E_OUTOFMEMORY;
5421 buffer = (char *)(dest + 1);
5422 if (src->lpstrSchema)
5425 dest->lpstrSchema = (LPOLESTR)buffer;
5426 len = strlenW(src->lpstrSchema);
5427 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5428 buffer += (len + 1) * sizeof(WCHAR);
5431 if (src->varkind == VAR_CONST)
5435 dest->u.lpvarValue = (VARIANT *)buffer;
5436 *dest->u.lpvarValue = *src->u.lpvarValue;
5437 buffer += sizeof(VARIANT);
5438 VariantInit(dest->u.lpvarValue);
5439 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5442 SysFreeString((BSTR)dest);
5446 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5449 if (src->varkind == VAR_CONST)
5450 VariantClear(dest->u.lpvarValue);
5451 SysFreeString((BSTR)dest);
5458 /* ITypeInfo::GetVarDesc
5460 * Retrieves a VARDESC structure that describes the specified variable.
5463 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5464 LPVARDESC *ppVarDesc)
5466 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5468 const TLBVarDesc *pVDesc;
5470 TRACE("(%p) index %d\n", This, index);
5472 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5476 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5478 return E_INVALIDARG;
5481 /* ITypeInfo_GetNames
5483 * Retrieves the variable with the specified member ID (or the name of the
5484 * property or method and its parameters) that correspond to the specified
5487 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5488 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5490 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5491 const TLBFuncDesc *pFDesc;
5492 const TLBVarDesc *pVDesc;
5494 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5495 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5498 /* function found, now return function and parameter names */
5499 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5502 *rgBstrNames=SysAllocString(pFDesc->Name);
5504 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5510 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5513 *rgBstrNames=SysAllocString(pVDesc->Name);
5518 if(This->impltypelist &&
5519 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5520 /* recursive search */
5523 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5525 if(SUCCEEDED(result))
5527 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5528 ITypeInfo_Release(pTInfo);
5531 WARN("Could not search inherited interface!\n");
5535 WARN("no names found\n");
5538 return TYPE_E_ELEMENTNOTFOUND;
5545 /* ITypeInfo::GetRefTypeOfImplType
5547 * If a type description describes a COM class, it retrieves the type
5548 * description of the implemented interface types. For an interface,
5549 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5553 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5558 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5561 const TLBImplType *pImpl = This->impltypelist;
5563 TRACE("(%p) index %d\n", This, index);
5564 if (TRACE_ON(ole)) dump_TypeInfo(This);
5568 /* only valid on dual interfaces;
5569 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5571 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5573 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5579 hr = TYPE_E_ELEMENTNOTFOUND;
5582 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5584 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5585 *pRefType = This->pTypeLib->dispatch_href;
5589 /* get element n from linked list */
5590 for(i=0; pImpl && i<index; i++)
5592 pImpl = pImpl->next;
5596 *pRefType = pImpl->hRef;
5598 hr = TYPE_E_ELEMENTNOTFOUND;
5604 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5606 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5612 /* ITypeInfo::GetImplTypeFlags
5614 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5615 * or base interface in a type description.
5617 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5618 UINT index, INT *pImplTypeFlags)
5620 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5624 TRACE("(%p) index %d\n", This, index);
5625 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5626 i++, pImpl=pImpl->next)
5628 if(i==index && pImpl){
5629 *pImplTypeFlags=pImpl->implflags;
5634 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5637 WARN("ImplType %d not found\n", index);
5638 return TYPE_E_ELEMENTNOTFOUND;
5642 * Maps between member names and member IDs, and parameter names and
5645 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5646 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5648 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5649 const TLBFuncDesc *pFDesc;
5650 const TLBVarDesc *pVDesc;
5654 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5657 /* init out parameters in case of failure */
5658 for (i = 0; i < cNames; i++)
5659 pMemId[i] = MEMBERID_NIL;
5661 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5663 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5664 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5665 for(i=1; i < cNames; i++){
5666 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5667 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5669 if( j<pFDesc->funcdesc.cParams)
5672 ret=DISP_E_UNKNOWNNAME;
5674 TRACE("-- 0x%08x\n", ret);
5678 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5679 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5680 if(cNames) *pMemId=pVDesc->vardesc.memid;
5684 /* not found, see if it can be found in an inherited interface */
5685 if(This->impltypelist) {
5686 /* recursive search */
5688 ret=ITypeInfo_GetRefTypeInfo(iface,
5689 This->impltypelist->hRef, &pTInfo);
5691 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5692 ITypeInfo_Release(pTInfo);
5695 WARN("Could not search inherited interface!\n");
5697 WARN("no names found\n");
5698 return DISP_E_UNKNOWNNAME;
5704 extern DWORD CDECL call_method( void *func, int nb_args, const DWORD *args );
5705 __ASM_GLOBAL_FUNC( call_method,
5707 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5708 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5709 "movl %esp,%ebp\n\t"
5710 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5712 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5714 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5715 "movl 12(%ebp),%edx\n\t"
5718 "subl %edx,%esp\n\t"
5719 "andl $~15,%esp\n\t"
5720 "movl 12(%ebp),%ecx\n\t"
5721 "movl 16(%ebp),%esi\n\t"
5722 "movl %esp,%edi\n\t"
5725 "1:\tcall *8(%ebp)\n\t"
5726 "leal -8(%ebp),%esp\n\t"
5728 __ASM_CFI(".cfi_same_value %edi\n\t")
5730 __ASM_CFI(".cfi_same_value %esi\n\t")
5732 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5733 __ASM_CFI(".cfi_same_value %ebp\n\t")
5736 /* ITypeInfo::Invoke
5738 * Invokes a method, or accesses a property of an object, that implements the
5739 * interface described by the type description.
5742 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5745 if (TRACE_ON(ole)) {
5747 TRACE("Calling %p(",func);
5748 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5749 if (nrargs > 30) TRACE("...");
5756 res = call_method( func, nrargs, args );
5759 FIXME("unsupported calling convention %d\n",callconv);
5763 TRACE("returns %08x\n",res);
5767 /* The size of the argument on the stack in DWORD units (in all x86 call
5768 * convetions the arguments on the stack are DWORD-aligned)
5770 static int _dispargsize(VARTYPE vt)
5775 return 8/sizeof(DWORD);
5777 return sizeof(double)/sizeof(DWORD);
5779 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5781 return sizeof(CY)/sizeof(DWORD);
5783 return sizeof(DATE)/sizeof(DWORD);
5785 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5787 FIXME("VT_RECORD not implemented\n");
5793 #endif /* __i386__ */
5795 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5798 ITypeInfo *tinfo2 = NULL;
5799 TYPEATTR *tattr = NULL;
5801 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5804 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5806 tdesc->u.hreftype, hr);
5809 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5812 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5813 ITypeInfo_Release(tinfo2);
5817 switch (tattr->typekind)
5824 tdesc = &tattr->tdescAlias;
5825 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5828 case TKIND_INTERFACE:
5829 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5835 case TKIND_DISPATCH:
5844 FIXME("TKIND_RECORD unhandled.\n");
5849 FIXME("TKIND_UNION unhandled.\n");
5854 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5858 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5859 ITypeInfo_Release(tinfo2);
5863 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5867 /* enforce only one level of pointer indirection */
5868 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5870 tdesc = tdesc->u.lptdesc;
5872 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5873 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5874 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5875 if ((tdesc->vt == VT_USERDEFINED) ||
5876 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5878 VARTYPE vt_userdefined = 0;
5879 const TYPEDESC *tdesc_userdefined = tdesc;
5880 if (tdesc->vt == VT_PTR)
5882 vt_userdefined = VT_BYREF;
5883 tdesc_userdefined = tdesc->u.lptdesc;
5885 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5887 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5888 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5890 *vt |= vt_userdefined;
5902 case VT_USERDEFINED:
5903 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5910 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5911 hr = DISP_E_BADVARTYPE;
5915 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5930 /***********************************************************************
5931 * DispCallFunc (OLEAUT32.@)
5933 * Invokes a function of the specified calling convention, passing the
5934 * specified arguments and returns the result.
5937 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5938 * oVft [I] The offset in the vtable. See notes.
5939 * cc [I] Calling convention of the function to call.
5940 * vtReturn [I] The return type of the function.
5941 * cActuals [I] Number of parameters.
5942 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5943 * prgpvarg [I] The arguments to pass.
5944 * pvargResult [O] The return value of the function. Can be NULL.
5948 * Failure: HRESULT code.
5951 * The HRESULT return value of this function is not affected by the return
5952 * value of the user supplied function, which is returned in pvargResult.
5954 * If pvInstance is NULL then a non-object function is to be called and oVft
5955 * is the address of the function to call.
5957 * The cc parameter can be one of the following values:
5970 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5971 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5974 int argsize, argspos;
5979 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5980 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5981 pvargResult, V_VT(pvargResult));
5985 argsize++; /* for This pointer */
5987 for (i=0;i<cActuals;i++)
5989 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5990 dump_Variant(prgpvarg[i]);
5991 argsize += _dispargsize(prgvt[i]);
5993 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5998 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
6002 for (i=0;i<cActuals;i++)
6004 VARIANT *arg = prgpvarg[i];
6005 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
6006 if (prgvt[i] == VT_VARIANT)
6007 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
6009 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
6010 argspos += _dispargsize(prgvt[i]);
6015 FARPROC *vtable = *(FARPROC**)pvInstance;
6016 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
6019 /* if we aren't invoking an object then the function pointer is stored
6021 hres = _invoke((FARPROC)oVft, cc, argsize, args);
6023 if (pvargResult && (vtReturn != VT_EMPTY))
6025 TRACE("Method returned 0x%08x\n",hres);
6026 V_VT(pvargResult) = vtReturn;
6027 V_UI4(pvargResult) = hres;
6029 HeapFree(GetProcessHeap(),0,args);
6032 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6033 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
6038 #define INVBUF_ELEMENT_SIZE \
6039 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6040 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6041 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6042 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6043 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6044 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6045 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6046 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6048 static HRESULT WINAPI ITypeInfo_fnInvoke(
6053 DISPPARAMS *pDispParams,
6054 VARIANT *pVarResult,
6055 EXCEPINFO *pExcepInfo,
6058 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6060 unsigned int var_index;
6063 const TLBFuncDesc *pFuncInfo;
6065 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6066 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6069 if( This->TypeAttr.wTypeFlags & TYPEFLAG_FRESTRICTED )
6070 return DISP_E_MEMBERNOTFOUND;
6074 ERR("NULL pDispParams not allowed\n");
6075 return E_INVALIDARG;
6078 dump_DispParms(pDispParams);
6080 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6082 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6083 pDispParams->cNamedArgs, pDispParams->cArgs);
6084 return E_INVALIDARG;
6087 /* we do this instead of using GetFuncDesc since it will return a fake
6088 * FUNCDESC for dispinterfaces and we want the real function description */
6089 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6090 if ((memid == pFuncInfo->funcdesc.memid) &&
6091 (wFlags & pFuncInfo->funcdesc.invkind) &&
6092 (pFuncInfo->funcdesc.wFuncFlags & FUNCFLAG_FRESTRICTED) == 0)
6096 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6100 TRACE("invoking:\n");
6101 dump_TLBFuncDescOne(pFuncInfo);
6104 switch (func_desc->funckind) {
6105 case FUNC_PUREVIRTUAL:
6106 case FUNC_VIRTUAL: {
6107 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6109 VARIANT retval; /* pointer for storing byref retvals in */
6110 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6111 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6112 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6113 UINT cNamedArgs = pDispParams->cNamedArgs;
6114 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6115 UINT vargs_converted=0;
6119 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6121 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6123 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6124 hres = DISP_E_PARAMNOTFOUND;
6129 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6131 ERR("functions with the vararg attribute do not support named arguments\n");
6132 hres = DISP_E_NONAMEDARGS;
6136 for (i = 0; i < func_desc->cParams; i++)
6138 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6139 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6144 TRACE("changing args\n");
6145 for (i = 0; i < func_desc->cParams; i++)
6147 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6148 VARIANTARG *src_arg;
6150 if (wParamFlags & PARAMFLAG_FLCID)
6153 arg = prgpvarg[i] = &rgvarg[i];
6155 V_I4(arg) = This->pTypeLib->lcid;
6164 for (j = 0; j < cNamedArgs; j++)
6165 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6167 src_arg = &pDispParams->rgvarg[j];
6172 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6174 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6178 if (wParamFlags & PARAMFLAG_FRETVAL)
6180 /* under most conditions the caller is not allowed to
6181 * pass in a dispparam arg in the index of what would be
6182 * the retval parameter. however, there is an exception
6183 * where the extra parameter is used in an extra
6184 * IDispatch::Invoke below */
6185 if ((i < pDispParams->cArgs) &&
6186 ((func_desc->cParams != 1) || !pVarResult ||
6187 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6189 hres = DISP_E_BADPARAMCOUNT;
6193 /* note: this check is placed so that if the caller passes
6194 * in a VARIANTARG for the retval we just ignore it, like
6196 if (i == func_desc->cParams - 1)
6199 arg = prgpvarg[i] = &rgvarg[i];
6200 memset(arg, 0, sizeof(*arg));
6201 V_VT(arg) = rgvt[i];
6202 memset(&retval, 0, sizeof(retval));
6203 V_BYREF(arg) = &retval;
6207 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6208 hres = E_UNEXPECTED;
6214 dump_Variant(src_arg);
6216 if (rgvt[i] == VT_VARIANT)
6217 hres = VariantCopy(&rgvarg[i], src_arg);
6218 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6220 if (rgvt[i] == V_VT(src_arg))
6221 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6224 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6225 if (wParamFlags & PARAMFLAG_FIN)
6226 hres = VariantCopy(&missing_arg[i], src_arg);
6227 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6229 V_VT(&rgvarg[i]) = rgvt[i];
6231 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6234 SAFEARRAYBOUND bound;
6238 bound.cElements = pDispParams->cArgs-i;
6239 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6241 ERR("SafeArrayCreate failed\n");
6244 hres = SafeArrayAccessData(a, (LPVOID)&v);
6247 ERR("SafeArrayAccessData failed with %x\n", hres);
6250 for (j = 0; j < bound.cElements; j++)
6251 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6252 hres = SafeArrayUnaccessData(a);
6255 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6258 V_ARRAY(&rgvarg[i]) = a;
6259 V_VT(&rgvarg[i]) = rgvt[i];
6261 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6263 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6264 if (wParamFlags & PARAMFLAG_FIN)
6265 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6267 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6268 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6269 V_VT(&rgvarg[i]) = rgvt[i];
6271 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6273 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6274 V_VT(&rgvarg[i]) = rgvt[i];
6278 /* FIXME: this doesn't work for VT_BYREF arguments if
6279 * they are not the same type as in the paramdesc */
6280 V_VT(&rgvarg[i]) = V_VT(src_arg);
6281 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6282 V_VT(&rgvarg[i]) = rgvt[i];
6287 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6288 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6289 debugstr_VT(src_arg), debugstr_VF(src_arg));
6292 prgpvarg[i] = &rgvarg[i];
6294 else if (wParamFlags & PARAMFLAG_FOPT)
6297 arg = prgpvarg[i] = &rgvarg[i];
6298 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6300 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6306 VARIANTARG *missing_arg;
6307 /* if the function wants a pointer to a variant then
6308 * set that up, otherwise just pass the VT_ERROR in
6309 * the argument by value */
6310 if (rgvt[i] & VT_BYREF)
6312 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6313 V_VT(arg) = VT_VARIANT | VT_BYREF;
6314 V_VARIANTREF(arg) = missing_arg;
6318 V_VT(missing_arg) = VT_ERROR;
6319 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6324 hres = DISP_E_BADPARAMCOUNT;
6328 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6330 /* VT_VOID is a special case for return types, so it is not
6331 * handled in the general function */
6332 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6333 V_VT(&varresult) = VT_EMPTY;
6336 V_VT(&varresult) = 0;
6337 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6338 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6341 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6342 V_VT(&varresult), func_desc->cParams, rgvt,
6343 prgpvarg, &varresult);
6345 vargs_converted = 0;
6347 for (i = 0; i < func_desc->cParams; i++)
6349 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6350 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6352 if (wParamFlags & PARAMFLAG_FLCID)
6354 else if (wParamFlags & PARAMFLAG_FRETVAL)
6358 TRACE("[retval] value: ");
6359 dump_Variant(prgpvarg[i]);
6364 VariantInit(pVarResult);
6365 /* deref return value */
6366 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6369 VARIANT_ClearInd(prgpvarg[i]);
6371 else if (vargs_converted < pDispParams->cArgs)
6373 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6374 if (wParamFlags & PARAMFLAG_FOUT)
6376 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6378 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6382 ERR("failed to convert param %d to vt %d\n", i,
6383 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6388 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6389 func_desc->cParamsOpt < 0 &&
6390 i == func_desc->cParams-1)
6392 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6395 hres = SafeArrayGetUBound(a, 1, &ubound);
6398 ERR("SafeArrayGetUBound failed with %x\n", hres);
6401 hres = SafeArrayAccessData(a, (LPVOID)&v);
6404 ERR("SafeArrayAccessData failed with %x\n", hres);
6407 for (j = 0; j <= ubound; j++)
6408 VariantClear(&v[j]);
6409 hres = SafeArrayUnaccessData(a);
6412 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6416 VariantClear(&rgvarg[i]);
6419 else if (wParamFlags & PARAMFLAG_FOPT)
6421 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6422 VariantClear(&rgvarg[i]);
6425 VariantClear(&missing_arg[i]);
6428 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6430 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6431 hres = DISP_E_EXCEPTION;
6434 IErrorInfo *pErrorInfo;
6435 pExcepInfo->scode = V_ERROR(&varresult);
6436 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6438 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6439 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6440 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6441 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6443 IErrorInfo_Release(pErrorInfo);
6447 if (V_VT(&varresult) != VT_ERROR)
6449 TRACE("varresult value: ");
6450 dump_Variant(&varresult);
6454 VariantClear(pVarResult);
6455 *pVarResult = varresult;
6458 VariantClear(&varresult);
6461 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6462 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6463 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6464 (pDispParams->cArgs != 0))
6466 if (V_VT(pVarResult) == VT_DISPATCH)
6468 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6469 /* Note: not VariantClear; we still need the dispatch
6470 * pointer to be valid */
6471 VariantInit(pVarResult);
6472 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6473 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6474 pDispParams, pVarResult, pExcepInfo, pArgErr);
6475 IDispatch_Release(pDispatch);
6479 VariantClear(pVarResult);
6480 hres = DISP_E_NOTACOLLECTION;
6485 HeapFree(GetProcessHeap(), 0, buffer);
6488 case FUNC_DISPATCH: {
6491 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6492 if (SUCCEEDED(hres)) {
6493 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6494 hres = IDispatch_Invoke(
6495 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6496 pVarResult,pExcepInfo,pArgErr
6499 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6500 IDispatch_Release(disp);
6502 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6506 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6511 TRACE("-- 0x%08x\n", hres);
6514 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6517 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6518 if(FAILED(hres)) return hres;
6520 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6521 dump_VARDESC(var_desc);
6522 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6526 /* not found, look for it in inherited interfaces */
6527 ITypeInfo2_GetTypeKind(iface, &type_kind);
6528 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6529 if(This->impltypelist) {
6530 /* recursive search */
6532 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6533 if(SUCCEEDED(hres)){
6534 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6535 ITypeInfo_Release(pTInfo);
6538 WARN("Could not search inherited interface!\n");
6541 WARN("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6542 return DISP_E_MEMBERNOTFOUND;
6545 /* ITypeInfo::GetDocumentation
6547 * Retrieves the documentation string, the complete Help file name and path,
6548 * and the context ID for the Help topic for a specified type description.
6550 * (Can be tested by the Visual Basic Editor in Word for instance.)
6552 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6553 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6554 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6556 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6557 const TLBFuncDesc *pFDesc;
6558 const TLBVarDesc *pVDesc;
6559 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6560 " HelpContext(%p) HelpFile(%p)\n",
6561 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6562 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6564 *pBstrName=SysAllocString(This->Name);
6566 *pBstrDocString=SysAllocString(This->DocString);
6568 *pdwHelpContext=This->dwHelpContext;
6570 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6572 }else {/* for a member */
6573 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6574 if(pFDesc->funcdesc.memid==memid){
6576 *pBstrName = SysAllocString(pFDesc->Name);
6578 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6580 *pdwHelpContext=pFDesc->helpcontext;
6583 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6584 if(pVDesc->vardesc.memid==memid){
6586 *pBstrName = SysAllocString(pVDesc->Name);
6588 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6590 *pdwHelpContext=pVDesc->HelpContext;
6595 if(This->impltypelist &&
6596 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6597 /* recursive search */
6600 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6602 if(SUCCEEDED(result)) {
6603 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6604 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6605 ITypeInfo_Release(pTInfo);
6608 WARN("Could not search inherited interface!\n");
6611 WARN("member %d not found\n", memid);
6612 return TYPE_E_ELEMENTNOTFOUND;
6615 /* ITypeInfo::GetDllEntry
6617 * Retrieves a description or specification of an entry point for a function
6620 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6621 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6624 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6625 const TLBFuncDesc *pFDesc;
6627 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6629 if (pBstrDllName) *pBstrDllName = NULL;
6630 if (pBstrName) *pBstrName = NULL;
6631 if (pwOrdinal) *pwOrdinal = 0;
6633 if (This->TypeAttr.typekind != TKIND_MODULE)
6634 return TYPE_E_BADMODULEKIND;
6636 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6637 if(pFDesc->funcdesc.memid==memid){
6638 dump_TypeInfo(This);
6640 dump_TLBFuncDescOne(pFDesc);
6643 *pBstrDllName = SysAllocString(This->DllName);
6645 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6647 *pBstrName = SysAllocString(pFDesc->Entry);
6655 *pwOrdinal = LOWORD(pFDesc->Entry);
6658 return TYPE_E_ELEMENTNOTFOUND;
6661 /* internal function to make the inherited interfaces' methods appear
6662 * part of the interface */
6663 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6664 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6666 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6669 TRACE("%p, 0x%x\n", iface, *hRefType);
6671 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6673 ITypeInfo *pSubTypeInfo;
6675 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6679 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6681 ITypeInfo_Release(pSubTypeInfo);
6685 *hRefType -= DISPATCH_HREF_OFFSET;
6687 if (!(*hRefType & DISPATCH_HREF_MASK))
6688 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6693 /* ITypeInfo::GetRefTypeInfo
6695 * If a type description references other type descriptions, it retrieves
6696 * the referenced type descriptions.
6698 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6701 ITypeInfo **ppTInfo)
6703 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6704 HRESULT result = E_FAIL;
6706 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6708 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6709 ITypeInfo_AddRef(*ppTInfo);
6712 else if (hRefType == -1 &&
6713 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6714 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6716 /* when we meet a DUAL dispinterface, we must create the interface
6719 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6722 /* the interface version contains the same information as the dispinterface
6723 * copy the contents of the structs.
6725 *pTypeInfoImpl = *This;
6726 pTypeInfoImpl->ref = 0;
6728 /* change the type to interface */
6729 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6731 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6733 /* the AddRef implicitly adds a reference to the parent typelib, which
6734 * stops the copied data from being destroyed until the new typeinfo's
6735 * refcount goes to zero, but we need to signal to the new instance to
6736 * not free its data structures when it is destroyed */
6737 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6739 ITypeInfo_AddRef(*ppTInfo);
6743 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6744 (This->TypeAttr.typekind == TKIND_DISPATCH))
6746 HREFTYPE href_dispatch = hRefType;
6747 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6749 TLBRefType *ref_type;
6750 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6752 if(ref_type->reference == hRefType)
6755 if(&ref_type->entry == &This->pTypeLib->ref_list)
6757 FIXME("Can't find pRefType for ref %x\n", hRefType);
6760 if(hRefType != -1) {
6761 ITypeLib *pTLib = NULL;
6763 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6765 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6767 if(ref_type->pImpTLInfo->pImpTypeLib) {
6768 TRACE("typeinfo in imported typelib that is already loaded\n");
6769 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6770 ITypeLib2_AddRef(pTLib);
6773 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6774 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6775 ref_type->pImpTLInfo->wVersionMajor,
6776 ref_type->pImpTLInfo->wVersionMinor,
6777 ref_type->pImpTLInfo->lcid,
6780 if(FAILED(result)) {
6781 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6782 result=LoadTypeLib(libnam, &pTLib);
6783 SysFreeString(libnam);
6785 if(SUCCEEDED(result)) {
6786 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6787 ITypeLib2_AddRef(pTLib);
6791 if(SUCCEEDED(result)) {
6792 if(ref_type->index == TLB_REF_USE_GUID)
6793 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6797 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6801 ITypeLib2_Release(pTLib);
6806 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6807 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6811 /* ITypeInfo::AddressOfMember
6813 * Retrieves the addresses of static functions or variables, such as those
6816 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6817 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6819 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6825 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6827 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6831 module = LoadLibraryW(dll);
6834 ERR("couldn't load %s\n", debugstr_w(dll));
6836 SysFreeString(entry);
6837 return STG_E_FILENOTFOUND;
6839 /* FIXME: store library somewhere where we can free it */
6844 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6845 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6846 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6848 *ppv = GetProcAddress(module, entryA);
6850 ERR("function not found %s\n", debugstr_a(entryA));
6852 HeapFree(GetProcessHeap(), 0, entryA);
6856 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6858 ERR("function not found %d\n", ordinal);
6862 SysFreeString(entry);
6865 return TYPE_E_DLLFUNCTIONNOTFOUND;
6870 /* ITypeInfo::CreateInstance
6872 * Creates a new instance of a type that describes a component object class
6875 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6876 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6878 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6882 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6888 WARN("Not able to aggregate\n");
6889 return CLASS_E_NOAGGREGATION;
6892 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6893 if(FAILED(hr)) return hr;
6895 if(pTA->typekind != TKIND_COCLASS)
6897 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6903 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6906 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6907 TRACE("GetActiveObject rets %08x\n", hr);
6910 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6911 IUnknown_Release(pUnk);
6916 hr = CoCreateInstance(&pTA->guid, NULL,
6917 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6921 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6925 /* ITypeInfo::GetMops
6927 * Retrieves marshalling information.
6929 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6932 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6933 FIXME("(%p %d) stub!\n", This, memid);
6938 /* ITypeInfo::GetContainingTypeLib
6940 * Retrieves the containing type library and the index of the type description
6941 * within that type library.
6943 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6944 ITypeLib * *ppTLib, UINT *pIndex)
6946 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6948 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6950 *pIndex=This->index;
6951 TRACE("returning pIndex=%d\n", *pIndex);
6955 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6956 ITypeLib2_AddRef(*ppTLib);
6957 TRACE("returning ppTLib=%p\n", *ppTLib);
6963 /* ITypeInfo::ReleaseTypeAttr
6965 * Releases a TYPEATTR previously returned by GetTypeAttr.
6968 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6969 TYPEATTR* pTypeAttr)
6971 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6972 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6973 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6976 /* ITypeInfo::ReleaseFuncDesc
6978 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6980 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6982 FUNCDESC *pFuncDesc)
6984 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6987 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6989 for (i = 0; i < pFuncDesc->cParams; i++)
6990 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6991 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6993 SysFreeString((BSTR)pFuncDesc);
6996 /* ITypeInfo::ReleaseVarDesc
6998 * Releases a VARDESC previously returned by GetVarDesc.
7000 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
7003 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7004 TRACE("(%p)->(%p)\n", This, pVarDesc);
7006 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
7007 if (pVarDesc->varkind == VAR_CONST)
7008 VariantClear(pVarDesc->u.lpvarValue);
7009 SysFreeString((BSTR)pVarDesc);
7012 /* ITypeInfo2::GetTypeKind
7014 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7017 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
7018 TYPEKIND *pTypeKind)
7020 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7021 *pTypeKind=This->TypeAttr.typekind;
7022 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
7026 /* ITypeInfo2::GetTypeFlags
7028 * Returns the type flags without any allocations. This returns a DWORD type
7029 * flag, which expands the type flags without growing the TYPEATTR (type
7033 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
7035 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7036 *pTypeFlags=This->TypeAttr.wTypeFlags;
7037 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
7041 /* ITypeInfo2::GetFuncIndexOfMemId
7042 * Binds to a specific member based on a known DISPID, where the member name
7043 * is not known (for example, when binding to a default member).
7046 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7047 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7049 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7050 const TLBFuncDesc *pFuncInfo;
7054 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7055 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7061 result = TYPE_E_ELEMENTNOTFOUND;
7063 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7064 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7068 /* TypeInfo2::GetVarIndexOfMemId
7070 * Binds to a specific member based on a known DISPID, where the member name
7071 * is not known (for example, when binding to a default member).
7074 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7075 MEMBERID memid, UINT *pVarIndex)
7077 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7078 TLBVarDesc *pVarInfo;
7081 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7082 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7088 result = TYPE_E_ELEMENTNOTFOUND;
7090 TRACE("(%p) memid 0x%08x -> %s\n", This,
7091 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7095 /* ITypeInfo2::GetCustData
7097 * Gets the custom data
7099 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7104 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7105 TLBCustData *pCData;
7107 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7108 if( IsEqualIID(guid, &pCData->guid)) break;
7110 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7112 VariantInit( pVarVal);
7114 VariantCopy( pVarVal, &pCData->data);
7116 VariantClear( pVarVal );
7120 /* ITypeInfo2::GetFuncCustData
7122 * Gets the custom data
7124 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7130 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7131 TLBCustData *pCData=NULL;
7132 TLBFuncDesc * pFDesc;
7134 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7135 pFDesc=pFDesc->next);
7138 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7139 if( IsEqualIID(guid, &pCData->guid)) break;
7141 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7144 VariantInit( pVarVal);
7145 VariantCopy( pVarVal, &pCData->data);
7148 return E_INVALIDARG; /* FIXME: correct? */
7151 /* ITypeInfo2::GetParamCustData
7153 * Gets the custom data
7155 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7162 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7163 TLBCustData *pCData=NULL;
7164 TLBFuncDesc * pFDesc;
7167 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7169 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7170 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7171 pCData = pCData->next)
7172 if( IsEqualIID(guid, &pCData->guid)) break;
7174 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7178 VariantInit( pVarVal);
7179 VariantCopy( pVarVal, &pCData->data);
7182 return E_INVALIDARG; /* FIXME: correct? */
7185 /* ITypeInfo2::GetVarCustData
7187 * Gets the custom data
7189 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7195 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7196 TLBCustData *pCData=NULL;
7197 TLBVarDesc * pVDesc;
7200 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7204 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7206 if( IsEqualIID(guid, &pCData->guid)) break;
7210 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7214 VariantInit( pVarVal);
7215 VariantCopy( pVarVal, &pCData->data);
7218 return E_INVALIDARG; /* FIXME: correct? */
7221 /* ITypeInfo2::GetImplCustData
7223 * Gets the custom data
7225 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7231 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7232 TLBCustData *pCData=NULL;
7233 TLBImplType * pRDesc;
7236 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7240 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7242 if( IsEqualIID(guid, &pCData->guid)) break;
7246 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7250 VariantInit( pVarVal);
7251 VariantCopy( pVarVal, &pCData->data);
7254 return E_INVALIDARG; /* FIXME: correct? */
7257 /* ITypeInfo2::GetDocumentation2
7259 * Retrieves the documentation string, the complete Help file name and path,
7260 * the localization context to use, and the context ID for the library Help
7261 * topic in the Help file.
7264 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7268 BSTR *pbstrHelpString,
7269 DWORD *pdwHelpStringContext,
7270 BSTR *pbstrHelpStringDll)
7272 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7273 const TLBFuncDesc *pFDesc;
7274 const TLBVarDesc *pVDesc;
7275 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7276 "HelpStringContext(%p) HelpStringDll(%p)\n",
7277 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7278 pbstrHelpStringDll );
7279 /* the help string should be obtained from the helpstringdll,
7280 * using the _DLLGetDocumentation function, based on the supplied
7281 * lcid. Nice to do sometime...
7283 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7285 *pbstrHelpString=SysAllocString(This->Name);
7286 if(pdwHelpStringContext)
7287 *pdwHelpStringContext=This->dwHelpStringContext;
7288 if(pbstrHelpStringDll)
7289 *pbstrHelpStringDll=
7290 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7292 }else {/* for a member */
7293 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7294 if(pFDesc->funcdesc.memid==memid){
7296 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7297 if(pdwHelpStringContext)
7298 *pdwHelpStringContext=pFDesc->HelpStringContext;
7299 if(pbstrHelpStringDll)
7300 *pbstrHelpStringDll=
7301 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7304 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7305 if(pVDesc->vardesc.memid==memid){
7307 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7308 if(pdwHelpStringContext)
7309 *pdwHelpStringContext=pVDesc->HelpStringContext;
7310 if(pbstrHelpStringDll)
7311 *pbstrHelpStringDll=
7312 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7316 return TYPE_E_ELEMENTNOTFOUND;
7319 /* ITypeInfo2::GetAllCustData
7321 * Gets all custom data items for the Type info.
7324 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7326 CUSTDATA *pCustData)
7328 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7329 TLBCustData *pCData;
7332 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7334 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7335 if(pCustData->prgCustData ){
7336 pCustData->cCustData=This->ctCustData;
7337 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7338 pCustData->prgCustData[i].guid=pCData->guid;
7339 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7342 ERR(" OUT OF MEMORY!\n");
7343 return E_OUTOFMEMORY;
7348 /* ITypeInfo2::GetAllFuncCustData
7350 * Gets all custom data items for the specified Function
7353 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7356 CUSTDATA *pCustData)
7358 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7359 TLBCustData *pCData;
7360 TLBFuncDesc * pFDesc;
7362 TRACE("(%p) index %d\n", This, index);
7363 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7364 pFDesc=pFDesc->next)
7367 pCustData->prgCustData =
7368 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7369 if(pCustData->prgCustData ){
7370 pCustData->cCustData=pFDesc->ctCustData;
7371 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7372 pCData = pCData->next){
7373 pCustData->prgCustData[i].guid=pCData->guid;
7374 VariantCopy(& pCustData->prgCustData[i].varValue,
7378 ERR(" OUT OF MEMORY!\n");
7379 return E_OUTOFMEMORY;
7383 return TYPE_E_ELEMENTNOTFOUND;
7386 /* ITypeInfo2::GetAllParamCustData
7388 * Gets all custom data items for the Functions
7391 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7392 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7394 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7395 TLBCustData *pCData=NULL;
7396 TLBFuncDesc * pFDesc;
7398 TRACE("(%p) index %d\n", This, indexFunc);
7399 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7400 pFDesc=pFDesc->next)
7402 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7403 pCustData->prgCustData =
7404 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7405 sizeof(CUSTDATAITEM));
7406 if(pCustData->prgCustData ){
7407 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7408 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7409 pCData; i++, pCData = pCData->next){
7410 pCustData->prgCustData[i].guid=pCData->guid;
7411 VariantCopy(& pCustData->prgCustData[i].varValue,
7415 ERR(" OUT OF MEMORY!\n");
7416 return E_OUTOFMEMORY;
7420 return TYPE_E_ELEMENTNOTFOUND;
7423 /* ITypeInfo2::GetAllVarCustData
7425 * Gets all custom data items for the specified Variable
7428 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7429 UINT index, CUSTDATA *pCustData)
7431 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7432 TLBCustData *pCData;
7433 TLBVarDesc * pVDesc;
7435 TRACE("(%p) index %d\n", This, index);
7436 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7437 pVDesc=pVDesc->next)
7440 pCustData->prgCustData =
7441 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7442 if(pCustData->prgCustData ){
7443 pCustData->cCustData=pVDesc->ctCustData;
7444 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7445 pCData = pCData->next){
7446 pCustData->prgCustData[i].guid=pCData->guid;
7447 VariantCopy(& pCustData->prgCustData[i].varValue,
7451 ERR(" OUT OF MEMORY!\n");
7452 return E_OUTOFMEMORY;
7456 return TYPE_E_ELEMENTNOTFOUND;
7459 /* ITypeInfo2::GetAllImplCustData
7461 * Gets all custom data items for the specified implementation type
7464 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7467 CUSTDATA *pCustData)
7469 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7470 TLBCustData *pCData;
7471 TLBImplType * pRDesc;
7473 TRACE("(%p) index %d\n", This, index);
7474 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7475 pRDesc=pRDesc->next)
7478 pCustData->prgCustData =
7479 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7480 if(pCustData->prgCustData ){
7481 pCustData->cCustData=pRDesc->ctCustData;
7482 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7483 pCData = pCData->next){
7484 pCustData->prgCustData[i].guid=pCData->guid;
7485 VariantCopy(& pCustData->prgCustData[i].varValue,
7489 ERR(" OUT OF MEMORY!\n");
7490 return E_OUTOFMEMORY;
7494 return TYPE_E_ELEMENTNOTFOUND;
7497 static const ITypeInfo2Vtbl tinfvt =
7500 ITypeInfo_fnQueryInterface,
7502 ITypeInfo_fnRelease,
7504 ITypeInfo_fnGetTypeAttr,
7505 ITypeInfo_fnGetTypeComp,
7506 ITypeInfo_fnGetFuncDesc,
7507 ITypeInfo_fnGetVarDesc,
7508 ITypeInfo_fnGetNames,
7509 ITypeInfo_fnGetRefTypeOfImplType,
7510 ITypeInfo_fnGetImplTypeFlags,
7511 ITypeInfo_fnGetIDsOfNames,
7513 ITypeInfo_fnGetDocumentation,
7514 ITypeInfo_fnGetDllEntry,
7515 ITypeInfo_fnGetRefTypeInfo,
7516 ITypeInfo_fnAddressOfMember,
7517 ITypeInfo_fnCreateInstance,
7518 ITypeInfo_fnGetMops,
7519 ITypeInfo_fnGetContainingTypeLib,
7520 ITypeInfo_fnReleaseTypeAttr,
7521 ITypeInfo_fnReleaseFuncDesc,
7522 ITypeInfo_fnReleaseVarDesc,
7524 ITypeInfo2_fnGetTypeKind,
7525 ITypeInfo2_fnGetTypeFlags,
7526 ITypeInfo2_fnGetFuncIndexOfMemId,
7527 ITypeInfo2_fnGetVarIndexOfMemId,
7528 ITypeInfo2_fnGetCustData,
7529 ITypeInfo2_fnGetFuncCustData,
7530 ITypeInfo2_fnGetParamCustData,
7531 ITypeInfo2_fnGetVarCustData,
7532 ITypeInfo2_fnGetImplTypeCustData,
7533 ITypeInfo2_fnGetDocumentation2,
7534 ITypeInfo2_fnGetAllCustData,
7535 ITypeInfo2_fnGetAllFuncCustData,
7536 ITypeInfo2_fnGetAllParamCustData,
7537 ITypeInfo2_fnGetAllVarCustData,
7538 ITypeInfo2_fnGetAllImplTypeCustData,
7541 /******************************************************************************
7542 * CreateDispTypeInfo [OLEAUT32.31]
7544 * Build type information for an object so it can be called through an
7545 * IDispatch interface.
7548 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7549 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7552 * This call allows an objects methods to be accessed through IDispatch, by
7553 * building an ITypeInfo object that IDispatch can use to call through.
7555 HRESULT WINAPI CreateDispTypeInfo(
7556 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7557 LCID lcid, /* [I] Locale Id */
7558 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7560 ITypeInfoImpl *pTIClass, *pTIIface;
7561 ITypeLibImpl *pTypeLibImpl;
7562 unsigned int param, func;
7563 TLBFuncDesc **ppFuncDesc;
7567 pTypeLibImpl = TypeLibImpl_Constructor();
7568 if (!pTypeLibImpl) return E_FAIL;
7570 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7571 pTIIface->pTypeLib = pTypeLibImpl;
7572 pTIIface->index = 0;
7573 pTIIface->Name = NULL;
7574 pTIIface->dwHelpContext = -1;
7575 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7576 pTIIface->TypeAttr.lcid = lcid;
7577 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7578 pTIIface->TypeAttr.wMajorVerNum = 0;
7579 pTIIface->TypeAttr.wMinorVerNum = 0;
7580 pTIIface->TypeAttr.cbAlignment = 2;
7581 pTIIface->TypeAttr.cbSizeInstance = -1;
7582 pTIIface->TypeAttr.cbSizeVft = -1;
7583 pTIIface->TypeAttr.cFuncs = 0;
7584 pTIIface->TypeAttr.cImplTypes = 0;
7585 pTIIface->TypeAttr.cVars = 0;
7586 pTIIface->TypeAttr.wTypeFlags = 0;
7588 ppFuncDesc = &pTIIface->funclist;
7589 for(func = 0; func < pidata->cMembers; func++) {
7590 METHODDATA *md = pidata->pmethdata + func;
7591 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7592 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7593 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7594 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7595 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7596 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7597 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7598 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7599 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7600 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7601 (*ppFuncDesc)->funcdesc.cScodes = 0;
7602 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7603 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7604 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7605 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7606 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7607 md->cArgs * sizeof(ELEMDESC));
7608 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7609 md->cArgs * sizeof(TLBParDesc));
7610 for(param = 0; param < md->cArgs; param++) {
7611 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7612 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7614 (*ppFuncDesc)->helpcontext = 0;
7615 (*ppFuncDesc)->HelpStringContext = 0;
7616 (*ppFuncDesc)->HelpString = NULL;
7617 (*ppFuncDesc)->Entry = NULL;
7618 (*ppFuncDesc)->ctCustData = 0;
7619 (*ppFuncDesc)->pCustData = NULL;
7620 (*ppFuncDesc)->next = NULL;
7621 pTIIface->TypeAttr.cFuncs++;
7622 ppFuncDesc = &(*ppFuncDesc)->next;
7625 dump_TypeInfo(pTIIface);
7627 pTypeLibImpl->pTypeInfo = pTIIface;
7628 pTypeLibImpl->TypeInfoCount++;
7630 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7631 pTIClass->pTypeLib = pTypeLibImpl;
7632 pTIClass->index = 1;
7633 pTIClass->Name = NULL;
7634 pTIClass->dwHelpContext = -1;
7635 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7636 pTIClass->TypeAttr.lcid = lcid;
7637 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7638 pTIClass->TypeAttr.wMajorVerNum = 0;
7639 pTIClass->TypeAttr.wMinorVerNum = 0;
7640 pTIClass->TypeAttr.cbAlignment = 2;
7641 pTIClass->TypeAttr.cbSizeInstance = -1;
7642 pTIClass->TypeAttr.cbSizeVft = -1;
7643 pTIClass->TypeAttr.cFuncs = 0;
7644 pTIClass->TypeAttr.cImplTypes = 1;
7645 pTIClass->TypeAttr.cVars = 0;
7646 pTIClass->TypeAttr.wTypeFlags = 0;
7648 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7649 pTIClass->impltypelist->hRef = 0;
7651 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7654 ref->pImpTLInfo = TLB_REF_INTERNAL;
7655 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7657 dump_TypeInfo(pTIClass);
7659 pTIIface->next = pTIClass;
7660 pTypeLibImpl->TypeInfoCount++;
7662 *pptinfo = (ITypeInfo*)pTIClass;
7664 ITypeInfo_AddRef(*pptinfo);
7665 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7671 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7673 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7675 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7678 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7680 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7682 return ITypeInfo_AddRef((ITypeInfo *)This);
7685 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7687 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7689 return ITypeInfo_Release((ITypeInfo *)This);
7692 static HRESULT WINAPI ITypeComp_fnBind(
7697 ITypeInfo ** ppTInfo,
7698 DESCKIND * pDescKind,
7701 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7702 const TLBFuncDesc *pFDesc;
7703 const TLBVarDesc *pVDesc;
7706 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This, debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7708 *pDescKind = DESCKIND_NONE;
7709 pBindPtr->lpfuncdesc = NULL;
7712 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7713 if (!strcmpiW(pFDesc->Name, szName)) {
7714 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7717 /* name found, but wrong flags */
7718 hr = TYPE_E_TYPEMISMATCH;
7723 HRESULT hr = TLB_AllocAndInitFuncDesc(
7725 &pBindPtr->lpfuncdesc,
7726 This->TypeAttr.typekind == TKIND_DISPATCH);
7729 *pDescKind = DESCKIND_FUNCDESC;
7730 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7731 ITypeInfo_AddRef(*ppTInfo);
7734 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7735 if (!strcmpiW(pVDesc->Name, szName)) {
7736 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7739 *pDescKind = DESCKIND_VARDESC;
7740 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7741 ITypeInfo_AddRef(*ppTInfo);
7746 /* FIXME: search each inherited interface, not just the first */
7747 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7748 /* recursive search */
7752 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7755 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7756 ITypeInfo_Release(pTInfo);
7760 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7761 ITypeComp_Release(pTComp);
7764 WARN("Could not search inherited interface!\n");
7766 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName), wFlags);
7770 static HRESULT WINAPI ITypeComp_fnBindType(
7774 ITypeInfo ** ppTInfo,
7775 ITypeComp ** ppTComp)
7777 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7779 /* strange behaviour (does nothing) but like the
7782 if (!ppTInfo || !ppTComp)
7791 static const ITypeCompVtbl tcompvt =
7794 ITypeComp_fnQueryInterface,
7796 ITypeComp_fnRelease,
7799 ITypeComp_fnBindType