4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
44 * -. lousy fatal error handling
49 #include "wine/port.h"
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
69 #include "wine/unicode.h"
72 #include "wine/debug.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
102 /****************************************************************************
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
141 p_iSize /= sizeof(WORD);
144 *Val = FromLEWord(*Val);
151 static void FromLEDWords(void *p_Val, int p_iSize)
155 p_iSize /= sizeof(DWORD);
158 *Val = FromLEDWord(*Val);
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
177 INT best_maj = -1, best_min = -1;
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
186 len = sizeof(key_name);
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
229 if (*wMaj == best_maj && best_min >= 0)
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
266 static const WCHAR win16W[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W[] = {'w','i','n','3','2',0};
268 static const WCHAR win64W[] = {'w','i','n','6','4',0};
270 sprintfW( buffer, LcidFormatW, lcid );
273 case SYS_WIN16: strcatW( buffer, win16W ); break;
274 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 case SYS_WIN64: strcatW( buffer, win64W ); break;
277 TRACE("Typelib is for unsupported syskind %i\n", syskind);
283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
286 /****************************************************************************
287 * QueryPathOfRegTypeLib [OLEAUT32.164]
289 * Gets the path to a registered type library.
292 * guid [I] referenced guid
293 * wMaj [I] major version
294 * wMin [I] minor version
296 * path [O] path of typelib
300 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
301 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
304 HRESULT WINAPI QueryPathOfRegTypeLib(
311 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
315 WCHAR Path[MAX_PATH];
318 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
320 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
321 get_typelib_key( guid, wMaj, wMin, buffer );
323 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
324 if (res == ERROR_FILE_NOT_FOUND)
326 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
327 return TYPE_E_LIBNOTREGISTERED;
329 else if (res != ERROR_SUCCESS)
331 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
332 return TYPE_E_REGISTRYACCESS;
337 LONG dwPathLen = sizeof(Path);
339 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
341 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
345 else if (myLCID == lcid)
347 /* try with sub-langid */
348 myLCID = SUBLANGID(lcid);
350 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
352 /* try with system langid */
362 *path = SysAllocString( Path );
367 TRACE_(typelib)("-- 0x%08x\n", hr);
371 /******************************************************************************
372 * CreateTypeLib [OLEAUT32.160] creates a typelib
378 HRESULT WINAPI CreateTypeLib(
379 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
381 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
385 /******************************************************************************
386 * LoadTypeLib [OLEAUT32.161]
388 * Loads a type library
391 * szFile [I] Name of file to load from.
392 * pptLib [O] Pointer that receives ITypeLib object on success.
399 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
401 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
403 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
404 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
407 /******************************************************************************
408 * LoadTypeLibEx [OLEAUT32.183]
410 * Loads and optionally registers a type library
416 HRESULT WINAPI LoadTypeLibEx(
417 LPCOLESTR szFile, /* [in] Name of file to load from */
418 REGKIND regkind, /* [in] Specify kind of registration */
419 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
421 WCHAR szPath[MAX_PATH+1];
424 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
428 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
433 case REGKIND_DEFAULT:
434 /* don't register typelibs supplied with full path. Experimentation confirms the following */
435 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
436 (szFile[0] && (szFile[1] == ':'))) break;
437 /* else fall-through */
439 case REGKIND_REGISTER:
440 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
442 IUnknown_Release(*pptLib);
450 TRACE(" returns %08x\n",res);
454 /******************************************************************************
455 * LoadRegTypeLib [OLEAUT32.162]
457 * Loads a registered type library.
460 * rguid [I] GUID of the registered type library.
461 * wVerMajor [I] major version.
462 * wVerMinor [I] minor version.
463 * lcid [I] locale ID.
464 * ppTLib [O] pointer that receives an ITypeLib object on success.
468 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
471 HRESULT WINAPI LoadRegTypeLib(
483 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
487 res= LoadTypeLib(bstr, ppTLib);
491 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
497 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
498 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
499 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
500 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
501 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
502 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
504 /******************************************************************************
505 * RegisterTypeLib [OLEAUT32.163]
506 * Adds information about a type library to the System Registry
508 * Docs: ITypeLib FAR * ptlib
509 * Docs: OLECHAR FAR* szFullPath
510 * Docs: OLECHAR FAR* szHelpDir
516 HRESULT WINAPI RegisterTypeLib(
517 ITypeLib * ptlib, /* [in] Pointer to the library*/
518 OLECHAR * szFullPath, /* [in] full Path of the library*/
519 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
522 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
523 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
524 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
534 if (ptlib == NULL || szFullPath == NULL)
537 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
541 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
543 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
546 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
549 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
550 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
554 /* Set the human-readable name of the typelib */
555 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
557 if (RegSetValueExW(key, NULL, 0, REG_SZ,
558 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
566 /* Make up the name of the typelib path subkey */
567 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
569 /* Create the typelib path subkey */
570 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
571 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
573 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
574 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
582 /* Create the flags subkey */
583 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
584 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
586 /* FIXME: is %u correct? */
587 static const WCHAR formatW[] = {'%','u',0};
589 sprintfW(buf, formatW, attr->wLibFlags);
590 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
591 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
599 /* create the helpdir subkey */
600 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
601 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
603 BOOL freeHelpDir = FALSE;
606 /* if we created a new key, and helpDir was null, set the helpdir
607 to the directory which contains the typelib. However,
608 if we just opened an existing key, we leave the helpdir alone */
609 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
610 szHelpDir = SysAllocString(szFullPath);
611 pIndexStr = strrchrW(szHelpDir, '\\');
618 /* if we have an szHelpDir, set it! */
619 if (szHelpDir != NULL) {
620 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
621 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
627 if (freeHelpDir) SysFreeString(szHelpDir);
639 /* register OLE Automation-compatible interfaces for this typelib */
640 types = ITypeLib_GetTypeInfoCount(ptlib);
641 for (tidx=0; tidx<types; tidx++) {
642 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
643 LPOLESTR name = NULL;
644 ITypeInfo *tinfo = NULL;
646 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
649 case TKIND_INTERFACE:
650 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
651 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
655 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
656 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
660 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
665 TYPEATTR *tattr = NULL;
666 ITypeInfo_GetTypeAttr(tinfo, &tattr);
669 TRACE_(typelib)("guid=%s, flags=%04x (",
670 debugstr_guid(&tattr->guid),
673 if (TRACE_ON(typelib)) {
674 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
694 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
696 /* register interface<->typelib coupling */
697 get_interface_key( &tattr->guid, keyName );
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
699 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
702 RegSetValueExW(key, NULL, 0, REG_SZ,
703 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
705 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
706 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
707 RegSetValueExW(subKey, NULL, 0, REG_SZ,
708 (const BYTE *)PSOA, sizeof PSOA);
712 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
713 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
714 RegSetValueExW(subKey, NULL, 0, REG_SZ,
715 (const BYTE *)PSOA, sizeof PSOA);
719 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
720 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
723 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
724 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
726 StringFromGUID2(&attr->guid, buffer, 40);
727 RegSetValueExW(subKey, NULL, 0, REG_SZ,
728 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
729 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
730 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
731 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
739 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
742 ITypeInfo_Release(tinfo);
749 ITypeLib_ReleaseTLibAttr(ptlib, attr);
755 /******************************************************************************
756 * UnRegisterTypeLib [OLEAUT32.186]
757 * Removes information about a type library from the System Registry
764 HRESULT WINAPI UnRegisterTypeLib(
765 REFGUID libid, /* [in] Guid of the library */
766 WORD wVerMajor, /* [in] major version */
767 WORD wVerMinor, /* [in] minor version */
768 LCID lcid, /* [in] locale id */
771 BSTR tlibPath = NULL;
774 WCHAR subKeyName[50];
777 BOOL deleteOtherStuff;
780 TYPEATTR* typeAttr = NULL;
782 ITypeInfo* typeInfo = NULL;
783 ITypeLib* typeLib = NULL;
786 TRACE("(IID: %s)\n",debugstr_guid(libid));
788 /* Create the path to the key */
789 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
791 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
793 TRACE("Unsupported syskind %i\n", syskind);
794 result = E_INVALIDARG;
798 /* get the path to the typelib on disk */
799 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
800 result = E_INVALIDARG;
804 /* Try and open the key to the type library. */
805 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
806 result = E_INVALIDARG;
810 /* Try and load the type library */
811 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
812 result = TYPE_E_INVALIDSTATE;
816 /* remove any types registered with this typelib */
817 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
818 for (i=0; i<numTypes; i++) {
819 /* get the kind of type */
820 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
824 /* skip non-interfaces, and get type info for the type */
825 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
828 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
831 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
835 /* the path to the type */
836 get_interface_key( &typeAttr->guid, subKeyName );
838 /* Delete its bits */
839 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
842 RegDeleteKeyW(subKey, ProxyStubClsidW);
843 RegDeleteKeyW(subKey, ProxyStubClsid32W);
844 RegDeleteKeyW(subKey, TypeLibW);
847 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
850 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
852 if (typeInfo) ITypeInfo_Release(typeInfo);
856 /* Now, delete the type library path subkey */
857 get_lcid_subkey( lcid, syskind, subKeyName );
858 RegDeleteKeyW(key, subKeyName);
859 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
860 RegDeleteKeyW(key, subKeyName);
862 /* check if there is anything besides the FLAGS/HELPDIR keys.
863 If there is, we don't delete them */
864 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
865 deleteOtherStuff = TRUE;
867 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
868 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
870 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
871 if (!strcmpW(subKeyName, FLAGSW)) continue;
872 if (!strcmpW(subKeyName, HELPDIRW)) continue;
873 deleteOtherStuff = FALSE;
877 /* only delete the other parts of the key if we're absolutely sure */
878 if (deleteOtherStuff) {
879 RegDeleteKeyW(key, FLAGSW);
880 RegDeleteKeyW(key, HELPDIRW);
884 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
885 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
886 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
890 SysFreeString(tlibPath);
891 if (typeLib) ITypeLib_Release(typeLib);
892 if (subKey) RegCloseKey(subKey);
893 if (key) RegCloseKey(key);
897 /*======================= ITypeLib implementation =======================*/
899 typedef struct tagTLBCustData
903 struct tagTLBCustData* next;
906 /* data structure for import typelibs */
907 typedef struct tagTLBImpLib
909 int offset; /* offset in the file (MSFT)
910 offset in nametable (SLTG)
911 just used to identify library while reading
913 GUID guid; /* libid */
914 BSTR name; /* name */
916 LCID lcid; /* lcid of imported typelib */
918 WORD wVersionMajor; /* major version number */
919 WORD wVersionMinor; /* minor version number */
921 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
922 NULL if not yet loaded */
923 struct tagTLBImpLib * next;
926 /* internal ITypeLib data */
927 typedef struct tagITypeLibImpl
929 const ITypeLib2Vtbl *lpVtbl;
930 const ITypeCompVtbl *lpVtblTypeComp;
932 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
934 /* strings can be stored in tlb as multibyte strings BUT they are *always*
935 * exported to the application as a UNICODE string.
941 unsigned long dwHelpContext;
942 int TypeInfoCount; /* nr of typeinfo's in librarry */
943 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
944 int ctCustData; /* number of items in cust data list */
945 TLBCustData * pCustData; /* linked list to cust data */
946 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
947 int ctTypeDesc; /* number of items in type desc array */
948 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
949 library. Only used while reading MSFT
951 struct list ref_list; /* list of ref types in this typelib */
952 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
955 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
956 struct tagITypeLibImpl *next, *prev;
961 static const ITypeLib2Vtbl tlbvt;
962 static const ITypeCompVtbl tlbtcvt;
964 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
966 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
969 /* ITypeLib methods */
970 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
971 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
973 /*======================= ITypeInfo implementation =======================*/
975 /* data for referenced types */
976 typedef struct tagTLBRefType
978 INT index; /* Type index for internal ref or for external ref
979 it the format is SLTG. -2 indicates to
982 GUID guid; /* guid of the referenced type */
983 /* if index == TLB_REF_USE_GUID */
985 HREFTYPE reference; /* The href of this ref */
986 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
987 TLB_REF_INTERNAL for internal refs
988 TLB_REF_NOT_FOUND for broken refs */
993 #define TLB_REF_USE_GUID -2
995 #define TLB_REF_INTERNAL (void*)-2
996 #define TLB_REF_NOT_FOUND (void*)-1
998 /* internal Parameter data */
999 typedef struct tagTLBParDesc
1003 TLBCustData * pCustData; /* linked list to cust data */
1006 /* internal Function data */
1007 typedef struct tagTLBFuncDesc
1009 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1010 BSTR Name; /* the name of this function */
1011 TLBParDesc *pParamDesc; /* array with param names and custom data */
1013 int HelpStringContext;
1015 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
1017 TLBCustData * pCustData; /* linked list to cust data; */
1018 struct tagTLBFuncDesc * next;
1021 /* internal Variable data */
1022 typedef struct tagTLBVarDesc
1024 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1025 BSTR Name; /* the name of this variable */
1027 int HelpStringContext; /* FIXME: where? */
1030 TLBCustData * pCustData;/* linked list to cust data; */
1031 struct tagTLBVarDesc * next;
1034 /* internal implemented interface data */
1035 typedef struct tagTLBImplType
1037 HREFTYPE hRef; /* hRef of interface */
1038 int implflags; /* IMPLFLAG_*s */
1040 TLBCustData * pCustData;/* linked list to custom data; */
1041 struct tagTLBImplType *next;
1044 /* internal TypeInfo data */
1045 typedef struct tagITypeInfoImpl
1047 const ITypeInfo2Vtbl *lpVtbl;
1048 const ITypeCompVtbl *lpVtblTypeComp;
1050 BOOL no_free_data; /* don't free data structures */
1051 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1052 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1053 int index; /* index in this typelib; */
1054 HREFTYPE hreftype; /* hreftype for app object binding */
1055 /* type libs seem to store the doc strings in ascii
1056 * so why should we do it in unicode?
1061 unsigned long dwHelpContext;
1062 unsigned long dwHelpStringContext;
1065 TLBFuncDesc * funclist; /* linked list with function descriptions */
1068 TLBVarDesc * varlist; /* linked list with variable descriptions */
1070 /* Implemented Interfaces */
1071 TLBImplType * impltypelist;
1074 TLBCustData * pCustData; /* linked list to cust data; */
1075 struct tagITypeInfoImpl * next;
1078 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1080 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1083 static const ITypeInfo2Vtbl tinfvt;
1084 static const ITypeCompVtbl tcompvt;
1086 static ITypeInfo2 * ITypeInfo_Constructor(void);
1088 typedef struct tagTLBContext
1090 unsigned int oStart; /* start of TLB in file */
1091 unsigned int pos; /* current pos */
1092 unsigned int length; /* total length */
1093 void *mapping; /* memory mapping */
1094 MSFT_SegDir * pTblDir;
1095 ITypeLibImpl* pLibInfo;
1099 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1104 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1105 if (pTD->vt & VT_RESERVED)
1106 szVarType += strlen(strcpy(szVarType, "reserved | "));
1107 if (pTD->vt & VT_BYREF)
1108 szVarType += strlen(strcpy(szVarType, "ref to "));
1109 if (pTD->vt & VT_ARRAY)
1110 szVarType += strlen(strcpy(szVarType, "array of "));
1111 if (pTD->vt & VT_VECTOR)
1112 szVarType += strlen(strcpy(szVarType, "vector of "));
1113 switch(pTD->vt & VT_TYPEMASK) {
1114 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1115 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1116 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1117 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1118 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1119 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1120 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1121 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1122 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1123 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1124 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1125 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1126 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1127 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1128 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1129 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1130 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1131 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1132 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1133 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1134 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1135 pTD->u.hreftype); break;
1136 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1137 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1138 case VT_PTR: sprintf(szVarType, "ptr to ");
1139 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1141 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1142 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1144 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1145 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1146 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1149 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1153 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1155 USHORT flags = edesc->u.paramdesc.wParamFlags;
1156 dump_TypeDesc(&edesc->tdesc,buf);
1157 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1158 MESSAGE("\t\tu.paramdesc.wParamFlags");
1159 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1160 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1161 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1162 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1163 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1164 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1165 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1166 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1167 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1169 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1171 MESSAGE("memid is %08x\n",funcdesc->memid);
1172 for (i=0;i<funcdesc->cParams;i++) {
1173 MESSAGE("Param %d:\n",i);
1174 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1176 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1177 switch (funcdesc->funckind) {
1178 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1179 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1180 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1181 case FUNC_STATIC: MESSAGE("static");break;
1182 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1183 default: MESSAGE("unknown");break;
1185 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1186 switch (funcdesc->invkind) {
1187 case INVOKE_FUNC: MESSAGE("func");break;
1188 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1189 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1190 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1192 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1193 switch (funcdesc->callconv) {
1194 case CC_CDECL: MESSAGE("cdecl");break;
1195 case CC_PASCAL: MESSAGE("pascal");break;
1196 case CC_STDCALL: MESSAGE("stdcall");break;
1197 case CC_SYSCALL: MESSAGE("syscall");break;
1200 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1201 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1202 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1204 MESSAGE("\telemdescFunc (return value type):\n");
1205 dump_ELEMDESC(&funcdesc->elemdescFunc);
1208 static const char * const typekind_desc[] =
1221 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1224 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1225 for (i=0;i<pfd->funcdesc.cParams;i++)
1226 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1229 dump_FUNCDESC(&(pfd->funcdesc));
1231 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1232 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1234 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1238 dump_TLBFuncDescOne(pfd);
1242 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1246 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1251 static void dump_TLBImpLib(const TLBImpLib *import)
1253 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1254 debugstr_w(import->name));
1255 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1256 import->wVersionMinor, import->lcid, import->offset);
1259 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1263 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1265 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1266 if(ref->index == -1)
1267 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1269 TRACE_(typelib)("type no: %d\n", ref->index);
1271 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1273 TRACE_(typelib)("in lib\n");
1274 dump_TLBImpLib(ref->pImpTLInfo);
1279 static void dump_TLBImplType(const TLBImplType * impl)
1283 "implementing/inheriting interface hRef = %x implflags %x\n",
1284 impl->hRef, impl->implflags);
1289 static void dump_Variant(const VARIANT * pvar)
1293 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1297 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1298 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1300 TRACE(",%p", V_BYREF(pvar));
1302 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1304 TRACE(",%p", V_ARRAY(pvar));
1306 else switch (V_TYPE(pvar))
1308 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1309 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1310 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1311 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1313 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1315 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1316 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1317 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1318 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1319 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1320 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1321 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1322 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1323 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1324 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1325 V_CY(pvar).s.Lo); break;
1327 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1328 TRACE(",<invalid>");
1330 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1331 st.wHour, st.wMinute, st.wSecond);
1335 case VT_USERDEFINED:
1337 case VT_NULL: break;
1338 default: TRACE(",?"); break;
1344 static void dump_DispParms(const DISPPARAMS * pdp)
1348 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1350 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1352 TRACE("named args:\n");
1353 for (index = 0; index < pdp->cNamedArgs; index++)
1354 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1357 if (pdp->cArgs && pdp->rgvarg)
1360 for (index = 0; index < pdp->cArgs; index++)
1361 dump_Variant( &pdp->rgvarg[index] );
1365 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1367 TRACE("%p ref=%u\n", pty, pty->ref);
1368 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1369 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1370 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1371 TRACE("fct:%u var:%u impl:%u\n",
1372 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1373 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1374 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1375 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1377 dump_TLBFuncDesc(pty->funclist);
1378 dump_TLBVarDesc(pty->varlist);
1379 dump_TLBImplType(pty->impltypelist);
1382 static void dump_VARDESC(const VARDESC *v)
1384 MESSAGE("memid %d\n",v->memid);
1385 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1386 MESSAGE("oInst %d\n",v->u.oInst);
1387 dump_ELEMDESC(&(v->elemdescVar));
1388 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1389 MESSAGE("varkind %d\n",v->varkind);
1392 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1394 /* VT_LPWSTR is largest type that */
1395 /* may appear in type description*/
1396 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1397 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1398 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1399 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1400 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1401 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1405 static void TLB_abort(void)
1410 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1411 static void * TLB_Alloc(unsigned size)
1414 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1416 ERR("cannot allocate memory\n");
1421 static void TLB_Free(void * ptr)
1423 HeapFree(GetProcessHeap(), 0, ptr);
1426 /* returns the size required for a deep copy of a typedesc into a
1428 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1432 if (alloc_initial_space)
1433 size += sizeof(TYPEDESC);
1439 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1442 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1443 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1449 /* deep copy a typedesc into a flat buffer */
1450 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1455 buffer = (char *)buffer + sizeof(TYPEDESC);
1464 dest->u.lptdesc = buffer;
1465 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1468 dest->u.lpadesc = buffer;
1469 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1470 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1471 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1477 /* free custom data allocated by MSFT_CustData */
1478 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1480 TLBCustData *pCustDataNext;
1481 for (; pCustData; pCustData = pCustDataNext)
1483 VariantClear(&pCustData->data);
1485 pCustDataNext = pCustData->next;
1486 TLB_Free(pCustData);
1490 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1495 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1496 ret = SysAllocStringLen(NULL, len - 1);
1497 if (!ret) return ret;
1498 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1502 /**********************************************************************
1504 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1506 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1511 static inline void MSFT_Seek(TLBContext *pcx, long where)
1513 if (where != DO_NOT_SEEK)
1515 where += pcx->oStart;
1516 if (where > pcx->length)
1519 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1527 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1529 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1530 pcx->pos, count, pcx->oStart, pcx->length, where);
1532 MSFT_Seek(pcx, where);
1533 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1534 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1539 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1544 ret = MSFT_Read(buffer, count, pcx, where);
1545 FromLEDWords(buffer, ret);
1550 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1555 ret = MSFT_Read(buffer, count, pcx, where);
1556 FromLEWords(buffer, ret);
1561 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1563 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1564 memset(pGuid,0, sizeof(GUID));
1567 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1568 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1569 pGuid->Data2 = FromLEWord(pGuid->Data2);
1570 pGuid->Data3 = FromLEWord(pGuid->Data3);
1571 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1574 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1576 MSFT_NameIntro niName;
1580 ERR_(typelib)("bad offset %d\n", offset);
1584 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1585 pcx->pTblDir->pNametab.offset+offset);
1587 return niName.hreftype;
1590 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1593 MSFT_NameIntro niName;
1595 BSTR bstrName = NULL;
1599 ERR_(typelib)("bad offset %d\n", offset);
1602 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1603 pcx->pTblDir->pNametab.offset+offset);
1604 niName.namelen &= 0xFF; /* FIXME: correct ? */
1605 name=TLB_Alloc((niName.namelen & 0xff) +1);
1606 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1607 name[niName.namelen & 0xff]='\0';
1609 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1612 /* no invalid characters in string */
1615 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1617 /* don't check for invalid character since this has been done previously */
1618 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1622 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1626 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1633 if(offset<0) return NULL;
1634 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1635 if(length <= 0) return 0;
1636 string=TLB_Alloc(length +1);
1637 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1638 string[length]='\0';
1640 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1641 string, -1, NULL, 0);
1643 /* no invalid characters in string */
1646 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1648 /* don't check for invalid character since this has been done previously */
1649 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1653 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1657 * read a value and fill a VARIANT structure
1659 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1663 TRACE_(typelib)("\n");
1665 if(offset <0) { /* data are packed in here */
1666 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1667 V_I4(pVar) = offset & 0x3ffffff;
1670 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1671 pcx->pTblDir->pCustData.offset + offset );
1672 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1673 switch (V_VT(pVar)){
1674 case VT_EMPTY: /* FIXME: is this right? */
1675 case VT_NULL: /* FIXME: is this right? */
1676 case VT_I2 : /* this should not happen */
1687 case VT_VOID : /* FIXME: is this right? */
1695 case VT_DECIMAL : /* FIXME: is this right? */
1698 /* pointer types with known behaviour */
1701 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1704 DWORD origPos = MSFT_Tell(pcx), nullPos;
1707 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1709 nullPos = MSFT_Tell(pcx);
1710 size = nullPos - origPos;
1711 MSFT_Seek(pcx, origPos);
1713 ptr=TLB_Alloc(size);/* allocate temp buffer */
1714 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1715 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1716 /* FIXME: do we need a AtoW conversion here? */
1717 V_UNION(pVar, bstrVal[size])='\0';
1718 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1722 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1729 case VT_USERDEFINED :
1735 case VT_STREAMED_OBJECT :
1736 case VT_STORED_OBJECT :
1737 case VT_BLOB_OBJECT :
1742 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1746 if(size>0) /* (big|small) endian correct? */
1747 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1751 * create a linked list with custom data
1753 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1759 TRACE_(typelib)("\n");
1763 pNew=TLB_Alloc(sizeof(TLBCustData));
1764 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1765 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1766 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1767 /* add new custom data at head of the list */
1768 pNew->next=*ppCustData;
1770 offset = entry.next;
1775 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1779 pTd->vt=type & VT_TYPEMASK;
1781 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1783 if(pTd->vt == VT_USERDEFINED)
1784 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1786 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1789 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1791 /* resolve referenced type if any */
1794 switch (lpTypeDesc->vt)
1797 lpTypeDesc = lpTypeDesc->u.lptdesc;
1801 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1804 case VT_USERDEFINED:
1805 MSFT_DoRefType(pcx, pTI->pTypeLib,
1806 lpTypeDesc->u.hreftype);
1818 MSFT_DoFuncs(TLBContext* pcx,
1823 TLBFuncDesc** pptfd)
1826 * member information is stored in a data structure at offset
1827 * indicated by the memoffset field of the typeinfo structure
1828 * There are several distinctive parts.
1829 * The first part starts with a field that holds the total length
1830 * of this (first) part excluding this field. Then follow the records,
1831 * for each member there is one record.
1833 * The first entry is always the length of the record (including this
1835 * The rest of the record depends on the type of the member. If there is
1836 * a field indicating the member type (function, variable, interface, etc)
1837 * I have not found it yet. At this time we depend on the information
1838 * in the type info and the usual order how things are stored.
1840 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1843 * Third is an equal sized array with file offsets to the name entry
1846 * The fourth and last (?) part is an array with offsets to the records
1847 * in the first part of this file segment.
1850 int infolen, nameoffset, reclength, nrattributes, i;
1851 int recoffset = offset + sizeof(INT);
1853 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1854 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1855 TLBFuncDesc *ptfd_prev = NULL;
1857 TRACE_(typelib)("\n");
1859 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1861 for ( i = 0; i < cFuncs ; i++ )
1863 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1865 /* name, eventually add to a hash table */
1866 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1867 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1869 /* nameoffset is sometimes -1 on the second half of a propget/propput
1870 * pair of functions */
1871 if ((nameoffset == -1) && (i > 0))
1872 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1874 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1876 /* read the function information record */
1877 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1879 reclength &= 0xffff;
1881 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1883 /* do the attributes */
1884 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1887 if ( nrattributes > 0 )
1889 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1891 if ( nrattributes > 1 )
1893 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1894 pFuncRec->OptAttr[1]) ;
1896 if ( nrattributes > 2 )
1898 if ( pFuncRec->FKCCIC & 0x2000 )
1900 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1901 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1902 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1906 (*pptfd)->Entry = MSFT_ReadString(pcx,
1907 pFuncRec->OptAttr[2]);
1909 if( nrattributes > 5 )
1911 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1913 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1916 pFuncRec->OptAttr[6],
1917 &(*pptfd)->pCustData);
1923 (*pptfd)->Entry = (BSTR)-1;
1928 /* fill the FuncDesc Structure */
1929 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1930 offset + infolen + ( i + 1) * sizeof(INT));
1932 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1933 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1934 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1935 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1936 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1937 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1938 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1942 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1944 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1946 /* do the parameters/arguments */
1947 if(pFuncRec->nrargs)
1950 MSFT_ParameterInfo paraminfo;
1952 (*pptfd)->funcdesc.lprgelemdescParam =
1953 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1955 (*pptfd)->pParamDesc =
1956 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1958 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1959 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1961 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1963 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1970 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1973 if (paraminfo.oName == -1)
1974 /* this occurs for [propput] or [propget] methods, so
1975 * we should just set the name of the parameter to the
1976 * name of the method. */
1977 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1979 (*pptfd)->pParamDesc[j].Name =
1980 MSFT_ReadName( pcx, paraminfo.oName );
1981 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1983 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1986 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1987 (pFuncRec->FKCCIC & 0x1000) )
1989 INT* pInt = (INT *)((char *)pFuncRec +
1991 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1993 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1995 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1996 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1998 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2002 elemdesc->u.paramdesc.pparamdescex = NULL;
2004 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2007 pFuncRec->OptAttr[7+j],
2008 &(*pptfd)->pParamDesc[j].pCustData);
2011 /* SEEK value = jump to offset,
2012 * from there jump to the end of record,
2013 * go back by (j-1) arguments
2015 MSFT_ReadLEDWords( ¶minfo ,
2016 sizeof(MSFT_ParameterInfo), pcx,
2017 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2018 * sizeof(MSFT_ParameterInfo)));
2022 /* scode is not used: archaic win16 stuff FIXME: right? */
2023 (*pptfd)->funcdesc.cScodes = 0 ;
2024 (*pptfd)->funcdesc.lprgscode = NULL ;
2027 pptfd = & ((*pptfd)->next);
2028 recoffset += reclength;
2030 HeapFree(GetProcessHeap(), 0, recbuf);
2033 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2034 int cVars, int offset, TLBVarDesc ** pptvd)
2036 int infolen, nameoffset, reclength;
2038 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2042 TRACE_(typelib)("\n");
2044 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2045 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2046 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2047 recoffset += offset+sizeof(INT);
2048 for(i=0;i<cVars;i++){
2049 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2050 /* name, eventually add to a hash table */
2051 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2052 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2053 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2054 /* read the variable information record */
2055 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2057 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2059 if(reclength >(6*sizeof(INT)) )
2060 (*pptvd)->HelpContext=pVarRec->HelpContext;
2061 if(reclength >(7*sizeof(INT)) )
2062 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2063 if(reclength >(8*sizeof(INT)) )
2064 if(reclength >(9*sizeof(INT)) )
2065 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2066 /* fill the VarDesc Structure */
2067 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2068 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2069 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2070 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2071 MSFT_GetTdesc(pcx, pVarRec->DataType,
2072 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2073 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2074 if(pVarRec->VarKind == VAR_CONST ){
2075 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2076 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2077 pVarRec->OffsValue, pcx);
2079 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2080 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2081 pptvd=&((*pptvd)->next);
2082 recoffset += reclength;
2085 /* fill in data for a hreftype (offset). When the referenced type is contained
2086 * in the typelib, it's just an (file) offset in the type info base dir.
2087 * If comes from import, it's an offset+1 in the ImpInfo table
2089 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2094 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2096 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2098 if(ref->reference == offset) return;
2101 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2102 list_add_tail(&pTL->ref_list, &ref->entry);
2104 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2105 /* external typelib */
2106 MSFT_ImpInfo impinfo;
2107 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2109 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2111 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2112 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2113 while (pImpLib){ /* search the known offsets of all import libraries */
2114 if(pImpLib->offset==impinfo.oImpFile) break;
2115 pImpLib=pImpLib->next;
2118 ref->reference = offset;
2119 ref->pImpTLInfo = pImpLib;
2120 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2121 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2122 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2123 ref->index = TLB_REF_USE_GUID;
2125 ref->index = impinfo.oGuid;
2127 ERR("Cannot find a reference\n");
2128 ref->reference = -1;
2129 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2132 /* in this typelib */
2133 ref->index = MSFT_HREFTYPE_INDEX(offset);
2134 ref->reference = offset;
2135 ref->pImpTLInfo = TLB_REF_INTERNAL;
2139 /* process Implemented Interfaces of a com class */
2140 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2144 MSFT_RefRecord refrec;
2145 TLBImplType **ppImpl = &pTI->impltypelist;
2147 TRACE_(typelib)("\n");
2149 for(i=0;i<count;i++){
2150 if(offset<0) break; /* paranoia */
2151 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2152 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2153 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2154 (*ppImpl)->hRef = refrec.reftype;
2155 (*ppImpl)->implflags=refrec.flags;
2156 (*ppImpl)->ctCustData=
2157 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2158 offset=refrec.onext;
2159 ppImpl=&((*ppImpl)->next);
2163 * process a typeinfo record
2165 static ITypeInfoImpl * MSFT_DoTypeInfo(
2168 ITypeLibImpl * pLibInfo)
2170 MSFT_TypeInfoBase tiBase;
2171 ITypeInfoImpl *ptiRet;
2173 TRACE_(typelib)("count=%u\n", count);
2175 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2176 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2177 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2179 /* this is where we are coming from */
2180 ptiRet->pTypeLib = pLibInfo;
2181 ptiRet->index=count;
2182 /* fill in the typeattr fields */
2184 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2185 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2186 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2187 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2188 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2189 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2190 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2191 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2192 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2193 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2194 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2195 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2196 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2197 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2198 MSFT_GetTdesc(pcx, tiBase.datatype1,
2199 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2202 /* IDLDESC idldescType; *//* never saw this one != zero */
2204 /* name, eventually add to a hash table */
2205 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2206 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2207 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2209 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2210 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2211 ptiRet->dwHelpContext=tiBase.helpcontext;
2213 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2214 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2216 /* note: InfoType's Help file and HelpStringDll come from the containing
2217 * library. Further HelpString and Docstring appear to be the same thing :(
2220 if(ptiRet->TypeAttr.cFuncs >0 )
2221 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2222 ptiRet->TypeAttr.cVars,
2223 tiBase.memoffset, & ptiRet->funclist);
2225 if(ptiRet->TypeAttr.cVars >0 )
2226 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2227 ptiRet->TypeAttr.cVars,
2228 tiBase.memoffset, & ptiRet->varlist);
2229 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2230 switch(ptiRet->TypeAttr.typekind)
2233 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2236 case TKIND_DISPATCH:
2237 /* This is not -1 when the interface is a non-base dual interface or
2238 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2239 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2243 if (tiBase.datatype1 != -1)
2245 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2246 ptiRet->impltypelist->hRef = tiBase.datatype1;
2247 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2251 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2252 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2253 ptiRet->impltypelist->hRef = tiBase.datatype1;
2258 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2260 TRACE_(typelib)("%s guid: %s kind:%s\n",
2261 debugstr_w(ptiRet->Name),
2262 debugstr_guid(&ptiRet->TypeAttr.guid),
2263 typekind_desc[ptiRet->TypeAttr.typekind]);
2264 if (TRACE_ON(typelib))
2265 dump_TypeInfo(ptiRet);
2270 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2271 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2272 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2275 static ITypeLibImpl *tlb_cache_first;
2276 static CRITICAL_SECTION cache_section;
2277 static CRITICAL_SECTION_DEBUG cache_section_debug =
2279 0, 0, &cache_section,
2280 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2281 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2283 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2286 typedef struct TLB_PEFile
2288 const IUnknownVtbl *lpvtbl;
2291 HRSRC typelib_resource;
2292 HGLOBAL typelib_global;
2293 LPVOID typelib_base;
2296 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2298 if (IsEqualIID(riid, &IID_IUnknown))
2301 IUnknown_AddRef(iface);
2305 return E_NOINTERFACE;
2308 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2310 TLB_PEFile *This = (TLB_PEFile *)iface;
2311 return InterlockedIncrement(&This->refs);
2314 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2316 TLB_PEFile *This = (TLB_PEFile *)iface;
2317 ULONG refs = InterlockedDecrement(&This->refs);
2320 if (This->typelib_global)
2321 FreeResource(This->typelib_global);
2323 FreeLibrary(This->dll);
2324 HeapFree(GetProcessHeap(), 0, This);
2329 static const IUnknownVtbl TLB_PEFile_Vtable =
2331 TLB_PEFile_QueryInterface,
2336 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2340 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2342 return E_OUTOFMEMORY;
2344 This->lpvtbl = &TLB_PEFile_Vtable;
2347 This->typelib_resource = NULL;
2348 This->typelib_global = NULL;
2349 This->typelib_base = NULL;
2351 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2352 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2356 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2357 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2358 if (This->typelib_resource)
2360 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2361 if (This->typelib_global)
2363 This->typelib_base = LockResource(This->typelib_global);
2365 if (This->typelib_base)
2367 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2368 *ppBase = This->typelib_base;
2369 *ppFile = (IUnknown *)&This->lpvtbl;
2376 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2377 return TYPE_E_CANTLOADLIBRARY;
2380 typedef struct TLB_NEFile
2382 const IUnknownVtbl *lpvtbl;
2384 LPVOID typelib_base;
2387 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2389 if (IsEqualIID(riid, &IID_IUnknown))
2392 IUnknown_AddRef(iface);
2396 return E_NOINTERFACE;
2399 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2401 TLB_NEFile *This = (TLB_NEFile *)iface;
2402 return InterlockedIncrement(&This->refs);
2405 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2407 TLB_NEFile *This = (TLB_NEFile *)iface;
2408 ULONG refs = InterlockedDecrement(&This->refs);
2411 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2412 HeapFree(GetProcessHeap(), 0, This);
2417 static const IUnknownVtbl TLB_NEFile_Vtable =
2419 TLB_NEFile_QueryInterface,
2424 /***********************************************************************
2425 * read_xx_header [internal]
2427 static int read_xx_header( HFILE lzfd )
2429 IMAGE_DOS_HEADER mzh;
2432 LZSeek( lzfd, 0, SEEK_SET );
2433 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2435 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2438 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2439 if ( 2 != LZRead( lzfd, magic, 2 ) )
2442 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2444 if ( magic[0] == 'N' && magic[1] == 'E' )
2445 return IMAGE_OS2_SIGNATURE;
2446 if ( magic[0] == 'P' && magic[1] == 'E' )
2447 return IMAGE_NT_SIGNATURE;
2450 WARN("Can't handle %s files.\n", magic );
2455 /***********************************************************************
2456 * find_ne_resource [internal]
2458 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2459 DWORD *resLen, DWORD *resOff )
2461 IMAGE_OS2_HEADER nehd;
2462 NE_TYPEINFO *typeInfo;
2463 NE_NAMEINFO *nameInfo;
2469 /* Read in NE header */
2470 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2471 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2473 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2476 TRACE("No resources in NE dll\n" );
2480 /* Read in resource table */
2481 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2482 if ( !resTab ) return FALSE;
2484 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2485 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2487 HeapFree( GetProcessHeap(), 0, resTab );
2492 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2494 if (HIWORD(typeid) != 0) /* named type */
2496 BYTE len = strlen( typeid );
2497 while (typeInfo->type_id)
2499 if (!(typeInfo->type_id & 0x8000))
2501 BYTE *p = resTab + typeInfo->type_id;
2502 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2504 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2505 typeInfo->count * sizeof(NE_NAMEINFO));
2508 else /* numeric type id */
2510 WORD id = LOWORD(typeid) | 0x8000;
2511 while (typeInfo->type_id)
2513 if (typeInfo->type_id == id) goto found_type;
2514 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2515 typeInfo->count * sizeof(NE_NAMEINFO));
2518 TRACE("No typeid entry found for %p\n", typeid );
2519 HeapFree( GetProcessHeap(), 0, resTab );
2523 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2525 if (HIWORD(resid) != 0) /* named resource */
2527 BYTE len = strlen( resid );
2528 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2530 BYTE *p = resTab + nameInfo->id;
2531 if (nameInfo->id & 0x8000) continue;
2532 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2535 else /* numeric resource id */
2537 WORD id = LOWORD(resid) | 0x8000;
2538 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2539 if (nameInfo->id == id) goto found_name;
2541 TRACE("No resid entry found for %p\n", typeid );
2542 HeapFree( GetProcessHeap(), 0, resTab );
2546 /* Return resource data */
2547 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2548 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2550 HeapFree( GetProcessHeap(), 0, resTab );
2554 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2558 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2559 TLB_NEFile *This = NULL;
2561 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2562 if (!This) return E_OUTOFMEMORY;
2564 This->lpvtbl = &TLB_NEFile_Vtable;
2566 This->typelib_base = NULL;
2568 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2569 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2571 DWORD reslen, offset;
2572 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2574 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2575 if( !This->typelib_base )
2579 LZSeek( lzfd, offset, SEEK_SET );
2580 reslen = LZRead( lzfd, This->typelib_base, reslen );
2582 *ppBase = This->typelib_base;
2583 *pdwTLBLength = reslen;
2584 *ppFile = (IUnknown *)&This->lpvtbl;
2590 if( lzfd >= 0) LZClose( lzfd );
2591 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2595 typedef struct TLB_Mapping
2597 const IUnknownVtbl *lpvtbl;
2601 LPVOID typelib_base;
2604 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2606 if (IsEqualIID(riid, &IID_IUnknown))
2609 IUnknown_AddRef(iface);
2613 return E_NOINTERFACE;
2616 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2618 TLB_Mapping *This = (TLB_Mapping *)iface;
2619 return InterlockedIncrement(&This->refs);
2622 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2624 TLB_Mapping *This = (TLB_Mapping *)iface;
2625 ULONG refs = InterlockedDecrement(&This->refs);
2628 if (This->typelib_base)
2629 UnmapViewOfFile(This->typelib_base);
2631 CloseHandle(This->mapping);
2632 if (This->file != INVALID_HANDLE_VALUE)
2633 CloseHandle(This->file);
2634 HeapFree(GetProcessHeap(), 0, This);
2639 static const IUnknownVtbl TLB_Mapping_Vtable =
2641 TLB_Mapping_QueryInterface,
2646 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2650 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2652 return E_OUTOFMEMORY;
2654 This->lpvtbl = &TLB_Mapping_Vtable;
2656 This->file = INVALID_HANDLE_VALUE;
2657 This->mapping = NULL;
2658 This->typelib_base = NULL;
2660 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2661 if (INVALID_HANDLE_VALUE != This->file)
2663 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2666 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2667 if(This->typelib_base)
2669 /* retrieve file size */
2670 *pdwTLBLength = GetFileSize(This->file, NULL);
2671 *ppBase = This->typelib_base;
2672 *ppFile = (IUnknown *)&This->lpvtbl;
2678 IUnknown_Release((IUnknown *)&This->lpvtbl);
2679 return TYPE_E_CANTLOADLIBRARY;
2682 /****************************************************************************
2685 * find the type of the typelib file and map the typelib resource into
2688 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2689 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2690 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2692 ITypeLibImpl *entry;
2695 LPWSTR index_str, file = (LPWSTR)pszFileName;
2696 LPVOID pBase = NULL;
2697 DWORD dwTLBLength = 0;
2698 IUnknown *pFile = NULL;
2702 index_str = strrchrW(pszFileName, '\\');
2703 if(index_str && *++index_str != '\0')
2706 long idx = strtolW(index_str, &end_ptr, 10);
2707 if(*end_ptr == '\0')
2709 int str_len = index_str - pszFileName - 1;
2711 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2712 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2717 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2719 if(strchrW(file, '\\'))
2721 lstrcpyW(pszPath, file);
2725 int len = GetSystemDirectoryW(pszPath, cchPath);
2726 pszPath[len] = '\\';
2727 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2731 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2733 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2735 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2736 EnterCriticalSection(&cache_section);
2737 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2739 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2741 TRACE("cache hit\n");
2742 *ppTypeLib = (ITypeLib2*)entry;
2743 ITypeLib_AddRef(*ppTypeLib);
2744 LeaveCriticalSection(&cache_section);
2748 LeaveCriticalSection(&cache_section);
2750 /* now actually load and parse the typelib */
2752 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2753 if (ret == TYPE_E_CANTLOADLIBRARY)
2754 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2755 if (ret == TYPE_E_CANTLOADLIBRARY)
2756 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2759 if (dwTLBLength >= 4)
2761 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2762 if (dwSignature == MSFT_SIGNATURE)
2763 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2764 else if (dwSignature == SLTG_SIGNATURE)
2765 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2768 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2769 ret = TYPE_E_CANTLOADLIBRARY;
2773 ret = TYPE_E_CANTLOADLIBRARY;
2774 IUnknown_Release(pFile);
2778 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2780 TRACE("adding to cache\n");
2781 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2782 lstrcpyW(impl->path, pszPath);
2783 /* We should really canonicalise the path here. */
2784 impl->index = index;
2786 /* FIXME: check if it has added already in the meantime */
2787 EnterCriticalSection(&cache_section);
2788 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2790 tlb_cache_first = impl;
2791 LeaveCriticalSection(&cache_section);
2794 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2799 /*================== ITypeLib(2) Methods ===================================*/
2801 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2803 ITypeLibImpl* pTypeLibImpl;
2805 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2806 if (!pTypeLibImpl) return NULL;
2808 pTypeLibImpl->lpVtbl = &tlbvt;
2809 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2810 pTypeLibImpl->ref = 1;
2812 list_init(&pTypeLibImpl->ref_list);
2813 pTypeLibImpl->dispatch_href = -1;
2815 return pTypeLibImpl;
2818 /****************************************************************************
2819 * ITypeLib2_Constructor_MSFT
2821 * loading an MSFT typelib from an in-memory image
2823 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2827 MSFT_Header tlbHeader;
2828 MSFT_SegDir tlbSegDir;
2829 ITypeLibImpl * pTypeLibImpl;
2831 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2833 pTypeLibImpl = TypeLibImpl_Constructor();
2834 if (!pTypeLibImpl) return NULL;
2836 /* get pointer to beginning of typelib data */
2840 cx.pLibInfo = pTypeLibImpl;
2841 cx.length = dwTLBLength;
2844 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2845 TRACE_(typelib)("header:\n");
2846 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2847 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2848 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2851 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2853 /* there is a small amount of information here until the next important
2855 * the segment directory . Try to calculate the amount of data */
2856 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2858 /* now read the segment directory */
2859 TRACE("read segment directory (at %ld)\n",lPSegDir);
2860 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2861 cx.pTblDir = &tlbSegDir;
2863 /* just check two entries */
2864 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2866 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2867 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2871 /* now fill our internal data */
2872 /* TLIBATTR fields */
2873 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2875 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2876 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2877 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2878 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2879 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2881 /* name, eventually add to a hash table */
2882 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2885 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2886 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2888 if( tlbHeader.varflags & HELPDLLFLAG)
2891 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2892 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2895 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2898 if(tlbHeader.CustomDataOffset >= 0)
2900 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2903 /* fill in type descriptions */
2904 if(tlbSegDir.pTypdescTab.length > 0)
2906 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2908 pTypeLibImpl->ctTypeDesc = cTD;
2909 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2910 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2913 /* FIXME: add several sanity checks here */
2914 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2915 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2917 /* FIXME: check safearray */
2919 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2921 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2923 else if(td[0] == VT_CARRAY)
2925 /* array descr table here */
2926 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2928 else if(td[0] == VT_USERDEFINED)
2930 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2932 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2935 /* second time around to fill the array subscript info */
2938 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2939 if(tlbSegDir.pArrayDescriptions.offset>0)
2941 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2942 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2945 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2947 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2949 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2951 for(j = 0; j<td[2]; j++)
2953 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2954 sizeof(INT), &cx, DO_NOT_SEEK);
2955 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2956 sizeof(INT), &cx, DO_NOT_SEEK);
2961 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2962 ERR("didn't find array description data\n");
2967 /* imported type libs */
2968 if(tlbSegDir.pImpFiles.offset>0)
2970 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2971 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2974 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2978 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2979 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2980 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2982 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2983 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2984 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2985 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2988 name = TLB_Alloc(size+1);
2989 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2990 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2992 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2993 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2995 ppImpLib = &(*ppImpLib)->next;
2999 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3000 if(pTypeLibImpl->dispatch_href != -1)
3001 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3004 if(tlbHeader.nrtypeinfos >= 0 )
3006 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3007 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3010 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3012 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3014 ppTI = &((*ppTI)->next);
3015 (pTypeLibImpl->TypeInfoCount)++;
3019 TRACE("(%p)\n", pTypeLibImpl);
3020 return (ITypeLib2*) pTypeLibImpl;
3024 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3030 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3031 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3035 guid->Data4[0] = s >> 8;
3036 guid->Data4[1] = s & 0xff;
3039 for(i = 0; i < 6; i++) {
3040 memcpy(b, str + 24 + 2 * i, 2);
3041 guid->Data4[i + 2] = strtol(b, NULL, 16);
3046 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3052 bytelen = *(const WORD*)ptr;
3053 if(bytelen == 0xffff) return 2;
3054 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3055 *pBstr = SysAllocStringLen(NULL, len - 1);
3057 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3061 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3066 bytelen = *(const WORD*)ptr;
3067 if(bytelen == 0xffff) return 2;
3068 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3069 memcpy(*str, ptr + 2, bytelen);
3070 (*str)[bytelen] = '\0';
3074 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3076 char *ptr = pLibBlk;
3079 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3080 FIXME("libblk magic = %04x\n", w);
3085 if((w = *(WORD*)ptr) != 0xffff) {
3086 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3091 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3093 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3095 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3098 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3101 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3102 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3104 pTypeLibImpl->LibAttr.lcid = 0;
3107 ptr += 4; /* skip res12 */
3109 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3112 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3115 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3118 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3119 ptr += sizeof(GUID);
3121 return ptr - (char*)pLibBlk;
3124 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3129 } sltg_ref_lookup_t;
3131 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3132 HREFTYPE *typelib_ref)
3134 if(typeinfo_ref < table->num)
3136 *typelib_ref = table->refs[typeinfo_ref];
3140 ERR_(typelib)("Unable to find reference\n");
3145 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3150 if((*pType & 0xe00) == 0xe00) {
3152 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3154 pTD = pTD->u.lptdesc;
3156 switch(*pType & 0x3f) {
3159 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3161 pTD = pTD->u.lptdesc;
3164 case VT_USERDEFINED:
3165 pTD->vt = VT_USERDEFINED;
3166 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3172 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3175 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3177 pTD->vt = VT_CARRAY;
3178 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3180 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3181 pTD->u.lpadesc->cDims = pSA->cDims;
3182 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3183 pSA->cDims * sizeof(SAFEARRAYBOUND));
3185 pTD = &pTD->u.lpadesc->tdescElem;
3191 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3195 pTD->vt = VT_SAFEARRAY;
3196 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3198 pTD = pTD->u.lptdesc;
3202 pTD->vt = *pType & 0x3f;
3211 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3212 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3214 /* Handle [in/out] first */
3215 if((*pType & 0xc000) == 0xc000)
3216 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3217 else if(*pType & 0x8000)
3218 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3219 else if(*pType & 0x4000)
3220 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3222 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3225 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3228 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3230 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3234 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3239 TLBRefType *ref_type;
3240 sltg_ref_lookup_t *table;
3241 HREFTYPE typelib_ref;
3243 if(pRef->magic != SLTG_REF_MAGIC) {
3244 FIXME("Ref magic = %x\n", pRef->magic);
3247 name = ( (char*)pRef->names + pRef->number);
3249 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3250 table->num = pRef->number >> 3;
3252 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3254 /* We don't want the first href to be 0 */
3255 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3257 for(ref = 0; ref < pRef->number >> 3; ref++) {
3259 unsigned int lib_offs, type_num;
3261 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3263 name += SLTG_ReadStringA(name, &refname);
3264 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3265 FIXME_(typelib)("Can't sscanf ref\n");
3266 if(lib_offs != 0xffff) {
3267 TLBImpLib **import = &pTL->pImpLibs;
3270 if((*import)->offset == lib_offs)
3272 import = &(*import)->next;
3275 char fname[MAX_PATH+1];
3278 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3280 (*import)->offset = lib_offs;
3281 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3283 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3284 &(*import)->wVersionMajor,
3285 &(*import)->wVersionMinor,
3286 &(*import)->lcid, fname) != 4) {
3287 FIXME_(typelib)("can't sscanf ref %s\n",
3288 pNameTable + lib_offs + 40);
3290 len = strlen(fname);
3291 if(fname[len-1] != '#')
3292 FIXME("fname = %s\n", fname);
3293 fname[len-1] = '\0';
3294 (*import)->name = TLB_MultiByteToBSTR(fname);
3296 ref_type->pImpTLInfo = *import;
3298 /* Store a reference to IDispatch */
3299 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3300 pTL->dispatch_href = typelib_ref;
3302 } else { /* internal ref */
3303 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3305 ref_type->reference = typelib_ref;
3306 ref_type->index = type_num;
3308 HeapFree(GetProcessHeap(), 0, refname);
3309 list_add_tail(&pTL->ref_list, &ref_type->entry);
3311 table->refs[ref] = typelib_ref;
3314 if((BYTE)*name != SLTG_REF_MAGIC)
3315 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3316 dump_TLBRefType(pTL);
3320 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3321 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3323 SLTG_ImplInfo *info;
3324 TLBImplType **ppImplType = &pTI->impltypelist;
3325 /* I don't really get this structure, usually it's 0x16 bytes
3326 long, but iuser.tlb contains some that are 0x18 bytes long.
3327 That's ok because we can use the next ptr to jump to the next
3328 one. But how do we know the length of the last one? The WORD
3329 at offs 0x8 might be the clue. For now I'm just assuming that
3330 the last one is the regular 0x16 bytes. */
3332 info = (SLTG_ImplInfo*)pBlk;
3334 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3335 sizeof(**ppImplType));
3336 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3337 (*ppImplType)->implflags = info->impltypeflags;
3338 pTI->TypeAttr.cImplTypes++;
3339 ppImplType = &(*ppImplType)->next;
3341 if(info->next == 0xffff)
3344 FIXME_(typelib)("Interface inheriting more than one interface\n");
3345 info = (SLTG_ImplInfo*)(pBlk + info->next);
3347 info++; /* see comment at top of function */
3351 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3352 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3354 TLBVarDesc **ppVarDesc = &pTI->varlist;
3355 BSTR bstrPrevName = NULL;
3356 SLTG_Variable *pItem;
3360 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3361 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3363 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3364 sizeof(**ppVarDesc));
3365 (*ppVarDesc)->vardesc.memid = pItem->memid;
3367 if (pItem->magic != SLTG_VAR_MAGIC &&
3368 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3369 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3373 if (pItem->name == 0xfffe)
3374 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3376 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3378 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3379 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3380 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3382 if(pItem->flags & 0x02)
3383 pType = &pItem->type;
3385 pType = (WORD*)(pBlk + pItem->type);
3387 if (pItem->flags & ~0xda)
3388 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3390 SLTG_DoElem(pType, pBlk,
3391 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3393 if (TRACE_ON(typelib)) {
3395 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3396 TRACE_(typelib)("elemdescVar: %s\n", buf);
3399 if (pItem->flags & 0x40) {
3400 TRACE_(typelib)("VAR_DISPATCH\n");
3401 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3403 else if (pItem->flags & 0x10) {
3404 TRACE_(typelib)("VAR_CONST\n");
3405 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3406 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3408 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3409 if (pItem->flags & 0x08)
3410 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3412 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3418 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3420 TRACE_(typelib)("len = %u\n", len);
3421 if (len == 0xffff) {
3424 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3425 str = SysAllocStringLen(NULL, alloc_len);
3426 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3428 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3429 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3438 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3439 *(INT*)(pBlk + pItem->byte_offs);
3442 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3447 TRACE_(typelib)("VAR_PERINSTANCE\n");
3448 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3449 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3452 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3453 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3455 if (pItem->flags & 0x80)
3456 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3458 bstrPrevName = (*ppVarDesc)->Name;
3459 ppVarDesc = &((*ppVarDesc)->next);
3461 pTI->TypeAttr.cVars = cVars;
3464 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3465 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3467 SLTG_Function *pFunc;
3469 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3471 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3472 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3477 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3478 sizeof(**ppFuncDesc));
3480 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3481 case SLTG_FUNCTION_MAGIC:
3482 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3484 case SLTG_DISPATCH_FUNCTION_MAGIC:
3485 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3487 case SLTG_STATIC_FUNCTION_MAGIC:
3488 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3491 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3492 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3496 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3498 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3499 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3500 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3501 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3502 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3503 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3505 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3506 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3508 if(pFunc->retnextopt & 0x80)
3509 pType = &pFunc->rettype;
3511 pType = (WORD*)(pBlk + pFunc->rettype);
3513 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3515 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3516 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3517 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3518 (*ppFuncDesc)->pParamDesc =
3519 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3520 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3522 pArg = (WORD*)(pBlk + pFunc->arg_off);
3524 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3525 char *paramName = pNameTable + *pArg;
3527 /* If arg type follows then paramName points to the 2nd
3528 letter of the name, else the next WORD is an offset to
3529 the arg type and paramName points to the first letter.
3530 So let's take one char off paramName and see if we're
3531 pointing at an alpha-numeric char. However if *pArg is
3532 0xffff or 0xfffe then the param has no name, the former
3533 meaning that the next WORD is the type, the latter
3534 meaning that the next WORD is an offset to the type. */
3539 else if(*pArg == 0xfffe) {
3543 else if(paramName[-1] && !isalnum(paramName[-1]))
3548 if(HaveOffs) { /* the next word is an offset to type */
3549 pType = (WORD*)(pBlk + *pArg);
3550 SLTG_DoElem(pType, pBlk,
3551 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3556 pArg = SLTG_DoElem(pArg, pBlk,
3557 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3560 /* Are we an optional param ? */
3561 if((*ppFuncDesc)->funcdesc.cParams - param <=
3562 (*ppFuncDesc)->funcdesc.cParamsOpt)
3563 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3566 (*ppFuncDesc)->pParamDesc[param].Name =
3567 TLB_MultiByteToBSTR(paramName);
3569 (*ppFuncDesc)->pParamDesc[param].Name =
3570 SysAllocString((*ppFuncDesc)->Name);
3574 ppFuncDesc = &((*ppFuncDesc)->next);
3575 if(pFunc->next == 0xffff) break;
3577 pTI->TypeAttr.cFuncs = cFuncs;
3580 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3581 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3582 SLTG_TypeInfoTail *pTITail)
3585 sltg_ref_lookup_t *ref_lookup = NULL;
3587 if(pTIHeader->href_table != 0xffffffff) {
3588 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3594 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3595 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3597 HeapFree(GetProcessHeap(), 0, ref_lookup);
3601 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3602 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3603 const SLTG_TypeInfoTail *pTITail)
3606 sltg_ref_lookup_t *ref_lookup = NULL;
3608 if(pTIHeader->href_table != 0xffffffff) {
3609 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3615 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3616 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3619 if (pTITail->funcs_off != 0xffff)
3620 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3622 HeapFree(GetProcessHeap(), 0, ref_lookup);
3624 if (TRACE_ON(typelib))
3625 dump_TLBFuncDesc(pTI->funclist);
3628 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3629 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3630 const SLTG_TypeInfoTail *pTITail)
3632 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3635 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3636 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3637 const SLTG_TypeInfoTail *pTITail)
3640 sltg_ref_lookup_t *ref_lookup = NULL;
3642 if (pTITail->simple_alias) {
3643 /* if simple alias, no more processing required */
3644 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3648 if(pTIHeader->href_table != 0xffffffff) {
3649 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3653 /* otherwise it is an offset to a type */
3654 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3656 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3658 HeapFree(GetProcessHeap(), 0, ref_lookup);
3661 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3662 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3663 const SLTG_TypeInfoTail *pTITail)
3665 sltg_ref_lookup_t *ref_lookup = NULL;
3666 if (pTIHeader->href_table != 0xffffffff)
3667 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3670 if (pTITail->vars_off != 0xffff)
3671 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3673 if (pTITail->funcs_off != 0xffff)
3674 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3676 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3677 * of dispinterface functions including the IDispatch ones, so
3678 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3679 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3681 HeapFree(GetProcessHeap(), 0, ref_lookup);
3682 if (TRACE_ON(typelib))
3683 dump_TLBFuncDesc(pTI->funclist);
3686 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3687 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3688 const SLTG_TypeInfoTail *pTITail)
3690 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3693 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3694 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3695 const SLTG_TypeInfoTail *pTITail)
3697 sltg_ref_lookup_t *ref_lookup = NULL;
3698 if (pTIHeader->href_table != 0xffffffff)
3699 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3702 if (pTITail->vars_off != 0xffff)
3703 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3705 if (pTITail->funcs_off != 0xffff)
3706 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3707 HeapFree(GetProcessHeap(), 0, ref_lookup);
3708 if (TRACE_ON(typelib))
3712 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3713 managable copy of it into this */
3726 } SLTG_InternalOtherTypeInfo;
3728 /****************************************************************************
3729 * ITypeLib2_Constructor_SLTG
3731 * loading a SLTG typelib from an in-memory image
3733 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3735 ITypeLibImpl *pTypeLibImpl;
3736 SLTG_Header *pHeader;
3737 SLTG_BlkEntry *pBlkEntry;
3741 LPVOID pBlk, pFirstBlk;
3742 SLTG_LibBlk *pLibBlk;
3743 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3744 char *pAfterOTIBlks = NULL;
3745 char *pNameTable, *ptr;
3748 ITypeInfoImpl **ppTypeInfoImpl;
3750 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3753 pTypeLibImpl = TypeLibImpl_Constructor();
3754 if (!pTypeLibImpl) return NULL;
3758 TRACE_(typelib)("header:\n");
3759 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3760 pHeader->nrOfFileBlks );
3761 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3762 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3763 pHeader->SLTG_magic);
3767 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3768 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3770 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3771 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3773 /* Next we have a magic block */
3774 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3776 /* Let's see if we're still in sync */
3777 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3778 sizeof(SLTG_COMPOBJ_MAGIC))) {
3779 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3782 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3783 sizeof(SLTG_DIR_MAGIC))) {
3784 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3788 pIndex = (SLTG_Index*)(pMagic+1);
3790 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3792 pFirstBlk = pPad9 + 1;
3794 /* We'll set up a ptr to the main library block, which is the last one. */
3796 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3797 pBlkEntry[order].next != 0;
3798 order = pBlkEntry[order].next - 1, i++) {
3799 pBlk = (char*)pBlk + pBlkEntry[order].len;
3803 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3805 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3810 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3812 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3813 sizeof(*pOtherTypeInfoBlks) *
3814 pTypeLibImpl->TypeInfoCount);
3817 ptr = (char*)pLibBlk + len;
3819 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3823 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3825 w = *(WORD*)(ptr + 2);
3828 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3830 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3831 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3833 w = *(WORD*)(ptr + 4 + len);
3835 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3837 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3839 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3840 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3842 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3843 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3844 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3846 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3848 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3851 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3852 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3853 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3854 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3855 len += sizeof(SLTG_OtherTypeInfo);
3859 pAfterOTIBlks = ptr;
3861 /* Skip this WORD and get the next DWORD */
3862 len = *(DWORD*)(pAfterOTIBlks + 2);
3864 /* Now add this to pLibBLk look at what we're pointing at and
3865 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3866 dust and we should be pointing at the beginning of the name
3869 pNameTable = (char*)pLibBlk + len;
3871 switch(*(WORD*)pNameTable) {
3878 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3882 pNameTable += 0x216;
3886 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3888 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3891 /* Hopefully we now have enough ptrs set up to actually read in
3892 some TypeInfos. It's not clear which order to do them in, so
3893 I'll just follow the links along the BlkEntry chain and read
3894 them in the order in which they are in the file */
3896 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3898 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3899 pBlkEntry[order].next != 0;
3900 order = pBlkEntry[order].next - 1, i++) {
3902 SLTG_TypeInfoHeader *pTIHeader;
3903 SLTG_TypeInfoTail *pTITail;
3904 SLTG_MemberHeader *pMemHeader;
3906 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3907 pOtherTypeInfoBlks[i].index_name)) {
3908 FIXME_(typelib)("Index strings don't match\n");
3913 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3914 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3917 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3918 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3919 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3921 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3922 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3923 (*ppTypeInfoImpl)->index = i;
3924 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3925 pOtherTypeInfoBlks[i].name_offs +
3927 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3928 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3929 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3930 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3931 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3932 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3933 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3935 if((pTIHeader->typeflags1 & 7) != 2)
3936 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3937 if(pTIHeader->typeflags3 != 2)
3938 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3940 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3941 debugstr_w((*ppTypeInfoImpl)->Name),
3942 typekind_desc[pTIHeader->typekind],
3943 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3944 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3946 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3948 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3950 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3951 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3952 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3954 switch(pTIHeader->typekind) {
3956 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3957 pTIHeader, pTITail);
3961 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3962 pTIHeader, pTITail);
3965 case TKIND_INTERFACE:
3966 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3967 pTIHeader, pTITail);
3971 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3972 pTIHeader, pTITail);
3976 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3977 pTIHeader, pTITail);
3980 case TKIND_DISPATCH:
3981 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3982 pTIHeader, pTITail);
3986 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3987 pTIHeader, pTITail);
3991 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3996 /* could get cFuncs, cVars and cImplTypes from here
3997 but we've already set those */
3998 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4013 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4014 pBlk = (char*)pBlk + pBlkEntry[order].len;
4017 if(i != pTypeLibImpl->TypeInfoCount) {
4018 FIXME("Somehow processed %d TypeInfos\n", i);
4022 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4023 return (ITypeLib2*)pTypeLibImpl;
4026 /* ITypeLib::QueryInterface
4028 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4033 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4035 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4038 if(IsEqualIID(riid, &IID_IUnknown) ||
4039 IsEqualIID(riid,&IID_ITypeLib)||
4040 IsEqualIID(riid,&IID_ITypeLib2))
4047 ITypeLib2_AddRef(iface);
4048 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4051 TRACE("-- Interface: E_NOINTERFACE\n");
4052 return E_NOINTERFACE;
4057 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4059 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4060 ULONG ref = InterlockedIncrement(&This->ref);
4062 TRACE("(%p)->ref was %u\n",This, ref - 1);
4067 /* ITypeLib::Release
4069 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4071 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4072 ULONG ref = InterlockedDecrement(&This->ref);
4074 TRACE("(%p)->(%u)\n",This, ref);
4078 TLBImpLib *pImpLib, *pImpLibNext;
4079 TLBCustData *pCustData, *pCustDataNext;
4080 TLBRefType *ref_type;
4084 /* remove cache entry */
4087 TRACE("removing from cache list\n");
4088 EnterCriticalSection(&cache_section);
4089 if (This->next) This->next->prev = This->prev;
4090 if (This->prev) This->prev->next = This->next;
4091 else tlb_cache_first = This->next;
4092 LeaveCriticalSection(&cache_section);
4093 HeapFree(GetProcessHeap(), 0, This->path);
4095 TRACE(" destroying ITypeLib(%p)\n",This);
4097 SysFreeString(This->Name);
4100 SysFreeString(This->DocString);
4101 This->DocString = NULL;
4103 SysFreeString(This->HelpFile);
4104 This->HelpFile = NULL;
4106 SysFreeString(This->HelpStringDll);
4107 This->HelpStringDll = NULL;
4109 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4111 VariantClear(&pCustData->data);
4113 pCustDataNext = pCustData->next;
4114 TLB_Free(pCustData);
4117 for (i = 0; i < This->ctTypeDesc; i++)
4118 if (This->pTypeDesc[i].vt == VT_CARRAY)
4119 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4121 TLB_Free(This->pTypeDesc);
4123 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4125 if (pImpLib->pImpTypeLib)
4126 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4127 SysFreeString(pImpLib->name);
4129 pImpLibNext = pImpLib->next;
4133 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4135 list_remove(&ref_type->entry);
4139 if (This->pTypeInfo) /* can be NULL */
4140 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4141 HeapFree(GetProcessHeap(),0,This);
4148 /* ITypeLib::GetTypeInfoCount
4150 * Returns the number of type descriptions in the type library
4152 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4154 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4155 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4156 return This->TypeInfoCount;
4159 /* ITypeLib::GetTypeInfo
4161 * retrieves the specified type description in the library.
4163 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4166 ITypeInfo **ppTInfo)
4170 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4171 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4173 TRACE("(%p)->(index=%d)\n", This, index);
4175 if (!ppTInfo) return E_INVALIDARG;
4177 /* search element n in list */
4178 for(i=0; i < index; i++)
4180 pTypeInfo = pTypeInfo->next;
4183 TRACE("-- element not found\n");
4184 return TYPE_E_ELEMENTNOTFOUND;
4188 *ppTInfo = (ITypeInfo *) pTypeInfo;
4190 ITypeInfo_AddRef(*ppTInfo);
4191 TRACE("-- found (%p)\n",*ppTInfo);
4196 /* ITypeLibs::GetTypeInfoType
4198 * Retrieves the type of a type description.
4200 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4205 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4207 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4209 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4210 return TYPE_E_ELEMENTNOTFOUND;
4212 TRACE("(%p) index %d\n", This, index);
4214 if(!pTKind) return E_INVALIDARG;
4216 /* search element n in list */
4217 for(i=0; i < index; i++)
4221 TRACE("-- element not found\n");
4222 return TYPE_E_ELEMENTNOTFOUND;
4224 pTInfo = pTInfo->next;
4227 *pTKind = pTInfo->TypeAttr.typekind;
4228 TRACE("-- found Type (%d)\n", *pTKind);
4232 /* ITypeLib::GetTypeInfoOfGuid
4234 * Retrieves the type description that corresponds to the specified GUID.
4237 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4240 ITypeInfo **ppTInfo)
4242 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4243 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4245 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4249 WARN("-- element not found\n");
4250 return TYPE_E_ELEMENTNOTFOUND;
4253 /* search linked list for guid */
4254 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4256 pTypeInfo = pTypeInfo->next;
4260 /* end of list reached */
4261 WARN("-- element not found\n");
4262 return TYPE_E_ELEMENTNOTFOUND;
4266 TRACE("-- found (%p, %s)\n",
4268 debugstr_w(pTypeInfo->Name));
4270 *ppTInfo = (ITypeInfo*)pTypeInfo;
4271 ITypeInfo_AddRef(*ppTInfo);
4275 /* ITypeLib::GetLibAttr
4277 * Retrieves the structure that contains the library's attributes.
4280 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4282 LPTLIBATTR *ppTLibAttr)
4284 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4285 TRACE("(%p)\n",This);
4286 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4287 **ppTLibAttr = This->LibAttr;
4291 /* ITypeLib::GetTypeComp
4293 * Enables a client compiler to bind to a library's types, variables,
4294 * constants, and global functions.
4297 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4299 ITypeComp **ppTComp)
4301 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4303 TRACE("(%p)->(%p)\n",This,ppTComp);
4304 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4305 ITypeComp_AddRef(*ppTComp);
4310 /* ITypeLib::GetDocumentation
4312 * Retrieves the library's documentation string, the complete Help file name
4313 * and path, and the context identifier for the library Help topic in the Help
4316 * On a successful return all non-null BSTR pointers will have been set,
4319 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4323 BSTR *pBstrDocString,
4324 DWORD *pdwHelpContext,
4325 BSTR *pBstrHelpFile)
4327 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4329 HRESULT result = E_INVALIDARG;
4334 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4336 pBstrName, pBstrDocString,
4337 pdwHelpContext, pBstrHelpFile);
4341 /* documentation for the typelib */
4346 if(!(*pBstrName = SysAllocString(This->Name)))
4354 if (This->DocString)
4356 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4359 else if (This->Name)
4361 if(!(*pBstrDocString = SysAllocString(This->Name)))
4365 *pBstrDocString = NULL;
4369 *pdwHelpContext = This->dwHelpContext;
4375 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4379 *pBstrHelpFile = NULL;
4386 /* for a typeinfo */
4387 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4389 if(SUCCEEDED(result))
4391 result = ITypeInfo_GetDocumentation(pTInfo,
4395 pdwHelpContext, pBstrHelpFile);
4397 ITypeInfo_Release(pTInfo);
4402 if (pBstrDocString) SysFreeString (*pBstrDocString);
4404 if (pBstrName) SysFreeString (*pBstrName);
4406 return STG_E_INSUFFICIENTMEMORY;
4411 * Indicates whether a passed-in string contains the name of a type or member
4412 * described in the library.
4415 static HRESULT WINAPI ITypeLib2_fnIsName(
4421 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4422 ITypeInfoImpl *pTInfo;
4423 TLBFuncDesc *pFInfo;
4426 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4428 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4432 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4433 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4434 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4435 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4436 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4437 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4438 goto ITypeLib2_fnIsName_exit;
4440 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4441 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4446 ITypeLib2_fnIsName_exit:
4447 TRACE("(%p)slow! search for %s: %s found!\n", This,
4448 debugstr_w(szNameBuf), *pfName?"NOT":"");
4453 /* ITypeLib::FindName
4455 * Finds occurrences of a type description in a type library. This may be used
4456 * to quickly verify that a name exists in a type library.
4459 static HRESULT WINAPI ITypeLib2_fnFindName(
4463 ITypeInfo **ppTInfo,
4467 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4468 ITypeInfoImpl *pTInfo;
4469 TLBFuncDesc *pFInfo;
4472 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4474 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4475 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4476 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4477 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4478 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4479 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4480 goto ITypeLib2_fnFindName_exit;
4483 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4484 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4486 ITypeLib2_fnFindName_exit:
4487 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4488 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4491 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4492 This, *pcFound, debugstr_w(szNameBuf), j);
4499 /* ITypeLib::ReleaseTLibAttr
4501 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4504 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4506 TLIBATTR *pTLibAttr)
4508 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4509 TRACE("freeing (%p)\n",This);
4510 HeapFree(GetProcessHeap(),0,pTLibAttr);
4514 /* ITypeLib2::GetCustData
4516 * gets the custom data
4518 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4523 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4524 TLBCustData *pCData;
4526 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4528 if( IsEqualIID(guid, &pCData->guid)) break;
4531 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4535 VariantInit( pVarVal);
4536 VariantCopy( pVarVal, &pCData->data);
4539 return E_INVALIDARG; /* FIXME: correct? */
4542 /* ITypeLib2::GetLibStatistics
4544 * Returns statistics about a type library that are required for efficient
4545 * sizing of hash tables.
4548 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4550 ULONG *pcUniqueNames,
4551 ULONG *pcchUniqueNames)
4553 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4555 FIXME("(%p): stub!\n", This);
4557 if(pcUniqueNames) *pcUniqueNames=1;
4558 if(pcchUniqueNames) *pcchUniqueNames=1;
4562 /* ITypeLib2::GetDocumentation2
4564 * Retrieves the library's documentation string, the complete Help file name
4565 * and path, the localization context to use, and the context ID for the
4566 * library Help topic in the Help file.
4569 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4573 BSTR *pbstrHelpString,
4574 DWORD *pdwHelpStringContext,
4575 BSTR *pbstrHelpStringDll)
4577 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4581 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4583 /* the help string should be obtained from the helpstringdll,
4584 * using the _DLLGetDocumentation function, based on the supplied
4585 * lcid. Nice to do sometime...
4589 /* documentation for the typelib */
4591 *pbstrHelpString=SysAllocString(This->DocString);
4592 if(pdwHelpStringContext)
4593 *pdwHelpStringContext=This->dwHelpContext;
4594 if(pbstrHelpStringDll)
4595 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4601 /* for a typeinfo */
4602 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4604 if(SUCCEEDED(result))
4606 ITypeInfo2 * pTInfo2;
4607 result = ITypeInfo_QueryInterface(pTInfo,
4609 (LPVOID*) &pTInfo2);
4611 if(SUCCEEDED(result))
4613 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4617 pdwHelpStringContext,
4618 pbstrHelpStringDll);
4620 ITypeInfo2_Release(pTInfo2);
4623 ITypeInfo_Release(pTInfo);
4629 /* ITypeLib2::GetAllCustData
4631 * Gets all custom data items for the library.
4634 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4636 CUSTDATA *pCustData)
4638 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4639 TLBCustData *pCData;
4641 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4642 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4643 if(pCustData->prgCustData ){
4644 pCustData->cCustData=This->ctCustData;
4645 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4646 pCustData->prgCustData[i].guid=pCData->guid;
4647 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4650 ERR(" OUT OF MEMORY!\n");
4651 return E_OUTOFMEMORY;
4656 static const ITypeLib2Vtbl tlbvt = {
4657 ITypeLib2_fnQueryInterface,
4659 ITypeLib2_fnRelease,
4660 ITypeLib2_fnGetTypeInfoCount,
4661 ITypeLib2_fnGetTypeInfo,
4662 ITypeLib2_fnGetTypeInfoType,
4663 ITypeLib2_fnGetTypeInfoOfGuid,
4664 ITypeLib2_fnGetLibAttr,
4665 ITypeLib2_fnGetTypeComp,
4666 ITypeLib2_fnGetDocumentation,
4668 ITypeLib2_fnFindName,
4669 ITypeLib2_fnReleaseTLibAttr,
4671 ITypeLib2_fnGetCustData,
4672 ITypeLib2_fnGetLibStatistics,
4673 ITypeLib2_fnGetDocumentation2,
4674 ITypeLib2_fnGetAllCustData
4678 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4680 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4682 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4685 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4687 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4689 return ITypeLib2_AddRef((ITypeLib2 *)This);
4692 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4694 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4696 return ITypeLib2_Release((ITypeLib2 *)This);
4699 static HRESULT WINAPI ITypeLibComp_fnBind(
4704 ITypeInfo ** ppTInfo,
4705 DESCKIND * pDescKind,
4708 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4709 ITypeInfoImpl *pTypeInfo;
4711 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4713 *pDescKind = DESCKIND_NONE;
4714 pBindPtr->lptcomp = NULL;
4717 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4719 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4721 /* FIXME: check wFlags here? */
4722 /* FIXME: we should use a hash table to look this info up using lHash
4723 * instead of an O(n) search */
4724 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4725 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4727 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4729 *pDescKind = DESCKIND_TYPECOMP;
4730 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4731 ITypeComp_AddRef(pBindPtr->lptcomp);
4732 TRACE("module or enum: %s\n", debugstr_w(szName));
4737 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4738 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4740 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4743 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4744 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4746 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4751 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4752 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4754 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4756 ITypeInfo *subtypeinfo;
4758 DESCKIND subdesckind;
4760 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4761 &subtypeinfo, &subdesckind, &subbindptr);
4762 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4764 TYPEDESC tdesc_appobject =
4767 (TYPEDESC *)pTypeInfo->hreftype
4771 const VARDESC vardesc_appobject =
4774 NULL, /* lpstrSchema */
4789 VAR_STATIC /* varkind */
4792 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4794 /* cleanup things filled in by Bind call so we can put our
4795 * application object data in there instead */
4796 switch (subdesckind)
4798 case DESCKIND_FUNCDESC:
4799 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4801 case DESCKIND_VARDESC:
4802 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4807 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4809 if (pTypeInfo->hreftype == -1)
4810 FIXME("no hreftype for interface %p\n", pTypeInfo);
4812 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4816 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4817 *ppTInfo = (ITypeInfo *)pTypeInfo;
4818 ITypeInfo_AddRef(*ppTInfo);
4824 TRACE("name not found %s\n", debugstr_w(szName));
4828 static HRESULT WINAPI ITypeLibComp_fnBindType(
4832 ITypeInfo ** ppTInfo,
4833 ITypeComp ** ppTComp)
4835 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4839 static const ITypeCompVtbl tlbtcvt =
4842 ITypeLibComp_fnQueryInterface,
4843 ITypeLibComp_fnAddRef,
4844 ITypeLibComp_fnRelease,
4846 ITypeLibComp_fnBind,
4847 ITypeLibComp_fnBindType
4850 /*================== ITypeInfo(2) Methods ===================================*/
4851 static ITypeInfo2 * ITypeInfo_Constructor(void)
4853 ITypeInfoImpl * pTypeInfoImpl;
4855 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4858 pTypeInfoImpl->lpVtbl = &tinfvt;
4859 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4860 pTypeInfoImpl->ref=1;
4861 pTypeInfoImpl->hreftype = -1;
4862 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4863 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4865 TRACE("(%p)\n", pTypeInfoImpl);
4866 return (ITypeInfo2*) pTypeInfoImpl;
4869 /* ITypeInfo::QueryInterface
4871 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4876 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4878 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4881 if(IsEqualIID(riid, &IID_IUnknown) ||
4882 IsEqualIID(riid,&IID_ITypeInfo)||
4883 IsEqualIID(riid,&IID_ITypeInfo2))
4887 ITypeInfo_AddRef(iface);
4888 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4891 TRACE("-- Interface: E_NOINTERFACE\n");
4892 return E_NOINTERFACE;
4895 /* ITypeInfo::AddRef
4897 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4899 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4900 ULONG ref = InterlockedIncrement(&This->ref);
4902 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4904 TRACE("(%p)->ref is %u\n",This, ref);
4908 /* ITypeInfo::Release
4910 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4912 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4913 ULONG ref = InterlockedDecrement(&This->ref);
4915 TRACE("(%p)->(%u)\n",This, ref);
4918 /* We don't release ITypeLib when ref=0 because
4919 it means that function is called by ITypeLib2_Release */
4920 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4922 TLBFuncDesc *pFInfo, *pFInfoNext;
4923 TLBVarDesc *pVInfo, *pVInfoNext;
4924 TLBImplType *pImpl, *pImplNext;
4926 TRACE("destroying ITypeInfo(%p)\n",This);
4928 if (This->no_free_data)
4931 SysFreeString(This->Name);
4934 SysFreeString(This->DocString);
4935 This->DocString = NULL;
4937 SysFreeString(This->DllName);
4938 This->DllName = NULL;
4940 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4943 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4945 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4946 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4948 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4949 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4951 SysFreeString(pFInfo->pParamDesc[i].Name);
4953 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4954 TLB_Free(pFInfo->pParamDesc);
4955 TLB_FreeCustData(pFInfo->pCustData);
4956 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4957 SysFreeString(pFInfo->Entry);
4958 SysFreeString(pFInfo->HelpString);
4959 SysFreeString(pFInfo->Name);
4961 pFInfoNext = pFInfo->next;
4964 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4966 if (pVInfo->vardesc.varkind == VAR_CONST)
4968 VariantClear(pVInfo->vardesc.u.lpvarValue);
4969 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4971 TLB_FreeCustData(pVInfo->pCustData);
4972 SysFreeString(pVInfo->Name);
4973 pVInfoNext = pVInfo->next;
4976 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4978 TLB_FreeCustData(pImpl->pCustData);
4979 pImplNext = pImpl->next;
4982 TLB_FreeCustData(This->pCustData);
4987 ITypeInfo_Release((ITypeInfo*)This->next);
4990 HeapFree(GetProcessHeap(),0,This);
4996 /* ITypeInfo::GetTypeAttr
4998 * Retrieves a TYPEATTR structure that contains the attributes of the type
5002 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5003 LPTYPEATTR *ppTypeAttr)
5005 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5008 TRACE("(%p)\n",This);
5010 size = sizeof(**ppTypeAttr);
5011 if (This->TypeAttr.typekind == TKIND_ALIAS)
5012 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5014 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5016 return E_OUTOFMEMORY;
5018 **ppTypeAttr = This->TypeAttr;
5020 if (This->TypeAttr.typekind == TKIND_ALIAS)
5021 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5022 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5024 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5025 /* This should include all the inherited funcs */
5026 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5027 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5028 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5033 /* ITypeInfo::GetTypeComp
5035 * Retrieves the ITypeComp interface for the type description, which enables a
5036 * client compiler to bind to the type description's members.
5039 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5040 ITypeComp * *ppTComp)
5042 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5044 TRACE("(%p)->(%p)\n", This, ppTComp);
5046 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5047 ITypeComp_AddRef(*ppTComp);
5051 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5053 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5054 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5055 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5059 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5062 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5063 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5065 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5066 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5067 *buffer += sizeof(PARAMDESCEX);
5068 *pparamdescex_dest = *pparamdescex_src;
5069 VariantInit(&pparamdescex_dest->varDefaultValue);
5070 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5071 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5074 dest->u.paramdesc.pparamdescex = NULL;
5078 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5080 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5081 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5084 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5088 SIZE_T size = sizeof(*src);
5092 size += sizeof(*src->lprgscode) * src->cScodes;
5093 size += TLB_SizeElemDesc(&src->elemdescFunc);
5094 for (i = 0; i < src->cParams; i++)
5096 size += sizeof(ELEMDESC);
5097 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5100 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5101 if (!dest) return E_OUTOFMEMORY;
5104 if (dispinterface) /* overwrite funckind */
5105 dest->funckind = FUNC_DISPATCH;
5106 buffer = (char *)(dest + 1);
5108 dest->lprgscode = (SCODE *)buffer;
5109 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5110 buffer += sizeof(*src->lprgscode) * src->cScodes;
5112 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5115 SysFreeString((BSTR)dest);
5119 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5120 buffer += sizeof(ELEMDESC) * src->cParams;
5121 for (i = 0; i < src->cParams; i++)
5123 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5129 /* undo the above actions */
5130 for (i = i - 1; i >= 0; i--)
5131 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5132 TLB_FreeElemDesc(&dest->elemdescFunc);
5133 SysFreeString((BSTR)dest);
5137 /* special treatment for dispinterfaces: this makes functions appear
5138 * to return their [retval] value when it is really returning an
5140 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5142 if (dest->cParams &&
5143 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5145 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5146 if (elemdesc->tdesc.vt != VT_PTR)
5148 ERR("elemdesc should have started with VT_PTR instead of:\n");
5150 dump_ELEMDESC(elemdesc);
5151 return E_UNEXPECTED;
5154 /* copy last parameter to the return value. we are using a flat
5155 * buffer so there is no danger of leaking memory in
5157 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5159 /* remove the last parameter */
5163 /* otherwise this function is made to appear to have no return
5165 dest->elemdescFunc.tdesc.vt = VT_VOID;
5173 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5175 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5176 const TLBFuncDesc *pFDesc;
5179 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5184 *ppFuncDesc = &pFDesc->funcdesc;
5188 return TYPE_E_ELEMENTNOTFOUND;
5191 /* internal function to make the inherited interfaces' methods appear
5192 * part of the interface */
5193 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5194 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5196 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5198 UINT implemented_funcs = 0;
5203 *hrefoffset = DISPATCH_HREF_OFFSET;
5205 if(This->impltypelist)
5207 ITypeInfo *pSubTypeInfo;
5210 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5214 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5217 &sub_funcs, hrefoffset);
5218 implemented_funcs += sub_funcs;
5219 ITypeInfo_Release(pSubTypeInfo);
5222 *hrefoffset += DISPATCH_HREF_OFFSET;
5226 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5230 if (index < implemented_funcs)
5231 return E_INVALIDARG;
5232 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5236 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5238 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5241 switch (pTypeDesc->vt)
5243 case VT_USERDEFINED:
5244 pTypeDesc->u.hreftype += hrefoffset;
5248 pTypeDesc = pTypeDesc->u.lptdesc;
5251 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5259 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5262 for (i = 0; i < pFuncDesc->cParams; i++)
5263 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5264 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5267 /* ITypeInfo::GetFuncDesc
5269 * Retrieves the FUNCDESC structure that contains information about a
5270 * specified function.
5273 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5274 LPFUNCDESC *ppFuncDesc)
5276 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5277 const FUNCDESC *internal_funcdesc;
5279 UINT hrefoffset = 0;
5281 TRACE("(%p) index %d\n", This, index);
5283 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5284 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5285 &internal_funcdesc, NULL,
5288 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5289 &internal_funcdesc);
5292 WARN("description for function %d not found\n", index);
5296 hr = TLB_AllocAndInitFuncDesc(
5299 This->TypeAttr.typekind == TKIND_DISPATCH);
5301 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5302 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5304 TRACE("-- 0x%08x\n", hr);
5308 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5312 SIZE_T size = sizeof(*src);
5315 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5316 if (src->varkind == VAR_CONST)
5317 size += sizeof(VARIANT);
5318 size += TLB_SizeElemDesc(&src->elemdescVar);
5320 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5321 if (!dest) return E_OUTOFMEMORY;
5324 buffer = (char *)(dest + 1);
5325 if (src->lpstrSchema)
5328 dest->lpstrSchema = (LPOLESTR)buffer;
5329 len = strlenW(src->lpstrSchema);
5330 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5331 buffer += (len + 1) * sizeof(WCHAR);
5334 if (src->varkind == VAR_CONST)
5338 dest->u.lpvarValue = (VARIANT *)buffer;
5339 *dest->u.lpvarValue = *src->u.lpvarValue;
5340 buffer += sizeof(VARIANT);
5341 VariantInit(dest->u.lpvarValue);
5342 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5345 SysFreeString((BSTR)dest_ptr);
5349 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5352 if (src->varkind == VAR_CONST)
5353 VariantClear(dest->u.lpvarValue);
5354 SysFreeString((BSTR)dest);
5361 /* ITypeInfo::GetVarDesc
5363 * Retrieves a VARDESC structure that describes the specified variable.
5366 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5367 LPVARDESC *ppVarDesc)
5369 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5371 const TLBVarDesc *pVDesc;
5373 TRACE("(%p) index %d\n", This, index);
5375 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5379 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5381 return E_INVALIDARG;
5384 /* ITypeInfo_GetNames
5386 * Retrieves the variable with the specified member ID (or the name of the
5387 * property or method and its parameters) that correspond to the specified
5390 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5391 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5393 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5394 const TLBFuncDesc *pFDesc;
5395 const TLBVarDesc *pVDesc;
5397 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5398 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5401 /* function found, now return function and parameter names */
5402 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5405 *rgBstrNames=SysAllocString(pFDesc->Name);
5407 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5413 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5416 *rgBstrNames=SysAllocString(pVDesc->Name);
5421 if(This->impltypelist &&
5422 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5423 /* recursive search */
5426 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5428 if(SUCCEEDED(result))
5430 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5431 ITypeInfo_Release(pTInfo);
5434 WARN("Could not search inherited interface!\n");
5438 WARN("no names found\n");
5441 return TYPE_E_ELEMENTNOTFOUND;
5448 /* ITypeInfo::GetRefTypeOfImplType
5450 * If a type description describes a COM class, it retrieves the type
5451 * description of the implemented interface types. For an interface,
5452 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5456 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5461 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5464 const TLBImplType *pImpl = This->impltypelist;
5466 TRACE("(%p) index %d\n", This, index);
5467 if (TRACE_ON(ole)) dump_TypeInfo(This);
5471 /* only valid on dual interfaces;
5472 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5474 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5476 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5477 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5483 hr = TYPE_E_ELEMENTNOTFOUND;
5486 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5488 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5489 *pRefType = This->pTypeLib->dispatch_href;
5493 /* get element n from linked list */
5494 for(i=0; pImpl && i<index; i++)
5496 pImpl = pImpl->next;
5500 *pRefType = pImpl->hRef;
5502 hr = TYPE_E_ELEMENTNOTFOUND;
5508 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5510 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5516 /* ITypeInfo::GetImplTypeFlags
5518 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5519 * or base interface in a type description.
5521 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5522 UINT index, INT *pImplTypeFlags)
5524 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5528 TRACE("(%p) index %d\n", This, index);
5529 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5530 i++, pImpl=pImpl->next)
5532 if(i==index && pImpl){
5533 *pImplTypeFlags=pImpl->implflags;
5537 return TYPE_E_ELEMENTNOTFOUND;
5541 * Maps between member names and member IDs, and parameter names and
5544 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5545 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5547 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5548 const TLBFuncDesc *pFDesc;
5549 const TLBVarDesc *pVDesc;
5553 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5556 /* init out parameters in case of failure */
5557 for (i = 0; i < cNames; i++)
5558 pMemId[i] = MEMBERID_NIL;
5560 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5562 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5563 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5564 for(i=1; i < cNames; i++){
5565 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5566 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5568 if( j<pFDesc->funcdesc.cParams)
5571 ret=DISP_E_UNKNOWNNAME;
5573 TRACE("-- 0x%08x\n", ret);
5577 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5578 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5579 if(cNames) *pMemId=pVDesc->vardesc.memid;
5583 /* not found, see if it can be found in an inherited interface */
5584 if(This->impltypelist) {
5585 /* recursive search */
5587 ret=ITypeInfo_GetRefTypeInfo(iface,
5588 This->impltypelist->hRef, &pTInfo);
5590 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5591 ITypeInfo_Release(pTInfo);
5594 WARN("Could not search inherited interface!\n");
5596 WARN("no names found\n");
5597 return DISP_E_UNKNOWNNAME;
5600 /* ITypeInfo::Invoke
5602 * Invokes a method, or accesses a property of an object, that implements the
5603 * interface described by the type description.
5606 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5609 if (TRACE_ON(ole)) {
5611 TRACE("Calling %p(",func);
5612 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5624 res = func(args[0]);
5627 res = func(args[0],args[1]);
5630 res = func(args[0],args[1],args[2]);
5633 res = func(args[0],args[1],args[2],args[3]);
5636 res = func(args[0],args[1],args[2],args[3],args[4]);
5639 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5642 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5645 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5648 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5651 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5654 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5657 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
5660 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
5663 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
5666 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5669 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5672 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5675 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5678 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5681 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5684 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5687 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5690 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5693 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23]);
5696 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24]);
5699 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25]);
5702 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26]);
5705 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27]);
5708 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28]);
5711 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5714 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5720 FIXME("unsupported calling convention %d\n",callconv);
5724 TRACE("returns %08x\n",res);
5728 /* The size of the argument on the stack in DWORD units (in all x86 call
5729 * convetions the arguments on the stack are DWORD-aligned)
5731 static int _dispargsize(VARTYPE vt)
5736 return 8/sizeof(DWORD);
5738 return sizeof(double)/sizeof(DWORD);
5740 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5742 return sizeof(CY)/sizeof(DWORD);
5744 return sizeof(DATE)/sizeof(DWORD);
5746 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5748 FIXME("VT_RECORD not implemented\n");
5755 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5758 ITypeInfo *tinfo2 = NULL;
5759 TYPEATTR *tattr = NULL;
5761 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5764 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5766 tdesc->u.hreftype, hr);
5769 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5772 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5773 ITypeInfo_Release(tinfo2);
5777 switch (tattr->typekind)
5784 tdesc = &tattr->tdescAlias;
5785 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5788 case TKIND_INTERFACE:
5789 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5795 case TKIND_DISPATCH:
5804 FIXME("TKIND_RECORD unhandled.\n");
5809 FIXME("TKIND_UNION unhandled.\n");
5814 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5818 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5819 ITypeInfo_Release(tinfo2);
5823 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5827 /* enforce only one level of pointer indirection */
5828 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5830 tdesc = tdesc->u.lptdesc;
5832 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5833 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5834 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5835 if ((tdesc->vt == VT_USERDEFINED) ||
5836 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5838 VARTYPE vt_userdefined = 0;
5839 const TYPEDESC *tdesc_userdefined = tdesc;
5840 if (tdesc->vt == VT_PTR)
5842 vt_userdefined = VT_BYREF;
5843 tdesc_userdefined = tdesc->u.lptdesc;
5845 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5847 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5848 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5850 *vt |= vt_userdefined;
5862 case VT_USERDEFINED:
5863 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5870 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5871 hr = DISP_E_BADVARTYPE;
5875 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5884 /***********************************************************************
5885 * DispCallFunc (OLEAUT32.@)
5887 * Invokes a function of the specified calling convention, passing the
5888 * specified arguments and returns the result.
5891 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5892 * oVft [I] The offset in the vtable. See notes.
5893 * cc [I] Calling convention of the function to call.
5894 * vtReturn [I] The return type of the function.
5895 * cActuals [I] Number of parameters.
5896 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5897 * prgpvarg [I] The arguments to pass.
5898 * pvargResult [O] The return value of the function. Can be NULL.
5902 * Failure: HRESULT code.
5905 * The HRESULT return value of this function is not affected by the return
5906 * value of the user supplied function, which is returned in pvargResult.
5908 * If pvInstance is NULL then a non-object function is to be called and oVft
5909 * is the address of the function to call.
5911 * The cc parameter can be one of the following values:
5924 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5925 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5927 int argsize, argspos;
5932 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5933 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5934 pvargResult, V_VT(pvargResult));
5938 argsize++; /* for This pointer */
5940 for (i=0;i<cActuals;i++)
5942 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5943 dump_Variant(prgpvarg[i]);
5944 argsize += _dispargsize(prgvt[i]);
5946 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5951 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5955 for (i=0;i<cActuals;i++)
5957 VARIANT *arg = prgpvarg[i];
5958 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5959 if (prgvt[i] == VT_VARIANT)
5960 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5962 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5963 argspos += _dispargsize(prgvt[i]);
5968 FARPROC *vtable = *(FARPROC**)pvInstance;
5969 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5972 /* if we aren't invoking an object then the function pointer is stored
5974 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5976 if (pvargResult && (vtReturn != VT_EMPTY))
5978 TRACE("Method returned 0x%08x\n",hres);
5979 V_VT(pvargResult) = vtReturn;
5980 V_UI4(pvargResult) = hres;
5983 HeapFree(GetProcessHeap(),0,args);
5987 #define INVBUF_ELEMENT_SIZE \
5988 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5989 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5990 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5991 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5992 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5993 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5994 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5995 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5997 static HRESULT WINAPI ITypeInfo_fnInvoke(
6002 DISPPARAMS *pDispParams,
6003 VARIANT *pVarResult,
6004 EXCEPINFO *pExcepInfo,
6007 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6009 unsigned int var_index;
6012 const TLBFuncDesc *pFuncInfo;
6014 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6015 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6020 ERR("NULL pDispParams not allowed\n");
6021 return E_INVALIDARG;
6024 dump_DispParms(pDispParams);
6026 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6028 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6029 pDispParams->cNamedArgs, pDispParams->cArgs);
6030 return E_INVALIDARG;
6033 /* we do this instead of using GetFuncDesc since it will return a fake
6034 * FUNCDESC for dispinterfaces and we want the real function description */
6035 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6036 if ((memid == pFuncInfo->funcdesc.memid) &&
6037 (wFlags & pFuncInfo->funcdesc.invkind))
6041 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6045 TRACE("invoking:\n");
6046 dump_TLBFuncDescOne(pFuncInfo);
6049 switch (func_desc->funckind) {
6050 case FUNC_PUREVIRTUAL:
6051 case FUNC_VIRTUAL: {
6052 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6054 VARIANT retval; /* pointer for storing byref retvals in */
6055 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6056 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6057 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6058 UINT cNamedArgs = pDispParams->cNamedArgs;
6059 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6063 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6065 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6067 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6068 hres = DISP_E_PARAMNOTFOUND;
6071 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6073 rgdispidNamedArgs++;
6076 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6078 ERR("functions with the vararg attribute do not support named arguments\n");
6079 hres = DISP_E_NONAMEDARGS;
6083 for (i = 0; i < func_desc->cParams; i++)
6085 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6086 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6091 TRACE("changing args\n");
6092 for (i = 0; i < func_desc->cParams; i++)
6094 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6095 VARIANTARG *src_arg;
6101 for (j = 0; j < cNamedArgs; j++)
6102 if (rgdispidNamedArgs[j] == i)
6104 src_arg = &pDispParams->rgvarg[j];
6109 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
6111 if (wParamFlags & PARAMFLAG_FRETVAL)
6113 /* under most conditions the caller is not allowed to
6114 * pass in a dispparam arg in the index of what would be
6115 * the retval parameter. however, there is an exception
6116 * where the extra parameter is used in an extra
6117 * IDispatch::Invoke below */
6118 if ((i < pDispParams->cArgs) &&
6119 ((func_desc->cParams != 1) || !pVarResult ||
6120 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6122 hres = DISP_E_BADPARAMCOUNT;
6126 /* note: this check is placed so that if the caller passes
6127 * in a VARIANTARG for the retval we just ignore it, like
6129 if (i == func_desc->cParams - 1)
6132 arg = prgpvarg[i] = &rgvarg[i];
6133 memset(arg, 0, sizeof(*arg));
6134 V_VT(arg) = rgvt[i];
6135 memset(&retval, 0, sizeof(retval));
6136 V_BYREF(arg) = &retval;
6140 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6141 hres = E_UNEXPECTED;
6147 dump_Variant(src_arg);
6149 if (rgvt[i] == VT_VARIANT)
6150 hres = VariantCopy(&rgvarg[i], src_arg);
6151 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6153 if (rgvt[i] == V_VT(src_arg))
6154 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6157 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6158 hres = VariantCopy(&missing_arg[i], src_arg);
6159 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6161 V_VT(&rgvarg[i]) = rgvt[i];
6163 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6166 SAFEARRAYBOUND bound;
6170 bound.cElements = pDispParams->cArgs-i;
6171 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6173 ERR("SafeArrayCreate failed\n");
6176 hres = SafeArrayAccessData(a, (LPVOID)&v);
6179 ERR("SafeArrayAccessData failed with %x\n", hres);
6182 for (j = 0; j < bound.cElements; j++)
6183 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6184 hres = SafeArrayUnaccessData(a);
6187 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6190 V_ARRAY(&rgvarg[i]) = a;
6191 V_VT(&rgvarg[i]) = rgvt[i];
6193 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6195 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6196 V_VT(&missing_arg[i]) = V_VT(src_arg);
6197 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6198 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6199 V_VT(&rgvarg[i]) = rgvt[i];
6201 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6203 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6204 V_VT(&rgvarg[i]) = rgvt[i];
6208 /* FIXME: this doesn't work for VT_BYREF arguments if
6209 * they are not the same type as in the paramdesc */
6210 V_VT(&rgvarg[i]) = V_VT(src_arg);
6211 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6212 V_VT(&rgvarg[i]) = rgvt[i];
6217 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6218 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6219 debugstr_VT(src_arg), debugstr_VF(src_arg));
6222 prgpvarg[i] = &rgvarg[i];
6224 else if (wParamFlags & PARAMFLAG_FOPT)
6227 arg = prgpvarg[i] = &rgvarg[i];
6228 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6230 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6236 VARIANTARG *missing_arg;
6237 /* if the function wants a pointer to a variant then
6238 * set that up, otherwise just pass the VT_ERROR in
6239 * the argument by value */
6240 if (rgvt[i] & VT_BYREF)
6242 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6243 V_VT(arg) = VT_VARIANT | VT_BYREF;
6244 V_VARIANTREF(arg) = missing_arg;
6248 V_VT(missing_arg) = VT_ERROR;
6249 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6254 hres = DISP_E_BADPARAMCOUNT;
6258 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6260 /* VT_VOID is a special case for return types, so it is not
6261 * handled in the general function */
6262 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6263 V_VT(&varresult) = VT_EMPTY;
6266 V_VT(&varresult) = 0;
6267 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6268 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6271 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6272 V_VT(&varresult), func_desc->cParams, rgvt,
6273 prgpvarg, &varresult);
6275 for (i = 0; i < func_desc->cParams; i++)
6277 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6278 if (wParamFlags & PARAMFLAG_FRETVAL)
6282 TRACE("[retval] value: ");
6283 dump_Variant(prgpvarg[i]);
6288 VariantInit(pVarResult);
6289 /* deref return value */
6290 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6293 /* free data stored in varresult. Note that
6294 * VariantClear doesn't do what we want because we are
6295 * working with byref types. */
6296 /* FIXME: clear safearrays, bstrs, records and
6297 * variants here too */
6298 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6299 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6301 if(*V_UNKNOWNREF(prgpvarg[i]))
6302 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6306 else if (i < pDispParams->cArgs)
6308 if (wParamFlags & PARAMFLAG_FOUT)
6310 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6312 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6313 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6317 ERR("failed to convert param %d to vt %d\n", i,
6318 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6322 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6323 func_desc->cParamsOpt < 0 &&
6324 i == func_desc->cParams-1)
6326 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6329 hres = SafeArrayGetUBound(a, 1, &ubound);
6332 ERR("SafeArrayGetUBound failed with %x\n", hres);
6335 hres = SafeArrayAccessData(a, (LPVOID)&v);
6338 ERR("SafeArrayAccessData failed with %x\n", hres);
6341 for (j = 0; j <= ubound; j++)
6342 VariantClear(&v[j]);
6343 hres = SafeArrayUnaccessData(a);
6346 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6350 VariantClear(&rgvarg[i]);
6352 else if (wParamFlags & PARAMFLAG_FOPT)
6354 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6355 VariantClear(&rgvarg[i]);
6359 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6361 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6362 hres = DISP_E_EXCEPTION;
6365 IErrorInfo *pErrorInfo;
6366 pExcepInfo->scode = V_ERROR(&varresult);
6367 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6369 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6370 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6371 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6372 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6374 IErrorInfo_Release(pErrorInfo);
6378 if (V_VT(&varresult) != VT_ERROR)
6380 TRACE("varresult value: ");
6381 dump_Variant(&varresult);
6385 VariantClear(pVarResult);
6386 *pVarResult = varresult;
6389 VariantClear(&varresult);
6392 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6393 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6394 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6395 (pDispParams->cArgs != 0))
6397 if (V_VT(pVarResult) == VT_DISPATCH)
6399 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6400 /* Note: not VariantClear; we still need the dispatch
6401 * pointer to be valid */
6402 VariantInit(pVarResult);
6403 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6404 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6405 pDispParams, pVarResult, pExcepInfo, pArgErr);
6406 IDispatch_Release(pDispatch);
6410 VariantClear(pVarResult);
6411 hres = DISP_E_NOTACOLLECTION;
6416 HeapFree(GetProcessHeap(), 0, buffer);
6419 case FUNC_DISPATCH: {
6422 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6423 if (SUCCEEDED(hres)) {
6424 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6425 hres = IDispatch_Invoke(
6426 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6427 pVarResult,pExcepInfo,pArgErr
6430 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6431 IDispatch_Release(disp);
6433 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6437 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6442 TRACE("-- 0x%08x\n", hres);
6445 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6448 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6449 if(FAILED(hres)) return hres;
6451 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6452 dump_VARDESC(var_desc);
6453 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6457 /* not found, look for it in inherited interfaces */
6458 ITypeInfo2_GetTypeKind(iface, &type_kind);
6459 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6460 if(This->impltypelist) {
6461 /* recursive search */
6463 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6464 if(SUCCEEDED(hres)){
6465 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6466 ITypeInfo_Release(pTInfo);
6469 WARN("Could not search inherited interface!\n");
6472 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6473 return DISP_E_MEMBERNOTFOUND;
6476 /* ITypeInfo::GetDocumentation
6478 * Retrieves the documentation string, the complete Help file name and path,
6479 * and the context ID for the Help topic for a specified type description.
6481 * (Can be tested by the Visual Basic Editor in Word for instance.)
6483 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6484 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6485 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6487 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6488 const TLBFuncDesc *pFDesc;
6489 const TLBVarDesc *pVDesc;
6490 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6491 " HelpContext(%p) HelpFile(%p)\n",
6492 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6493 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6495 *pBstrName=SysAllocString(This->Name);
6497 *pBstrDocString=SysAllocString(This->DocString);
6499 *pdwHelpContext=This->dwHelpContext;
6501 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6503 }else {/* for a member */
6504 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6505 if(pFDesc->funcdesc.memid==memid){
6507 *pBstrName = SysAllocString(pFDesc->Name);
6509 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6511 *pdwHelpContext=pFDesc->helpcontext;
6514 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6515 if(pVDesc->vardesc.memid==memid){
6517 *pBstrName = SysAllocString(pVDesc->Name);
6519 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6521 *pdwHelpContext=pVDesc->HelpContext;
6526 if(This->impltypelist &&
6527 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6528 /* recursive search */
6531 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6533 if(SUCCEEDED(result)) {
6534 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6535 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6536 ITypeInfo_Release(pTInfo);
6539 WARN("Could not search inherited interface!\n");
6542 WARN("member %d not found\n", memid);
6543 return TYPE_E_ELEMENTNOTFOUND;
6546 /* ITypeInfo::GetDllEntry
6548 * Retrieves a description or specification of an entry point for a function
6551 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6552 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6555 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6556 const TLBFuncDesc *pFDesc;
6558 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6560 if (pBstrDllName) *pBstrDllName = NULL;
6561 if (pBstrName) *pBstrName = NULL;
6562 if (pwOrdinal) *pwOrdinal = 0;
6564 if (This->TypeAttr.typekind != TKIND_MODULE)
6565 return TYPE_E_BADMODULEKIND;
6567 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6568 if(pFDesc->funcdesc.memid==memid){
6569 dump_TypeInfo(This);
6571 dump_TLBFuncDescOne(pFDesc);
6574 *pBstrDllName = SysAllocString(This->DllName);
6576 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6578 *pBstrName = SysAllocString(pFDesc->Entry);
6586 *pwOrdinal = (DWORD)pFDesc->Entry;
6589 return TYPE_E_ELEMENTNOTFOUND;
6592 /* internal function to make the inherited interfaces' methods appear
6593 * part of the interface */
6594 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6595 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6597 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6600 TRACE("%p, 0x%x\n", iface, *hRefType);
6602 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6604 ITypeInfo *pSubTypeInfo;
6606 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6610 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6612 ITypeInfo_Release(pSubTypeInfo);
6616 *hRefType -= DISPATCH_HREF_OFFSET;
6618 if (!(*hRefType & DISPATCH_HREF_MASK))
6619 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6624 /* ITypeInfo::GetRefTypeInfo
6626 * If a type description references other type descriptions, it retrieves
6627 * the referenced type descriptions.
6629 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6632 ITypeInfo **ppTInfo)
6634 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6635 HRESULT result = E_FAIL;
6637 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6639 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6640 ITypeInfo_AddRef(*ppTInfo);
6643 else if (hRefType == -1 &&
6644 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6645 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6647 /* when we meet a DUAL dispinterface, we must create the interface
6650 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6653 /* the interface version contains the same information as the dispinterface
6654 * copy the contents of the structs.
6656 *pTypeInfoImpl = *This;
6657 pTypeInfoImpl->ref = 0;
6659 /* change the type to interface */
6660 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6662 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6664 /* we use data structures from This, so we need to keep a reference
6665 * to it to stop it being destroyed and signal to the new instance to
6666 * not free its data structures when it is destroyed */
6667 pTypeInfoImpl->no_free_data = TRUE;
6668 pTypeInfoImpl->next = This;
6669 ITypeInfo_AddRef((ITypeInfo*) This);
6671 ITypeInfo_AddRef(*ppTInfo);
6675 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6676 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6677 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6679 HREFTYPE href_dispatch = hRefType;
6680 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6682 TLBRefType *ref_type;
6683 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6685 if(ref_type->reference == hRefType)
6688 if(&ref_type->entry == &This->pTypeLib->ref_list)
6690 FIXME("Can't find pRefType for ref %x\n", hRefType);
6693 if(hRefType != -1) {
6694 ITypeLib *pTLib = NULL;
6696 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6698 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6700 if(ref_type->pImpTLInfo->pImpTypeLib) {
6701 TRACE("typeinfo in imported typelib that is already loaded\n");
6702 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6703 ITypeLib2_AddRef(pTLib);
6706 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6707 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6708 ref_type->pImpTLInfo->wVersionMajor,
6709 ref_type->pImpTLInfo->wVersionMinor,
6710 ref_type->pImpTLInfo->lcid,
6713 if(FAILED(result)) {
6714 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6715 result=LoadTypeLib(libnam, &pTLib);
6716 SysFreeString(libnam);
6718 if(SUCCEEDED(result)) {
6719 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6720 ITypeLib2_AddRef(pTLib);
6724 if(SUCCEEDED(result)) {
6725 if(ref_type->index == TLB_REF_USE_GUID)
6726 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6730 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6734 ITypeLib2_Release(pTLib);
6739 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6740 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6744 /* ITypeInfo::AddressOfMember
6746 * Retrieves the addresses of static functions or variables, such as those
6749 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6750 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6752 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6758 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6760 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6764 module = LoadLibraryW(dll);
6767 ERR("couldn't load %s\n", debugstr_w(dll));
6769 SysFreeString(entry);
6770 return STG_E_FILENOTFOUND;
6772 /* FIXME: store library somewhere where we can free it */
6777 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6778 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6779 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6781 *ppv = GetProcAddress(module, entryA);
6783 ERR("function not found %s\n", debugstr_a(entryA));
6785 HeapFree(GetProcessHeap(), 0, entryA);
6789 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6791 ERR("function not found %d\n", ordinal);
6795 SysFreeString(entry);
6798 return TYPE_E_DLLFUNCTIONNOTFOUND;
6803 /* ITypeInfo::CreateInstance
6805 * Creates a new instance of a type that describes a component object class
6808 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6809 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6811 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6815 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6821 WARN("Not able to aggregate\n");
6822 return CLASS_E_NOAGGREGATION;
6825 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6826 if(FAILED(hr)) return hr;
6828 if(pTA->typekind != TKIND_COCLASS)
6830 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6836 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6839 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6840 TRACE("GetActiveObject rets %08x\n", hr);
6843 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6844 IUnknown_Release(pUnk);
6849 hr = CoCreateInstance(&pTA->guid, NULL,
6850 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6854 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6858 /* ITypeInfo::GetMops
6860 * Retrieves marshalling information.
6862 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6865 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6866 FIXME("(%p) stub!\n", This);
6870 /* ITypeInfo::GetContainingTypeLib
6872 * Retrieves the containing type library and the index of the type description
6873 * within that type library.
6875 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6876 ITypeLib * *ppTLib, UINT *pIndex)
6878 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6880 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6882 *pIndex=This->index;
6883 TRACE("returning pIndex=%d\n", *pIndex);
6887 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6888 ITypeLib2_AddRef(*ppTLib);
6889 TRACE("returning ppTLib=%p\n", *ppTLib);
6895 /* ITypeInfo::ReleaseTypeAttr
6897 * Releases a TYPEATTR previously returned by GetTypeAttr.
6900 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6901 TYPEATTR* pTypeAttr)
6903 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6904 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6905 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6908 /* ITypeInfo::ReleaseFuncDesc
6910 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6912 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6914 FUNCDESC *pFuncDesc)
6916 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6919 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6921 for (i = 0; i < pFuncDesc->cParams; i++)
6922 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6923 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6925 SysFreeString((BSTR)pFuncDesc);
6928 /* ITypeInfo::ReleaseVarDesc
6930 * Releases a VARDESC previously returned by GetVarDesc.
6932 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6935 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6936 TRACE("(%p)->(%p)\n", This, pVarDesc);
6938 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6939 if (pVarDesc->varkind == VAR_CONST)
6940 VariantClear(pVarDesc->u.lpvarValue);
6941 SysFreeString((BSTR)pVarDesc);
6944 /* ITypeInfo2::GetTypeKind
6946 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6949 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6950 TYPEKIND *pTypeKind)
6952 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6953 *pTypeKind=This->TypeAttr.typekind;
6954 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6958 /* ITypeInfo2::GetTypeFlags
6960 * Returns the type flags without any allocations. This returns a DWORD type
6961 * flag, which expands the type flags without growing the TYPEATTR (type
6965 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6967 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6968 *pTypeFlags=This->TypeAttr.wTypeFlags;
6969 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6973 /* ITypeInfo2::GetFuncIndexOfMemId
6974 * Binds to a specific member based on a known DISPID, where the member name
6975 * is not known (for example, when binding to a default member).
6978 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6979 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6981 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6982 const TLBFuncDesc *pFuncInfo;
6986 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6987 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6993 result = TYPE_E_ELEMENTNOTFOUND;
6995 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6996 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7000 /* TypeInfo2::GetVarIndexOfMemId
7002 * Binds to a specific member based on a known DISPID, where the member name
7003 * is not known (for example, when binding to a default member).
7006 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7007 MEMBERID memid, UINT *pVarIndex)
7009 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7010 TLBVarDesc *pVarInfo;
7013 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7014 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7020 result = TYPE_E_ELEMENTNOTFOUND;
7022 TRACE("(%p) memid 0x%08x -> %s\n", This,
7023 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7027 /* ITypeInfo2::GetCustData
7029 * Gets the custom data
7031 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7036 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7037 TLBCustData *pCData;
7039 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7040 if( IsEqualIID(guid, &pCData->guid)) break;
7042 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7046 VariantInit( pVarVal);
7047 VariantCopy( pVarVal, &pCData->data);
7050 return E_INVALIDARG; /* FIXME: correct? */
7053 /* ITypeInfo2::GetFuncCustData
7055 * Gets the custom data
7057 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7063 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7064 TLBCustData *pCData=NULL;
7065 TLBFuncDesc * pFDesc;
7067 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7068 pFDesc=pFDesc->next);
7071 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7072 if( IsEqualIID(guid, &pCData->guid)) break;
7074 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7077 VariantInit( pVarVal);
7078 VariantCopy( pVarVal, &pCData->data);
7081 return E_INVALIDARG; /* FIXME: correct? */
7084 /* ITypeInfo2::GetParamCustData
7086 * Gets the custom data
7088 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7095 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7096 TLBCustData *pCData=NULL;
7097 TLBFuncDesc * pFDesc;
7100 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7102 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7103 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7104 pCData = pCData->next)
7105 if( IsEqualIID(guid, &pCData->guid)) break;
7107 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7111 VariantInit( pVarVal);
7112 VariantCopy( pVarVal, &pCData->data);
7115 return E_INVALIDARG; /* FIXME: correct? */
7118 /* ITypeInfo2::GetVarCustData
7120 * Gets the custom data
7122 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7128 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7129 TLBCustData *pCData=NULL;
7130 TLBVarDesc * pVDesc;
7133 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7137 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7139 if( IsEqualIID(guid, &pCData->guid)) break;
7143 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7147 VariantInit( pVarVal);
7148 VariantCopy( pVarVal, &pCData->data);
7151 return E_INVALIDARG; /* FIXME: correct? */
7154 /* ITypeInfo2::GetImplCustData
7156 * Gets the custom data
7158 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7164 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7165 TLBCustData *pCData=NULL;
7166 TLBImplType * pRDesc;
7169 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7173 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7175 if( IsEqualIID(guid, &pCData->guid)) break;
7179 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7183 VariantInit( pVarVal);
7184 VariantCopy( pVarVal, &pCData->data);
7187 return E_INVALIDARG; /* FIXME: correct? */
7190 /* ITypeInfo2::GetDocumentation2
7192 * Retrieves the documentation string, the complete Help file name and path,
7193 * the localization context to use, and the context ID for the library Help
7194 * topic in the Help file.
7197 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7201 BSTR *pbstrHelpString,
7202 DWORD *pdwHelpStringContext,
7203 BSTR *pbstrHelpStringDll)
7205 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7206 const TLBFuncDesc *pFDesc;
7207 const TLBVarDesc *pVDesc;
7208 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7209 "HelpStringContext(%p) HelpStringDll(%p)\n",
7210 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7211 pbstrHelpStringDll );
7212 /* the help string should be obtained from the helpstringdll,
7213 * using the _DLLGetDocumentation function, based on the supplied
7214 * lcid. Nice to do sometime...
7216 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7218 *pbstrHelpString=SysAllocString(This->Name);
7219 if(pdwHelpStringContext)
7220 *pdwHelpStringContext=This->dwHelpStringContext;
7221 if(pbstrHelpStringDll)
7222 *pbstrHelpStringDll=
7223 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7225 }else {/* for a member */
7226 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7227 if(pFDesc->funcdesc.memid==memid){
7229 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7230 if(pdwHelpStringContext)
7231 *pdwHelpStringContext=pFDesc->HelpStringContext;
7232 if(pbstrHelpStringDll)
7233 *pbstrHelpStringDll=
7234 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7237 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7238 if(pVDesc->vardesc.memid==memid){
7240 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7241 if(pdwHelpStringContext)
7242 *pdwHelpStringContext=pVDesc->HelpStringContext;
7243 if(pbstrHelpStringDll)
7244 *pbstrHelpStringDll=
7245 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7249 return TYPE_E_ELEMENTNOTFOUND;
7252 /* ITypeInfo2::GetAllCustData
7254 * Gets all custom data items for the Type info.
7257 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7259 CUSTDATA *pCustData)
7261 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7262 TLBCustData *pCData;
7265 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7267 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7268 if(pCustData->prgCustData ){
7269 pCustData->cCustData=This->ctCustData;
7270 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7271 pCustData->prgCustData[i].guid=pCData->guid;
7272 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7275 ERR(" OUT OF MEMORY!\n");
7276 return E_OUTOFMEMORY;
7281 /* ITypeInfo2::GetAllFuncCustData
7283 * Gets all custom data items for the specified Function
7286 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7289 CUSTDATA *pCustData)
7291 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7292 TLBCustData *pCData;
7293 TLBFuncDesc * pFDesc;
7295 TRACE("(%p) index %d\n", This, index);
7296 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7297 pFDesc=pFDesc->next)
7300 pCustData->prgCustData =
7301 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7302 if(pCustData->prgCustData ){
7303 pCustData->cCustData=pFDesc->ctCustData;
7304 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7305 pCData = pCData->next){
7306 pCustData->prgCustData[i].guid=pCData->guid;
7307 VariantCopy(& pCustData->prgCustData[i].varValue,
7311 ERR(" OUT OF MEMORY!\n");
7312 return E_OUTOFMEMORY;
7316 return TYPE_E_ELEMENTNOTFOUND;
7319 /* ITypeInfo2::GetAllParamCustData
7321 * Gets all custom data items for the Functions
7324 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7325 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7327 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7328 TLBCustData *pCData=NULL;
7329 TLBFuncDesc * pFDesc;
7331 TRACE("(%p) index %d\n", This, indexFunc);
7332 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7333 pFDesc=pFDesc->next)
7335 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7336 pCustData->prgCustData =
7337 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7338 sizeof(CUSTDATAITEM));
7339 if(pCustData->prgCustData ){
7340 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7341 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7342 pCData; i++, pCData = pCData->next){
7343 pCustData->prgCustData[i].guid=pCData->guid;
7344 VariantCopy(& pCustData->prgCustData[i].varValue,
7348 ERR(" OUT OF MEMORY!\n");
7349 return E_OUTOFMEMORY;
7353 return TYPE_E_ELEMENTNOTFOUND;
7356 /* ITypeInfo2::GetAllVarCustData
7358 * Gets all custom data items for the specified Variable
7361 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7362 UINT index, CUSTDATA *pCustData)
7364 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7365 TLBCustData *pCData;
7366 TLBVarDesc * pVDesc;
7368 TRACE("(%p) index %d\n", This, index);
7369 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7370 pVDesc=pVDesc->next)
7373 pCustData->prgCustData =
7374 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7375 if(pCustData->prgCustData ){
7376 pCustData->cCustData=pVDesc->ctCustData;
7377 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7378 pCData = pCData->next){
7379 pCustData->prgCustData[i].guid=pCData->guid;
7380 VariantCopy(& pCustData->prgCustData[i].varValue,
7384 ERR(" OUT OF MEMORY!\n");
7385 return E_OUTOFMEMORY;
7389 return TYPE_E_ELEMENTNOTFOUND;
7392 /* ITypeInfo2::GetAllImplCustData
7394 * Gets all custom data items for the specified implementation type
7397 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7400 CUSTDATA *pCustData)
7402 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7403 TLBCustData *pCData;
7404 TLBImplType * pRDesc;
7406 TRACE("(%p) index %d\n", This, index);
7407 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7408 pRDesc=pRDesc->next)
7411 pCustData->prgCustData =
7412 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7413 if(pCustData->prgCustData ){
7414 pCustData->cCustData=pRDesc->ctCustData;
7415 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7416 pCData = pCData->next){
7417 pCustData->prgCustData[i].guid=pCData->guid;
7418 VariantCopy(& pCustData->prgCustData[i].varValue,
7422 ERR(" OUT OF MEMORY!\n");
7423 return E_OUTOFMEMORY;
7427 return TYPE_E_ELEMENTNOTFOUND;
7430 static const ITypeInfo2Vtbl tinfvt =
7433 ITypeInfo_fnQueryInterface,
7435 ITypeInfo_fnRelease,
7437 ITypeInfo_fnGetTypeAttr,
7438 ITypeInfo_fnGetTypeComp,
7439 ITypeInfo_fnGetFuncDesc,
7440 ITypeInfo_fnGetVarDesc,
7441 ITypeInfo_fnGetNames,
7442 ITypeInfo_fnGetRefTypeOfImplType,
7443 ITypeInfo_fnGetImplTypeFlags,
7444 ITypeInfo_fnGetIDsOfNames,
7446 ITypeInfo_fnGetDocumentation,
7447 ITypeInfo_fnGetDllEntry,
7448 ITypeInfo_fnGetRefTypeInfo,
7449 ITypeInfo_fnAddressOfMember,
7450 ITypeInfo_fnCreateInstance,
7451 ITypeInfo_fnGetMops,
7452 ITypeInfo_fnGetContainingTypeLib,
7453 ITypeInfo_fnReleaseTypeAttr,
7454 ITypeInfo_fnReleaseFuncDesc,
7455 ITypeInfo_fnReleaseVarDesc,
7457 ITypeInfo2_fnGetTypeKind,
7458 ITypeInfo2_fnGetTypeFlags,
7459 ITypeInfo2_fnGetFuncIndexOfMemId,
7460 ITypeInfo2_fnGetVarIndexOfMemId,
7461 ITypeInfo2_fnGetCustData,
7462 ITypeInfo2_fnGetFuncCustData,
7463 ITypeInfo2_fnGetParamCustData,
7464 ITypeInfo2_fnGetVarCustData,
7465 ITypeInfo2_fnGetImplTypeCustData,
7466 ITypeInfo2_fnGetDocumentation2,
7467 ITypeInfo2_fnGetAllCustData,
7468 ITypeInfo2_fnGetAllFuncCustData,
7469 ITypeInfo2_fnGetAllParamCustData,
7470 ITypeInfo2_fnGetAllVarCustData,
7471 ITypeInfo2_fnGetAllImplTypeCustData,
7474 /******************************************************************************
7475 * CreateDispTypeInfo [OLEAUT32.31]
7477 * Build type information for an object so it can be called through an
7478 * IDispatch interface.
7481 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7482 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7485 * This call allows an objects methods to be accessed through IDispatch, by
7486 * building an ITypeInfo object that IDispatch can use to call through.
7488 HRESULT WINAPI CreateDispTypeInfo(
7489 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7490 LCID lcid, /* [I] Locale Id */
7491 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7493 ITypeInfoImpl *pTIClass, *pTIIface;
7494 ITypeLibImpl *pTypeLibImpl;
7495 unsigned int param, func;
7496 TLBFuncDesc **ppFuncDesc;
7500 pTypeLibImpl = TypeLibImpl_Constructor();
7501 if (!pTypeLibImpl) return E_FAIL;
7503 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7504 pTIIface->pTypeLib = pTypeLibImpl;
7505 pTIIface->index = 0;
7506 pTIIface->Name = NULL;
7507 pTIIface->dwHelpContext = -1;
7508 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7509 pTIIface->TypeAttr.lcid = lcid;
7510 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7511 pTIIface->TypeAttr.wMajorVerNum = 0;
7512 pTIIface->TypeAttr.wMinorVerNum = 0;
7513 pTIIface->TypeAttr.cbAlignment = 2;
7514 pTIIface->TypeAttr.cbSizeInstance = -1;
7515 pTIIface->TypeAttr.cbSizeVft = -1;
7516 pTIIface->TypeAttr.cFuncs = 0;
7517 pTIIface->TypeAttr.cImplTypes = 0;
7518 pTIIface->TypeAttr.cVars = 0;
7519 pTIIface->TypeAttr.wTypeFlags = 0;
7521 ppFuncDesc = &pTIIface->funclist;
7522 for(func = 0; func < pidata->cMembers; func++) {
7523 METHODDATA *md = pidata->pmethdata + func;
7524 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7525 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7526 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7527 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7528 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7529 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7530 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7531 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7532 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7533 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7534 (*ppFuncDesc)->funcdesc.cScodes = 0;
7535 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7536 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7537 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7538 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7539 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7540 md->cArgs * sizeof(ELEMDESC));
7541 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7542 md->cArgs * sizeof(TLBParDesc));
7543 for(param = 0; param < md->cArgs; param++) {
7544 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7545 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7547 (*ppFuncDesc)->helpcontext = 0;
7548 (*ppFuncDesc)->HelpStringContext = 0;
7549 (*ppFuncDesc)->HelpString = NULL;
7550 (*ppFuncDesc)->Entry = NULL;
7551 (*ppFuncDesc)->ctCustData = 0;
7552 (*ppFuncDesc)->pCustData = NULL;
7553 (*ppFuncDesc)->next = NULL;
7554 pTIIface->TypeAttr.cFuncs++;
7555 ppFuncDesc = &(*ppFuncDesc)->next;
7558 dump_TypeInfo(pTIIface);
7560 pTypeLibImpl->pTypeInfo = pTIIface;
7561 pTypeLibImpl->TypeInfoCount++;
7563 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7564 pTIClass->pTypeLib = pTypeLibImpl;
7565 pTIClass->index = 1;
7566 pTIClass->Name = NULL;
7567 pTIClass->dwHelpContext = -1;
7568 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7569 pTIClass->TypeAttr.lcid = lcid;
7570 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7571 pTIClass->TypeAttr.wMajorVerNum = 0;
7572 pTIClass->TypeAttr.wMinorVerNum = 0;
7573 pTIClass->TypeAttr.cbAlignment = 2;
7574 pTIClass->TypeAttr.cbSizeInstance = -1;
7575 pTIClass->TypeAttr.cbSizeVft = -1;
7576 pTIClass->TypeAttr.cFuncs = 0;
7577 pTIClass->TypeAttr.cImplTypes = 1;
7578 pTIClass->TypeAttr.cVars = 0;
7579 pTIClass->TypeAttr.wTypeFlags = 0;
7581 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7582 pTIClass->impltypelist->hRef = 0;
7584 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7587 ref->pImpTLInfo = TLB_REF_INTERNAL;
7588 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7590 dump_TypeInfo(pTIClass);
7592 pTIIface->next = pTIClass;
7593 pTypeLibImpl->TypeInfoCount++;
7595 *pptinfo = (ITypeInfo*)pTIClass;
7597 ITypeInfo_AddRef(*pptinfo);
7598 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7604 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7606 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7608 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7611 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7613 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7615 return ITypeInfo_AddRef((ITypeInfo *)This);
7618 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7620 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7622 return ITypeInfo_Release((ITypeInfo *)This);
7625 static HRESULT WINAPI ITypeComp_fnBind(
7630 ITypeInfo ** ppTInfo,
7631 DESCKIND * pDescKind,
7634 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7635 const TLBFuncDesc *pFDesc;
7636 const TLBVarDesc *pVDesc;
7637 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7639 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7641 *pDescKind = DESCKIND_NONE;
7642 pBindPtr->lpfuncdesc = NULL;
7645 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7646 if (!strcmpiW(pFDesc->Name, szName)) {
7647 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7650 /* name found, but wrong flags */
7651 hr = TYPE_E_TYPEMISMATCH;
7656 HRESULT hr = TLB_AllocAndInitFuncDesc(
7658 &pBindPtr->lpfuncdesc,
7659 This->TypeAttr.typekind == TKIND_DISPATCH);
7662 *pDescKind = DESCKIND_FUNCDESC;
7663 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7664 ITypeInfo_AddRef(*ppTInfo);
7667 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7668 if (!strcmpiW(pVDesc->Name, szName)) {
7669 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7672 *pDescKind = DESCKIND_VARDESC;
7673 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7674 ITypeInfo_AddRef(*ppTInfo);
7679 /* FIXME: search each inherited interface, not just the first */
7680 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7681 /* recursive search */
7685 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7688 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7689 ITypeInfo_Release(pTInfo);
7693 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7694 ITypeComp_Release(pTComp);
7697 WARN("Could not search inherited interface!\n");
7699 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7703 static HRESULT WINAPI ITypeComp_fnBindType(
7707 ITypeInfo ** ppTInfo,
7708 ITypeComp ** ppTComp)
7710 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7712 /* strange behaviour (does nothing) but like the
7715 if (!ppTInfo || !ppTComp)
7724 static const ITypeCompVtbl tcompvt =
7727 ITypeComp_fnQueryInterface,
7729 ITypeComp_fnRelease,
7732 ITypeComp_fnBindType