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 (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
559 if (RegSetValueExW(key, NULL, 0, REG_SZ,
560 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
566 /* Make up the name of the typelib path subkey */
567 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
569 /* Create the typelib path subkey */
570 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
571 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
573 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
574 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
582 /* Create the flags subkey */
583 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
584 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
586 /* FIXME: is %u correct? */
587 static const WCHAR formatW[] = {'%','u',0};
589 sprintfW(buf, formatW, attr->wLibFlags);
590 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
591 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
599 /* create the helpdir subkey */
600 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
601 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
603 BOOL freeHelpDir = FALSE;
606 /* if we created a new key, and helpDir was null, set the helpdir
607 to the directory which contains the typelib. However,
608 if we just opened an existing key, we leave the helpdir alone */
609 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
610 szHelpDir = SysAllocString(szFullPath);
611 pIndexStr = strrchrW(szHelpDir, '\\');
618 /* if we have an szHelpDir, set it! */
619 if (szHelpDir != NULL) {
620 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
621 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
627 if (freeHelpDir) SysFreeString(szHelpDir);
639 /* register OLE Automation-compatible interfaces for this typelib */
640 types = ITypeLib_GetTypeInfoCount(ptlib);
641 for (tidx=0; tidx<types; tidx++) {
642 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
643 LPOLESTR name = NULL;
644 ITypeInfo *tinfo = NULL;
646 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
649 case TKIND_INTERFACE:
650 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
651 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
655 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
656 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
660 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
665 TYPEATTR *tattr = NULL;
666 ITypeInfo_GetTypeAttr(tinfo, &tattr);
669 TRACE_(typelib)("guid=%s, flags=%04x (",
670 debugstr_guid(&tattr->guid),
673 if (TRACE_ON(typelib)) {
674 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
694 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
696 /* register interface<->typelib coupling */
697 get_interface_key( &tattr->guid, keyName );
698 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
699 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
702 RegSetValueExW(key, NULL, 0, REG_SZ,
703 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
705 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
706 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
707 RegSetValueExW(subKey, NULL, 0, REG_SZ,
708 (const BYTE *)PSOA, sizeof PSOA);
712 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
713 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
714 RegSetValueExW(subKey, NULL, 0, REG_SZ,
715 (const BYTE *)PSOA, sizeof PSOA);
719 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
720 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
723 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
724 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
726 StringFromGUID2(&attr->guid, buffer, 40);
727 RegSetValueExW(subKey, NULL, 0, REG_SZ,
728 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
729 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
730 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
731 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
739 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
742 ITypeInfo_Release(tinfo);
749 ITypeLib_ReleaseTLibAttr(ptlib, attr);
755 /******************************************************************************
756 * UnRegisterTypeLib [OLEAUT32.186]
757 * Removes information about a type library from the System Registry
764 HRESULT WINAPI UnRegisterTypeLib(
765 REFGUID libid, /* [in] Guid of the library */
766 WORD wVerMajor, /* [in] major version */
767 WORD wVerMinor, /* [in] minor version */
768 LCID lcid, /* [in] locale id */
771 BSTR tlibPath = NULL;
774 WCHAR subKeyName[50];
777 BOOL deleteOtherStuff;
780 TYPEATTR* typeAttr = NULL;
782 ITypeInfo* typeInfo = NULL;
783 ITypeLib* typeLib = NULL;
786 TRACE("(IID: %s)\n",debugstr_guid(libid));
788 /* Create the path to the key */
789 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
791 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
793 TRACE("Unsupported syskind %i\n", syskind);
794 result = E_INVALIDARG;
798 /* get the path to the typelib on disk */
799 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
800 result = E_INVALIDARG;
804 /* Try and open the key to the type library. */
805 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
806 result = E_INVALIDARG;
810 /* Try and load the type library */
811 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
812 result = TYPE_E_INVALIDSTATE;
816 /* remove any types registered with this typelib */
817 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
818 for (i=0; i<numTypes; i++) {
819 /* get the kind of type */
820 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
824 /* skip non-interfaces, and get type info for the type */
825 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
828 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
831 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
835 /* the path to the type */
836 get_interface_key( &typeAttr->guid, subKeyName );
838 /* Delete its bits */
839 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
842 RegDeleteKeyW(subKey, ProxyStubClsidW);
843 RegDeleteKeyW(subKey, ProxyStubClsid32W);
844 RegDeleteKeyW(subKey, TypeLibW);
847 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
850 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
852 if (typeInfo) ITypeInfo_Release(typeInfo);
856 /* Now, delete the type library path subkey */
857 get_lcid_subkey( lcid, syskind, subKeyName );
858 RegDeleteKeyW(key, subKeyName);
859 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
860 RegDeleteKeyW(key, subKeyName);
862 /* check if there is anything besides the FLAGS/HELPDIR keys.
863 If there is, we don't delete them */
864 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
865 deleteOtherStuff = TRUE;
867 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
868 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
870 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
871 if (!strcmpW(subKeyName, FLAGSW)) continue;
872 if (!strcmpW(subKeyName, HELPDIRW)) continue;
873 deleteOtherStuff = FALSE;
877 /* only delete the other parts of the key if we're absolutely sure */
878 if (deleteOtherStuff) {
879 RegDeleteKeyW(key, FLAGSW);
880 RegDeleteKeyW(key, HELPDIRW);
884 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
885 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
886 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
890 SysFreeString(tlibPath);
891 if (typeLib) ITypeLib_Release(typeLib);
892 if (subKey) RegCloseKey(subKey);
893 if (key) RegCloseKey(key);
897 /*======================= ITypeLib implementation =======================*/
899 typedef struct tagTLBCustData
903 struct tagTLBCustData* next;
906 /* data structure for import typelibs */
907 typedef struct tagTLBImpLib
909 int offset; /* offset in the file (MSFT)
910 offset in nametable (SLTG)
911 just used to identify library while reading
913 GUID guid; /* libid */
914 BSTR name; /* name */
916 LCID lcid; /* lcid of imported typelib */
918 WORD wVersionMajor; /* major version number */
919 WORD wVersionMinor; /* minor version number */
921 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
922 NULL if not yet loaded */
923 struct tagTLBImpLib * next;
926 /* internal ITypeLib data */
927 typedef struct tagITypeLibImpl
929 const ITypeLib2Vtbl *lpVtbl;
930 const ITypeCompVtbl *lpVtblTypeComp;
932 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
935 /* strings can be stored in tlb as multibyte strings BUT they are *always*
936 * exported to the application as a UNICODE string.
943 int TypeInfoCount; /* nr of typeinfo's in librarry */
944 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
945 int ctCustData; /* number of items in cust data list */
946 TLBCustData * pCustData; /* linked list to cust data */
947 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
948 int ctTypeDesc; /* number of items in type desc array */
949 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
950 library. Only used while reading MSFT
952 struct list ref_list; /* list of ref types in this typelib */
953 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
956 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
957 struct tagITypeLibImpl *next, *prev;
962 static const ITypeLib2Vtbl tlbvt;
963 static const ITypeCompVtbl tlbtcvt;
965 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
967 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
970 /* ITypeLib methods */
971 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
972 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
974 /*======================= ITypeInfo implementation =======================*/
976 /* data for referenced types */
977 typedef struct tagTLBRefType
979 INT index; /* Type index for internal ref or for external ref
980 it the format is SLTG. -2 indicates to
983 GUID guid; /* guid of the referenced type */
984 /* if index == TLB_REF_USE_GUID */
986 HREFTYPE reference; /* The href of this ref */
987 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
988 TLB_REF_INTERNAL for internal refs
989 TLB_REF_NOT_FOUND for broken refs */
994 #define TLB_REF_USE_GUID -2
996 #define TLB_REF_INTERNAL (void*)-2
997 #define TLB_REF_NOT_FOUND (void*)-1
999 /* internal Parameter data */
1000 typedef struct tagTLBParDesc
1004 TLBCustData * pCustData; /* linked list to cust data */
1007 /* internal Function data */
1008 typedef struct tagTLBFuncDesc
1010 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1011 BSTR Name; /* the name of this function */
1012 TLBParDesc *pParamDesc; /* array with param names and custom data */
1014 int HelpStringContext;
1016 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1018 TLBCustData * pCustData; /* linked list to cust data; */
1019 struct tagTLBFuncDesc * next;
1022 /* internal Variable data */
1023 typedef struct tagTLBVarDesc
1025 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1026 BSTR Name; /* the name of this variable */
1028 int HelpStringContext; /* FIXME: where? */
1031 TLBCustData * pCustData;/* linked list to cust data; */
1032 struct tagTLBVarDesc * next;
1035 /* internal implemented interface data */
1036 typedef struct tagTLBImplType
1038 HREFTYPE hRef; /* hRef of interface */
1039 int implflags; /* IMPLFLAG_*s */
1041 TLBCustData * pCustData;/* linked list to custom data; */
1042 struct tagTLBImplType *next;
1045 /* internal TypeInfo data */
1046 typedef struct tagITypeInfoImpl
1048 const ITypeInfo2Vtbl *lpVtbl;
1049 const ITypeCompVtbl *lpVtblTypeComp;
1051 BOOL not_attached_to_typelib;
1052 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1053 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1054 int index; /* index in this typelib; */
1055 HREFTYPE hreftype; /* hreftype for app object binding */
1056 /* type libs seem to store the doc strings in ascii
1057 * so why should we do it in unicode?
1062 DWORD dwHelpContext;
1063 DWORD dwHelpStringContext;
1066 TLBFuncDesc * funclist; /* linked list with function descriptions */
1069 TLBVarDesc * varlist; /* linked list with variable descriptions */
1071 /* Implemented Interfaces */
1072 TLBImplType * impltypelist;
1075 TLBCustData * pCustData; /* linked list to cust data; */
1076 struct tagITypeInfoImpl * next;
1079 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1081 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1084 static const ITypeInfo2Vtbl tinfvt;
1085 static const ITypeCompVtbl tcompvt;
1087 static ITypeInfo2 * ITypeInfo_Constructor(void);
1088 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This);
1090 typedef struct tagTLBContext
1092 unsigned int oStart; /* start of TLB in file */
1093 unsigned int pos; /* current pos */
1094 unsigned int length; /* total length */
1095 void *mapping; /* memory mapping */
1096 MSFT_SegDir * pTblDir;
1097 ITypeLibImpl* pLibInfo;
1101 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1106 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1107 if (pTD->vt & VT_RESERVED)
1108 szVarType += strlen(strcpy(szVarType, "reserved | "));
1109 if (pTD->vt & VT_BYREF)
1110 szVarType += strlen(strcpy(szVarType, "ref to "));
1111 if (pTD->vt & VT_ARRAY)
1112 szVarType += strlen(strcpy(szVarType, "array of "));
1113 if (pTD->vt & VT_VECTOR)
1114 szVarType += strlen(strcpy(szVarType, "vector of "));
1115 switch(pTD->vt & VT_TYPEMASK) {
1116 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1117 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1118 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1119 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1120 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1121 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1122 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1123 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1124 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1125 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1126 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1127 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1128 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1129 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1130 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1131 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1132 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1133 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1134 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1135 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1136 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1137 pTD->u.hreftype); break;
1138 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1139 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1140 case VT_PTR: sprintf(szVarType, "ptr to ");
1141 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1143 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1144 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1146 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1147 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1148 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1151 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1155 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1157 USHORT flags = edesc->u.paramdesc.wParamFlags;
1158 dump_TypeDesc(&edesc->tdesc,buf);
1159 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1160 MESSAGE("\t\tu.paramdesc.wParamFlags");
1161 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1162 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1163 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1164 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1165 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1166 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1167 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1168 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1169 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1171 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1173 MESSAGE("memid is %08x\n",funcdesc->memid);
1174 for (i=0;i<funcdesc->cParams;i++) {
1175 MESSAGE("Param %d:\n",i);
1176 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1178 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1179 switch (funcdesc->funckind) {
1180 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1181 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1182 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1183 case FUNC_STATIC: MESSAGE("static");break;
1184 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1185 default: MESSAGE("unknown");break;
1187 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1188 switch (funcdesc->invkind) {
1189 case INVOKE_FUNC: MESSAGE("func");break;
1190 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1191 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1192 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1194 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1195 switch (funcdesc->callconv) {
1196 case CC_CDECL: MESSAGE("cdecl");break;
1197 case CC_PASCAL: MESSAGE("pascal");break;
1198 case CC_STDCALL: MESSAGE("stdcall");break;
1199 case CC_SYSCALL: MESSAGE("syscall");break;
1202 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1203 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1204 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1206 MESSAGE("\telemdescFunc (return value type):\n");
1207 dump_ELEMDESC(&funcdesc->elemdescFunc);
1210 static const char * const typekind_desc[] =
1223 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1226 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1227 for (i=0;i<pfd->funcdesc.cParams;i++)
1228 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1231 dump_FUNCDESC(&(pfd->funcdesc));
1233 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1234 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1236 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1240 dump_TLBFuncDescOne(pfd);
1244 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1248 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1253 static void dump_TLBImpLib(const TLBImpLib *import)
1255 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1256 debugstr_w(import->name));
1257 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1258 import->wVersionMinor, import->lcid, import->offset);
1261 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1265 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1267 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1268 if(ref->index == -1)
1269 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1271 TRACE_(typelib)("type no: %d\n", ref->index);
1273 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1275 TRACE_(typelib)("in lib\n");
1276 dump_TLBImpLib(ref->pImpTLInfo);
1281 static void dump_TLBImplType(const TLBImplType * impl)
1285 "implementing/inheriting interface hRef = %x implflags %x\n",
1286 impl->hRef, impl->implflags);
1291 static void dump_Variant(const VARIANT * pvar)
1295 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1299 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1300 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1302 TRACE(",%p", V_BYREF(pvar));
1304 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1306 TRACE(",%p", V_ARRAY(pvar));
1308 else switch (V_TYPE(pvar))
1310 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1311 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1312 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1313 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1315 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1317 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1318 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1319 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1320 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1321 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1322 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1323 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1324 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1325 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1326 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1327 V_CY(pvar).s.Lo); break;
1329 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1330 TRACE(",<invalid>");
1332 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1333 st.wHour, st.wMinute, st.wSecond);
1337 case VT_USERDEFINED:
1339 case VT_NULL: break;
1340 default: TRACE(",?"); break;
1346 static void dump_DispParms(const DISPPARAMS * pdp)
1350 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1352 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1354 TRACE("named args:\n");
1355 for (index = 0; index < pdp->cNamedArgs; index++)
1356 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1359 if (pdp->cArgs && pdp->rgvarg)
1362 for (index = 0; index < pdp->cArgs; index++)
1363 dump_Variant( &pdp->rgvarg[index] );
1367 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1369 TRACE("%p ref=%u\n", pty, pty->ref);
1370 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1371 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1372 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1373 TRACE("fct:%u var:%u impl:%u\n",
1374 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1375 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1376 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1377 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1379 dump_TLBFuncDesc(pty->funclist);
1380 dump_TLBVarDesc(pty->varlist);
1381 dump_TLBImplType(pty->impltypelist);
1384 static void dump_VARDESC(const VARDESC *v)
1386 MESSAGE("memid %d\n",v->memid);
1387 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1388 MESSAGE("oInst %d\n",v->u.oInst);
1389 dump_ELEMDESC(&(v->elemdescVar));
1390 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1391 MESSAGE("varkind %d\n",v->varkind);
1394 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1396 /* VT_LPWSTR is largest type that */
1397 /* may appear in type description*/
1398 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1399 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1400 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1401 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1402 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1403 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1407 static void TLB_abort(void)
1412 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1413 static void * TLB_Alloc(unsigned size)
1416 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1418 ERR("cannot allocate memory\n");
1423 static void TLB_Free(void * ptr)
1425 HeapFree(GetProcessHeap(), 0, ptr);
1428 /* returns the size required for a deep copy of a typedesc into a
1430 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1434 if (alloc_initial_space)
1435 size += sizeof(TYPEDESC);
1441 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1444 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1445 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1451 /* deep copy a typedesc into a flat buffer */
1452 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1457 buffer = (char *)buffer + sizeof(TYPEDESC);
1466 dest->u.lptdesc = buffer;
1467 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1470 dest->u.lpadesc = buffer;
1471 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1472 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1473 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1479 /* free custom data allocated by MSFT_CustData */
1480 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1482 TLBCustData *pCustDataNext;
1483 for (; pCustData; pCustData = pCustDataNext)
1485 VariantClear(&pCustData->data);
1487 pCustDataNext = pCustData->next;
1488 TLB_Free(pCustData);
1492 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1497 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1498 ret = SysAllocStringLen(NULL, len - 1);
1499 if (!ret) return ret;
1500 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1504 /**********************************************************************
1506 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1508 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1513 static inline void MSFT_Seek(TLBContext *pcx, long where)
1515 if (where != DO_NOT_SEEK)
1517 where += pcx->oStart;
1518 if (where > pcx->length)
1521 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1529 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1531 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1532 pcx->pos, count, pcx->oStart, pcx->length, where);
1534 MSFT_Seek(pcx, where);
1535 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1536 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1541 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1546 ret = MSFT_Read(buffer, count, pcx, where);
1547 FromLEDWords(buffer, ret);
1552 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1557 ret = MSFT_Read(buffer, count, pcx, where);
1558 FromLEWords(buffer, ret);
1563 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1565 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1566 memset(pGuid,0, sizeof(GUID));
1569 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1570 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1571 pGuid->Data2 = FromLEWord(pGuid->Data2);
1572 pGuid->Data3 = FromLEWord(pGuid->Data3);
1573 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1576 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1578 MSFT_NameIntro niName;
1582 ERR_(typelib)("bad offset %d\n", offset);
1586 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1587 pcx->pTblDir->pNametab.offset+offset);
1589 return niName.hreftype;
1592 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1595 MSFT_NameIntro niName;
1597 BSTR bstrName = NULL;
1601 ERR_(typelib)("bad offset %d\n", offset);
1604 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1605 pcx->pTblDir->pNametab.offset+offset);
1606 niName.namelen &= 0xFF; /* FIXME: correct ? */
1607 name=TLB_Alloc((niName.namelen & 0xff) +1);
1608 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1609 name[niName.namelen & 0xff]='\0';
1611 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1614 /* no invalid characters in string */
1617 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1619 /* don't check for invalid character since this has been done previously */
1620 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1624 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1628 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1635 if(offset<0) return NULL;
1636 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1637 if(length <= 0) return 0;
1638 string=TLB_Alloc(length +1);
1639 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1640 string[length]='\0';
1642 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1643 string, -1, NULL, 0);
1645 /* no invalid characters in string */
1648 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1650 /* don't check for invalid character since this has been done previously */
1651 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1655 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1659 * read a value and fill a VARIANT structure
1661 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1665 TRACE_(typelib)("\n");
1667 if(offset <0) { /* data are packed in here */
1668 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1669 V_I4(pVar) = offset & 0x3ffffff;
1672 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1673 pcx->pTblDir->pCustData.offset + offset );
1674 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1675 switch (V_VT(pVar)){
1676 case VT_EMPTY: /* FIXME: is this right? */
1677 case VT_NULL: /* FIXME: is this right? */
1678 case VT_I2 : /* this should not happen */
1689 case VT_VOID : /* FIXME: is this right? */
1697 case VT_DECIMAL : /* FIXME: is this right? */
1700 /* pointer types with known behaviour */
1703 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1706 DWORD origPos = MSFT_Tell(pcx), nullPos;
1709 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1711 nullPos = MSFT_Tell(pcx);
1712 size = nullPos - origPos;
1713 MSFT_Seek(pcx, origPos);
1715 ptr=TLB_Alloc(size);/* allocate temp buffer */
1716 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1717 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1718 /* FIXME: do we need a AtoW conversion here? */
1719 V_UNION(pVar, bstrVal[size])='\0';
1720 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1724 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1731 case VT_USERDEFINED :
1737 case VT_STREAMED_OBJECT :
1738 case VT_STORED_OBJECT :
1739 case VT_BLOB_OBJECT :
1744 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1748 if(size>0) /* (big|small) endian correct? */
1749 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1753 * create a linked list with custom data
1755 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1761 TRACE_(typelib)("\n");
1765 pNew=TLB_Alloc(sizeof(TLBCustData));
1766 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1767 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1768 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1769 /* add new custom data at head of the list */
1770 pNew->next=*ppCustData;
1772 offset = entry.next;
1777 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1781 pTd->vt=type & VT_TYPEMASK;
1783 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1785 if(pTd->vt == VT_USERDEFINED)
1786 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1788 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1791 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1793 /* resolve referenced type if any */
1796 switch (lpTypeDesc->vt)
1799 lpTypeDesc = lpTypeDesc->u.lptdesc;
1803 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1806 case VT_USERDEFINED:
1807 MSFT_DoRefType(pcx, pTI->pTypeLib,
1808 lpTypeDesc->u.hreftype);
1820 MSFT_DoFuncs(TLBContext* pcx,
1825 TLBFuncDesc** pptfd)
1828 * member information is stored in a data structure at offset
1829 * indicated by the memoffset field of the typeinfo structure
1830 * There are several distinctive parts.
1831 * The first part starts with a field that holds the total length
1832 * of this (first) part excluding this field. Then follow the records,
1833 * for each member there is one record.
1835 * The first entry is always the length of the record (including this
1837 * The rest of the record depends on the type of the member. If there is
1838 * a field indicating the member type (function, variable, interface, etc)
1839 * I have not found it yet. At this time we depend on the information
1840 * in the type info and the usual order how things are stored.
1842 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1845 * Third is an equal sized array with file offsets to the name entry
1848 * The fourth and last (?) part is an array with offsets to the records
1849 * in the first part of this file segment.
1852 int infolen, nameoffset, reclength, nrattributes, i;
1853 int recoffset = offset + sizeof(INT);
1855 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1856 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1857 TLBFuncDesc *ptfd_prev = NULL;
1859 TRACE_(typelib)("\n");
1861 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1863 for ( i = 0; i < cFuncs ; i++ )
1865 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1867 /* name, eventually add to a hash table */
1868 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1869 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1871 /* nameoffset is sometimes -1 on the second half of a propget/propput
1872 * pair of functions */
1873 if ((nameoffset == -1) && (i > 0))
1874 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1876 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1878 /* read the function information record */
1879 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1881 reclength &= 0xffff;
1883 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1885 /* do the attributes */
1886 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1889 if ( nrattributes > 0 )
1891 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1893 if ( nrattributes > 1 )
1895 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1896 pFuncRec->OptAttr[1]) ;
1898 if ( nrattributes > 2 )
1900 if ( pFuncRec->FKCCIC & 0x2000 )
1902 if (!IS_INTRESOURCE(pFuncRec->OptAttr[2]))
1903 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->OptAttr[2]);
1904 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1908 (*pptfd)->Entry = MSFT_ReadString(pcx,
1909 pFuncRec->OptAttr[2]);
1911 if( nrattributes > 5 )
1913 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1915 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1918 pFuncRec->OptAttr[6],
1919 &(*pptfd)->pCustData);
1925 (*pptfd)->Entry = (BSTR)-1;
1930 /* fill the FuncDesc Structure */
1931 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1932 offset + infolen + ( i + 1) * sizeof(INT));
1934 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1935 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1936 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1937 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1938 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1939 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1940 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1944 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1946 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1948 /* do the parameters/arguments */
1949 if(pFuncRec->nrargs)
1952 MSFT_ParameterInfo paraminfo;
1954 (*pptfd)->funcdesc.lprgelemdescParam =
1955 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1957 (*pptfd)->pParamDesc =
1958 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1960 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1961 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1963 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1965 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1972 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1975 if (paraminfo.oName == -1)
1976 /* this occurs for [propput] or [propget] methods, so
1977 * we should just set the name of the parameter to the
1978 * name of the method. */
1979 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1981 (*pptfd)->pParamDesc[j].Name =
1982 MSFT_ReadName( pcx, paraminfo.oName );
1983 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1985 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1988 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1989 (pFuncRec->FKCCIC & 0x1000) )
1991 INT* pInt = (INT *)((char *)pFuncRec +
1993 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1995 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1997 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1998 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2000 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2004 elemdesc->u.paramdesc.pparamdescex = NULL;
2006 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2009 pFuncRec->OptAttr[7+j],
2010 &(*pptfd)->pParamDesc[j].pCustData);
2013 /* SEEK value = jump to offset,
2014 * from there jump to the end of record,
2015 * go back by (j-1) arguments
2017 MSFT_ReadLEDWords( ¶minfo ,
2018 sizeof(MSFT_ParameterInfo), pcx,
2019 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2020 * sizeof(MSFT_ParameterInfo)));
2024 /* scode is not used: archaic win16 stuff FIXME: right? */
2025 (*pptfd)->funcdesc.cScodes = 0 ;
2026 (*pptfd)->funcdesc.lprgscode = NULL ;
2029 pptfd = & ((*pptfd)->next);
2030 recoffset += reclength;
2032 HeapFree(GetProcessHeap(), 0, recbuf);
2035 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2036 int cVars, int offset, TLBVarDesc ** pptvd)
2038 int infolen, nameoffset, reclength;
2040 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2044 TRACE_(typelib)("\n");
2046 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2047 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2048 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2049 recoffset += offset+sizeof(INT);
2050 for(i=0;i<cVars;i++){
2051 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2052 /* name, eventually add to a hash table */
2053 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2054 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2055 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2056 /* read the variable information record */
2057 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2059 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2061 if(reclength >(6*sizeof(INT)) )
2062 (*pptvd)->HelpContext=pVarRec->HelpContext;
2063 if(reclength >(7*sizeof(INT)) )
2064 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2065 if(reclength >(8*sizeof(INT)) )
2066 if(reclength >(9*sizeof(INT)) )
2067 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2068 /* fill the VarDesc Structure */
2069 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2070 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2071 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2072 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2073 MSFT_GetTdesc(pcx, pVarRec->DataType,
2074 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2075 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2076 if(pVarRec->VarKind == VAR_CONST ){
2077 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2078 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2079 pVarRec->OffsValue, pcx);
2081 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2082 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2083 pptvd=&((*pptvd)->next);
2084 recoffset += reclength;
2087 /* fill in data for a hreftype (offset). When the referenced type is contained
2088 * in the typelib, it's just an (file) offset in the type info base dir.
2089 * If comes from import, it's an offset+1 in the ImpInfo table
2091 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2096 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2098 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2100 if(ref->reference == offset) return;
2103 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2104 list_add_tail(&pTL->ref_list, &ref->entry);
2106 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2107 /* external typelib */
2108 MSFT_ImpInfo impinfo;
2109 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2111 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2113 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2114 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2115 while (pImpLib){ /* search the known offsets of all import libraries */
2116 if(pImpLib->offset==impinfo.oImpFile) break;
2117 pImpLib=pImpLib->next;
2120 ref->reference = offset;
2121 ref->pImpTLInfo = pImpLib;
2122 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2123 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2124 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2125 ref->index = TLB_REF_USE_GUID;
2127 ref->index = impinfo.oGuid;
2129 ERR("Cannot find a reference\n");
2130 ref->reference = -1;
2131 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2134 /* in this typelib */
2135 ref->index = MSFT_HREFTYPE_INDEX(offset);
2136 ref->reference = offset;
2137 ref->pImpTLInfo = TLB_REF_INTERNAL;
2141 /* process Implemented Interfaces of a com class */
2142 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2146 MSFT_RefRecord refrec;
2147 TLBImplType **ppImpl = &pTI->impltypelist;
2149 TRACE_(typelib)("\n");
2151 for(i=0;i<count;i++){
2152 if(offset<0) break; /* paranoia */
2153 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2154 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2155 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2156 (*ppImpl)->hRef = refrec.reftype;
2157 (*ppImpl)->implflags=refrec.flags;
2158 (*ppImpl)->ctCustData=
2159 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2160 offset=refrec.onext;
2161 ppImpl=&((*ppImpl)->next);
2165 * process a typeinfo record
2167 static ITypeInfoImpl * MSFT_DoTypeInfo(
2170 ITypeLibImpl * pLibInfo)
2172 MSFT_TypeInfoBase tiBase;
2173 ITypeInfoImpl *ptiRet;
2175 TRACE_(typelib)("count=%u\n", count);
2177 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2178 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2179 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2181 /* this is where we are coming from */
2182 ptiRet->pTypeLib = pLibInfo;
2183 ptiRet->index=count;
2184 /* fill in the typeattr fields */
2186 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2187 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2188 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2189 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2190 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2191 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2192 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2193 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2194 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2195 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2196 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2197 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2198 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2199 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2200 MSFT_GetTdesc(pcx, tiBase.datatype1,
2201 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2204 /* IDLDESC idldescType; *//* never saw this one != zero */
2206 /* name, eventually add to a hash table */
2207 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2208 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2209 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2211 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2212 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2213 ptiRet->dwHelpContext=tiBase.helpcontext;
2215 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2216 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2218 /* note: InfoType's Help file and HelpStringDll come from the containing
2219 * library. Further HelpString and Docstring appear to be the same thing :(
2222 if(ptiRet->TypeAttr.cFuncs >0 )
2223 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2224 ptiRet->TypeAttr.cVars,
2225 tiBase.memoffset, & ptiRet->funclist);
2227 if(ptiRet->TypeAttr.cVars >0 )
2228 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2229 ptiRet->TypeAttr.cVars,
2230 tiBase.memoffset, & ptiRet->varlist);
2231 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2232 switch(ptiRet->TypeAttr.typekind)
2235 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2238 case TKIND_DISPATCH:
2239 /* This is not -1 when the interface is a non-base dual interface or
2240 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2241 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2245 if (tiBase.datatype1 != -1)
2247 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2248 ptiRet->impltypelist->hRef = tiBase.datatype1;
2249 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2253 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2254 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2255 ptiRet->impltypelist->hRef = tiBase.datatype1;
2260 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2262 TRACE_(typelib)("%s guid: %s kind:%s\n",
2263 debugstr_w(ptiRet->Name),
2264 debugstr_guid(&ptiRet->TypeAttr.guid),
2265 typekind_desc[ptiRet->TypeAttr.typekind]);
2266 if (TRACE_ON(typelib))
2267 dump_TypeInfo(ptiRet);
2272 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2273 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2274 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2277 static ITypeLibImpl *tlb_cache_first;
2278 static CRITICAL_SECTION cache_section;
2279 static CRITICAL_SECTION_DEBUG cache_section_debug =
2281 0, 0, &cache_section,
2282 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2283 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2285 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2288 typedef struct TLB_PEFile
2290 const IUnknownVtbl *lpvtbl;
2293 HRSRC typelib_resource;
2294 HGLOBAL typelib_global;
2295 LPVOID typelib_base;
2298 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2300 if (IsEqualIID(riid, &IID_IUnknown))
2303 IUnknown_AddRef(iface);
2307 return E_NOINTERFACE;
2310 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2312 TLB_PEFile *This = (TLB_PEFile *)iface;
2313 return InterlockedIncrement(&This->refs);
2316 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2318 TLB_PEFile *This = (TLB_PEFile *)iface;
2319 ULONG refs = InterlockedDecrement(&This->refs);
2322 if (This->typelib_global)
2323 FreeResource(This->typelib_global);
2325 FreeLibrary(This->dll);
2326 HeapFree(GetProcessHeap(), 0, This);
2331 static const IUnknownVtbl TLB_PEFile_Vtable =
2333 TLB_PEFile_QueryInterface,
2338 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2342 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2344 return E_OUTOFMEMORY;
2346 This->lpvtbl = &TLB_PEFile_Vtable;
2349 This->typelib_resource = NULL;
2350 This->typelib_global = NULL;
2351 This->typelib_base = NULL;
2353 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2354 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2358 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2359 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2360 if (This->typelib_resource)
2362 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2363 if (This->typelib_global)
2365 This->typelib_base = LockResource(This->typelib_global);
2367 if (This->typelib_base)
2369 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2370 *ppBase = This->typelib_base;
2371 *ppFile = (IUnknown *)&This->lpvtbl;
2378 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2379 return TYPE_E_CANTLOADLIBRARY;
2382 typedef struct TLB_NEFile
2384 const IUnknownVtbl *lpvtbl;
2386 LPVOID typelib_base;
2389 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2391 if (IsEqualIID(riid, &IID_IUnknown))
2394 IUnknown_AddRef(iface);
2398 return E_NOINTERFACE;
2401 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2403 TLB_NEFile *This = (TLB_NEFile *)iface;
2404 return InterlockedIncrement(&This->refs);
2407 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2409 TLB_NEFile *This = (TLB_NEFile *)iface;
2410 ULONG refs = InterlockedDecrement(&This->refs);
2413 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2414 HeapFree(GetProcessHeap(), 0, This);
2419 static const IUnknownVtbl TLB_NEFile_Vtable =
2421 TLB_NEFile_QueryInterface,
2426 /***********************************************************************
2427 * read_xx_header [internal]
2429 static int read_xx_header( HFILE lzfd )
2431 IMAGE_DOS_HEADER mzh;
2434 LZSeek( lzfd, 0, SEEK_SET );
2435 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2437 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2440 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2441 if ( 2 != LZRead( lzfd, magic, 2 ) )
2444 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2446 if ( magic[0] == 'N' && magic[1] == 'E' )
2447 return IMAGE_OS2_SIGNATURE;
2448 if ( magic[0] == 'P' && magic[1] == 'E' )
2449 return IMAGE_NT_SIGNATURE;
2452 WARN("Can't handle %s files.\n", magic );
2457 /***********************************************************************
2458 * find_ne_resource [internal]
2460 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2461 DWORD *resLen, DWORD *resOff )
2463 IMAGE_OS2_HEADER nehd;
2464 NE_TYPEINFO *typeInfo;
2465 NE_NAMEINFO *nameInfo;
2471 /* Read in NE header */
2472 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2473 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2475 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2478 TRACE("No resources in NE dll\n" );
2482 /* Read in resource table */
2483 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2484 if ( !resTab ) return FALSE;
2486 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2487 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2489 HeapFree( GetProcessHeap(), 0, resTab );
2494 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2496 if (!IS_INTRESOURCE(typeid)) /* named type */
2498 BYTE len = strlen( typeid );
2499 while (typeInfo->type_id)
2501 if (!(typeInfo->type_id & 0x8000))
2503 BYTE *p = resTab + typeInfo->type_id;
2504 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2506 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2507 typeInfo->count * sizeof(NE_NAMEINFO));
2510 else /* numeric type id */
2512 WORD id = LOWORD(typeid) | 0x8000;
2513 while (typeInfo->type_id)
2515 if (typeInfo->type_id == id) goto found_type;
2516 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2517 typeInfo->count * sizeof(NE_NAMEINFO));
2520 TRACE("No typeid entry found for %p\n", typeid );
2521 HeapFree( GetProcessHeap(), 0, resTab );
2525 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2527 if (!IS_INTRESOURCE(resid)) /* named resource */
2529 BYTE len = strlen( resid );
2530 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2532 BYTE *p = resTab + nameInfo->id;
2533 if (nameInfo->id & 0x8000) continue;
2534 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2537 else /* numeric resource id */
2539 WORD id = LOWORD(resid) | 0x8000;
2540 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2541 if (nameInfo->id == id) goto found_name;
2543 TRACE("No resid entry found for %p\n", typeid );
2544 HeapFree( GetProcessHeap(), 0, resTab );
2548 /* Return resource data */
2549 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2550 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2552 HeapFree( GetProcessHeap(), 0, resTab );
2556 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2560 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2561 TLB_NEFile *This = NULL;
2563 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2564 if (!This) return E_OUTOFMEMORY;
2566 This->lpvtbl = &TLB_NEFile_Vtable;
2568 This->typelib_base = NULL;
2570 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2571 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2573 DWORD reslen, offset;
2574 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2576 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2577 if( !This->typelib_base )
2581 LZSeek( lzfd, offset, SEEK_SET );
2582 reslen = LZRead( lzfd, This->typelib_base, reslen );
2584 *ppBase = This->typelib_base;
2585 *pdwTLBLength = reslen;
2586 *ppFile = (IUnknown *)&This->lpvtbl;
2592 if( lzfd >= 0) LZClose( lzfd );
2593 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2597 typedef struct TLB_Mapping
2599 const IUnknownVtbl *lpvtbl;
2603 LPVOID typelib_base;
2606 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2608 if (IsEqualIID(riid, &IID_IUnknown))
2611 IUnknown_AddRef(iface);
2615 return E_NOINTERFACE;
2618 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2620 TLB_Mapping *This = (TLB_Mapping *)iface;
2621 return InterlockedIncrement(&This->refs);
2624 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2626 TLB_Mapping *This = (TLB_Mapping *)iface;
2627 ULONG refs = InterlockedDecrement(&This->refs);
2630 if (This->typelib_base)
2631 UnmapViewOfFile(This->typelib_base);
2633 CloseHandle(This->mapping);
2634 if (This->file != INVALID_HANDLE_VALUE)
2635 CloseHandle(This->file);
2636 HeapFree(GetProcessHeap(), 0, This);
2641 static const IUnknownVtbl TLB_Mapping_Vtable =
2643 TLB_Mapping_QueryInterface,
2648 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2652 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2654 return E_OUTOFMEMORY;
2656 This->lpvtbl = &TLB_Mapping_Vtable;
2658 This->file = INVALID_HANDLE_VALUE;
2659 This->mapping = NULL;
2660 This->typelib_base = NULL;
2662 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2663 if (INVALID_HANDLE_VALUE != This->file)
2665 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2668 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2669 if(This->typelib_base)
2671 /* retrieve file size */
2672 *pdwTLBLength = GetFileSize(This->file, NULL);
2673 *ppBase = This->typelib_base;
2674 *ppFile = (IUnknown *)&This->lpvtbl;
2680 IUnknown_Release((IUnknown *)&This->lpvtbl);
2681 return TYPE_E_CANTLOADLIBRARY;
2684 /****************************************************************************
2687 * find the type of the typelib file and map the typelib resource into
2690 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2691 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2692 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2694 ITypeLibImpl *entry;
2697 LPWSTR index_str, file = (LPWSTR)pszFileName;
2698 LPVOID pBase = NULL;
2699 DWORD dwTLBLength = 0;
2700 IUnknown *pFile = NULL;
2704 index_str = strrchrW(pszFileName, '\\');
2705 if(index_str && *++index_str != '\0')
2708 long idx = strtolW(index_str, &end_ptr, 10);
2709 if(*end_ptr == '\0')
2711 int str_len = index_str - pszFileName - 1;
2713 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2714 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2719 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2721 if(strchrW(file, '\\'))
2723 lstrcpyW(pszPath, file);
2727 int len = GetSystemDirectoryW(pszPath, cchPath);
2728 pszPath[len] = '\\';
2729 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2733 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2735 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2737 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2738 EnterCriticalSection(&cache_section);
2739 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2741 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2743 TRACE("cache hit\n");
2744 *ppTypeLib = (ITypeLib2*)entry;
2745 ITypeLib_AddRef(*ppTypeLib);
2746 LeaveCriticalSection(&cache_section);
2750 LeaveCriticalSection(&cache_section);
2752 /* now actually load and parse the typelib */
2754 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2755 if (ret == TYPE_E_CANTLOADLIBRARY)
2756 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2757 if (ret == TYPE_E_CANTLOADLIBRARY)
2758 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2761 if (dwTLBLength >= 4)
2763 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2764 if (dwSignature == MSFT_SIGNATURE)
2765 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2766 else if (dwSignature == SLTG_SIGNATURE)
2767 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2770 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2771 ret = TYPE_E_CANTLOADLIBRARY;
2775 ret = TYPE_E_CANTLOADLIBRARY;
2776 IUnknown_Release(pFile);
2780 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2782 TRACE("adding to cache\n");
2783 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2784 lstrcpyW(impl->path, pszPath);
2785 /* We should really canonicalise the path here. */
2786 impl->index = index;
2788 /* FIXME: check if it has added already in the meantime */
2789 EnterCriticalSection(&cache_section);
2790 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2792 tlb_cache_first = impl;
2793 LeaveCriticalSection(&cache_section);
2796 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2801 /*================== ITypeLib(2) Methods ===================================*/
2803 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2805 ITypeLibImpl* pTypeLibImpl;
2807 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2808 if (!pTypeLibImpl) return NULL;
2810 pTypeLibImpl->lpVtbl = &tlbvt;
2811 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2812 pTypeLibImpl->ref = 1;
2814 list_init(&pTypeLibImpl->ref_list);
2815 pTypeLibImpl->dispatch_href = -1;
2817 return pTypeLibImpl;
2820 /****************************************************************************
2821 * ITypeLib2_Constructor_MSFT
2823 * loading an MSFT typelib from an in-memory image
2825 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2829 MSFT_Header tlbHeader;
2830 MSFT_SegDir tlbSegDir;
2831 ITypeLibImpl * pTypeLibImpl;
2833 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2835 pTypeLibImpl = TypeLibImpl_Constructor();
2836 if (!pTypeLibImpl) return NULL;
2838 /* get pointer to beginning of typelib data */
2842 cx.pLibInfo = pTypeLibImpl;
2843 cx.length = dwTLBLength;
2846 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2847 TRACE_(typelib)("header:\n");
2848 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2849 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2850 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2853 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2855 /* there is a small amount of information here until the next important
2857 * the segment directory . Try to calculate the amount of data */
2858 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2860 /* now read the segment directory */
2861 TRACE("read segment directory (at %ld)\n",lPSegDir);
2862 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2863 cx.pTblDir = &tlbSegDir;
2865 /* just check two entries */
2866 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2868 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2869 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2873 /* now fill our internal data */
2874 /* TLIBATTR fields */
2875 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2877 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2878 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2879 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2880 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2881 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2883 pTypeLibImpl->lcid = tlbHeader.lcid;
2885 /* name, eventually add to a hash table */
2886 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2889 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2890 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2892 if( tlbHeader.varflags & HELPDLLFLAG)
2895 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2896 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2899 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2902 if(tlbHeader.CustomDataOffset >= 0)
2904 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2907 /* fill in type descriptions */
2908 if(tlbSegDir.pTypdescTab.length > 0)
2910 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2912 pTypeLibImpl->ctTypeDesc = cTD;
2913 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2914 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2917 /* FIXME: add several sanity checks here */
2918 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2919 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2921 /* FIXME: check safearray */
2923 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2925 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2927 else if(td[0] == VT_CARRAY)
2929 /* array descr table here */
2930 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2932 else if(td[0] == VT_USERDEFINED)
2934 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2936 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2939 /* second time around to fill the array subscript info */
2942 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2943 if(tlbSegDir.pArrayDescriptions.offset>0)
2945 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2946 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2949 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2951 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
2953 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2955 for(j = 0; j<td[2]; j++)
2957 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2958 sizeof(INT), &cx, DO_NOT_SEEK);
2959 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2960 sizeof(INT), &cx, DO_NOT_SEEK);
2965 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2966 ERR("didn't find array description data\n");
2971 /* imported type libs */
2972 if(tlbSegDir.pImpFiles.offset>0)
2974 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2975 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2978 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2982 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2983 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2984 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2986 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2987 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2988 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2989 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2992 name = TLB_Alloc(size+1);
2993 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2994 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2997 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2998 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3000 ppImpLib = &(*ppImpLib)->next;
3004 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3005 if(pTypeLibImpl->dispatch_href != -1)
3006 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3009 if(tlbHeader.nrtypeinfos >= 0 )
3011 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3012 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3015 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3017 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3019 ppTI = &((*ppTI)->next);
3020 (pTypeLibImpl->TypeInfoCount)++;
3024 TRACE("(%p)\n", pTypeLibImpl);
3025 return (ITypeLib2*) pTypeLibImpl;
3029 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3035 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3036 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3040 guid->Data4[0] = s >> 8;
3041 guid->Data4[1] = s & 0xff;
3044 for(i = 0; i < 6; i++) {
3045 memcpy(b, str + 24 + 2 * i, 2);
3046 guid->Data4[i + 2] = strtol(b, NULL, 16);
3051 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3057 bytelen = *(const WORD*)ptr;
3058 if(bytelen == 0xffff) return 2;
3059 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3060 *pBstr = SysAllocStringLen(NULL, len);
3062 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3066 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3071 bytelen = *(const WORD*)ptr;
3072 if(bytelen == 0xffff) return 2;
3073 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3074 memcpy(*str, ptr + 2, bytelen);
3075 (*str)[bytelen] = '\0';
3079 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3081 char *ptr = pLibBlk;
3084 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3085 FIXME("libblk magic = %04x\n", w);
3090 if((w = *(WORD*)ptr) != 0xffff) {
3091 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3096 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3098 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3100 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3103 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3106 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3107 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3109 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3112 ptr += 4; /* skip res12 */
3114 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3117 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3120 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3123 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3124 ptr += sizeof(GUID);
3126 return ptr - (char*)pLibBlk;
3129 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3134 } sltg_ref_lookup_t;
3136 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3137 HREFTYPE *typelib_ref)
3139 if(table && typeinfo_ref < table->num)
3141 *typelib_ref = table->refs[typeinfo_ref];
3145 ERR_(typelib)("Unable to find reference\n");
3150 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3155 if((*pType & 0xe00) == 0xe00) {
3157 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3159 pTD = pTD->u.lptdesc;
3161 switch(*pType & 0x3f) {
3164 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3166 pTD = pTD->u.lptdesc;
3169 case VT_USERDEFINED:
3170 pTD->vt = VT_USERDEFINED;
3171 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3177 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3180 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3182 pTD->vt = VT_CARRAY;
3183 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3185 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3186 pTD->u.lpadesc->cDims = pSA->cDims;
3187 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3188 pSA->cDims * sizeof(SAFEARRAYBOUND));
3190 pTD = &pTD->u.lpadesc->tdescElem;
3196 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3200 pTD->vt = VT_SAFEARRAY;
3201 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3203 pTD = pTD->u.lptdesc;
3207 pTD->vt = *pType & 0x3f;
3216 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3217 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3219 /* Handle [in/out] first */
3220 if((*pType & 0xc000) == 0xc000)
3221 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3222 else if(*pType & 0x8000)
3223 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3224 else if(*pType & 0x4000)
3225 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3227 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3230 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3233 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3235 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3239 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3244 TLBRefType *ref_type;
3245 sltg_ref_lookup_t *table;
3246 HREFTYPE typelib_ref;
3248 if(pRef->magic != SLTG_REF_MAGIC) {
3249 FIXME("Ref magic = %x\n", pRef->magic);
3252 name = ( (char*)pRef->names + pRef->number);
3254 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3255 table->num = pRef->number >> 3;
3257 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3259 /* We don't want the first href to be 0 */
3260 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3262 for(ref = 0; ref < pRef->number >> 3; ref++) {
3264 unsigned int lib_offs, type_num;
3266 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3268 name += SLTG_ReadStringA(name, &refname);
3269 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3270 FIXME_(typelib)("Can't sscanf ref\n");
3271 if(lib_offs != 0xffff) {
3272 TLBImpLib **import = &pTL->pImpLibs;
3275 if((*import)->offset == lib_offs)
3277 import = &(*import)->next;
3280 char fname[MAX_PATH+1];
3283 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3285 (*import)->offset = lib_offs;
3286 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3288 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3289 &(*import)->wVersionMajor,
3290 &(*import)->wVersionMinor,
3291 &(*import)->lcid, fname) != 4) {
3292 FIXME_(typelib)("can't sscanf ref %s\n",
3293 pNameTable + lib_offs + 40);
3295 len = strlen(fname);
3296 if(fname[len-1] != '#')
3297 FIXME("fname = %s\n", fname);
3298 fname[len-1] = '\0';
3299 (*import)->name = TLB_MultiByteToBSTR(fname);
3301 ref_type->pImpTLInfo = *import;
3303 /* Store a reference to IDispatch */
3304 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3305 pTL->dispatch_href = typelib_ref;
3307 } else { /* internal ref */
3308 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3310 ref_type->reference = typelib_ref;
3311 ref_type->index = type_num;
3313 HeapFree(GetProcessHeap(), 0, refname);
3314 list_add_tail(&pTL->ref_list, &ref_type->entry);
3316 table->refs[ref] = typelib_ref;
3319 if((BYTE)*name != SLTG_REF_MAGIC)
3320 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3321 dump_TLBRefType(pTL);
3325 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3326 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3328 SLTG_ImplInfo *info;
3329 TLBImplType **ppImplType = &pTI->impltypelist;
3330 /* I don't really get this structure, usually it's 0x16 bytes
3331 long, but iuser.tlb contains some that are 0x18 bytes long.
3332 That's ok because we can use the next ptr to jump to the next
3333 one. But how do we know the length of the last one? The WORD
3334 at offs 0x8 might be the clue. For now I'm just assuming that
3335 the last one is the regular 0x16 bytes. */
3337 info = (SLTG_ImplInfo*)pBlk;
3339 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3340 sizeof(**ppImplType));
3341 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3342 (*ppImplType)->implflags = info->impltypeflags;
3343 pTI->TypeAttr.cImplTypes++;
3344 ppImplType = &(*ppImplType)->next;
3346 if(info->next == 0xffff)
3349 FIXME_(typelib)("Interface inheriting more than one interface\n");
3350 info = (SLTG_ImplInfo*)(pBlk + info->next);
3352 info++; /* see comment at top of function */
3356 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3357 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3359 TLBVarDesc **ppVarDesc = &pTI->varlist;
3360 BSTR bstrPrevName = NULL;
3361 SLTG_Variable *pItem;
3365 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3366 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3368 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3369 sizeof(**ppVarDesc));
3370 (*ppVarDesc)->vardesc.memid = pItem->memid;
3372 if (pItem->magic != SLTG_VAR_MAGIC &&
3373 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3374 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3378 if (pItem->name == 0xfffe)
3379 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3381 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3383 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3384 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3385 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3387 if(pItem->flags & 0x02)
3388 pType = &pItem->type;
3390 pType = (WORD*)(pBlk + pItem->type);
3392 if (pItem->flags & ~0xda)
3393 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3395 SLTG_DoElem(pType, pBlk,
3396 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3398 if (TRACE_ON(typelib)) {
3400 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3401 TRACE_(typelib)("elemdescVar: %s\n", buf);
3404 if (pItem->flags & 0x40) {
3405 TRACE_(typelib)("VAR_DISPATCH\n");
3406 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3408 else if (pItem->flags & 0x10) {
3409 TRACE_(typelib)("VAR_CONST\n");
3410 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3411 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3413 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3414 if (pItem->flags & 0x08)
3415 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3417 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3423 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3425 TRACE_(typelib)("len = %u\n", len);
3426 if (len == 0xffff) {
3429 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3430 str = SysAllocStringLen(NULL, alloc_len);
3431 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3433 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3434 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3443 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3444 *(INT*)(pBlk + pItem->byte_offs);
3447 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3452 TRACE_(typelib)("VAR_PERINSTANCE\n");
3453 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3454 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3457 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3458 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3460 if (pItem->flags & 0x80)
3461 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3463 bstrPrevName = (*ppVarDesc)->Name;
3464 ppVarDesc = &((*ppVarDesc)->next);
3466 pTI->TypeAttr.cVars = cVars;
3469 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3470 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3472 SLTG_Function *pFunc;
3474 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3476 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3477 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3482 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3483 sizeof(**ppFuncDesc));
3485 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3486 case SLTG_FUNCTION_MAGIC:
3487 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3489 case SLTG_DISPATCH_FUNCTION_MAGIC:
3490 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3492 case SLTG_STATIC_FUNCTION_MAGIC:
3493 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3496 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3497 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3501 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3503 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3504 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3505 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3506 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3507 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3508 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3510 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3511 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3513 if(pFunc->retnextopt & 0x80)
3514 pType = &pFunc->rettype;
3516 pType = (WORD*)(pBlk + pFunc->rettype);
3518 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3520 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3521 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3522 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3523 (*ppFuncDesc)->pParamDesc =
3524 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3525 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3527 pArg = (WORD*)(pBlk + pFunc->arg_off);
3529 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3530 char *paramName = pNameTable + *pArg;
3532 /* If arg type follows then paramName points to the 2nd
3533 letter of the name, else the next WORD is an offset to
3534 the arg type and paramName points to the first letter.
3535 So let's take one char off paramName and see if we're
3536 pointing at an alpha-numeric char. However if *pArg is
3537 0xffff or 0xfffe then the param has no name, the former
3538 meaning that the next WORD is the type, the latter
3539 meaning that the next WORD is an offset to the type. */
3544 else if(*pArg == 0xfffe) {
3548 else if(paramName[-1] && !isalnum(paramName[-1]))
3553 if(HaveOffs) { /* the next word is an offset to type */
3554 pType = (WORD*)(pBlk + *pArg);
3555 SLTG_DoElem(pType, pBlk,
3556 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3561 pArg = SLTG_DoElem(pArg, pBlk,
3562 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3565 /* Are we an optional param ? */
3566 if((*ppFuncDesc)->funcdesc.cParams - param <=
3567 (*ppFuncDesc)->funcdesc.cParamsOpt)
3568 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3571 (*ppFuncDesc)->pParamDesc[param].Name =
3572 TLB_MultiByteToBSTR(paramName);
3574 (*ppFuncDesc)->pParamDesc[param].Name =
3575 SysAllocString((*ppFuncDesc)->Name);
3579 ppFuncDesc = &((*ppFuncDesc)->next);
3580 if(pFunc->next == 0xffff) break;
3582 pTI->TypeAttr.cFuncs = cFuncs;
3585 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3586 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3587 SLTG_TypeInfoTail *pTITail)
3590 sltg_ref_lookup_t *ref_lookup = NULL;
3592 if(pTIHeader->href_table != 0xffffffff) {
3593 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3599 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3600 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3602 HeapFree(GetProcessHeap(), 0, ref_lookup);
3606 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3607 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3608 const SLTG_TypeInfoTail *pTITail)
3611 sltg_ref_lookup_t *ref_lookup = NULL;
3613 if(pTIHeader->href_table != 0xffffffff) {
3614 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3620 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3621 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3624 if (pTITail->funcs_off != 0xffff)
3625 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3627 HeapFree(GetProcessHeap(), 0, ref_lookup);
3629 if (TRACE_ON(typelib))
3630 dump_TLBFuncDesc(pTI->funclist);
3633 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3634 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3635 const SLTG_TypeInfoTail *pTITail)
3637 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3640 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3641 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3642 const SLTG_TypeInfoTail *pTITail)
3645 sltg_ref_lookup_t *ref_lookup = NULL;
3647 if (pTITail->simple_alias) {
3648 /* if simple alias, no more processing required */
3649 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3653 if(pTIHeader->href_table != 0xffffffff) {
3654 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3658 /* otherwise it is an offset to a type */
3659 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3661 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3663 HeapFree(GetProcessHeap(), 0, ref_lookup);
3666 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3667 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3668 const SLTG_TypeInfoTail *pTITail)
3670 sltg_ref_lookup_t *ref_lookup = NULL;
3671 if (pTIHeader->href_table != 0xffffffff)
3672 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3675 if (pTITail->vars_off != 0xffff)
3676 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3678 if (pTITail->funcs_off != 0xffff)
3679 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3681 if (pTITail->impls_off != 0xffff)
3682 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3684 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3685 * of dispinterface functions including the IDispatch ones, so
3686 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3687 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3689 HeapFree(GetProcessHeap(), 0, ref_lookup);
3690 if (TRACE_ON(typelib))
3691 dump_TLBFuncDesc(pTI->funclist);
3694 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3695 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3696 const SLTG_TypeInfoTail *pTITail)
3698 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3701 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3702 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3703 const SLTG_TypeInfoTail *pTITail)
3705 sltg_ref_lookup_t *ref_lookup = NULL;
3706 if (pTIHeader->href_table != 0xffffffff)
3707 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3710 if (pTITail->vars_off != 0xffff)
3711 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3713 if (pTITail->funcs_off != 0xffff)
3714 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3715 HeapFree(GetProcessHeap(), 0, ref_lookup);
3716 if (TRACE_ON(typelib))
3720 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3721 managable copy of it into this */
3734 } SLTG_InternalOtherTypeInfo;
3736 /****************************************************************************
3737 * ITypeLib2_Constructor_SLTG
3739 * loading a SLTG typelib from an in-memory image
3741 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3743 ITypeLibImpl *pTypeLibImpl;
3744 SLTG_Header *pHeader;
3745 SLTG_BlkEntry *pBlkEntry;
3749 LPVOID pBlk, pFirstBlk;
3750 SLTG_LibBlk *pLibBlk;
3751 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3752 char *pAfterOTIBlks = NULL;
3753 char *pNameTable, *ptr;
3756 ITypeInfoImpl **ppTypeInfoImpl;
3758 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3761 pTypeLibImpl = TypeLibImpl_Constructor();
3762 if (!pTypeLibImpl) return NULL;
3766 TRACE_(typelib)("header:\n");
3767 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3768 pHeader->nrOfFileBlks );
3769 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3770 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3771 pHeader->SLTG_magic);
3775 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3776 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3778 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3779 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3781 /* Next we have a magic block */
3782 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3784 /* Let's see if we're still in sync */
3785 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3786 sizeof(SLTG_COMPOBJ_MAGIC))) {
3787 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3790 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3791 sizeof(SLTG_DIR_MAGIC))) {
3792 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3796 pIndex = (SLTG_Index*)(pMagic+1);
3798 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3800 pFirstBlk = pPad9 + 1;
3802 /* We'll set up a ptr to the main library block, which is the last one. */
3804 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3805 pBlkEntry[order].next != 0;
3806 order = pBlkEntry[order].next - 1, i++) {
3807 pBlk = (char*)pBlk + pBlkEntry[order].len;
3811 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3813 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3818 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3820 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3821 sizeof(*pOtherTypeInfoBlks) *
3822 pTypeLibImpl->TypeInfoCount);
3825 ptr = (char*)pLibBlk + len;
3827 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3831 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3833 w = *(WORD*)(ptr + 2);
3836 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3838 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3839 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3841 w = *(WORD*)(ptr + 4 + len);
3843 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3845 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3847 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3848 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3850 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3851 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3852 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3854 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3856 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3859 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3860 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3861 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3862 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3863 len += sizeof(SLTG_OtherTypeInfo);
3867 pAfterOTIBlks = ptr;
3869 /* Skip this WORD and get the next DWORD */
3870 len = *(DWORD*)(pAfterOTIBlks + 2);
3872 /* Now add this to pLibBLk look at what we're pointing at and
3873 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3874 dust and we should be pointing at the beginning of the name
3877 pNameTable = (char*)pLibBlk + len;
3879 switch(*(WORD*)pNameTable) {
3886 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3890 pNameTable += 0x216;
3894 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3896 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3899 /* Hopefully we now have enough ptrs set up to actually read in
3900 some TypeInfos. It's not clear which order to do them in, so
3901 I'll just follow the links along the BlkEntry chain and read
3902 them in the order in which they are in the file */
3904 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3906 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3907 pBlkEntry[order].next != 0;
3908 order = pBlkEntry[order].next - 1, i++) {
3910 SLTG_TypeInfoHeader *pTIHeader;
3911 SLTG_TypeInfoTail *pTITail;
3912 SLTG_MemberHeader *pMemHeader;
3914 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3915 pOtherTypeInfoBlks[i].index_name)) {
3916 FIXME_(typelib)("Index strings don't match\n");
3921 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3922 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3925 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3926 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3927 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3929 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3930 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3931 (*ppTypeInfoImpl)->index = i;
3932 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3933 pOtherTypeInfoBlks[i].name_offs +
3935 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3936 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3937 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3938 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3939 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3940 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3941 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3943 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3944 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3946 if((pTIHeader->typeflags1 & 7) != 2)
3947 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3948 if(pTIHeader->typeflags3 != 2)
3949 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3951 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3952 debugstr_w((*ppTypeInfoImpl)->Name),
3953 typekind_desc[pTIHeader->typekind],
3954 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3955 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3957 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3959 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3961 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3962 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3963 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3965 switch(pTIHeader->typekind) {
3967 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3968 pTIHeader, pTITail);
3972 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3973 pTIHeader, pTITail);
3976 case TKIND_INTERFACE:
3977 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3978 pTIHeader, pTITail);
3982 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3983 pTIHeader, pTITail);
3987 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3988 pTIHeader, pTITail);
3991 case TKIND_DISPATCH:
3992 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3993 pTIHeader, pTITail);
3997 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3998 pTIHeader, pTITail);
4002 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4007 /* could get cFuncs, cVars and cImplTypes from here
4008 but we've already set those */
4009 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4024 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4025 pBlk = (char*)pBlk + pBlkEntry[order].len;
4028 if(i != pTypeLibImpl->TypeInfoCount) {
4029 FIXME("Somehow processed %d TypeInfos\n", i);
4033 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4034 return (ITypeLib2*)pTypeLibImpl;
4037 /* ITypeLib::QueryInterface
4039 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4044 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4046 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4049 if(IsEqualIID(riid, &IID_IUnknown) ||
4050 IsEqualIID(riid,&IID_ITypeLib)||
4051 IsEqualIID(riid,&IID_ITypeLib2))
4058 ITypeLib2_AddRef(iface);
4059 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4062 TRACE("-- Interface: E_NOINTERFACE\n");
4063 return E_NOINTERFACE;
4068 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4070 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4071 ULONG ref = InterlockedIncrement(&This->ref);
4073 TRACE("(%p)->ref was %u\n",This, ref - 1);
4078 /* ITypeLib::Release
4080 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4082 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4083 ULONG ref = InterlockedDecrement(&This->ref);
4085 TRACE("(%p)->(%u)\n",This, ref);
4089 TLBImpLib *pImpLib, *pImpLibNext;
4090 TLBCustData *pCustData, *pCustDataNext;
4091 TLBRefType *ref_type;
4094 ITypeInfoImpl *pTI, *pTINext;
4096 /* remove cache entry */
4099 TRACE("removing from cache list\n");
4100 EnterCriticalSection(&cache_section);
4101 if (This->next) This->next->prev = This->prev;
4102 if (This->prev) This->prev->next = This->next;
4103 else tlb_cache_first = This->next;
4104 LeaveCriticalSection(&cache_section);
4105 HeapFree(GetProcessHeap(), 0, This->path);
4107 TRACE(" destroying ITypeLib(%p)\n",This);
4109 SysFreeString(This->Name);
4112 SysFreeString(This->DocString);
4113 This->DocString = NULL;
4115 SysFreeString(This->HelpFile);
4116 This->HelpFile = NULL;
4118 SysFreeString(This->HelpStringDll);
4119 This->HelpStringDll = NULL;
4121 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4123 VariantClear(&pCustData->data);
4125 pCustDataNext = pCustData->next;
4126 TLB_Free(pCustData);
4129 for (i = 0; i < This->ctTypeDesc; i++)
4130 if (This->pTypeDesc[i].vt == VT_CARRAY)
4131 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4133 TLB_Free(This->pTypeDesc);
4135 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4137 if (pImpLib->pImpTypeLib)
4138 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4139 SysFreeString(pImpLib->name);
4141 pImpLibNext = pImpLib->next;
4145 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4147 list_remove(&ref_type->entry);
4151 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4153 pTINext = pTI->next;
4154 ITypeInfo_fnDestroy(pTI);
4156 HeapFree(GetProcessHeap(),0,This);
4163 /* ITypeLib::GetTypeInfoCount
4165 * Returns the number of type descriptions in the type library
4167 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4169 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4170 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4171 return This->TypeInfoCount;
4174 /* ITypeLib::GetTypeInfo
4176 * retrieves the specified type description in the library.
4178 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4181 ITypeInfo **ppTInfo)
4185 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4186 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4188 TRACE("(%p)->(index=%d)\n", This, index);
4190 if (!ppTInfo) return E_INVALIDARG;
4192 /* search element n in list */
4193 for(i=0; i < index; i++)
4195 pTypeInfo = pTypeInfo->next;
4198 TRACE("-- element not found\n");
4199 return TYPE_E_ELEMENTNOTFOUND;
4203 *ppTInfo = (ITypeInfo *) pTypeInfo;
4205 ITypeInfo_AddRef(*ppTInfo);
4206 TRACE("-- found (%p)\n",*ppTInfo);
4211 /* ITypeLibs::GetTypeInfoType
4213 * Retrieves the type of a type description.
4215 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4220 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4222 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4224 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4225 return TYPE_E_ELEMENTNOTFOUND;
4227 TRACE("(%p) index %d\n", This, index);
4229 if(!pTKind) return E_INVALIDARG;
4231 /* search element n in list */
4232 for(i=0; i < index; i++)
4236 TRACE("-- element not found\n");
4237 return TYPE_E_ELEMENTNOTFOUND;
4239 pTInfo = pTInfo->next;
4242 *pTKind = pTInfo->TypeAttr.typekind;
4243 TRACE("-- found Type (%d)\n", *pTKind);
4247 /* ITypeLib::GetTypeInfoOfGuid
4249 * Retrieves the type description that corresponds to the specified GUID.
4252 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4255 ITypeInfo **ppTInfo)
4257 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4258 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4260 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4264 WARN("-- element not found\n");
4265 return TYPE_E_ELEMENTNOTFOUND;
4268 /* search linked list for guid */
4269 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4271 pTypeInfo = pTypeInfo->next;
4275 /* end of list reached */
4276 WARN("-- element not found\n");
4277 return TYPE_E_ELEMENTNOTFOUND;
4281 TRACE("-- found (%p, %s)\n",
4283 debugstr_w(pTypeInfo->Name));
4285 *ppTInfo = (ITypeInfo*)pTypeInfo;
4286 ITypeInfo_AddRef(*ppTInfo);
4290 /* ITypeLib::GetLibAttr
4292 * Retrieves the structure that contains the library's attributes.
4295 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4297 LPTLIBATTR *ppTLibAttr)
4299 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4300 TRACE("(%p)\n",This);
4301 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4302 **ppTLibAttr = This->LibAttr;
4306 /* ITypeLib::GetTypeComp
4308 * Enables a client compiler to bind to a library's types, variables,
4309 * constants, and global functions.
4312 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4314 ITypeComp **ppTComp)
4316 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4318 TRACE("(%p)->(%p)\n",This,ppTComp);
4319 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4320 ITypeComp_AddRef(*ppTComp);
4325 /* ITypeLib::GetDocumentation
4327 * Retrieves the library's documentation string, the complete Help file name
4328 * and path, and the context identifier for the library Help topic in the Help
4331 * On a successful return all non-null BSTR pointers will have been set,
4334 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4338 BSTR *pBstrDocString,
4339 DWORD *pdwHelpContext,
4340 BSTR *pBstrHelpFile)
4342 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4344 HRESULT result = E_INVALIDARG;
4349 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4351 pBstrName, pBstrDocString,
4352 pdwHelpContext, pBstrHelpFile);
4356 /* documentation for the typelib */
4361 if(!(*pBstrName = SysAllocString(This->Name)))
4369 if (This->DocString)
4371 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4374 else if (This->Name)
4376 if(!(*pBstrDocString = SysAllocString(This->Name)))
4380 *pBstrDocString = NULL;
4384 *pdwHelpContext = This->dwHelpContext;
4390 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4394 *pBstrHelpFile = NULL;
4401 /* for a typeinfo */
4402 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4404 if(SUCCEEDED(result))
4406 result = ITypeInfo_GetDocumentation(pTInfo,
4410 pdwHelpContext, pBstrHelpFile);
4412 ITypeInfo_Release(pTInfo);
4417 if (pBstrDocString) SysFreeString (*pBstrDocString);
4419 if (pBstrName) SysFreeString (*pBstrName);
4421 return STG_E_INSUFFICIENTMEMORY;
4426 * Indicates whether a passed-in string contains the name of a type or member
4427 * described in the library.
4430 static HRESULT WINAPI ITypeLib2_fnIsName(
4436 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4437 ITypeInfoImpl *pTInfo;
4438 TLBFuncDesc *pFInfo;
4441 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4443 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4447 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4448 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4449 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4450 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4451 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4452 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4453 goto ITypeLib2_fnIsName_exit;
4455 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4456 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4461 ITypeLib2_fnIsName_exit:
4462 TRACE("(%p)slow! search for %s: %s found!\n", This,
4463 debugstr_w(szNameBuf), *pfName?"NOT":"");
4468 /* ITypeLib::FindName
4470 * Finds occurrences of a type description in a type library. This may be used
4471 * to quickly verify that a name exists in a type library.
4474 static HRESULT WINAPI ITypeLib2_fnFindName(
4478 ITypeInfo **ppTInfo,
4482 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4483 ITypeInfoImpl *pTInfo;
4484 TLBFuncDesc *pFInfo;
4487 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4489 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4490 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4491 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4492 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4493 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4494 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4495 goto ITypeLib2_fnFindName_exit;
4498 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4499 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4501 ITypeLib2_fnFindName_exit:
4502 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4503 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4506 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4507 This, *pcFound, debugstr_w(szNameBuf), j);
4514 /* ITypeLib::ReleaseTLibAttr
4516 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4519 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4521 TLIBATTR *pTLibAttr)
4523 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4524 TRACE("freeing (%p)\n",This);
4525 HeapFree(GetProcessHeap(),0,pTLibAttr);
4529 /* ITypeLib2::GetCustData
4531 * gets the custom data
4533 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4538 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4539 TLBCustData *pCData;
4541 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4543 if( IsEqualIID(guid, &pCData->guid)) break;
4546 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4550 VariantInit( pVarVal);
4551 VariantCopy( pVarVal, &pCData->data);
4554 return E_INVALIDARG; /* FIXME: correct? */
4557 /* ITypeLib2::GetLibStatistics
4559 * Returns statistics about a type library that are required for efficient
4560 * sizing of hash tables.
4563 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4565 ULONG *pcUniqueNames,
4566 ULONG *pcchUniqueNames)
4568 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4570 FIXME("(%p): stub!\n", This);
4572 if(pcUniqueNames) *pcUniqueNames=1;
4573 if(pcchUniqueNames) *pcchUniqueNames=1;
4577 /* ITypeLib2::GetDocumentation2
4579 * Retrieves the library's documentation string, the complete Help file name
4580 * and path, the localization context to use, and the context ID for the
4581 * library Help topic in the Help file.
4584 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4588 BSTR *pbstrHelpString,
4589 DWORD *pdwHelpStringContext,
4590 BSTR *pbstrHelpStringDll)
4592 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4596 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4598 /* the help string should be obtained from the helpstringdll,
4599 * using the _DLLGetDocumentation function, based on the supplied
4600 * lcid. Nice to do sometime...
4604 /* documentation for the typelib */
4606 *pbstrHelpString=SysAllocString(This->DocString);
4607 if(pdwHelpStringContext)
4608 *pdwHelpStringContext=This->dwHelpContext;
4609 if(pbstrHelpStringDll)
4610 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4616 /* for a typeinfo */
4617 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4619 if(SUCCEEDED(result))
4621 ITypeInfo2 * pTInfo2;
4622 result = ITypeInfo_QueryInterface(pTInfo,
4624 (LPVOID*) &pTInfo2);
4626 if(SUCCEEDED(result))
4628 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4632 pdwHelpStringContext,
4633 pbstrHelpStringDll);
4635 ITypeInfo2_Release(pTInfo2);
4638 ITypeInfo_Release(pTInfo);
4644 /* ITypeLib2::GetAllCustData
4646 * Gets all custom data items for the library.
4649 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4651 CUSTDATA *pCustData)
4653 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4654 TLBCustData *pCData;
4656 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4657 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4658 if(pCustData->prgCustData ){
4659 pCustData->cCustData=This->ctCustData;
4660 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4661 pCustData->prgCustData[i].guid=pCData->guid;
4662 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4665 ERR(" OUT OF MEMORY!\n");
4666 return E_OUTOFMEMORY;
4671 static const ITypeLib2Vtbl tlbvt = {
4672 ITypeLib2_fnQueryInterface,
4674 ITypeLib2_fnRelease,
4675 ITypeLib2_fnGetTypeInfoCount,
4676 ITypeLib2_fnGetTypeInfo,
4677 ITypeLib2_fnGetTypeInfoType,
4678 ITypeLib2_fnGetTypeInfoOfGuid,
4679 ITypeLib2_fnGetLibAttr,
4680 ITypeLib2_fnGetTypeComp,
4681 ITypeLib2_fnGetDocumentation,
4683 ITypeLib2_fnFindName,
4684 ITypeLib2_fnReleaseTLibAttr,
4686 ITypeLib2_fnGetCustData,
4687 ITypeLib2_fnGetLibStatistics,
4688 ITypeLib2_fnGetDocumentation2,
4689 ITypeLib2_fnGetAllCustData
4693 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4695 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4697 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4700 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4702 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4704 return ITypeLib2_AddRef((ITypeLib2 *)This);
4707 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4709 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4711 return ITypeLib2_Release((ITypeLib2 *)This);
4714 static HRESULT WINAPI ITypeLibComp_fnBind(
4719 ITypeInfo ** ppTInfo,
4720 DESCKIND * pDescKind,
4723 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4724 ITypeInfoImpl *pTypeInfo;
4726 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4728 *pDescKind = DESCKIND_NONE;
4729 pBindPtr->lptcomp = NULL;
4732 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4734 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4736 /* FIXME: check wFlags here? */
4737 /* FIXME: we should use a hash table to look this info up using lHash
4738 * instead of an O(n) search */
4739 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4740 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4742 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4744 *pDescKind = DESCKIND_TYPECOMP;
4745 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4746 ITypeComp_AddRef(pBindPtr->lptcomp);
4747 TRACE("module or enum: %s\n", debugstr_w(szName));
4752 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4753 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4755 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4758 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4759 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4761 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4766 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4767 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4769 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4771 ITypeInfo *subtypeinfo;
4773 DESCKIND subdesckind;
4775 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4776 &subtypeinfo, &subdesckind, &subbindptr);
4777 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4779 TYPEDESC tdesc_appobject =
4782 (TYPEDESC *)pTypeInfo->hreftype
4786 const VARDESC vardesc_appobject =
4789 NULL, /* lpstrSchema */
4804 VAR_STATIC /* varkind */
4807 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4809 /* cleanup things filled in by Bind call so we can put our
4810 * application object data in there instead */
4811 switch (subdesckind)
4813 case DESCKIND_FUNCDESC:
4814 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4816 case DESCKIND_VARDESC:
4817 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4822 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4824 if (pTypeInfo->hreftype == -1)
4825 FIXME("no hreftype for interface %p\n", pTypeInfo);
4827 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4831 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4832 *ppTInfo = (ITypeInfo *)pTypeInfo;
4833 ITypeInfo_AddRef(*ppTInfo);
4839 TRACE("name not found %s\n", debugstr_w(szName));
4843 static HRESULT WINAPI ITypeLibComp_fnBindType(
4847 ITypeInfo ** ppTInfo,
4848 ITypeComp ** ppTComp)
4850 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4851 ITypeInfoImpl *pTypeInfo;
4853 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4855 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4857 /* FIXME: should use lHash to do the search */
4858 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4860 TRACE("returning %p\n", pTypeInfo);
4861 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4862 ITypeInfo_AddRef(*ppTInfo);
4863 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4864 ITypeComp_AddRef(*ppTComp);
4869 TRACE("not found\n");
4875 static const ITypeCompVtbl tlbtcvt =
4878 ITypeLibComp_fnQueryInterface,
4879 ITypeLibComp_fnAddRef,
4880 ITypeLibComp_fnRelease,
4882 ITypeLibComp_fnBind,
4883 ITypeLibComp_fnBindType
4886 /*================== ITypeInfo(2) Methods ===================================*/
4887 static ITypeInfo2 * ITypeInfo_Constructor(void)
4889 ITypeInfoImpl * pTypeInfoImpl;
4891 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4894 pTypeInfoImpl->lpVtbl = &tinfvt;
4895 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4896 pTypeInfoImpl->ref = 0;
4897 pTypeInfoImpl->hreftype = -1;
4898 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4899 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4901 TRACE("(%p)\n", pTypeInfoImpl);
4902 return (ITypeInfo2*) pTypeInfoImpl;
4905 /* ITypeInfo::QueryInterface
4907 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4912 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4914 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4917 if(IsEqualIID(riid, &IID_IUnknown) ||
4918 IsEqualIID(riid,&IID_ITypeInfo)||
4919 IsEqualIID(riid,&IID_ITypeInfo2))
4923 ITypeInfo_AddRef(iface);
4924 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4927 TRACE("-- Interface: E_NOINTERFACE\n");
4928 return E_NOINTERFACE;
4931 /* ITypeInfo::AddRef
4933 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4935 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4936 ULONG ref = InterlockedIncrement(&This->ref);
4938 TRACE("(%p)->ref is %u\n",This, ref);
4940 if (ref == 1 /* incremented from 0 */)
4941 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4946 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This)
4948 TLBFuncDesc *pFInfo, *pFInfoNext;
4949 TLBVarDesc *pVInfo, *pVInfoNext;
4950 TLBImplType *pImpl, *pImplNext;
4952 TRACE("destroying ITypeInfo(%p)\n",This);
4954 SysFreeString(This->Name);
4957 SysFreeString(This->DocString);
4958 This->DocString = NULL;
4960 SysFreeString(This->DllName);
4961 This->DllName = NULL;
4963 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4966 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4968 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4969 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4971 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4972 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4974 SysFreeString(pFInfo->pParamDesc[i].Name);
4976 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4977 TLB_Free(pFInfo->pParamDesc);
4978 TLB_FreeCustData(pFInfo->pCustData);
4979 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
4980 SysFreeString(pFInfo->Entry);
4981 SysFreeString(pFInfo->HelpString);
4982 SysFreeString(pFInfo->Name);
4984 pFInfoNext = pFInfo->next;
4987 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4989 if (pVInfo->vardesc.varkind == VAR_CONST)
4991 VariantClear(pVInfo->vardesc.u.lpvarValue);
4992 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4994 TLB_FreeCustData(pVInfo->pCustData);
4995 SysFreeString(pVInfo->Name);
4996 pVInfoNext = pVInfo->next;
4999 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5001 TLB_FreeCustData(pImpl->pCustData);
5002 pImplNext = pImpl->next;
5005 TLB_FreeCustData(This->pCustData);
5007 HeapFree(GetProcessHeap(), 0, This);
5010 /* ITypeInfo::Release
5012 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5014 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5015 ULONG ref = InterlockedDecrement(&This->ref);
5017 TRACE("(%p)->(%u)\n",This, ref);
5021 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5022 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5023 if (not_attached_to_typelib)
5024 HeapFree(GetProcessHeap(), 0, This);
5025 /* otherwise This will be freed when typelib is freed */
5031 /* ITypeInfo::GetTypeAttr
5033 * Retrieves a TYPEATTR structure that contains the attributes of the type
5037 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5038 LPTYPEATTR *ppTypeAttr)
5040 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5043 TRACE("(%p)\n",This);
5045 size = sizeof(**ppTypeAttr);
5046 if (This->TypeAttr.typekind == TKIND_ALIAS)
5047 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5049 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5051 return E_OUTOFMEMORY;
5053 **ppTypeAttr = This->TypeAttr;
5055 if (This->TypeAttr.typekind == TKIND_ALIAS)
5056 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5057 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5059 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5060 /* This should include all the inherited funcs */
5061 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5062 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5063 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5068 /* ITypeInfo::GetTypeComp
5070 * Retrieves the ITypeComp interface for the type description, which enables a
5071 * client compiler to bind to the type description's members.
5074 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5075 ITypeComp * *ppTComp)
5077 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5079 TRACE("(%p)->(%p)\n", This, ppTComp);
5081 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5082 ITypeComp_AddRef(*ppTComp);
5086 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5088 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5089 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5090 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5094 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5097 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5098 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5100 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5101 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5102 *buffer += sizeof(PARAMDESCEX);
5103 *pparamdescex_dest = *pparamdescex_src;
5104 VariantInit(&pparamdescex_dest->varDefaultValue);
5105 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5106 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5109 dest->u.paramdesc.pparamdescex = NULL;
5113 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5115 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5116 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5119 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5123 SIZE_T size = sizeof(*src);
5127 size += sizeof(*src->lprgscode) * src->cScodes;
5128 size += TLB_SizeElemDesc(&src->elemdescFunc);
5129 for (i = 0; i < src->cParams; i++)
5131 size += sizeof(ELEMDESC);
5132 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5135 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5136 if (!dest) return E_OUTOFMEMORY;
5139 if (dispinterface) /* overwrite funckind */
5140 dest->funckind = FUNC_DISPATCH;
5141 buffer = (char *)(dest + 1);
5143 dest->lprgscode = (SCODE *)buffer;
5144 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5145 buffer += sizeof(*src->lprgscode) * src->cScodes;
5147 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5150 SysFreeString((BSTR)dest);
5154 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5155 buffer += sizeof(ELEMDESC) * src->cParams;
5156 for (i = 0; i < src->cParams; i++)
5158 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5164 /* undo the above actions */
5165 for (i = i - 1; i >= 0; i--)
5166 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5167 TLB_FreeElemDesc(&dest->elemdescFunc);
5168 SysFreeString((BSTR)dest);
5172 /* special treatment for dispinterfaces: this makes functions appear
5173 * to return their [retval] value when it is really returning an
5175 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5177 if (dest->cParams &&
5178 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5180 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5181 if (elemdesc->tdesc.vt != VT_PTR)
5183 ERR("elemdesc should have started with VT_PTR instead of:\n");
5185 dump_ELEMDESC(elemdesc);
5186 return E_UNEXPECTED;
5189 /* copy last parameter to the return value. we are using a flat
5190 * buffer so there is no danger of leaking memory in
5192 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5194 /* remove the last parameter */
5198 /* otherwise this function is made to appear to have no return
5200 dest->elemdescFunc.tdesc.vt = VT_VOID;
5208 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5210 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5211 const TLBFuncDesc *pFDesc;
5214 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5219 *ppFuncDesc = &pFDesc->funcdesc;
5223 return TYPE_E_ELEMENTNOTFOUND;
5226 /* internal function to make the inherited interfaces' methods appear
5227 * part of the interface */
5228 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5229 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5231 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5233 UINT implemented_funcs = 0;
5238 *hrefoffset = DISPATCH_HREF_OFFSET;
5240 if(This->impltypelist)
5242 ITypeInfo *pSubTypeInfo;
5245 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5249 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5252 &sub_funcs, hrefoffset);
5253 implemented_funcs += sub_funcs;
5254 ITypeInfo_Release(pSubTypeInfo);
5257 *hrefoffset += DISPATCH_HREF_OFFSET;
5261 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5265 if (index < implemented_funcs)
5266 return E_INVALIDARG;
5267 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5271 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5273 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5276 switch (pTypeDesc->vt)
5278 case VT_USERDEFINED:
5279 pTypeDesc->u.hreftype += hrefoffset;
5283 pTypeDesc = pTypeDesc->u.lptdesc;
5286 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5294 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5297 for (i = 0; i < pFuncDesc->cParams; i++)
5298 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5299 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5302 /* ITypeInfo::GetFuncDesc
5304 * Retrieves the FUNCDESC structure that contains information about a
5305 * specified function.
5308 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5309 LPFUNCDESC *ppFuncDesc)
5311 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5312 const FUNCDESC *internal_funcdesc;
5314 UINT hrefoffset = 0;
5316 TRACE("(%p) index %d\n", This, index);
5318 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5319 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5320 &internal_funcdesc, NULL,
5323 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5324 &internal_funcdesc);
5327 WARN("description for function %d not found\n", index);
5331 hr = TLB_AllocAndInitFuncDesc(
5334 This->TypeAttr.typekind == TKIND_DISPATCH);
5336 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5337 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5339 TRACE("-- 0x%08x\n", hr);
5343 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5347 SIZE_T size = sizeof(*src);
5350 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5351 if (src->varkind == VAR_CONST)
5352 size += sizeof(VARIANT);
5353 size += TLB_SizeElemDesc(&src->elemdescVar);
5355 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5356 if (!dest) return E_OUTOFMEMORY;
5359 buffer = (char *)(dest + 1);
5360 if (src->lpstrSchema)
5363 dest->lpstrSchema = (LPOLESTR)buffer;
5364 len = strlenW(src->lpstrSchema);
5365 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5366 buffer += (len + 1) * sizeof(WCHAR);
5369 if (src->varkind == VAR_CONST)
5373 dest->u.lpvarValue = (VARIANT *)buffer;
5374 *dest->u.lpvarValue = *src->u.lpvarValue;
5375 buffer += sizeof(VARIANT);
5376 VariantInit(dest->u.lpvarValue);
5377 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5380 SysFreeString((BSTR)dest);
5384 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5387 if (src->varkind == VAR_CONST)
5388 VariantClear(dest->u.lpvarValue);
5389 SysFreeString((BSTR)dest);
5396 /* ITypeInfo::GetVarDesc
5398 * Retrieves a VARDESC structure that describes the specified variable.
5401 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5402 LPVARDESC *ppVarDesc)
5404 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5406 const TLBVarDesc *pVDesc;
5408 TRACE("(%p) index %d\n", This, index);
5410 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5414 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5416 return E_INVALIDARG;
5419 /* ITypeInfo_GetNames
5421 * Retrieves the variable with the specified member ID (or the name of the
5422 * property or method and its parameters) that correspond to the specified
5425 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5426 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5428 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5429 const TLBFuncDesc *pFDesc;
5430 const TLBVarDesc *pVDesc;
5432 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5433 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5436 /* function found, now return function and parameter names */
5437 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5440 *rgBstrNames=SysAllocString(pFDesc->Name);
5442 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5448 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5451 *rgBstrNames=SysAllocString(pVDesc->Name);
5456 if(This->impltypelist &&
5457 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5458 /* recursive search */
5461 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5463 if(SUCCEEDED(result))
5465 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5466 ITypeInfo_Release(pTInfo);
5469 WARN("Could not search inherited interface!\n");
5473 WARN("no names found\n");
5476 return TYPE_E_ELEMENTNOTFOUND;
5483 /* ITypeInfo::GetRefTypeOfImplType
5485 * If a type description describes a COM class, it retrieves the type
5486 * description of the implemented interface types. For an interface,
5487 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5491 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5496 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5499 const TLBImplType *pImpl = This->impltypelist;
5501 TRACE("(%p) index %d\n", This, index);
5502 if (TRACE_ON(ole)) dump_TypeInfo(This);
5506 /* only valid on dual interfaces;
5507 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5509 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5511 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5517 hr = TYPE_E_ELEMENTNOTFOUND;
5520 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5522 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5523 *pRefType = This->pTypeLib->dispatch_href;
5527 /* get element n from linked list */
5528 for(i=0; pImpl && i<index; i++)
5530 pImpl = pImpl->next;
5534 *pRefType = pImpl->hRef;
5536 hr = TYPE_E_ELEMENTNOTFOUND;
5542 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5544 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5550 /* ITypeInfo::GetImplTypeFlags
5552 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5553 * or base interface in a type description.
5555 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5556 UINT index, INT *pImplTypeFlags)
5558 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5562 TRACE("(%p) index %d\n", This, index);
5563 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5564 i++, pImpl=pImpl->next)
5566 if(i==index && pImpl){
5567 *pImplTypeFlags=pImpl->implflags;
5571 return TYPE_E_ELEMENTNOTFOUND;
5575 * Maps between member names and member IDs, and parameter names and
5578 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5579 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5581 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5582 const TLBFuncDesc *pFDesc;
5583 const TLBVarDesc *pVDesc;
5587 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5590 /* init out parameters in case of failure */
5591 for (i = 0; i < cNames; i++)
5592 pMemId[i] = MEMBERID_NIL;
5594 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5596 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5597 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5598 for(i=1; i < cNames; i++){
5599 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5600 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5602 if( j<pFDesc->funcdesc.cParams)
5605 ret=DISP_E_UNKNOWNNAME;
5607 TRACE("-- 0x%08x\n", ret);
5611 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5612 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5613 if(cNames) *pMemId=pVDesc->vardesc.memid;
5617 /* not found, see if it can be found in an inherited interface */
5618 if(This->impltypelist) {
5619 /* recursive search */
5621 ret=ITypeInfo_GetRefTypeInfo(iface,
5622 This->impltypelist->hRef, &pTInfo);
5624 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5625 ITypeInfo_Release(pTInfo);
5628 WARN("Could not search inherited interface!\n");
5630 WARN("no names found\n");
5631 return DISP_E_UNKNOWNNAME;
5637 extern DWORD CDECL call_method( void *func, int nb_args, const DWORD *args );
5638 __ASM_GLOBAL_FUNC( call_method,
5640 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5641 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5642 "movl %esp,%ebp\n\t"
5643 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5645 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5647 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5648 "movl 12(%ebp),%edx\n\t"
5651 "subl %edx,%esp\n\t"
5652 "andl $~15,%esp\n\t"
5653 "movl 12(%ebp),%ecx\n\t"
5654 "movl 16(%ebp),%esi\n\t"
5655 "movl %esp,%edi\n\t"
5658 "1:\tcall *8(%ebp)\n\t"
5659 "leal -8(%ebp),%esp\n\t"
5661 __ASM_CFI(".cfi_same_value %edi\n\t")
5663 __ASM_CFI(".cfi_same_value %esi\n\t")
5665 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5666 __ASM_CFI(".cfi_same_value %ebp\n\t")
5669 /* ITypeInfo::Invoke
5671 * Invokes a method, or accesses a property of an object, that implements the
5672 * interface described by the type description.
5675 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5678 if (TRACE_ON(ole)) {
5680 TRACE("Calling %p(",func);
5681 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5688 res = call_method( func, nrargs, args );
5691 FIXME("unsupported calling convention %d\n",callconv);
5695 TRACE("returns %08x\n",res);
5699 /* The size of the argument on the stack in DWORD units (in all x86 call
5700 * convetions the arguments on the stack are DWORD-aligned)
5702 static int _dispargsize(VARTYPE vt)
5707 return 8/sizeof(DWORD);
5709 return sizeof(double)/sizeof(DWORD);
5711 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5713 return sizeof(CY)/sizeof(DWORD);
5715 return sizeof(DATE)/sizeof(DWORD);
5717 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5719 FIXME("VT_RECORD not implemented\n");
5725 #endif /* __i386__ */
5727 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5730 ITypeInfo *tinfo2 = NULL;
5731 TYPEATTR *tattr = NULL;
5733 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5736 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5738 tdesc->u.hreftype, hr);
5741 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5744 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5745 ITypeInfo_Release(tinfo2);
5749 switch (tattr->typekind)
5756 tdesc = &tattr->tdescAlias;
5757 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5760 case TKIND_INTERFACE:
5761 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5767 case TKIND_DISPATCH:
5776 FIXME("TKIND_RECORD unhandled.\n");
5781 FIXME("TKIND_UNION unhandled.\n");
5786 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5790 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5791 ITypeInfo_Release(tinfo2);
5795 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5799 /* enforce only one level of pointer indirection */
5800 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5802 tdesc = tdesc->u.lptdesc;
5804 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5805 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5806 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5807 if ((tdesc->vt == VT_USERDEFINED) ||
5808 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5810 VARTYPE vt_userdefined = 0;
5811 const TYPEDESC *tdesc_userdefined = tdesc;
5812 if (tdesc->vt == VT_PTR)
5814 vt_userdefined = VT_BYREF;
5815 tdesc_userdefined = tdesc->u.lptdesc;
5817 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5819 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5820 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5822 *vt |= vt_userdefined;
5834 case VT_USERDEFINED:
5835 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5842 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5843 hr = DISP_E_BADVARTYPE;
5847 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5862 /***********************************************************************
5863 * DispCallFunc (OLEAUT32.@)
5865 * Invokes a function of the specified calling convention, passing the
5866 * specified arguments and returns the result.
5869 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5870 * oVft [I] The offset in the vtable. See notes.
5871 * cc [I] Calling convention of the function to call.
5872 * vtReturn [I] The return type of the function.
5873 * cActuals [I] Number of parameters.
5874 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5875 * prgpvarg [I] The arguments to pass.
5876 * pvargResult [O] The return value of the function. Can be NULL.
5880 * Failure: HRESULT code.
5883 * The HRESULT return value of this function is not affected by the return
5884 * value of the user supplied function, which is returned in pvargResult.
5886 * If pvInstance is NULL then a non-object function is to be called and oVft
5887 * is the address of the function to call.
5889 * The cc parameter can be one of the following values:
5902 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5903 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5906 int argsize, argspos;
5911 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5912 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5913 pvargResult, V_VT(pvargResult));
5917 argsize++; /* for This pointer */
5919 for (i=0;i<cActuals;i++)
5921 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5922 dump_Variant(prgpvarg[i]);
5923 argsize += _dispargsize(prgvt[i]);
5925 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5930 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5934 for (i=0;i<cActuals;i++)
5936 VARIANT *arg = prgpvarg[i];
5937 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5938 if (prgvt[i] == VT_VARIANT)
5939 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5941 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5942 argspos += _dispargsize(prgvt[i]);
5947 FARPROC *vtable = *(FARPROC**)pvInstance;
5948 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5951 /* if we aren't invoking an object then the function pointer is stored
5953 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5955 if (pvargResult && (vtReturn != VT_EMPTY))
5957 TRACE("Method returned 0x%08x\n",hres);
5958 V_VT(pvargResult) = vtReturn;
5959 V_UI4(pvargResult) = hres;
5961 HeapFree(GetProcessHeap(),0,args);
5964 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
5965 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
5970 #define INVBUF_ELEMENT_SIZE \
5971 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5972 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5973 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5974 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5975 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5976 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5977 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5978 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5980 static HRESULT WINAPI ITypeInfo_fnInvoke(
5985 DISPPARAMS *pDispParams,
5986 VARIANT *pVarResult,
5987 EXCEPINFO *pExcepInfo,
5990 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5992 unsigned int var_index;
5995 const TLBFuncDesc *pFuncInfo;
5997 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5998 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6003 ERR("NULL pDispParams not allowed\n");
6004 return E_INVALIDARG;
6007 dump_DispParms(pDispParams);
6009 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6011 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6012 pDispParams->cNamedArgs, pDispParams->cArgs);
6013 return E_INVALIDARG;
6016 /* we do this instead of using GetFuncDesc since it will return a fake
6017 * FUNCDESC for dispinterfaces and we want the real function description */
6018 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6019 if ((memid == pFuncInfo->funcdesc.memid) &&
6020 (wFlags & pFuncInfo->funcdesc.invkind))
6024 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6028 TRACE("invoking:\n");
6029 dump_TLBFuncDescOne(pFuncInfo);
6032 switch (func_desc->funckind) {
6033 case FUNC_PUREVIRTUAL:
6034 case FUNC_VIRTUAL: {
6035 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6037 VARIANT retval; /* pointer for storing byref retvals in */
6038 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6039 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6040 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6041 UINT cNamedArgs = pDispParams->cNamedArgs;
6042 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6043 UINT vargs_converted=0;
6047 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6049 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6051 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6052 hres = DISP_E_PARAMNOTFOUND;
6055 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6057 rgdispidNamedArgs++;
6060 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6062 ERR("functions with the vararg attribute do not support named arguments\n");
6063 hres = DISP_E_NONAMEDARGS;
6067 for (i = 0; i < func_desc->cParams; i++)
6069 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6070 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6075 TRACE("changing args\n");
6076 for (i = 0; i < func_desc->cParams; i++)
6078 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6079 VARIANTARG *src_arg;
6081 if (wParamFlags & PARAMFLAG_FLCID)
6084 arg = prgpvarg[i] = &rgvarg[i];
6086 V_I4(arg) = This->pTypeLib->lcid;
6094 for (j = 0; j < cNamedArgs; j++)
6095 if (rgdispidNamedArgs[j] == i)
6097 src_arg = &pDispParams->rgvarg[j];
6103 src_arg = vargs_converted < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted] : NULL;
6107 if (wParamFlags & PARAMFLAG_FRETVAL)
6109 /* under most conditions the caller is not allowed to
6110 * pass in a dispparam arg in the index of what would be
6111 * the retval parameter. however, there is an exception
6112 * where the extra parameter is used in an extra
6113 * IDispatch::Invoke below */
6114 if ((i < pDispParams->cArgs) &&
6115 ((func_desc->cParams != 1) || !pVarResult ||
6116 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6118 hres = DISP_E_BADPARAMCOUNT;
6122 /* note: this check is placed so that if the caller passes
6123 * in a VARIANTARG for the retval we just ignore it, like
6125 if (i == func_desc->cParams - 1)
6128 arg = prgpvarg[i] = &rgvarg[i];
6129 memset(arg, 0, sizeof(*arg));
6130 V_VT(arg) = rgvt[i];
6131 memset(&retval, 0, sizeof(retval));
6132 V_BYREF(arg) = &retval;
6136 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6137 hres = E_UNEXPECTED;
6143 dump_Variant(src_arg);
6145 if (rgvt[i] == VT_VARIANT)
6146 hres = VariantCopy(&rgvarg[i], src_arg);
6147 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6149 if (rgvt[i] == V_VT(src_arg))
6150 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6153 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6154 if (wParamFlags & PARAMFLAG_FIN)
6155 hres = VariantCopy(&missing_arg[i], src_arg);
6156 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6158 V_VT(&rgvarg[i]) = rgvt[i];
6160 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6163 SAFEARRAYBOUND bound;
6167 bound.cElements = pDispParams->cArgs-i;
6168 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6170 ERR("SafeArrayCreate failed\n");
6173 hres = SafeArrayAccessData(a, (LPVOID)&v);
6176 ERR("SafeArrayAccessData failed with %x\n", hres);
6179 for (j = 0; j < bound.cElements; j++)
6180 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6181 hres = SafeArrayUnaccessData(a);
6184 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6187 V_ARRAY(&rgvarg[i]) = a;
6188 V_VT(&rgvarg[i]) = rgvt[i];
6190 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6192 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6193 if (wParamFlags & PARAMFLAG_FIN)
6194 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6196 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6197 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6198 V_VT(&rgvarg[i]) = rgvt[i];
6200 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6202 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6203 V_VT(&rgvarg[i]) = rgvt[i];
6207 /* FIXME: this doesn't work for VT_BYREF arguments if
6208 * they are not the same type as in the paramdesc */
6209 V_VT(&rgvarg[i]) = V_VT(src_arg);
6210 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6211 V_VT(&rgvarg[i]) = rgvt[i];
6216 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6217 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6218 debugstr_VT(src_arg), debugstr_VF(src_arg));
6221 prgpvarg[i] = &rgvarg[i];
6223 else if (wParamFlags & PARAMFLAG_FOPT)
6226 arg = prgpvarg[i] = &rgvarg[i];
6227 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6229 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6235 VARIANTARG *missing_arg;
6236 /* if the function wants a pointer to a variant then
6237 * set that up, otherwise just pass the VT_ERROR in
6238 * the argument by value */
6239 if (rgvt[i] & VT_BYREF)
6241 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6242 V_VT(arg) = VT_VARIANT | VT_BYREF;
6243 V_VARIANTREF(arg) = missing_arg;
6247 V_VT(missing_arg) = VT_ERROR;
6248 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6253 hres = DISP_E_BADPARAMCOUNT;
6257 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6259 /* VT_VOID is a special case for return types, so it is not
6260 * handled in the general function */
6261 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6262 V_VT(&varresult) = VT_EMPTY;
6265 V_VT(&varresult) = 0;
6266 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6267 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6270 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6271 V_VT(&varresult), func_desc->cParams, rgvt,
6272 prgpvarg, &varresult);
6274 vargs_converted = 0;
6276 for (i = 0; i < func_desc->cParams; i++)
6278 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6279 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6281 if (wParamFlags & PARAMFLAG_FLCID)
6283 else if (wParamFlags & PARAMFLAG_FRETVAL)
6287 TRACE("[retval] value: ");
6288 dump_Variant(prgpvarg[i]);
6293 VariantInit(pVarResult);
6294 /* deref return value */
6295 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6298 VARIANT_ClearInd(prgpvarg[i]);
6300 else if (vargs_converted < pDispParams->cArgs)
6302 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6303 if (wParamFlags & PARAMFLAG_FOUT)
6305 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6307 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6311 ERR("failed to convert param %d to vt %d\n", i,
6312 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6317 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6318 func_desc->cParamsOpt < 0 &&
6319 i == func_desc->cParams-1)
6321 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6324 hres = SafeArrayGetUBound(a, 1, &ubound);
6327 ERR("SafeArrayGetUBound failed with %x\n", hres);
6330 hres = SafeArrayAccessData(a, (LPVOID)&v);
6333 ERR("SafeArrayAccessData failed with %x\n", hres);
6336 for (j = 0; j <= ubound; j++)
6337 VariantClear(&v[j]);
6338 hres = SafeArrayUnaccessData(a);
6341 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6345 VariantClear(&rgvarg[i]);
6348 else if (wParamFlags & PARAMFLAG_FOPT)
6350 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6351 VariantClear(&rgvarg[i]);
6354 VariantClear(&missing_arg[i]);
6357 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6359 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6360 hres = DISP_E_EXCEPTION;
6363 IErrorInfo *pErrorInfo;
6364 pExcepInfo->scode = V_ERROR(&varresult);
6365 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6367 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6368 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6369 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6370 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6372 IErrorInfo_Release(pErrorInfo);
6376 if (V_VT(&varresult) != VT_ERROR)
6378 TRACE("varresult value: ");
6379 dump_Variant(&varresult);
6383 VariantClear(pVarResult);
6384 *pVarResult = varresult;
6387 VariantClear(&varresult);
6390 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6391 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6392 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6393 (pDispParams->cArgs != 0))
6395 if (V_VT(pVarResult) == VT_DISPATCH)
6397 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6398 /* Note: not VariantClear; we still need the dispatch
6399 * pointer to be valid */
6400 VariantInit(pVarResult);
6401 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6402 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6403 pDispParams, pVarResult, pExcepInfo, pArgErr);
6404 IDispatch_Release(pDispatch);
6408 VariantClear(pVarResult);
6409 hres = DISP_E_NOTACOLLECTION;
6414 HeapFree(GetProcessHeap(), 0, buffer);
6417 case FUNC_DISPATCH: {
6420 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6421 if (SUCCEEDED(hres)) {
6422 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6423 hres = IDispatch_Invoke(
6424 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6425 pVarResult,pExcepInfo,pArgErr
6428 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6429 IDispatch_Release(disp);
6431 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6435 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6440 TRACE("-- 0x%08x\n", hres);
6443 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6446 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6447 if(FAILED(hres)) return hres;
6449 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6450 dump_VARDESC(var_desc);
6451 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6455 /* not found, look for it in inherited interfaces */
6456 ITypeInfo2_GetTypeKind(iface, &type_kind);
6457 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6458 if(This->impltypelist) {
6459 /* recursive search */
6461 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6462 if(SUCCEEDED(hres)){
6463 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6464 ITypeInfo_Release(pTInfo);
6467 WARN("Could not search inherited interface!\n");
6470 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6471 return DISP_E_MEMBERNOTFOUND;
6474 /* ITypeInfo::GetDocumentation
6476 * Retrieves the documentation string, the complete Help file name and path,
6477 * and the context ID for the Help topic for a specified type description.
6479 * (Can be tested by the Visual Basic Editor in Word for instance.)
6481 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6482 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6483 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6485 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6486 const TLBFuncDesc *pFDesc;
6487 const TLBVarDesc *pVDesc;
6488 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6489 " HelpContext(%p) HelpFile(%p)\n",
6490 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6491 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6493 *pBstrName=SysAllocString(This->Name);
6495 *pBstrDocString=SysAllocString(This->DocString);
6497 *pdwHelpContext=This->dwHelpContext;
6499 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6501 }else {/* for a member */
6502 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6503 if(pFDesc->funcdesc.memid==memid){
6505 *pBstrName = SysAllocString(pFDesc->Name);
6507 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6509 *pdwHelpContext=pFDesc->helpcontext;
6512 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6513 if(pVDesc->vardesc.memid==memid){
6515 *pBstrName = SysAllocString(pVDesc->Name);
6517 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6519 *pdwHelpContext=pVDesc->HelpContext;
6524 if(This->impltypelist &&
6525 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6526 /* recursive search */
6529 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6531 if(SUCCEEDED(result)) {
6532 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6533 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6534 ITypeInfo_Release(pTInfo);
6537 WARN("Could not search inherited interface!\n");
6540 WARN("member %d not found\n", memid);
6541 return TYPE_E_ELEMENTNOTFOUND;
6544 /* ITypeInfo::GetDllEntry
6546 * Retrieves a description or specification of an entry point for a function
6549 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6550 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6553 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6554 const TLBFuncDesc *pFDesc;
6556 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6558 if (pBstrDllName) *pBstrDllName = NULL;
6559 if (pBstrName) *pBstrName = NULL;
6560 if (pwOrdinal) *pwOrdinal = 0;
6562 if (This->TypeAttr.typekind != TKIND_MODULE)
6563 return TYPE_E_BADMODULEKIND;
6565 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6566 if(pFDesc->funcdesc.memid==memid){
6567 dump_TypeInfo(This);
6569 dump_TLBFuncDescOne(pFDesc);
6572 *pBstrDllName = SysAllocString(This->DllName);
6574 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6576 *pBstrName = SysAllocString(pFDesc->Entry);
6584 *pwOrdinal = (DWORD)pFDesc->Entry;
6587 return TYPE_E_ELEMENTNOTFOUND;
6590 /* internal function to make the inherited interfaces' methods appear
6591 * part of the interface */
6592 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6593 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6595 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6598 TRACE("%p, 0x%x\n", iface, *hRefType);
6600 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6602 ITypeInfo *pSubTypeInfo;
6604 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6608 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6610 ITypeInfo_Release(pSubTypeInfo);
6614 *hRefType -= DISPATCH_HREF_OFFSET;
6616 if (!(*hRefType & DISPATCH_HREF_MASK))
6617 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6622 /* ITypeInfo::GetRefTypeInfo
6624 * If a type description references other type descriptions, it retrieves
6625 * the referenced type descriptions.
6627 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6630 ITypeInfo **ppTInfo)
6632 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6633 HRESULT result = E_FAIL;
6635 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6637 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6638 ITypeInfo_AddRef(*ppTInfo);
6641 else if (hRefType == -1 &&
6642 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6643 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6645 /* when we meet a DUAL dispinterface, we must create the interface
6648 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6651 /* the interface version contains the same information as the dispinterface
6652 * copy the contents of the structs.
6654 *pTypeInfoImpl = *This;
6655 pTypeInfoImpl->ref = 0;
6657 /* change the type to interface */
6658 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6660 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6662 /* the AddRef implicitly adds a reference to the parent typelib, which
6663 * stops the copied data from being destroyed until the new typeinfo's
6664 * refcount goes to zero, but we need to signal to the new instance to
6665 * not free its data structures when it is destroyed */
6666 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6668 ITypeInfo_AddRef(*ppTInfo);
6672 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6673 (This->TypeAttr.typekind == TKIND_DISPATCH))
6675 HREFTYPE href_dispatch = hRefType;
6676 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6678 TLBRefType *ref_type;
6679 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6681 if(ref_type->reference == hRefType)
6684 if(&ref_type->entry == &This->pTypeLib->ref_list)
6686 FIXME("Can't find pRefType for ref %x\n", hRefType);
6689 if(hRefType != -1) {
6690 ITypeLib *pTLib = NULL;
6692 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6694 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6696 if(ref_type->pImpTLInfo->pImpTypeLib) {
6697 TRACE("typeinfo in imported typelib that is already loaded\n");
6698 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6699 ITypeLib2_AddRef(pTLib);
6702 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6703 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6704 ref_type->pImpTLInfo->wVersionMajor,
6705 ref_type->pImpTLInfo->wVersionMinor,
6706 ref_type->pImpTLInfo->lcid,
6709 if(FAILED(result)) {
6710 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6711 result=LoadTypeLib(libnam, &pTLib);
6712 SysFreeString(libnam);
6714 if(SUCCEEDED(result)) {
6715 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6716 ITypeLib2_AddRef(pTLib);
6720 if(SUCCEEDED(result)) {
6721 if(ref_type->index == TLB_REF_USE_GUID)
6722 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6726 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6730 ITypeLib2_Release(pTLib);
6735 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6736 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6740 /* ITypeInfo::AddressOfMember
6742 * Retrieves the addresses of static functions or variables, such as those
6745 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6746 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6748 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6754 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6756 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6760 module = LoadLibraryW(dll);
6763 ERR("couldn't load %s\n", debugstr_w(dll));
6765 SysFreeString(entry);
6766 return STG_E_FILENOTFOUND;
6768 /* FIXME: store library somewhere where we can free it */
6773 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6774 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6775 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6777 *ppv = GetProcAddress(module, entryA);
6779 ERR("function not found %s\n", debugstr_a(entryA));
6781 HeapFree(GetProcessHeap(), 0, entryA);
6785 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6787 ERR("function not found %d\n", ordinal);
6791 SysFreeString(entry);
6794 return TYPE_E_DLLFUNCTIONNOTFOUND;
6799 /* ITypeInfo::CreateInstance
6801 * Creates a new instance of a type that describes a component object class
6804 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6805 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6807 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6811 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6817 WARN("Not able to aggregate\n");
6818 return CLASS_E_NOAGGREGATION;
6821 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6822 if(FAILED(hr)) return hr;
6824 if(pTA->typekind != TKIND_COCLASS)
6826 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6832 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6835 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6836 TRACE("GetActiveObject rets %08x\n", hr);
6839 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6840 IUnknown_Release(pUnk);
6845 hr = CoCreateInstance(&pTA->guid, NULL,
6846 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6850 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6854 /* ITypeInfo::GetMops
6856 * Retrieves marshalling information.
6858 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6861 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6862 FIXME("(%p) stub!\n", This);
6866 /* ITypeInfo::GetContainingTypeLib
6868 * Retrieves the containing type library and the index of the type description
6869 * within that type library.
6871 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6872 ITypeLib * *ppTLib, UINT *pIndex)
6874 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6876 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6878 *pIndex=This->index;
6879 TRACE("returning pIndex=%d\n", *pIndex);
6883 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6884 ITypeLib2_AddRef(*ppTLib);
6885 TRACE("returning ppTLib=%p\n", *ppTLib);
6891 /* ITypeInfo::ReleaseTypeAttr
6893 * Releases a TYPEATTR previously returned by GetTypeAttr.
6896 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6897 TYPEATTR* pTypeAttr)
6899 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6900 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6901 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6904 /* ITypeInfo::ReleaseFuncDesc
6906 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6908 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6910 FUNCDESC *pFuncDesc)
6912 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6915 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6917 for (i = 0; i < pFuncDesc->cParams; i++)
6918 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6919 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6921 SysFreeString((BSTR)pFuncDesc);
6924 /* ITypeInfo::ReleaseVarDesc
6926 * Releases a VARDESC previously returned by GetVarDesc.
6928 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6931 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6932 TRACE("(%p)->(%p)\n", This, pVarDesc);
6934 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6935 if (pVarDesc->varkind == VAR_CONST)
6936 VariantClear(pVarDesc->u.lpvarValue);
6937 SysFreeString((BSTR)pVarDesc);
6940 /* ITypeInfo2::GetTypeKind
6942 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6945 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6946 TYPEKIND *pTypeKind)
6948 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6949 *pTypeKind=This->TypeAttr.typekind;
6950 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6954 /* ITypeInfo2::GetTypeFlags
6956 * Returns the type flags without any allocations. This returns a DWORD type
6957 * flag, which expands the type flags without growing the TYPEATTR (type
6961 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6963 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6964 *pTypeFlags=This->TypeAttr.wTypeFlags;
6965 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6969 /* ITypeInfo2::GetFuncIndexOfMemId
6970 * Binds to a specific member based on a known DISPID, where the member name
6971 * is not known (for example, when binding to a default member).
6974 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6975 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6977 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6978 const TLBFuncDesc *pFuncInfo;
6982 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6983 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6989 result = TYPE_E_ELEMENTNOTFOUND;
6991 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6992 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6996 /* TypeInfo2::GetVarIndexOfMemId
6998 * Binds to a specific member based on a known DISPID, where the member name
6999 * is not known (for example, when binding to a default member).
7002 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7003 MEMBERID memid, UINT *pVarIndex)
7005 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7006 TLBVarDesc *pVarInfo;
7009 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7010 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7016 result = TYPE_E_ELEMENTNOTFOUND;
7018 TRACE("(%p) memid 0x%08x -> %s\n", This,
7019 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7023 /* ITypeInfo2::GetCustData
7025 * Gets the custom data
7027 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7032 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7033 TLBCustData *pCData;
7035 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7036 if( IsEqualIID(guid, &pCData->guid)) break;
7038 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7040 VariantInit( pVarVal);
7042 VariantCopy( pVarVal, &pCData->data);
7044 VariantClear( pVarVal );
7048 /* ITypeInfo2::GetFuncCustData
7050 * Gets the custom data
7052 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7058 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7059 TLBCustData *pCData=NULL;
7060 TLBFuncDesc * pFDesc;
7062 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7063 pFDesc=pFDesc->next);
7066 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7067 if( IsEqualIID(guid, &pCData->guid)) break;
7069 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7072 VariantInit( pVarVal);
7073 VariantCopy( pVarVal, &pCData->data);
7076 return E_INVALIDARG; /* FIXME: correct? */
7079 /* ITypeInfo2::GetParamCustData
7081 * Gets the custom data
7083 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7090 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7091 TLBCustData *pCData=NULL;
7092 TLBFuncDesc * pFDesc;
7095 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7097 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7098 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7099 pCData = pCData->next)
7100 if( IsEqualIID(guid, &pCData->guid)) break;
7102 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7106 VariantInit( pVarVal);
7107 VariantCopy( pVarVal, &pCData->data);
7110 return E_INVALIDARG; /* FIXME: correct? */
7113 /* ITypeInfo2::GetVarCustData
7115 * Gets the custom data
7117 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7123 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7124 TLBCustData *pCData=NULL;
7125 TLBVarDesc * pVDesc;
7128 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7132 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7134 if( IsEqualIID(guid, &pCData->guid)) break;
7138 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7142 VariantInit( pVarVal);
7143 VariantCopy( pVarVal, &pCData->data);
7146 return E_INVALIDARG; /* FIXME: correct? */
7149 /* ITypeInfo2::GetImplCustData
7151 * Gets the custom data
7153 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7159 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7160 TLBCustData *pCData=NULL;
7161 TLBImplType * pRDesc;
7164 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7168 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7170 if( IsEqualIID(guid, &pCData->guid)) break;
7174 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7178 VariantInit( pVarVal);
7179 VariantCopy( pVarVal, &pCData->data);
7182 return E_INVALIDARG; /* FIXME: correct? */
7185 /* ITypeInfo2::GetDocumentation2
7187 * Retrieves the documentation string, the complete Help file name and path,
7188 * the localization context to use, and the context ID for the library Help
7189 * topic in the Help file.
7192 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7196 BSTR *pbstrHelpString,
7197 DWORD *pdwHelpStringContext,
7198 BSTR *pbstrHelpStringDll)
7200 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7201 const TLBFuncDesc *pFDesc;
7202 const TLBVarDesc *pVDesc;
7203 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7204 "HelpStringContext(%p) HelpStringDll(%p)\n",
7205 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7206 pbstrHelpStringDll );
7207 /* the help string should be obtained from the helpstringdll,
7208 * using the _DLLGetDocumentation function, based on the supplied
7209 * lcid. Nice to do sometime...
7211 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7213 *pbstrHelpString=SysAllocString(This->Name);
7214 if(pdwHelpStringContext)
7215 *pdwHelpStringContext=This->dwHelpStringContext;
7216 if(pbstrHelpStringDll)
7217 *pbstrHelpStringDll=
7218 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7220 }else {/* for a member */
7221 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7222 if(pFDesc->funcdesc.memid==memid){
7224 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7225 if(pdwHelpStringContext)
7226 *pdwHelpStringContext=pFDesc->HelpStringContext;
7227 if(pbstrHelpStringDll)
7228 *pbstrHelpStringDll=
7229 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7232 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7233 if(pVDesc->vardesc.memid==memid){
7235 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7236 if(pdwHelpStringContext)
7237 *pdwHelpStringContext=pVDesc->HelpStringContext;
7238 if(pbstrHelpStringDll)
7239 *pbstrHelpStringDll=
7240 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7244 return TYPE_E_ELEMENTNOTFOUND;
7247 /* ITypeInfo2::GetAllCustData
7249 * Gets all custom data items for the Type info.
7252 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7254 CUSTDATA *pCustData)
7256 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7257 TLBCustData *pCData;
7260 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7262 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7263 if(pCustData->prgCustData ){
7264 pCustData->cCustData=This->ctCustData;
7265 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7266 pCustData->prgCustData[i].guid=pCData->guid;
7267 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7270 ERR(" OUT OF MEMORY!\n");
7271 return E_OUTOFMEMORY;
7276 /* ITypeInfo2::GetAllFuncCustData
7278 * Gets all custom data items for the specified Function
7281 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7284 CUSTDATA *pCustData)
7286 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7287 TLBCustData *pCData;
7288 TLBFuncDesc * pFDesc;
7290 TRACE("(%p) index %d\n", This, index);
7291 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7292 pFDesc=pFDesc->next)
7295 pCustData->prgCustData =
7296 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7297 if(pCustData->prgCustData ){
7298 pCustData->cCustData=pFDesc->ctCustData;
7299 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7300 pCData = pCData->next){
7301 pCustData->prgCustData[i].guid=pCData->guid;
7302 VariantCopy(& pCustData->prgCustData[i].varValue,
7306 ERR(" OUT OF MEMORY!\n");
7307 return E_OUTOFMEMORY;
7311 return TYPE_E_ELEMENTNOTFOUND;
7314 /* ITypeInfo2::GetAllParamCustData
7316 * Gets all custom data items for the Functions
7319 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7320 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7322 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7323 TLBCustData *pCData=NULL;
7324 TLBFuncDesc * pFDesc;
7326 TRACE("(%p) index %d\n", This, indexFunc);
7327 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7328 pFDesc=pFDesc->next)
7330 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7331 pCustData->prgCustData =
7332 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7333 sizeof(CUSTDATAITEM));
7334 if(pCustData->prgCustData ){
7335 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7336 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7337 pCData; i++, pCData = pCData->next){
7338 pCustData->prgCustData[i].guid=pCData->guid;
7339 VariantCopy(& pCustData->prgCustData[i].varValue,
7343 ERR(" OUT OF MEMORY!\n");
7344 return E_OUTOFMEMORY;
7348 return TYPE_E_ELEMENTNOTFOUND;
7351 /* ITypeInfo2::GetAllVarCustData
7353 * Gets all custom data items for the specified Variable
7356 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7357 UINT index, CUSTDATA *pCustData)
7359 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7360 TLBCustData *pCData;
7361 TLBVarDesc * pVDesc;
7363 TRACE("(%p) index %d\n", This, index);
7364 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7365 pVDesc=pVDesc->next)
7368 pCustData->prgCustData =
7369 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7370 if(pCustData->prgCustData ){
7371 pCustData->cCustData=pVDesc->ctCustData;
7372 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7373 pCData = pCData->next){
7374 pCustData->prgCustData[i].guid=pCData->guid;
7375 VariantCopy(& pCustData->prgCustData[i].varValue,
7379 ERR(" OUT OF MEMORY!\n");
7380 return E_OUTOFMEMORY;
7384 return TYPE_E_ELEMENTNOTFOUND;
7387 /* ITypeInfo2::GetAllImplCustData
7389 * Gets all custom data items for the specified implementation type
7392 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7395 CUSTDATA *pCustData)
7397 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7398 TLBCustData *pCData;
7399 TLBImplType * pRDesc;
7401 TRACE("(%p) index %d\n", This, index);
7402 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7403 pRDesc=pRDesc->next)
7406 pCustData->prgCustData =
7407 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7408 if(pCustData->prgCustData ){
7409 pCustData->cCustData=pRDesc->ctCustData;
7410 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7411 pCData = pCData->next){
7412 pCustData->prgCustData[i].guid=pCData->guid;
7413 VariantCopy(& pCustData->prgCustData[i].varValue,
7417 ERR(" OUT OF MEMORY!\n");
7418 return E_OUTOFMEMORY;
7422 return TYPE_E_ELEMENTNOTFOUND;
7425 static const ITypeInfo2Vtbl tinfvt =
7428 ITypeInfo_fnQueryInterface,
7430 ITypeInfo_fnRelease,
7432 ITypeInfo_fnGetTypeAttr,
7433 ITypeInfo_fnGetTypeComp,
7434 ITypeInfo_fnGetFuncDesc,
7435 ITypeInfo_fnGetVarDesc,
7436 ITypeInfo_fnGetNames,
7437 ITypeInfo_fnGetRefTypeOfImplType,
7438 ITypeInfo_fnGetImplTypeFlags,
7439 ITypeInfo_fnGetIDsOfNames,
7441 ITypeInfo_fnGetDocumentation,
7442 ITypeInfo_fnGetDllEntry,
7443 ITypeInfo_fnGetRefTypeInfo,
7444 ITypeInfo_fnAddressOfMember,
7445 ITypeInfo_fnCreateInstance,
7446 ITypeInfo_fnGetMops,
7447 ITypeInfo_fnGetContainingTypeLib,
7448 ITypeInfo_fnReleaseTypeAttr,
7449 ITypeInfo_fnReleaseFuncDesc,
7450 ITypeInfo_fnReleaseVarDesc,
7452 ITypeInfo2_fnGetTypeKind,
7453 ITypeInfo2_fnGetTypeFlags,
7454 ITypeInfo2_fnGetFuncIndexOfMemId,
7455 ITypeInfo2_fnGetVarIndexOfMemId,
7456 ITypeInfo2_fnGetCustData,
7457 ITypeInfo2_fnGetFuncCustData,
7458 ITypeInfo2_fnGetParamCustData,
7459 ITypeInfo2_fnGetVarCustData,
7460 ITypeInfo2_fnGetImplTypeCustData,
7461 ITypeInfo2_fnGetDocumentation2,
7462 ITypeInfo2_fnGetAllCustData,
7463 ITypeInfo2_fnGetAllFuncCustData,
7464 ITypeInfo2_fnGetAllParamCustData,
7465 ITypeInfo2_fnGetAllVarCustData,
7466 ITypeInfo2_fnGetAllImplTypeCustData,
7469 /******************************************************************************
7470 * CreateDispTypeInfo [OLEAUT32.31]
7472 * Build type information for an object so it can be called through an
7473 * IDispatch interface.
7476 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7477 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7480 * This call allows an objects methods to be accessed through IDispatch, by
7481 * building an ITypeInfo object that IDispatch can use to call through.
7483 HRESULT WINAPI CreateDispTypeInfo(
7484 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7485 LCID lcid, /* [I] Locale Id */
7486 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7488 ITypeInfoImpl *pTIClass, *pTIIface;
7489 ITypeLibImpl *pTypeLibImpl;
7490 unsigned int param, func;
7491 TLBFuncDesc **ppFuncDesc;
7495 pTypeLibImpl = TypeLibImpl_Constructor();
7496 if (!pTypeLibImpl) return E_FAIL;
7498 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7499 pTIIface->pTypeLib = pTypeLibImpl;
7500 pTIIface->index = 0;
7501 pTIIface->Name = NULL;
7502 pTIIface->dwHelpContext = -1;
7503 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7504 pTIIface->TypeAttr.lcid = lcid;
7505 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7506 pTIIface->TypeAttr.wMajorVerNum = 0;
7507 pTIIface->TypeAttr.wMinorVerNum = 0;
7508 pTIIface->TypeAttr.cbAlignment = 2;
7509 pTIIface->TypeAttr.cbSizeInstance = -1;
7510 pTIIface->TypeAttr.cbSizeVft = -1;
7511 pTIIface->TypeAttr.cFuncs = 0;
7512 pTIIface->TypeAttr.cImplTypes = 0;
7513 pTIIface->TypeAttr.cVars = 0;
7514 pTIIface->TypeAttr.wTypeFlags = 0;
7516 ppFuncDesc = &pTIIface->funclist;
7517 for(func = 0; func < pidata->cMembers; func++) {
7518 METHODDATA *md = pidata->pmethdata + func;
7519 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7520 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7521 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7522 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7523 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7524 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7525 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7526 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7527 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7528 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7529 (*ppFuncDesc)->funcdesc.cScodes = 0;
7530 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7531 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7532 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7533 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7534 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7535 md->cArgs * sizeof(ELEMDESC));
7536 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7537 md->cArgs * sizeof(TLBParDesc));
7538 for(param = 0; param < md->cArgs; param++) {
7539 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7540 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7542 (*ppFuncDesc)->helpcontext = 0;
7543 (*ppFuncDesc)->HelpStringContext = 0;
7544 (*ppFuncDesc)->HelpString = NULL;
7545 (*ppFuncDesc)->Entry = NULL;
7546 (*ppFuncDesc)->ctCustData = 0;
7547 (*ppFuncDesc)->pCustData = NULL;
7548 (*ppFuncDesc)->next = NULL;
7549 pTIIface->TypeAttr.cFuncs++;
7550 ppFuncDesc = &(*ppFuncDesc)->next;
7553 dump_TypeInfo(pTIIface);
7555 pTypeLibImpl->pTypeInfo = pTIIface;
7556 pTypeLibImpl->TypeInfoCount++;
7558 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7559 pTIClass->pTypeLib = pTypeLibImpl;
7560 pTIClass->index = 1;
7561 pTIClass->Name = NULL;
7562 pTIClass->dwHelpContext = -1;
7563 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7564 pTIClass->TypeAttr.lcid = lcid;
7565 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7566 pTIClass->TypeAttr.wMajorVerNum = 0;
7567 pTIClass->TypeAttr.wMinorVerNum = 0;
7568 pTIClass->TypeAttr.cbAlignment = 2;
7569 pTIClass->TypeAttr.cbSizeInstance = -1;
7570 pTIClass->TypeAttr.cbSizeVft = -1;
7571 pTIClass->TypeAttr.cFuncs = 0;
7572 pTIClass->TypeAttr.cImplTypes = 1;
7573 pTIClass->TypeAttr.cVars = 0;
7574 pTIClass->TypeAttr.wTypeFlags = 0;
7576 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7577 pTIClass->impltypelist->hRef = 0;
7579 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7582 ref->pImpTLInfo = TLB_REF_INTERNAL;
7583 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7585 dump_TypeInfo(pTIClass);
7587 pTIIface->next = pTIClass;
7588 pTypeLibImpl->TypeInfoCount++;
7590 *pptinfo = (ITypeInfo*)pTIClass;
7592 ITypeInfo_AddRef(*pptinfo);
7593 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7599 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7601 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7603 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7606 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7608 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7610 return ITypeInfo_AddRef((ITypeInfo *)This);
7613 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7615 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7617 return ITypeInfo_Release((ITypeInfo *)This);
7620 static HRESULT WINAPI ITypeComp_fnBind(
7625 ITypeInfo ** ppTInfo,
7626 DESCKIND * pDescKind,
7629 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7630 const TLBFuncDesc *pFDesc;
7631 const TLBVarDesc *pVDesc;
7632 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7634 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7636 *pDescKind = DESCKIND_NONE;
7637 pBindPtr->lpfuncdesc = NULL;
7640 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7641 if (!strcmpiW(pFDesc->Name, szName)) {
7642 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7645 /* name found, but wrong flags */
7646 hr = TYPE_E_TYPEMISMATCH;
7651 HRESULT hr = TLB_AllocAndInitFuncDesc(
7653 &pBindPtr->lpfuncdesc,
7654 This->TypeAttr.typekind == TKIND_DISPATCH);
7657 *pDescKind = DESCKIND_FUNCDESC;
7658 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7659 ITypeInfo_AddRef(*ppTInfo);
7662 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7663 if (!strcmpiW(pVDesc->Name, szName)) {
7664 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7667 *pDescKind = DESCKIND_VARDESC;
7668 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7669 ITypeInfo_AddRef(*ppTInfo);
7674 /* FIXME: search each inherited interface, not just the first */
7675 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7676 /* recursive search */
7680 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7683 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7684 ITypeInfo_Release(pTInfo);
7688 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7689 ITypeComp_Release(pTComp);
7692 WARN("Could not search inherited interface!\n");
7694 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7698 static HRESULT WINAPI ITypeComp_fnBindType(
7702 ITypeInfo ** ppTInfo,
7703 ITypeComp ** ppTComp)
7705 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7707 /* strange behaviour (does nothing) but like the
7710 if (!ppTInfo || !ppTComp)
7719 static const ITypeCompVtbl tcompvt =
7722 ITypeComp_fnQueryInterface,
7724 ITypeComp_fnRelease,
7727 ITypeComp_fnBindType