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};
269 sprintfW( buffer, LcidFormatW, lcid );
272 case SYS_WIN16: strcatW( buffer, win16W ); break;
273 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 TRACE("Typelib is for unsupported syskind %i\n", syskind);
281 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
284 /****************************************************************************
285 * QueryPathOfRegTypeLib [OLEAUT32.164]
287 * Gets the path to a registered type library.
290 * guid [I] referenced guid
291 * wMaj [I] major version
292 * wMin [I] minor version
294 * path [O] path of typelib
298 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
299 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
302 HRESULT WINAPI QueryPathOfRegTypeLib(
309 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
313 WCHAR Path[MAX_PATH];
316 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
318 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
319 get_typelib_key( guid, wMaj, wMin, buffer );
321 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
322 if (res == ERROR_FILE_NOT_FOUND)
324 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
325 return TYPE_E_LIBNOTREGISTERED;
327 else if (res != ERROR_SUCCESS)
329 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
330 return TYPE_E_REGISTRYACCESS;
335 LONG dwPathLen = sizeof(Path);
337 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
339 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
343 else if (myLCID == lcid)
345 /* try with sub-langid */
346 myLCID = SUBLANGID(lcid);
348 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
350 /* try with system langid */
360 *path = SysAllocString( Path );
365 TRACE_(typelib)("-- 0x%08x\n", hr);
369 /******************************************************************************
370 * CreateTypeLib [OLEAUT32.160] creates a typelib
376 HRESULT WINAPI CreateTypeLib(
377 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
379 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
383 /******************************************************************************
384 * LoadTypeLib [OLEAUT32.161]
386 * Loads a type library
389 * szFile [I] Name of file to load from.
390 * pptLib [O] Pointer that receives ITypeLib object on success.
397 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
399 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
401 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
402 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
405 /******************************************************************************
406 * LoadTypeLibEx [OLEAUT32.183]
408 * Loads and optionally registers a type library
414 HRESULT WINAPI LoadTypeLibEx(
415 LPCOLESTR szFile, /* [in] Name of file to load from */
416 REGKIND regkind, /* [in] Specify kind of registration */
417 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
419 WCHAR szPath[MAX_PATH+1];
422 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
426 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
431 case REGKIND_DEFAULT:
432 /* don't register typelibs supplied with full path. Experimentation confirms the following */
433 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
434 (szFile[0] && (szFile[1] == ':'))) break;
435 /* else fall-through */
437 case REGKIND_REGISTER:
438 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
440 IUnknown_Release(*pptLib);
448 TRACE(" returns %08x\n",res);
452 /******************************************************************************
453 * LoadRegTypeLib [OLEAUT32.162]
455 * Loads a registered type library.
458 * rguid [I] GUID of the registered type library.
459 * wVerMajor [I] major version.
460 * wVerMinor [I] minor version.
461 * lcid [I] locale ID.
462 * ppTLib [O] pointer that receives an ITypeLib object on success.
466 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
469 HRESULT WINAPI LoadRegTypeLib(
481 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
485 res= LoadTypeLib(bstr, ppTLib);
489 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
495 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
496 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
497 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
498 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
499 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
500 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
502 /******************************************************************************
503 * RegisterTypeLib [OLEAUT32.163]
504 * Adds information about a type library to the System Registry
506 * Docs: ITypeLib FAR * ptlib
507 * Docs: OLECHAR FAR* szFullPath
508 * Docs: OLECHAR FAR* szHelpDir
514 HRESULT WINAPI RegisterTypeLib(
515 ITypeLib * ptlib, /* [in] Pointer to the library*/
516 OLECHAR * szFullPath, /* [in] full Path of the library*/
517 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
520 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
521 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
522 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
532 if (ptlib == NULL || szFullPath == NULL)
535 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
538 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
541 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
542 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
546 /* Set the human-readable name of the typelib */
547 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
549 if (RegSetValueExW(key, NULL, 0, REG_SZ,
550 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
558 /* Make up the name of the typelib path subkey */
559 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
561 /* Create the typelib path subkey */
562 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
563 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
565 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
566 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
574 /* Create the flags subkey */
575 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
576 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
578 /* FIXME: is %u correct? */
579 static const WCHAR formatW[] = {'%','u',0};
581 sprintfW(buf, formatW, attr->wLibFlags);
582 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
583 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
591 /* create the helpdir subkey */
592 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
593 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
595 BOOL freeHelpDir = FALSE;
598 /* if we created a new key, and helpDir was null, set the helpdir
599 to the directory which contains the typelib. However,
600 if we just opened an existing key, we leave the helpdir alone */
601 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
602 szHelpDir = SysAllocString(szFullPath);
603 pIndexStr = strrchrW(szHelpDir, '\\');
610 /* if we have an szHelpDir, set it! */
611 if (szHelpDir != NULL) {
612 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
613 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
619 if (freeHelpDir) SysFreeString(szHelpDir);
631 /* register OLE Automation-compatible interfaces for this typelib */
632 types = ITypeLib_GetTypeInfoCount(ptlib);
633 for (tidx=0; tidx<types; tidx++) {
634 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
635 LPOLESTR name = NULL;
636 ITypeInfo *tinfo = NULL;
638 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
641 case TKIND_INTERFACE:
642 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
643 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
647 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
648 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
652 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
657 TYPEATTR *tattr = NULL;
658 ITypeInfo_GetTypeAttr(tinfo, &tattr);
661 TRACE_(typelib)("guid=%s, flags=%04x (",
662 debugstr_guid(&tattr->guid),
665 if (TRACE_ON(typelib)) {
666 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
686 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
688 /* register interface<->typelib coupling */
689 get_interface_key( &tattr->guid, keyName );
690 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
691 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
694 RegSetValueExW(key, NULL, 0, REG_SZ,
695 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
697 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
698 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
699 RegSetValueExW(subKey, NULL, 0, REG_SZ,
700 (const BYTE *)PSOA, sizeof PSOA);
704 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
705 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
706 RegSetValueExW(subKey, NULL, 0, REG_SZ,
707 (const BYTE *)PSOA, sizeof PSOA);
711 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
712 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
715 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
716 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
718 StringFromGUID2(&attr->guid, buffer, 40);
719 RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
721 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
722 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
723 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
731 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
734 ITypeInfo_Release(tinfo);
741 ITypeLib_ReleaseTLibAttr(ptlib, attr);
747 /******************************************************************************
748 * UnRegisterTypeLib [OLEAUT32.186]
749 * Removes information about a type library from the System Registry
756 HRESULT WINAPI UnRegisterTypeLib(
757 REFGUID libid, /* [in] Guid of the library */
758 WORD wVerMajor, /* [in] major version */
759 WORD wVerMinor, /* [in] minor version */
760 LCID lcid, /* [in] locale id */
763 BSTR tlibPath = NULL;
766 WCHAR subKeyName[50];
769 BOOL deleteOtherStuff;
772 TYPEATTR* typeAttr = NULL;
774 ITypeInfo* typeInfo = NULL;
775 ITypeLib* typeLib = NULL;
778 TRACE("(IID: %s)\n",debugstr_guid(libid));
780 /* Create the path to the key */
781 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
783 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
785 TRACE("Unsupported syskind %i\n", syskind);
786 result = E_INVALIDARG;
790 /* get the path to the typelib on disk */
791 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
792 result = E_INVALIDARG;
796 /* Try and open the key to the type library. */
797 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
798 result = E_INVALIDARG;
802 /* Try and load the type library */
803 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
804 result = TYPE_E_INVALIDSTATE;
808 /* remove any types registered with this typelib */
809 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
810 for (i=0; i<numTypes; i++) {
811 /* get the kind of type */
812 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
816 /* skip non-interfaces, and get type info for the type */
817 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
820 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
823 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
827 /* the path to the type */
828 get_interface_key( &typeAttr->guid, subKeyName );
830 /* Delete its bits */
831 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
834 RegDeleteKeyW(subKey, ProxyStubClsidW);
835 RegDeleteKeyW(subKey, ProxyStubClsid32W);
836 RegDeleteKeyW(subKey, TypeLibW);
839 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
842 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
844 if (typeInfo) ITypeInfo_Release(typeInfo);
848 /* Now, delete the type library path subkey */
849 get_lcid_subkey( lcid, syskind, subKeyName );
850 RegDeleteKeyW(key, subKeyName);
851 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
852 RegDeleteKeyW(key, subKeyName);
854 /* check if there is anything besides the FLAGS/HELPDIR keys.
855 If there is, we don't delete them */
856 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
857 deleteOtherStuff = TRUE;
859 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
860 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
862 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
863 if (!strcmpW(subKeyName, FLAGSW)) continue;
864 if (!strcmpW(subKeyName, HELPDIRW)) continue;
865 deleteOtherStuff = FALSE;
869 /* only delete the other parts of the key if we're absolutely sure */
870 if (deleteOtherStuff) {
871 RegDeleteKeyW(key, FLAGSW);
872 RegDeleteKeyW(key, HELPDIRW);
876 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
877 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
878 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
882 SysFreeString(tlibPath);
883 if (typeLib) ITypeLib_Release(typeLib);
884 if (subKey) RegCloseKey(subKey);
885 if (key) RegCloseKey(key);
889 /*======================= ITypeLib implementation =======================*/
891 typedef struct tagTLBCustData
895 struct tagTLBCustData* next;
898 /* data structure for import typelibs */
899 typedef struct tagTLBImpLib
901 int offset; /* offset in the file (MSFT)
902 offset in nametable (SLTG)
903 just used to identify library while reading
905 GUID guid; /* libid */
906 BSTR name; /* name */
908 LCID lcid; /* lcid of imported typelib */
910 WORD wVersionMajor; /* major version number */
911 WORD wVersionMinor; /* minor version number */
913 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
914 NULL if not yet loaded */
915 struct tagTLBImpLib * next;
918 /* internal ITypeLib data */
919 typedef struct tagITypeLibImpl
921 const ITypeLib2Vtbl *lpVtbl;
922 const ITypeCompVtbl *lpVtblTypeComp;
924 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
926 /* strings can be stored in tlb as multibyte strings BUT they are *always*
927 * exported to the application as a UNICODE string.
933 unsigned long dwHelpContext;
934 int TypeInfoCount; /* nr of typeinfo's in librarry */
935 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
936 int ctCustData; /* number of items in cust data list */
937 TLBCustData * pCustData; /* linked list to cust data */
938 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
939 int ctTypeDesc; /* number of items in type desc array */
940 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
941 library. Only used while reading MSFT
943 struct list ref_list; /* list of ref types in this typelib */
944 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
947 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
948 struct tagITypeLibImpl *next, *prev;
953 static const ITypeLib2Vtbl tlbvt;
954 static const ITypeCompVtbl tlbtcvt;
956 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
958 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
961 /* ITypeLib methods */
962 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
963 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
965 /*======================= ITypeInfo implementation =======================*/
967 /* data for referenced types */
968 typedef struct tagTLBRefType
970 INT index; /* Type index for internal ref or for external ref
971 it the format is SLTG. -2 indicates to
974 GUID guid; /* guid of the referenced type */
975 /* if index == TLB_REF_USE_GUID */
977 HREFTYPE reference; /* The href of this ref */
978 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
979 TLB_REF_INTERNAL for internal refs
980 TLB_REF_NOT_FOUND for broken refs */
985 #define TLB_REF_USE_GUID -2
987 #define TLB_REF_INTERNAL (void*)-2
988 #define TLB_REF_NOT_FOUND (void*)-1
990 /* internal Parameter data */
991 typedef struct tagTLBParDesc
995 TLBCustData * pCustData; /* linked list to cust data */
998 /* internal Function data */
999 typedef struct tagTLBFuncDesc
1001 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1002 BSTR Name; /* the name of this function */
1003 TLBParDesc *pParamDesc; /* array with param names and custom data */
1005 int HelpStringContext;
1007 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
1009 TLBCustData * pCustData; /* linked list to cust data; */
1010 struct tagTLBFuncDesc * next;
1013 /* internal Variable data */
1014 typedef struct tagTLBVarDesc
1016 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1017 BSTR Name; /* the name of this variable */
1019 int HelpStringContext; /* FIXME: where? */
1022 TLBCustData * pCustData;/* linked list to cust data; */
1023 struct tagTLBVarDesc * next;
1026 /* internal implemented interface data */
1027 typedef struct tagTLBImplType
1029 HREFTYPE hRef; /* hRef of interface */
1030 int implflags; /* IMPLFLAG_*s */
1032 TLBCustData * pCustData;/* linked list to custom data; */
1033 struct tagTLBImplType *next;
1036 /* internal TypeInfo data */
1037 typedef struct tagITypeInfoImpl
1039 const ITypeInfo2Vtbl *lpVtbl;
1040 const ITypeCompVtbl *lpVtblTypeComp;
1042 BOOL no_free_data; /* don't free data structures */
1043 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1044 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1045 int index; /* index in this typelib; */
1046 HREFTYPE hreftype; /* hreftype for app object binding */
1047 /* type libs seem to store the doc strings in ascii
1048 * so why should we do it in unicode?
1053 unsigned long dwHelpContext;
1054 unsigned long dwHelpStringContext;
1057 TLBFuncDesc * funclist; /* linked list with function descriptions */
1060 TLBVarDesc * varlist; /* linked list with variable descriptions */
1062 /* Implemented Interfaces */
1063 TLBImplType * impltypelist;
1066 TLBCustData * pCustData; /* linked list to cust data; */
1067 struct tagITypeInfoImpl * next;
1070 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1072 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1075 static const ITypeInfo2Vtbl tinfvt;
1076 static const ITypeCompVtbl tcompvt;
1078 static ITypeInfo2 * ITypeInfo_Constructor(void);
1080 typedef struct tagTLBContext
1082 unsigned int oStart; /* start of TLB in file */
1083 unsigned int pos; /* current pos */
1084 unsigned int length; /* total length */
1085 void *mapping; /* memory mapping */
1086 MSFT_SegDir * pTblDir;
1087 ITypeLibImpl* pLibInfo;
1091 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1096 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1097 if (pTD->vt & VT_RESERVED)
1098 szVarType += strlen(strcpy(szVarType, "reserved | "));
1099 if (pTD->vt & VT_BYREF)
1100 szVarType += strlen(strcpy(szVarType, "ref to "));
1101 if (pTD->vt & VT_ARRAY)
1102 szVarType += strlen(strcpy(szVarType, "array of "));
1103 if (pTD->vt & VT_VECTOR)
1104 szVarType += strlen(strcpy(szVarType, "vector of "));
1105 switch(pTD->vt & VT_TYPEMASK) {
1106 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1107 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1108 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1109 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1110 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1111 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1112 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1113 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1114 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1115 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1116 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1117 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1118 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1119 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1120 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1121 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1122 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1123 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1124 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1125 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1126 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1127 pTD->u.hreftype); break;
1128 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1129 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1130 case VT_PTR: sprintf(szVarType, "ptr to ");
1131 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1133 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1134 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1136 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1137 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1138 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1141 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1145 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1147 USHORT flags = edesc->u.paramdesc.wParamFlags;
1148 dump_TypeDesc(&edesc->tdesc,buf);
1149 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1150 MESSAGE("\t\tu.paramdesc.wParamFlags");
1151 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1152 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1153 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1154 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1155 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1156 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1157 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1158 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1159 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1161 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1163 MESSAGE("memid is %08x\n",funcdesc->memid);
1164 for (i=0;i<funcdesc->cParams;i++) {
1165 MESSAGE("Param %d:\n",i);
1166 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1168 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1169 switch (funcdesc->funckind) {
1170 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1171 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1172 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1173 case FUNC_STATIC: MESSAGE("static");break;
1174 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1175 default: MESSAGE("unknown");break;
1177 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1178 switch (funcdesc->invkind) {
1179 case INVOKE_FUNC: MESSAGE("func");break;
1180 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1181 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1182 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1184 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1185 switch (funcdesc->callconv) {
1186 case CC_CDECL: MESSAGE("cdecl");break;
1187 case CC_PASCAL: MESSAGE("pascal");break;
1188 case CC_STDCALL: MESSAGE("stdcall");break;
1189 case CC_SYSCALL: MESSAGE("syscall");break;
1192 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1193 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1194 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1196 MESSAGE("\telemdescFunc (return value type):\n");
1197 dump_ELEMDESC(&funcdesc->elemdescFunc);
1200 static const char * const typekind_desc[] =
1213 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1216 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1217 for (i=0;i<pfd->funcdesc.cParams;i++)
1218 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1221 dump_FUNCDESC(&(pfd->funcdesc));
1223 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1224 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1226 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1230 dump_TLBFuncDescOne(pfd);
1234 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1238 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1243 static void dump_TLBImpLib(const TLBImpLib *import)
1245 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1246 debugstr_w(import->name));
1247 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1248 import->wVersionMinor, import->lcid, import->offset);
1251 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1255 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1257 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1258 if(ref->index == -1)
1259 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1261 TRACE_(typelib)("type no: %d\n", ref->index);
1263 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1265 TRACE_(typelib)("in lib\n");
1266 dump_TLBImpLib(ref->pImpTLInfo);
1271 static void dump_TLBImplType(const TLBImplType * impl)
1275 "implementing/inheriting interface hRef = %x implflags %x\n",
1276 impl->hRef, impl->implflags);
1281 static void dump_Variant(const VARIANT * pvar)
1285 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1289 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1290 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1292 TRACE(",%p", V_BYREF(pvar));
1294 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1296 TRACE(",%p", V_ARRAY(pvar));
1298 else switch (V_TYPE(pvar))
1300 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1301 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1302 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1303 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1305 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1307 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1308 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1309 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1310 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1311 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1312 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1313 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1314 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1315 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1316 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1317 V_CY(pvar).s.Lo); break;
1319 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1320 TRACE(",<invalid>");
1322 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1323 st.wHour, st.wMinute, st.wSecond);
1327 case VT_USERDEFINED:
1329 case VT_NULL: break;
1330 default: TRACE(",?"); break;
1336 static void dump_DispParms(const DISPPARAMS * pdp)
1340 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1342 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1344 TRACE("named args:\n");
1345 for (index = 0; index < pdp->cNamedArgs; index++)
1346 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1349 if (pdp->cArgs && pdp->rgvarg)
1352 for (index = 0; index < pdp->cArgs; index++)
1353 dump_Variant( &pdp->rgvarg[index] );
1357 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1359 TRACE("%p ref=%u\n", pty, pty->ref);
1360 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1361 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1362 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1363 TRACE("fct:%u var:%u impl:%u\n",
1364 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1365 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1366 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1367 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1369 dump_TLBFuncDesc(pty->funclist);
1370 dump_TLBVarDesc(pty->varlist);
1371 dump_TLBImplType(pty->impltypelist);
1374 static void dump_VARDESC(const VARDESC *v)
1376 MESSAGE("memid %d\n",v->memid);
1377 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1378 MESSAGE("oInst %d\n",v->u.oInst);
1379 dump_ELEMDESC(&(v->elemdescVar));
1380 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1381 MESSAGE("varkind %d\n",v->varkind);
1384 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1386 /* VT_LPWSTR is largest type that */
1387 /* may appear in type description*/
1388 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1389 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1390 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1391 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1392 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1393 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1397 static void TLB_abort(void)
1402 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1403 static void * TLB_Alloc(unsigned size)
1406 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1408 ERR("cannot allocate memory\n");
1413 static void TLB_Free(void * ptr)
1415 HeapFree(GetProcessHeap(), 0, ptr);
1418 /* returns the size required for a deep copy of a typedesc into a
1420 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1424 if (alloc_initial_space)
1425 size += sizeof(TYPEDESC);
1431 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1434 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1435 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1441 /* deep copy a typedesc into a flat buffer */
1442 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1447 buffer = (char *)buffer + sizeof(TYPEDESC);
1456 dest->u.lptdesc = buffer;
1457 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1460 dest->u.lpadesc = buffer;
1461 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1462 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1463 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1469 /* free custom data allocated by MSFT_CustData */
1470 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1472 TLBCustData *pCustDataNext;
1473 for (; pCustData; pCustData = pCustDataNext)
1475 VariantClear(&pCustData->data);
1477 pCustDataNext = pCustData->next;
1478 TLB_Free(pCustData);
1482 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1487 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1488 ret = SysAllocStringLen(NULL, len - 1);
1489 if (!ret) return ret;
1490 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1494 /**********************************************************************
1496 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1498 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1503 static inline void MSFT_Seek(TLBContext *pcx, long where)
1505 if (where != DO_NOT_SEEK)
1507 where += pcx->oStart;
1508 if (where > pcx->length)
1511 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1519 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1521 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1522 pcx->pos, count, pcx->oStart, pcx->length, where);
1524 MSFT_Seek(pcx, where);
1525 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1526 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1531 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1536 ret = MSFT_Read(buffer, count, pcx, where);
1537 FromLEDWords(buffer, ret);
1542 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1547 ret = MSFT_Read(buffer, count, pcx, where);
1548 FromLEWords(buffer, ret);
1553 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1555 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1556 memset(pGuid,0, sizeof(GUID));
1559 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1560 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1561 pGuid->Data2 = FromLEWord(pGuid->Data2);
1562 pGuid->Data3 = FromLEWord(pGuid->Data3);
1563 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1566 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1568 MSFT_NameIntro niName;
1572 ERR_(typelib)("bad offset %d\n", offset);
1576 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1577 pcx->pTblDir->pNametab.offset+offset);
1579 return niName.hreftype;
1582 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1585 MSFT_NameIntro niName;
1587 BSTR bstrName = NULL;
1591 ERR_(typelib)("bad offset %d\n", offset);
1594 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1595 pcx->pTblDir->pNametab.offset+offset);
1596 niName.namelen &= 0xFF; /* FIXME: correct ? */
1597 name=TLB_Alloc((niName.namelen & 0xff) +1);
1598 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1599 name[niName.namelen & 0xff]='\0';
1601 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1604 /* no invalid characters in string */
1607 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1609 /* don't check for invalid character since this has been done previously */
1610 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1614 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1618 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1625 if(offset<0) return NULL;
1626 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1627 if(length <= 0) return 0;
1628 string=TLB_Alloc(length +1);
1629 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1630 string[length]='\0';
1632 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1633 string, -1, NULL, 0);
1635 /* no invalid characters in string */
1638 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1640 /* don't check for invalid character since this has been done previously */
1641 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1645 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1649 * read a value and fill a VARIANT structure
1651 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1655 TRACE_(typelib)("\n");
1657 if(offset <0) { /* data are packed in here */
1658 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1659 V_I4(pVar) = offset & 0x3ffffff;
1662 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1663 pcx->pTblDir->pCustData.offset + offset );
1664 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1665 switch (V_VT(pVar)){
1666 case VT_EMPTY: /* FIXME: is this right? */
1667 case VT_NULL: /* FIXME: is this right? */
1668 case VT_I2 : /* this should not happen */
1679 case VT_VOID : /* FIXME: is this right? */
1687 case VT_DECIMAL : /* FIXME: is this right? */
1690 /* pointer types with known behaviour */
1693 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1696 DWORD origPos = MSFT_Tell(pcx), nullPos;
1699 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1701 nullPos = MSFT_Tell(pcx);
1702 size = nullPos - origPos;
1703 MSFT_Seek(pcx, origPos);
1705 ptr=TLB_Alloc(size);/* allocate temp buffer */
1706 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1707 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1708 /* FIXME: do we need a AtoW conversion here? */
1709 V_UNION(pVar, bstrVal[size])='\0';
1710 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1714 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1721 case VT_USERDEFINED :
1727 case VT_STREAMED_OBJECT :
1728 case VT_STORED_OBJECT :
1729 case VT_BLOB_OBJECT :
1734 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1738 if(size>0) /* (big|small) endian correct? */
1739 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1743 * create a linked list with custom data
1745 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1751 TRACE_(typelib)("\n");
1755 pNew=TLB_Alloc(sizeof(TLBCustData));
1756 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1757 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1758 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1759 /* add new custom data at head of the list */
1760 pNew->next=*ppCustData;
1762 offset = entry.next;
1767 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1771 pTd->vt=type & VT_TYPEMASK;
1773 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1775 if(pTd->vt == VT_USERDEFINED)
1776 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1778 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1781 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1783 /* resolve referenced type if any */
1786 switch (lpTypeDesc->vt)
1789 lpTypeDesc = lpTypeDesc->u.lptdesc;
1793 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1796 case VT_USERDEFINED:
1797 MSFT_DoRefType(pcx, pTI->pTypeLib,
1798 lpTypeDesc->u.hreftype);
1810 MSFT_DoFuncs(TLBContext* pcx,
1815 TLBFuncDesc** pptfd)
1818 * member information is stored in a data structure at offset
1819 * indicated by the memoffset field of the typeinfo structure
1820 * There are several distinctive parts.
1821 * The first part starts with a field that holds the total length
1822 * of this (first) part excluding this field. Then follow the records,
1823 * for each member there is one record.
1825 * The first entry is always the length of the record (including this
1827 * The rest of the record depends on the type of the member. If there is
1828 * a field indicating the member type (function, variable, interface, etc)
1829 * I have not found it yet. At this time we depend on the information
1830 * in the type info and the usual order how things are stored.
1832 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1835 * Third is an equal sized array with file offsets to the name entry
1838 * The fourth and last (?) part is an array with offsets to the records
1839 * in the first part of this file segment.
1842 int infolen, nameoffset, reclength, nrattributes, i;
1843 int recoffset = offset + sizeof(INT);
1845 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1846 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1847 TLBFuncDesc *ptfd_prev = NULL;
1849 TRACE_(typelib)("\n");
1851 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1853 for ( i = 0; i < cFuncs ; i++ )
1855 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1857 /* name, eventually add to a hash table */
1858 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1859 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1861 /* nameoffset is sometimes -1 on the second half of a propget/propput
1862 * pair of functions */
1863 if ((nameoffset == -1) && (i > 0))
1864 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1866 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1868 /* read the function information record */
1869 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1871 reclength &= 0xffff;
1873 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1875 /* do the attributes */
1876 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1879 if ( nrattributes > 0 )
1881 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1883 if ( nrattributes > 1 )
1885 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1886 pFuncRec->OptAttr[1]) ;
1888 if ( nrattributes > 2 )
1890 if ( pFuncRec->FKCCIC & 0x2000 )
1892 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1893 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1894 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1898 (*pptfd)->Entry = MSFT_ReadString(pcx,
1899 pFuncRec->OptAttr[2]);
1901 if( nrattributes > 5 )
1903 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1905 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1908 pFuncRec->OptAttr[6],
1909 &(*pptfd)->pCustData);
1915 (*pptfd)->Entry = (BSTR)-1;
1920 /* fill the FuncDesc Structure */
1921 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1922 offset + infolen + ( i + 1) * sizeof(INT));
1924 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1925 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1926 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1927 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1928 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1929 (*pptfd)->funcdesc.oVft = (pFuncRec->VtableOffset * sizeof(void *))/4;
1930 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1934 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1936 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1938 /* do the parameters/arguments */
1939 if(pFuncRec->nrargs)
1942 MSFT_ParameterInfo paraminfo;
1944 (*pptfd)->funcdesc.lprgelemdescParam =
1945 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1947 (*pptfd)->pParamDesc =
1948 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1950 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1951 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1953 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1955 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1962 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1965 if (paraminfo.oName == -1)
1966 /* this occurs for [propput] or [propget] methods, so
1967 * we should just set the name of the parameter to the
1968 * name of the method. */
1969 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1971 (*pptfd)->pParamDesc[j].Name =
1972 MSFT_ReadName( pcx, paraminfo.oName );
1973 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1975 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1978 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1979 (pFuncRec->FKCCIC & 0x1000) )
1981 INT* pInt = (INT *)((char *)pFuncRec +
1983 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1985 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1987 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1988 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1990 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1994 elemdesc->u.paramdesc.pparamdescex = NULL;
1996 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1999 pFuncRec->OptAttr[7+j],
2000 &(*pptfd)->pParamDesc[j].pCustData);
2003 /* SEEK value = jump to offset,
2004 * from there jump to the end of record,
2005 * go back by (j-1) arguments
2007 MSFT_ReadLEDWords( ¶minfo ,
2008 sizeof(MSFT_ParameterInfo), pcx,
2009 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2010 * sizeof(MSFT_ParameterInfo)));
2014 /* scode is not used: archaic win16 stuff FIXME: right? */
2015 (*pptfd)->funcdesc.cScodes = 0 ;
2016 (*pptfd)->funcdesc.lprgscode = NULL ;
2019 pptfd = & ((*pptfd)->next);
2020 recoffset += reclength;
2022 HeapFree(GetProcessHeap(), 0, recbuf);
2025 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2026 int cVars, int offset, TLBVarDesc ** pptvd)
2028 int infolen, nameoffset, reclength;
2030 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2034 TRACE_(typelib)("\n");
2036 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2037 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2038 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2039 recoffset += offset+sizeof(INT);
2040 for(i=0;i<cVars;i++){
2041 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2042 /* name, eventually add to a hash table */
2043 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2044 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2045 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2046 /* read the variable information record */
2047 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2049 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2051 if(reclength >(6*sizeof(INT)) )
2052 (*pptvd)->HelpContext=pVarRec->HelpContext;
2053 if(reclength >(7*sizeof(INT)) )
2054 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2055 if(reclength >(8*sizeof(INT)) )
2056 if(reclength >(9*sizeof(INT)) )
2057 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2058 /* fill the VarDesc Structure */
2059 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2060 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2061 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2062 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2063 MSFT_GetTdesc(pcx, pVarRec->DataType,
2064 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2065 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2066 if(pVarRec->VarKind == VAR_CONST ){
2067 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2068 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2069 pVarRec->OffsValue, pcx);
2071 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2072 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2073 pptvd=&((*pptvd)->next);
2074 recoffset += reclength;
2077 /* fill in data for a hreftype (offset). When the referenced type is contained
2078 * in the typelib, it's just an (file) offset in the type info base dir.
2079 * If comes from import, it's an offset+1 in the ImpInfo table
2081 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2086 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2088 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2090 if(ref->reference == offset) return;
2093 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2094 list_add_tail(&pTL->ref_list, &ref->entry);
2096 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2097 /* external typelib */
2098 MSFT_ImpInfo impinfo;
2099 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2101 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2103 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2104 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2105 while (pImpLib){ /* search the known offsets of all import libraries */
2106 if(pImpLib->offset==impinfo.oImpFile) break;
2107 pImpLib=pImpLib->next;
2110 ref->reference = offset;
2111 ref->pImpTLInfo = pImpLib;
2112 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2113 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2114 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2115 ref->index = TLB_REF_USE_GUID;
2117 ref->index = impinfo.oGuid;
2119 ERR("Cannot find a reference\n");
2120 ref->reference = -1;
2121 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2124 /* in this typelib */
2125 ref->index = MSFT_HREFTYPE_INDEX(offset);
2126 ref->reference = offset;
2127 ref->pImpTLInfo = TLB_REF_INTERNAL;
2131 /* process Implemented Interfaces of a com class */
2132 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2136 MSFT_RefRecord refrec;
2137 TLBImplType **ppImpl = &pTI->impltypelist;
2139 TRACE_(typelib)("\n");
2141 for(i=0;i<count;i++){
2142 if(offset<0) break; /* paranoia */
2143 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2144 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2145 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2146 (*ppImpl)->hRef = refrec.reftype;
2147 (*ppImpl)->implflags=refrec.flags;
2148 (*ppImpl)->ctCustData=
2149 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2150 offset=refrec.onext;
2151 ppImpl=&((*ppImpl)->next);
2155 * process a typeinfo record
2157 static ITypeInfoImpl * MSFT_DoTypeInfo(
2160 ITypeLibImpl * pLibInfo)
2162 MSFT_TypeInfoBase tiBase;
2163 ITypeInfoImpl *ptiRet;
2165 TRACE_(typelib)("count=%u\n", count);
2167 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2168 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2169 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2171 /* this is where we are coming from */
2172 ptiRet->pTypeLib = pLibInfo;
2173 ptiRet->index=count;
2174 /* fill in the typeattr fields */
2176 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2177 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2178 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2179 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2180 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2181 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2182 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2183 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2184 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2185 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2186 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2187 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2188 ptiRet->TypeAttr.cbSizeVft=(tiBase.cbSizeVft * sizeof(void *))/4; /* FIXME: this is only the non inherited part */
2189 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2190 MSFT_GetTdesc(pcx, tiBase.datatype1,
2191 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2194 /* IDLDESC idldescType; *//* never saw this one != zero */
2196 /* name, eventually add to a hash table */
2197 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2198 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2199 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2201 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2202 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2203 ptiRet->dwHelpContext=tiBase.helpcontext;
2205 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2206 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2208 /* note: InfoType's Help file and HelpStringDll come from the containing
2209 * library. Further HelpString and Docstring appear to be the same thing :(
2212 if(ptiRet->TypeAttr.cFuncs >0 )
2213 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2214 ptiRet->TypeAttr.cVars,
2215 tiBase.memoffset, & ptiRet->funclist);
2217 if(ptiRet->TypeAttr.cVars >0 )
2218 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2219 ptiRet->TypeAttr.cVars,
2220 tiBase.memoffset, & ptiRet->varlist);
2221 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2222 switch(ptiRet->TypeAttr.typekind)
2225 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2228 case TKIND_DISPATCH:
2229 /* This is not -1 when the interface is a non-base dual interface or
2230 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2231 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2235 if (tiBase.datatype1 != -1)
2237 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2238 ptiRet->impltypelist->hRef = tiBase.datatype1;
2239 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2243 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2244 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2245 ptiRet->impltypelist->hRef = tiBase.datatype1;
2250 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2252 TRACE_(typelib)("%s guid: %s kind:%s\n",
2253 debugstr_w(ptiRet->Name),
2254 debugstr_guid(&ptiRet->TypeAttr.guid),
2255 typekind_desc[ptiRet->TypeAttr.typekind]);
2256 if (TRACE_ON(typelib))
2257 dump_TypeInfo(ptiRet);
2262 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2263 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2264 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2267 static ITypeLibImpl *tlb_cache_first;
2268 static CRITICAL_SECTION cache_section;
2269 static CRITICAL_SECTION_DEBUG cache_section_debug =
2271 0, 0, &cache_section,
2272 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2273 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2275 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2278 typedef struct TLB_PEFile
2280 const IUnknownVtbl *lpvtbl;
2283 HRSRC typelib_resource;
2284 HGLOBAL typelib_global;
2285 LPVOID typelib_base;
2288 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2290 if (IsEqualIID(riid, &IID_IUnknown))
2293 IUnknown_AddRef(iface);
2297 return E_NOINTERFACE;
2300 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2302 TLB_PEFile *This = (TLB_PEFile *)iface;
2303 return InterlockedIncrement(&This->refs);
2306 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2308 TLB_PEFile *This = (TLB_PEFile *)iface;
2309 ULONG refs = InterlockedDecrement(&This->refs);
2312 if (This->typelib_global)
2313 FreeResource(This->typelib_global);
2315 FreeLibrary(This->dll);
2316 HeapFree(GetProcessHeap(), 0, This);
2321 static const IUnknownVtbl TLB_PEFile_Vtable =
2323 TLB_PEFile_QueryInterface,
2328 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2332 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2334 return E_OUTOFMEMORY;
2336 This->lpvtbl = &TLB_PEFile_Vtable;
2339 This->typelib_resource = NULL;
2340 This->typelib_global = NULL;
2341 This->typelib_base = NULL;
2343 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2344 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2348 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2349 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2350 if (This->typelib_resource)
2352 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2353 if (This->typelib_global)
2355 This->typelib_base = LockResource(This->typelib_global);
2357 if (This->typelib_base)
2359 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2360 *ppBase = This->typelib_base;
2361 *ppFile = (IUnknown *)&This->lpvtbl;
2368 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2369 return TYPE_E_CANTLOADLIBRARY;
2372 typedef struct TLB_NEFile
2374 const IUnknownVtbl *lpvtbl;
2376 LPVOID typelib_base;
2379 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2381 if (IsEqualIID(riid, &IID_IUnknown))
2384 IUnknown_AddRef(iface);
2388 return E_NOINTERFACE;
2391 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2393 TLB_NEFile *This = (TLB_NEFile *)iface;
2394 return InterlockedIncrement(&This->refs);
2397 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2399 TLB_NEFile *This = (TLB_NEFile *)iface;
2400 ULONG refs = InterlockedDecrement(&This->refs);
2403 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2404 HeapFree(GetProcessHeap(), 0, This);
2409 static const IUnknownVtbl TLB_NEFile_Vtable =
2411 TLB_NEFile_QueryInterface,
2416 /***********************************************************************
2417 * read_xx_header [internal]
2419 static int read_xx_header( HFILE lzfd )
2421 IMAGE_DOS_HEADER mzh;
2424 LZSeek( lzfd, 0, SEEK_SET );
2425 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2427 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2430 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2431 if ( 2 != LZRead( lzfd, magic, 2 ) )
2434 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2436 if ( magic[0] == 'N' && magic[1] == 'E' )
2437 return IMAGE_OS2_SIGNATURE;
2438 if ( magic[0] == 'P' && magic[1] == 'E' )
2439 return IMAGE_NT_SIGNATURE;
2442 WARN("Can't handle %s files.\n", magic );
2447 /***********************************************************************
2448 * find_ne_resource [internal]
2450 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2451 DWORD *resLen, DWORD *resOff )
2453 IMAGE_OS2_HEADER nehd;
2454 NE_TYPEINFO *typeInfo;
2455 NE_NAMEINFO *nameInfo;
2461 /* Read in NE header */
2462 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2463 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2465 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2468 TRACE("No resources in NE dll\n" );
2472 /* Read in resource table */
2473 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2474 if ( !resTab ) return FALSE;
2476 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2477 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2479 HeapFree( GetProcessHeap(), 0, resTab );
2484 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2486 if (HIWORD(typeid) != 0) /* named type */
2488 BYTE len = strlen( typeid );
2489 while (typeInfo->type_id)
2491 if (!(typeInfo->type_id & 0x8000))
2493 BYTE *p = resTab + typeInfo->type_id;
2494 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2496 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2497 typeInfo->count * sizeof(NE_NAMEINFO));
2500 else /* numeric type id */
2502 WORD id = LOWORD(typeid) | 0x8000;
2503 while (typeInfo->type_id)
2505 if (typeInfo->type_id == id) goto found_type;
2506 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2507 typeInfo->count * sizeof(NE_NAMEINFO));
2510 TRACE("No typeid entry found for %p\n", typeid );
2511 HeapFree( GetProcessHeap(), 0, resTab );
2515 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2517 if (HIWORD(resid) != 0) /* named resource */
2519 BYTE len = strlen( resid );
2520 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2522 BYTE *p = resTab + nameInfo->id;
2523 if (nameInfo->id & 0x8000) continue;
2524 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2527 else /* numeric resource id */
2529 WORD id = LOWORD(resid) | 0x8000;
2530 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2531 if (nameInfo->id == id) goto found_name;
2533 TRACE("No resid entry found for %p\n", typeid );
2534 HeapFree( GetProcessHeap(), 0, resTab );
2538 /* Return resource data */
2539 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2540 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2542 HeapFree( GetProcessHeap(), 0, resTab );
2546 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2550 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2551 TLB_NEFile *This = NULL;
2553 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2554 if (!This) return E_OUTOFMEMORY;
2556 This->lpvtbl = &TLB_NEFile_Vtable;
2558 This->typelib_base = NULL;
2560 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2561 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2563 DWORD reslen, offset;
2564 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2566 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2567 if( !This->typelib_base )
2571 LZSeek( lzfd, offset, SEEK_SET );
2572 reslen = LZRead( lzfd, This->typelib_base, reslen );
2574 *ppBase = This->typelib_base;
2575 *pdwTLBLength = reslen;
2576 *ppFile = (IUnknown *)&This->lpvtbl;
2582 if( lzfd >= 0) LZClose( lzfd );
2583 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2587 typedef struct TLB_Mapping
2589 const IUnknownVtbl *lpvtbl;
2593 LPVOID typelib_base;
2596 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2598 if (IsEqualIID(riid, &IID_IUnknown))
2601 IUnknown_AddRef(iface);
2605 return E_NOINTERFACE;
2608 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2610 TLB_Mapping *This = (TLB_Mapping *)iface;
2611 return InterlockedIncrement(&This->refs);
2614 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2616 TLB_Mapping *This = (TLB_Mapping *)iface;
2617 ULONG refs = InterlockedDecrement(&This->refs);
2620 if (This->typelib_base)
2621 UnmapViewOfFile(This->typelib_base);
2623 CloseHandle(This->mapping);
2624 if (This->file != INVALID_HANDLE_VALUE)
2625 CloseHandle(This->file);
2626 HeapFree(GetProcessHeap(), 0, This);
2631 static const IUnknownVtbl TLB_Mapping_Vtable =
2633 TLB_Mapping_QueryInterface,
2638 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2642 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2644 return E_OUTOFMEMORY;
2646 This->lpvtbl = &TLB_Mapping_Vtable;
2648 This->file = INVALID_HANDLE_VALUE;
2649 This->mapping = NULL;
2650 This->typelib_base = NULL;
2652 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2653 if (INVALID_HANDLE_VALUE != This->file)
2655 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2658 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2659 if(This->typelib_base)
2661 /* retrieve file size */
2662 *pdwTLBLength = GetFileSize(This->file, NULL);
2663 *ppBase = This->typelib_base;
2664 *ppFile = (IUnknown *)&This->lpvtbl;
2670 IUnknown_Release((IUnknown *)&This->lpvtbl);
2671 return TYPE_E_CANTLOADLIBRARY;
2674 /****************************************************************************
2677 * find the type of the typelib file and map the typelib resource into
2680 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2681 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2682 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2684 ITypeLibImpl *entry;
2687 LPWSTR index_str, file = (LPWSTR)pszFileName;
2688 LPVOID pBase = NULL;
2689 DWORD dwTLBLength = 0;
2690 IUnknown *pFile = NULL;
2694 index_str = strrchrW(pszFileName, '\\');
2695 if(index_str && *++index_str != '\0')
2698 long idx = strtolW(index_str, &end_ptr, 10);
2699 if(*end_ptr == '\0')
2701 int str_len = index_str - pszFileName - 1;
2703 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2704 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2709 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2711 if(strchrW(file, '\\'))
2713 lstrcpyW(pszPath, file);
2717 int len = GetSystemDirectoryW(pszPath, cchPath);
2718 pszPath[len] = '\\';
2719 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2723 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2725 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2727 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2728 EnterCriticalSection(&cache_section);
2729 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2731 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2733 TRACE("cache hit\n");
2734 *ppTypeLib = (ITypeLib2*)entry;
2735 ITypeLib_AddRef(*ppTypeLib);
2736 LeaveCriticalSection(&cache_section);
2740 LeaveCriticalSection(&cache_section);
2742 /* now actually load and parse the typelib */
2744 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2745 if (ret == TYPE_E_CANTLOADLIBRARY)
2746 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2747 if (ret == TYPE_E_CANTLOADLIBRARY)
2748 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2751 if (dwTLBLength >= 4)
2753 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2754 if (dwSignature == MSFT_SIGNATURE)
2755 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2756 else if (dwSignature == SLTG_SIGNATURE)
2757 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2760 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2761 ret = TYPE_E_CANTLOADLIBRARY;
2765 ret = TYPE_E_CANTLOADLIBRARY;
2766 IUnknown_Release(pFile);
2770 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2772 TRACE("adding to cache\n");
2773 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2774 lstrcpyW(impl->path, pszPath);
2775 /* We should really canonicalise the path here. */
2776 impl->index = index;
2778 /* FIXME: check if it has added already in the meantime */
2779 EnterCriticalSection(&cache_section);
2780 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2782 tlb_cache_first = impl;
2783 LeaveCriticalSection(&cache_section);
2786 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2791 /*================== ITypeLib(2) Methods ===================================*/
2793 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2795 ITypeLibImpl* pTypeLibImpl;
2797 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2798 if (!pTypeLibImpl) return NULL;
2800 pTypeLibImpl->lpVtbl = &tlbvt;
2801 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2802 pTypeLibImpl->ref = 1;
2804 list_init(&pTypeLibImpl->ref_list);
2805 pTypeLibImpl->dispatch_href = -1;
2807 return pTypeLibImpl;
2810 /****************************************************************************
2811 * ITypeLib2_Constructor_MSFT
2813 * loading an MSFT typelib from an in-memory image
2815 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2819 MSFT_Header tlbHeader;
2820 MSFT_SegDir tlbSegDir;
2821 ITypeLibImpl * pTypeLibImpl;
2823 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2825 pTypeLibImpl = TypeLibImpl_Constructor();
2826 if (!pTypeLibImpl) return NULL;
2828 /* get pointer to beginning of typelib data */
2832 cx.pLibInfo = pTypeLibImpl;
2833 cx.length = dwTLBLength;
2836 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2837 TRACE_(typelib)("header:\n");
2838 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2839 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2840 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2843 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2845 /* there is a small amount of information here until the next important
2847 * the segment directory . Try to calculate the amount of data */
2848 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2850 /* now read the segment directory */
2851 TRACE("read segment directory (at %ld)\n",lPSegDir);
2852 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2853 cx.pTblDir = &tlbSegDir;
2855 /* just check two entries */
2856 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2858 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2859 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2863 /* now fill our internal data */
2864 /* TLIBATTR fields */
2865 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2867 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2868 /* Windows seems to have zero here, is this correct? */
2869 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2870 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2872 pTypeLibImpl->LibAttr.lcid = 0;
2874 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2875 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2876 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2877 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2879 /* name, eventually add to a hash table */
2880 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2883 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2884 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2886 if( tlbHeader.varflags & HELPDLLFLAG)
2889 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2890 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2893 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2896 if(tlbHeader.CustomDataOffset >= 0)
2898 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2901 /* fill in type descriptions */
2902 if(tlbSegDir.pTypdescTab.length > 0)
2904 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2906 pTypeLibImpl->ctTypeDesc = cTD;
2907 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2908 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2911 /* FIXME: add several sanity checks here */
2912 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2913 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2915 /* FIXME: check safearray */
2917 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2919 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2921 else if(td[0] == VT_CARRAY)
2923 /* array descr table here */
2924 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2926 else if(td[0] == VT_USERDEFINED)
2928 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2930 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2933 /* second time around to fill the array subscript info */
2936 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2937 if(tlbSegDir.pArrayDescriptions.offset>0)
2939 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2940 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2943 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2945 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2947 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2949 for(j = 0; j<td[2]; j++)
2951 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2952 sizeof(INT), &cx, DO_NOT_SEEK);
2953 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2954 sizeof(INT), &cx, DO_NOT_SEEK);
2959 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2960 ERR("didn't find array description data\n");
2965 /* imported type libs */
2966 if(tlbSegDir.pImpFiles.offset>0)
2968 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2969 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2972 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2976 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2977 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2978 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2980 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2981 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2982 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2983 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2986 name = TLB_Alloc(size+1);
2987 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2988 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2990 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2991 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2993 ppImpLib = &(*ppImpLib)->next;
2997 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2998 if(pTypeLibImpl->dispatch_href != -1)
2999 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3002 if(tlbHeader.nrtypeinfos >= 0 )
3004 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3005 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3008 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3010 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3012 ppTI = &((*ppTI)->next);
3013 (pTypeLibImpl->TypeInfoCount)++;
3017 TRACE("(%p)\n", pTypeLibImpl);
3018 return (ITypeLib2*) pTypeLibImpl;
3022 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3028 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3029 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3033 guid->Data4[0] = s >> 8;
3034 guid->Data4[1] = s & 0xff;
3037 for(i = 0; i < 6; i++) {
3038 memcpy(b, str + 24 + 2 * i, 2);
3039 guid->Data4[i + 2] = strtol(b, NULL, 16);
3044 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3050 bytelen = *(const WORD*)ptr;
3051 if(bytelen == 0xffff) return 2;
3052 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3053 *pBstr = SysAllocStringLen(NULL, len - 1);
3055 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3059 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3064 bytelen = *(const WORD*)ptr;
3065 if(bytelen == 0xffff) return 2;
3066 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3067 memcpy(*str, ptr + 2, bytelen);
3068 (*str)[bytelen] = '\0';
3072 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3074 char *ptr = pLibBlk;
3077 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3078 FIXME("libblk magic = %04x\n", w);
3083 if((w = *(WORD*)ptr) != 0xffff) {
3084 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3089 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3091 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3093 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3096 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3099 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3100 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3102 pTypeLibImpl->LibAttr.lcid = 0;
3105 ptr += 4; /* skip res12 */
3107 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3110 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3113 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3116 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3117 ptr += sizeof(GUID);
3119 return ptr - (char*)pLibBlk;
3122 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3127 } sltg_ref_lookup_t;
3129 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3130 HREFTYPE *typelib_ref)
3132 if(typeinfo_ref < table->num)
3134 *typelib_ref = table->refs[typeinfo_ref];
3138 ERR_(typelib)("Unable to find reference\n");
3143 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3148 if((*pType & 0xe00) == 0xe00) {
3150 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3152 pTD = pTD->u.lptdesc;
3154 switch(*pType & 0x3f) {
3157 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3159 pTD = pTD->u.lptdesc;
3162 case VT_USERDEFINED:
3163 pTD->vt = VT_USERDEFINED;
3164 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3170 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3173 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3175 pTD->vt = VT_CARRAY;
3176 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3178 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3179 pTD->u.lpadesc->cDims = pSA->cDims;
3180 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3181 pSA->cDims * sizeof(SAFEARRAYBOUND));
3183 pTD = &pTD->u.lpadesc->tdescElem;
3189 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3193 pTD->vt = VT_SAFEARRAY;
3194 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3196 pTD = pTD->u.lptdesc;
3200 pTD->vt = *pType & 0x3f;
3209 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3210 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3212 /* Handle [in/out] first */
3213 if((*pType & 0xc000) == 0xc000)
3214 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3215 else if(*pType & 0x8000)
3216 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3217 else if(*pType & 0x4000)
3218 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3220 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3223 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3226 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3228 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3232 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3237 TLBRefType *ref_type;
3238 sltg_ref_lookup_t *table;
3239 HREFTYPE typelib_ref;
3241 if(pRef->magic != SLTG_REF_MAGIC) {
3242 FIXME("Ref magic = %x\n", pRef->magic);
3245 name = ( (char*)pRef->names + pRef->number);
3247 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3248 table->num = pRef->number >> 3;
3250 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3252 /* We don't want the first href to be 0 */
3253 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3255 for(ref = 0; ref < pRef->number >> 3; ref++) {
3257 unsigned int lib_offs, type_num;
3259 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3261 name += SLTG_ReadStringA(name, &refname);
3262 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3263 FIXME_(typelib)("Can't sscanf ref\n");
3264 if(lib_offs != 0xffff) {
3265 TLBImpLib **import = &pTL->pImpLibs;
3268 if((*import)->offset == lib_offs)
3270 import = &(*import)->next;
3273 char fname[MAX_PATH+1];
3276 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3278 (*import)->offset = lib_offs;
3279 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3281 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3282 &(*import)->wVersionMajor,
3283 &(*import)->wVersionMinor,
3284 &(*import)->lcid, fname) != 4) {
3285 FIXME_(typelib)("can't sscanf ref %s\n",
3286 pNameTable + lib_offs + 40);
3288 len = strlen(fname);
3289 if(fname[len-1] != '#')
3290 FIXME("fname = %s\n", fname);
3291 fname[len-1] = '\0';
3292 (*import)->name = TLB_MultiByteToBSTR(fname);
3294 ref_type->pImpTLInfo = *import;
3296 /* Store a reference to IDispatch */
3297 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3298 pTL->dispatch_href = typelib_ref;
3300 } else { /* internal ref */
3301 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3303 ref_type->reference = typelib_ref;
3304 ref_type->index = type_num;
3306 HeapFree(GetProcessHeap(), 0, refname);
3307 list_add_tail(&pTL->ref_list, &ref_type->entry);
3309 table->refs[ref] = typelib_ref;
3312 if((BYTE)*name != SLTG_REF_MAGIC)
3313 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3314 dump_TLBRefType(pTL);
3318 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3319 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3321 SLTG_ImplInfo *info;
3322 TLBImplType **ppImplType = &pTI->impltypelist;
3323 /* I don't really get this structure, usually it's 0x16 bytes
3324 long, but iuser.tlb contains some that are 0x18 bytes long.
3325 That's ok because we can use the next ptr to jump to the next
3326 one. But how do we know the length of the last one? The WORD
3327 at offs 0x8 might be the clue. For now I'm just assuming that
3328 the last one is the regular 0x16 bytes. */
3330 info = (SLTG_ImplInfo*)pBlk;
3332 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3333 sizeof(**ppImplType));
3334 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3335 (*ppImplType)->implflags = info->impltypeflags;
3336 pTI->TypeAttr.cImplTypes++;
3337 ppImplType = &(*ppImplType)->next;
3339 if(info->next == 0xffff)
3342 FIXME_(typelib)("Interface inheriting more than one interface\n");
3343 info = (SLTG_ImplInfo*)(pBlk + info->next);
3345 info++; /* see comment at top of function */
3349 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3350 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3352 TLBVarDesc **ppVarDesc = &pTI->varlist;
3353 BSTR bstrPrevName = NULL;
3354 SLTG_Variable *pItem;
3358 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3359 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3361 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3362 sizeof(**ppVarDesc));
3363 (*ppVarDesc)->vardesc.memid = pItem->memid;
3365 if (pItem->magic != SLTG_VAR_MAGIC &&
3366 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3367 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3371 if (pItem->name == 0xfffe)
3372 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3374 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3376 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3377 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3378 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3380 if(pItem->flags & 0x02)
3381 pType = &pItem->type;
3383 pType = (WORD*)(pBlk + pItem->type);
3385 if (pItem->flags & ~0xda)
3386 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3388 SLTG_DoElem(pType, pBlk,
3389 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3391 if (TRACE_ON(typelib)) {
3393 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3394 TRACE_(typelib)("elemdescVar: %s\n", buf);
3397 if (pItem->flags & 0x40) {
3398 TRACE_(typelib)("VAR_DISPATCH\n");
3399 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3401 else if (pItem->flags & 0x10) {
3402 TRACE_(typelib)("VAR_CONST\n");
3403 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3404 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3406 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3407 if (pItem->flags & 0x08)
3408 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3410 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3416 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3418 TRACE_(typelib)("len = %u\n", len);
3419 if (len == 0xffff) {
3422 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3423 str = SysAllocStringLen(NULL, alloc_len);
3424 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3426 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3427 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3436 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3437 *(INT*)(pBlk + pItem->byte_offs);
3440 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3445 TRACE_(typelib)("VAR_PERINSTANCE\n");
3446 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3447 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3450 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3451 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3453 if (pItem->flags & 0x80)
3454 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3456 bstrPrevName = (*ppVarDesc)->Name;
3457 ppVarDesc = &((*ppVarDesc)->next);
3459 pTI->TypeAttr.cVars = cVars;
3462 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3463 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3465 SLTG_Function *pFunc;
3467 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3469 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3470 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3475 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3476 sizeof(**ppFuncDesc));
3478 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3479 case SLTG_FUNCTION_MAGIC:
3480 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3482 case SLTG_DISPATCH_FUNCTION_MAGIC:
3483 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3485 case SLTG_STATIC_FUNCTION_MAGIC:
3486 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3489 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3490 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3494 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3496 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3497 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3498 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3499 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3500 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3501 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3503 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3504 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3506 if(pFunc->retnextopt & 0x80)
3507 pType = &pFunc->rettype;
3509 pType = (WORD*)(pBlk + pFunc->rettype);
3511 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3513 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3514 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3515 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3516 (*ppFuncDesc)->pParamDesc =
3517 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3518 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3520 pArg = (WORD*)(pBlk + pFunc->arg_off);
3522 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3523 char *paramName = pNameTable + *pArg;
3525 /* If arg type follows then paramName points to the 2nd
3526 letter of the name, else the next WORD is an offset to
3527 the arg type and paramName points to the first letter.
3528 So let's take one char off paramName and see if we're
3529 pointing at an alpha-numeric char. However if *pArg is
3530 0xffff or 0xfffe then the param has no name, the former
3531 meaning that the next WORD is the type, the latter
3532 meaning that the next WORD is an offset to the type. */
3537 else if(*pArg == 0xfffe) {
3541 else if(paramName[-1] && !isalnum(paramName[-1]))
3546 if(HaveOffs) { /* the next word is an offset to type */
3547 pType = (WORD*)(pBlk + *pArg);
3548 SLTG_DoElem(pType, pBlk,
3549 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3554 pArg = SLTG_DoElem(pArg, pBlk,
3555 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3558 /* Are we an optional param ? */
3559 if((*ppFuncDesc)->funcdesc.cParams - param <=
3560 (*ppFuncDesc)->funcdesc.cParamsOpt)
3561 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3564 (*ppFuncDesc)->pParamDesc[param].Name =
3565 TLB_MultiByteToBSTR(paramName);
3567 (*ppFuncDesc)->pParamDesc[param].Name =
3568 SysAllocString((*ppFuncDesc)->Name);
3572 ppFuncDesc = &((*ppFuncDesc)->next);
3573 if(pFunc->next == 0xffff) break;
3575 pTI->TypeAttr.cFuncs = cFuncs;
3578 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3579 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3580 SLTG_TypeInfoTail *pTITail)
3583 sltg_ref_lookup_t *ref_lookup = NULL;
3585 if(pTIHeader->href_table != 0xffffffff) {
3586 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3592 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3593 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3595 HeapFree(GetProcessHeap(), 0, ref_lookup);
3599 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3600 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3601 const SLTG_TypeInfoTail *pTITail)
3604 sltg_ref_lookup_t *ref_lookup = NULL;
3606 if(pTIHeader->href_table != 0xffffffff) {
3607 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3613 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3614 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3617 if (pTITail->funcs_off != 0xffff)
3618 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3620 HeapFree(GetProcessHeap(), 0, ref_lookup);
3622 if (TRACE_ON(typelib))
3623 dump_TLBFuncDesc(pTI->funclist);
3626 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3627 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3628 const SLTG_TypeInfoTail *pTITail)
3630 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3633 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3634 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3635 const SLTG_TypeInfoTail *pTITail)
3638 sltg_ref_lookup_t *ref_lookup = NULL;
3640 if (pTITail->simple_alias) {
3641 /* if simple alias, no more processing required */
3642 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3646 if(pTIHeader->href_table != 0xffffffff) {
3647 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3651 /* otherwise it is an offset to a type */
3652 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3654 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3656 HeapFree(GetProcessHeap(), 0, ref_lookup);
3659 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3660 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3661 const SLTG_TypeInfoTail *pTITail)
3663 sltg_ref_lookup_t *ref_lookup = NULL;
3664 if (pTIHeader->href_table != 0xffffffff)
3665 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3668 if (pTITail->vars_off != 0xffff)
3669 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3671 if (pTITail->funcs_off != 0xffff)
3672 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3674 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3675 * of dispinterface functions including the IDispatch ones, so
3676 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3677 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3679 HeapFree(GetProcessHeap(), 0, ref_lookup);
3680 if (TRACE_ON(typelib))
3681 dump_TLBFuncDesc(pTI->funclist);
3684 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3685 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3686 const SLTG_TypeInfoTail *pTITail)
3688 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3691 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3692 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3693 const SLTG_TypeInfoTail *pTITail)
3695 sltg_ref_lookup_t *ref_lookup = NULL;
3696 if (pTIHeader->href_table != 0xffffffff)
3697 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3700 if (pTITail->vars_off != 0xffff)
3701 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3703 if (pTITail->funcs_off != 0xffff)
3704 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3705 HeapFree(GetProcessHeap(), 0, ref_lookup);
3706 if (TRACE_ON(typelib))
3710 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3711 managable copy of it into this */
3724 } SLTG_InternalOtherTypeInfo;
3726 /****************************************************************************
3727 * ITypeLib2_Constructor_SLTG
3729 * loading a SLTG typelib from an in-memory image
3731 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3733 ITypeLibImpl *pTypeLibImpl;
3734 SLTG_Header *pHeader;
3735 SLTG_BlkEntry *pBlkEntry;
3739 LPVOID pBlk, pFirstBlk;
3740 SLTG_LibBlk *pLibBlk;
3741 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3742 char *pAfterOTIBlks = NULL;
3743 char *pNameTable, *ptr;
3746 ITypeInfoImpl **ppTypeInfoImpl;
3748 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3751 pTypeLibImpl = TypeLibImpl_Constructor();
3752 if (!pTypeLibImpl) return NULL;
3756 TRACE_(typelib)("header:\n");
3757 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3758 pHeader->nrOfFileBlks );
3759 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3760 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3761 pHeader->SLTG_magic);
3765 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3766 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3768 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3769 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3771 /* Next we have a magic block */
3772 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3774 /* Let's see if we're still in sync */
3775 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3776 sizeof(SLTG_COMPOBJ_MAGIC))) {
3777 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3780 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3781 sizeof(SLTG_DIR_MAGIC))) {
3782 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3786 pIndex = (SLTG_Index*)(pMagic+1);
3788 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3790 pFirstBlk = pPad9 + 1;
3792 /* We'll set up a ptr to the main library block, which is the last one. */
3794 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3795 pBlkEntry[order].next != 0;
3796 order = pBlkEntry[order].next - 1, i++) {
3797 pBlk = (char*)pBlk + pBlkEntry[order].len;
3801 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3803 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3808 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3810 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3811 sizeof(*pOtherTypeInfoBlks) *
3812 pTypeLibImpl->TypeInfoCount);
3815 ptr = (char*)pLibBlk + len;
3817 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3821 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3823 w = *(WORD*)(ptr + 2);
3826 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3828 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3829 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3831 w = *(WORD*)(ptr + 4 + len);
3833 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3835 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3837 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3838 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3840 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3841 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3842 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3844 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3846 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3849 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3850 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3851 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3852 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3853 len += sizeof(SLTG_OtherTypeInfo);
3857 pAfterOTIBlks = ptr;
3859 /* Skip this WORD and get the next DWORD */
3860 len = *(DWORD*)(pAfterOTIBlks + 2);
3862 /* Now add this to pLibBLk look at what we're pointing at and
3863 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3864 dust and we should be pointing at the beginning of the name
3867 pNameTable = (char*)pLibBlk + len;
3869 switch(*(WORD*)pNameTable) {
3876 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3880 pNameTable += 0x216;
3884 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3886 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3889 /* Hopefully we now have enough ptrs set up to actually read in
3890 some TypeInfos. It's not clear which order to do them in, so
3891 I'll just follow the links along the BlkEntry chain and read
3892 them in the order in which they are in the file */
3894 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3896 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3897 pBlkEntry[order].next != 0;
3898 order = pBlkEntry[order].next - 1, i++) {
3900 SLTG_TypeInfoHeader *pTIHeader;
3901 SLTG_TypeInfoTail *pTITail;
3902 SLTG_MemberHeader *pMemHeader;
3904 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3905 pOtherTypeInfoBlks[i].index_name)) {
3906 FIXME_(typelib)("Index strings don't match\n");
3911 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3912 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3915 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3916 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3917 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3919 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3920 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3921 (*ppTypeInfoImpl)->index = i;
3922 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3923 pOtherTypeInfoBlks[i].name_offs +
3925 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3926 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3927 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3928 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3929 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3930 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3931 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3933 if((pTIHeader->typeflags1 & 7) != 2)
3934 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3935 if(pTIHeader->typeflags3 != 2)
3936 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3938 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3939 debugstr_w((*ppTypeInfoImpl)->Name),
3940 typekind_desc[pTIHeader->typekind],
3941 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3942 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3944 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3946 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3948 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3949 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3950 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = (pTITail->cbSizeVft * sizeof(void *))/4;
3952 switch(pTIHeader->typekind) {
3954 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3955 pTIHeader, pTITail);
3959 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3960 pTIHeader, pTITail);
3963 case TKIND_INTERFACE:
3964 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3965 pTIHeader, pTITail);
3969 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3970 pTIHeader, pTITail);
3974 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3975 pTIHeader, pTITail);
3978 case TKIND_DISPATCH:
3979 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3980 pTIHeader, pTITail);
3984 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3985 pTIHeader, pTITail);
3989 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3994 /* could get cFuncs, cVars and cImplTypes from here
3995 but we've already set those */
3996 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4011 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4012 pBlk = (char*)pBlk + pBlkEntry[order].len;
4015 if(i != pTypeLibImpl->TypeInfoCount) {
4016 FIXME("Somehow processed %d TypeInfos\n", i);
4020 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4021 return (ITypeLib2*)pTypeLibImpl;
4024 /* ITypeLib::QueryInterface
4026 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4031 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4033 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4036 if(IsEqualIID(riid, &IID_IUnknown) ||
4037 IsEqualIID(riid,&IID_ITypeLib)||
4038 IsEqualIID(riid,&IID_ITypeLib2))
4045 ITypeLib2_AddRef(iface);
4046 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4049 TRACE("-- Interface: E_NOINTERFACE\n");
4050 return E_NOINTERFACE;
4055 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4057 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4058 ULONG ref = InterlockedIncrement(&This->ref);
4060 TRACE("(%p)->ref was %u\n",This, ref - 1);
4065 /* ITypeLib::Release
4067 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4069 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4070 ULONG ref = InterlockedDecrement(&This->ref);
4072 TRACE("(%p)->(%u)\n",This, ref);
4076 TLBImpLib *pImpLib, *pImpLibNext;
4077 TLBCustData *pCustData, *pCustDataNext;
4078 TLBRefType *ref_type;
4082 /* remove cache entry */
4085 TRACE("removing from cache list\n");
4086 EnterCriticalSection(&cache_section);
4087 if (This->next) This->next->prev = This->prev;
4088 if (This->prev) This->prev->next = This->next;
4089 else tlb_cache_first = This->next;
4090 LeaveCriticalSection(&cache_section);
4091 HeapFree(GetProcessHeap(), 0, This->path);
4093 TRACE(" destroying ITypeLib(%p)\n",This);
4095 SysFreeString(This->Name);
4098 SysFreeString(This->DocString);
4099 This->DocString = NULL;
4101 SysFreeString(This->HelpFile);
4102 This->HelpFile = NULL;
4104 SysFreeString(This->HelpStringDll);
4105 This->HelpStringDll = NULL;
4107 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4109 VariantClear(&pCustData->data);
4111 pCustDataNext = pCustData->next;
4112 TLB_Free(pCustData);
4115 for (i = 0; i < This->ctTypeDesc; i++)
4116 if (This->pTypeDesc[i].vt == VT_CARRAY)
4117 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4119 TLB_Free(This->pTypeDesc);
4121 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4123 if (pImpLib->pImpTypeLib)
4124 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4125 SysFreeString(pImpLib->name);
4127 pImpLibNext = pImpLib->next;
4131 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4133 list_remove(&ref_type->entry);
4137 if (This->pTypeInfo) /* can be NULL */
4138 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
4139 HeapFree(GetProcessHeap(),0,This);
4146 /* ITypeLib::GetTypeInfoCount
4148 * Returns the number of type descriptions in the type library
4150 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4152 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4153 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4154 return This->TypeInfoCount;
4157 /* ITypeLib::GetTypeInfo
4159 * retrieves the specified type description in the library.
4161 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4164 ITypeInfo **ppTInfo)
4168 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4169 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4171 TRACE("(%p)->(index=%d)\n", This, index);
4173 if (!ppTInfo) return E_INVALIDARG;
4175 /* search element n in list */
4176 for(i=0; i < index; i++)
4178 pTypeInfo = pTypeInfo->next;
4181 TRACE("-- element not found\n");
4182 return TYPE_E_ELEMENTNOTFOUND;
4186 *ppTInfo = (ITypeInfo *) pTypeInfo;
4188 ITypeInfo_AddRef(*ppTInfo);
4189 TRACE("-- found (%p)\n",*ppTInfo);
4194 /* ITypeLibs::GetTypeInfoType
4196 * Retrieves the type of a type description.
4198 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4203 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4205 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4207 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4208 return TYPE_E_ELEMENTNOTFOUND;
4210 TRACE("(%p) index %d\n", This, index);
4212 if(!pTKind) return E_INVALIDARG;
4214 /* search element n in list */
4215 for(i=0; i < index; i++)
4219 TRACE("-- element not found\n");
4220 return TYPE_E_ELEMENTNOTFOUND;
4222 pTInfo = pTInfo->next;
4225 *pTKind = pTInfo->TypeAttr.typekind;
4226 TRACE("-- found Type (%d)\n", *pTKind);
4230 /* ITypeLib::GetTypeInfoOfGuid
4232 * Retrieves the type description that corresponds to the specified GUID.
4235 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4238 ITypeInfo **ppTInfo)
4240 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4241 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4243 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4247 WARN("-- element not found\n");
4248 return TYPE_E_ELEMENTNOTFOUND;
4251 /* search linked list for guid */
4252 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4254 pTypeInfo = pTypeInfo->next;
4258 /* end of list reached */
4259 WARN("-- element not found\n");
4260 return TYPE_E_ELEMENTNOTFOUND;
4264 TRACE("-- found (%p, %s)\n",
4266 debugstr_w(pTypeInfo->Name));
4268 *ppTInfo = (ITypeInfo*)pTypeInfo;
4269 ITypeInfo_AddRef(*ppTInfo);
4273 /* ITypeLib::GetLibAttr
4275 * Retrieves the structure that contains the library's attributes.
4278 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4280 LPTLIBATTR *ppTLibAttr)
4282 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4283 TRACE("(%p)\n",This);
4284 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4285 **ppTLibAttr = This->LibAttr;
4289 /* ITypeLib::GetTypeComp
4291 * Enables a client compiler to bind to a library's types, variables,
4292 * constants, and global functions.
4295 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4297 ITypeComp **ppTComp)
4299 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4301 TRACE("(%p)->(%p)\n",This,ppTComp);
4302 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4303 ITypeComp_AddRef(*ppTComp);
4308 /* ITypeLib::GetDocumentation
4310 * Retrieves the library's documentation string, the complete Help file name
4311 * and path, and the context identifier for the library Help topic in the Help
4314 * On a successful return all non-null BSTR pointers will have been set,
4317 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4321 BSTR *pBstrDocString,
4322 DWORD *pdwHelpContext,
4323 BSTR *pBstrHelpFile)
4325 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4327 HRESULT result = E_INVALIDARG;
4332 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4334 pBstrName, pBstrDocString,
4335 pdwHelpContext, pBstrHelpFile);
4339 /* documentation for the typelib */
4344 if(!(*pBstrName = SysAllocString(This->Name)))
4352 if (This->DocString)
4354 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4357 else if (This->Name)
4359 if(!(*pBstrDocString = SysAllocString(This->Name)))
4363 *pBstrDocString = NULL;
4367 *pdwHelpContext = This->dwHelpContext;
4373 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4377 *pBstrHelpFile = NULL;
4384 /* for a typeinfo */
4385 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4387 if(SUCCEEDED(result))
4389 result = ITypeInfo_GetDocumentation(pTInfo,
4393 pdwHelpContext, pBstrHelpFile);
4395 ITypeInfo_Release(pTInfo);
4400 if (pBstrDocString) SysFreeString (*pBstrDocString);
4402 if (pBstrName) SysFreeString (*pBstrName);
4404 return STG_E_INSUFFICIENTMEMORY;
4409 * Indicates whether a passed-in string contains the name of a type or member
4410 * described in the library.
4413 static HRESULT WINAPI ITypeLib2_fnIsName(
4419 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4420 ITypeInfoImpl *pTInfo;
4421 TLBFuncDesc *pFInfo;
4424 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4426 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4430 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4431 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4432 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4433 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4434 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4435 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4436 goto ITypeLib2_fnIsName_exit;
4438 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4439 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4444 ITypeLib2_fnIsName_exit:
4445 TRACE("(%p)slow! search for %s: %s found!\n", This,
4446 debugstr_w(szNameBuf), *pfName?"NOT":"");
4451 /* ITypeLib::FindName
4453 * Finds occurrences of a type description in a type library. This may be used
4454 * to quickly verify that a name exists in a type library.
4457 static HRESULT WINAPI ITypeLib2_fnFindName(
4461 ITypeInfo **ppTInfo,
4465 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4466 ITypeInfoImpl *pTInfo;
4467 TLBFuncDesc *pFInfo;
4470 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4472 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4473 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4474 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4475 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4476 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4477 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4478 goto ITypeLib2_fnFindName_exit;
4481 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4482 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4484 ITypeLib2_fnFindName_exit:
4485 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4486 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4489 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4490 This, *pcFound, debugstr_w(szNameBuf), j);
4497 /* ITypeLib::ReleaseTLibAttr
4499 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4502 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4504 TLIBATTR *pTLibAttr)
4506 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4507 TRACE("freeing (%p)\n",This);
4508 HeapFree(GetProcessHeap(),0,pTLibAttr);
4512 /* ITypeLib2::GetCustData
4514 * gets the custom data
4516 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4521 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4522 TLBCustData *pCData;
4524 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4526 if( IsEqualIID(guid, &pCData->guid)) break;
4529 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4533 VariantInit( pVarVal);
4534 VariantCopy( pVarVal, &pCData->data);
4537 return E_INVALIDARG; /* FIXME: correct? */
4540 /* ITypeLib2::GetLibStatistics
4542 * Returns statistics about a type library that are required for efficient
4543 * sizing of hash tables.
4546 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4548 ULONG *pcUniqueNames,
4549 ULONG *pcchUniqueNames)
4551 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4553 FIXME("(%p): stub!\n", This);
4555 if(pcUniqueNames) *pcUniqueNames=1;
4556 if(pcchUniqueNames) *pcchUniqueNames=1;
4560 /* ITypeLib2::GetDocumentation2
4562 * Retrieves the library's documentation string, the complete Help file name
4563 * and path, the localization context to use, and the context ID for the
4564 * library Help topic in the Help file.
4567 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4571 BSTR *pbstrHelpString,
4572 DWORD *pdwHelpStringContext,
4573 BSTR *pbstrHelpStringDll)
4575 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4579 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4581 /* the help string should be obtained from the helpstringdll,
4582 * using the _DLLGetDocumentation function, based on the supplied
4583 * lcid. Nice to do sometime...
4587 /* documentation for the typelib */
4589 *pbstrHelpString=SysAllocString(This->DocString);
4590 if(pdwHelpStringContext)
4591 *pdwHelpStringContext=This->dwHelpContext;
4592 if(pbstrHelpStringDll)
4593 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4599 /* for a typeinfo */
4600 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4602 if(SUCCEEDED(result))
4604 ITypeInfo2 * pTInfo2;
4605 result = ITypeInfo_QueryInterface(pTInfo,
4607 (LPVOID*) &pTInfo2);
4609 if(SUCCEEDED(result))
4611 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4615 pdwHelpStringContext,
4616 pbstrHelpStringDll);
4618 ITypeInfo2_Release(pTInfo2);
4621 ITypeInfo_Release(pTInfo);
4627 /* ITypeLib2::GetAllCustData
4629 * Gets all custom data items for the library.
4632 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4634 CUSTDATA *pCustData)
4636 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4637 TLBCustData *pCData;
4639 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4640 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4641 if(pCustData->prgCustData ){
4642 pCustData->cCustData=This->ctCustData;
4643 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4644 pCustData->prgCustData[i].guid=pCData->guid;
4645 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4648 ERR(" OUT OF MEMORY!\n");
4649 return E_OUTOFMEMORY;
4654 static const ITypeLib2Vtbl tlbvt = {
4655 ITypeLib2_fnQueryInterface,
4657 ITypeLib2_fnRelease,
4658 ITypeLib2_fnGetTypeInfoCount,
4659 ITypeLib2_fnGetTypeInfo,
4660 ITypeLib2_fnGetTypeInfoType,
4661 ITypeLib2_fnGetTypeInfoOfGuid,
4662 ITypeLib2_fnGetLibAttr,
4663 ITypeLib2_fnGetTypeComp,
4664 ITypeLib2_fnGetDocumentation,
4666 ITypeLib2_fnFindName,
4667 ITypeLib2_fnReleaseTLibAttr,
4669 ITypeLib2_fnGetCustData,
4670 ITypeLib2_fnGetLibStatistics,
4671 ITypeLib2_fnGetDocumentation2,
4672 ITypeLib2_fnGetAllCustData
4676 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4678 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4680 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4683 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4685 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4687 return ITypeLib2_AddRef((ITypeLib2 *)This);
4690 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4692 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4694 return ITypeLib2_Release((ITypeLib2 *)This);
4697 static HRESULT WINAPI ITypeLibComp_fnBind(
4702 ITypeInfo ** ppTInfo,
4703 DESCKIND * pDescKind,
4706 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4707 ITypeInfoImpl *pTypeInfo;
4709 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4711 *pDescKind = DESCKIND_NONE;
4712 pBindPtr->lptcomp = NULL;
4715 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4717 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4719 /* FIXME: check wFlags here? */
4720 /* FIXME: we should use a hash table to look this info up using lHash
4721 * instead of an O(n) search */
4722 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4723 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4725 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4727 *pDescKind = DESCKIND_TYPECOMP;
4728 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4729 ITypeComp_AddRef(pBindPtr->lptcomp);
4730 TRACE("module or enum: %s\n", debugstr_w(szName));
4735 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4736 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4738 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4741 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4742 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4744 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4749 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4750 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4752 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4754 ITypeInfo *subtypeinfo;
4756 DESCKIND subdesckind;
4758 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4759 &subtypeinfo, &subdesckind, &subbindptr);
4760 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4762 TYPEDESC tdesc_appobject =
4765 (TYPEDESC *)pTypeInfo->hreftype
4769 const VARDESC vardesc_appobject =
4772 NULL, /* lpstrSchema */
4787 VAR_STATIC /* varkind */
4790 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4792 /* cleanup things filled in by Bind call so we can put our
4793 * application object data in there instead */
4794 switch (subdesckind)
4796 case DESCKIND_FUNCDESC:
4797 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4799 case DESCKIND_VARDESC:
4800 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4805 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4807 if (pTypeInfo->hreftype == -1)
4808 FIXME("no hreftype for interface %p\n", pTypeInfo);
4810 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4814 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4815 *ppTInfo = (ITypeInfo *)pTypeInfo;
4816 ITypeInfo_AddRef(*ppTInfo);
4822 TRACE("name not found %s\n", debugstr_w(szName));
4826 static HRESULT WINAPI ITypeLibComp_fnBindType(
4830 ITypeInfo ** ppTInfo,
4831 ITypeComp ** ppTComp)
4833 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4837 static const ITypeCompVtbl tlbtcvt =
4840 ITypeLibComp_fnQueryInterface,
4841 ITypeLibComp_fnAddRef,
4842 ITypeLibComp_fnRelease,
4844 ITypeLibComp_fnBind,
4845 ITypeLibComp_fnBindType
4848 /*================== ITypeInfo(2) Methods ===================================*/
4849 static ITypeInfo2 * ITypeInfo_Constructor(void)
4851 ITypeInfoImpl * pTypeInfoImpl;
4853 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4856 pTypeInfoImpl->lpVtbl = &tinfvt;
4857 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4858 pTypeInfoImpl->ref=1;
4859 pTypeInfoImpl->hreftype = -1;
4860 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4861 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4863 TRACE("(%p)\n", pTypeInfoImpl);
4864 return (ITypeInfo2*) pTypeInfoImpl;
4867 /* ITypeInfo::QueryInterface
4869 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4874 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4876 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4879 if(IsEqualIID(riid, &IID_IUnknown) ||
4880 IsEqualIID(riid,&IID_ITypeInfo)||
4881 IsEqualIID(riid,&IID_ITypeInfo2))
4885 ITypeInfo_AddRef(iface);
4886 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4889 TRACE("-- Interface: E_NOINTERFACE\n");
4890 return E_NOINTERFACE;
4893 /* ITypeInfo::AddRef
4895 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4897 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4898 ULONG ref = InterlockedIncrement(&This->ref);
4900 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4902 TRACE("(%p)->ref is %u\n",This, ref);
4906 /* ITypeInfo::Release
4908 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4910 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4911 ULONG ref = InterlockedDecrement(&This->ref);
4913 TRACE("(%p)->(%u)\n",This, ref);
4916 /* We don't release ITypeLib when ref=0 because
4917 it means that function is called by ITypeLib2_Release */
4918 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4920 TLBFuncDesc *pFInfo, *pFInfoNext;
4921 TLBVarDesc *pVInfo, *pVInfoNext;
4922 TLBImplType *pImpl, *pImplNext;
4924 TRACE("destroying ITypeInfo(%p)\n",This);
4926 if (This->no_free_data)
4929 SysFreeString(This->Name);
4932 SysFreeString(This->DocString);
4933 This->DocString = NULL;
4935 SysFreeString(This->DllName);
4936 This->DllName = NULL;
4938 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4941 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4943 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4944 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4946 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4947 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4949 SysFreeString(pFInfo->pParamDesc[i].Name);
4951 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4952 TLB_Free(pFInfo->pParamDesc);
4953 TLB_FreeCustData(pFInfo->pCustData);
4954 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4955 SysFreeString(pFInfo->Entry);
4956 SysFreeString(pFInfo->HelpString);
4957 SysFreeString(pFInfo->Name);
4959 pFInfoNext = pFInfo->next;
4962 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4964 if (pVInfo->vardesc.varkind == VAR_CONST)
4966 VariantClear(pVInfo->vardesc.u.lpvarValue);
4967 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4969 TLB_FreeCustData(pVInfo->pCustData);
4970 SysFreeString(pVInfo->Name);
4971 pVInfoNext = pVInfo->next;
4974 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4976 TLB_FreeCustData(pImpl->pCustData);
4977 pImplNext = pImpl->next;
4980 TLB_FreeCustData(This->pCustData);
4985 ITypeInfo_Release((ITypeInfo*)This->next);
4988 HeapFree(GetProcessHeap(),0,This);
4994 /* ITypeInfo::GetTypeAttr
4996 * Retrieves a TYPEATTR structure that contains the attributes of the type
5000 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5001 LPTYPEATTR *ppTypeAttr)
5003 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5006 TRACE("(%p)\n",This);
5008 size = sizeof(**ppTypeAttr);
5009 if (This->TypeAttr.typekind == TKIND_ALIAS)
5010 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5012 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5014 return E_OUTOFMEMORY;
5016 **ppTypeAttr = This->TypeAttr;
5018 if (This->TypeAttr.typekind == TKIND_ALIAS)
5019 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5020 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5022 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5023 /* This should include all the inherited funcs */
5024 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5025 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5026 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5031 /* ITypeInfo::GetTypeComp
5033 * Retrieves the ITypeComp interface for the type description, which enables a
5034 * client compiler to bind to the type description's members.
5037 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5038 ITypeComp * *ppTComp)
5040 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5042 TRACE("(%p)->(%p)\n", This, ppTComp);
5044 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5045 ITypeComp_AddRef(*ppTComp);
5049 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5051 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5052 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5053 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5057 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5060 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5061 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5063 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5064 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5065 *buffer += sizeof(PARAMDESCEX);
5066 *pparamdescex_dest = *pparamdescex_src;
5067 VariantInit(&pparamdescex_dest->varDefaultValue);
5068 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5069 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5072 dest->u.paramdesc.pparamdescex = NULL;
5076 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5078 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5079 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5082 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5086 SIZE_T size = sizeof(*src);
5090 size += sizeof(*src->lprgscode) * src->cScodes;
5091 size += TLB_SizeElemDesc(&src->elemdescFunc);
5092 for (i = 0; i < src->cParams; i++)
5094 size += sizeof(ELEMDESC);
5095 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5098 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5099 if (!dest) return E_OUTOFMEMORY;
5102 if (dispinterface) /* overwrite funckind */
5103 dest->funckind = FUNC_DISPATCH;
5104 buffer = (char *)(dest + 1);
5106 dest->lprgscode = (SCODE *)buffer;
5107 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5108 buffer += sizeof(*src->lprgscode) * src->cScodes;
5110 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5113 SysFreeString((BSTR)dest);
5117 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5118 buffer += sizeof(ELEMDESC) * src->cParams;
5119 for (i = 0; i < src->cParams; i++)
5121 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5127 /* undo the above actions */
5128 for (i = i - 1; i >= 0; i--)
5129 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5130 TLB_FreeElemDesc(&dest->elemdescFunc);
5131 SysFreeString((BSTR)dest);
5135 /* special treatment for dispinterfaces: this makes functions appear
5136 * to return their [retval] value when it is really returning an
5138 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5140 if (dest->cParams &&
5141 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5143 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5144 if (elemdesc->tdesc.vt != VT_PTR)
5146 ERR("elemdesc should have started with VT_PTR instead of:\n");
5148 dump_ELEMDESC(elemdesc);
5149 return E_UNEXPECTED;
5152 /* copy last parameter to the return value. we are using a flat
5153 * buffer so there is no danger of leaking memory in
5155 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5157 /* remove the last parameter */
5161 /* otherwise this function is made to appear to have no return
5163 dest->elemdescFunc.tdesc.vt = VT_VOID;
5171 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5173 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5174 const TLBFuncDesc *pFDesc;
5177 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5182 *ppFuncDesc = &pFDesc->funcdesc;
5186 return TYPE_E_ELEMENTNOTFOUND;
5189 /* internal function to make the inherited interfaces' methods appear
5190 * part of the interface */
5191 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5192 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5194 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5196 UINT implemented_funcs = 0;
5201 *hrefoffset = DISPATCH_HREF_OFFSET;
5203 if(This->impltypelist)
5205 ITypeInfo *pSubTypeInfo;
5208 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5212 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5215 &sub_funcs, hrefoffset);
5216 implemented_funcs += sub_funcs;
5217 ITypeInfo_Release(pSubTypeInfo);
5220 *hrefoffset += DISPATCH_HREF_OFFSET;
5224 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5228 if (index < implemented_funcs)
5229 return E_INVALIDARG;
5230 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5234 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5236 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5239 switch (pTypeDesc->vt)
5241 case VT_USERDEFINED:
5242 pTypeDesc->u.hreftype += hrefoffset;
5246 pTypeDesc = pTypeDesc->u.lptdesc;
5249 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5257 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5260 for (i = 0; i < pFuncDesc->cParams; i++)
5261 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5262 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5265 /* ITypeInfo::GetFuncDesc
5267 * Retrieves the FUNCDESC structure that contains information about a
5268 * specified function.
5271 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5272 LPFUNCDESC *ppFuncDesc)
5274 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5275 const FUNCDESC *internal_funcdesc;
5277 UINT hrefoffset = 0;
5279 TRACE("(%p) index %d\n", This, index);
5281 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5282 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5283 &internal_funcdesc, NULL,
5286 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5287 &internal_funcdesc);
5290 WARN("description for function %d not found\n", index);
5294 hr = TLB_AllocAndInitFuncDesc(
5297 This->TypeAttr.typekind == TKIND_DISPATCH);
5299 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5300 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5302 TRACE("-- 0x%08x\n", hr);
5306 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5310 SIZE_T size = sizeof(*src);
5313 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5314 if (src->varkind == VAR_CONST)
5315 size += sizeof(VARIANT);
5316 size += TLB_SizeElemDesc(&src->elemdescVar);
5318 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5319 if (!dest) return E_OUTOFMEMORY;
5322 buffer = (char *)(dest + 1);
5323 if (src->lpstrSchema)
5326 dest->lpstrSchema = (LPOLESTR)buffer;
5327 len = strlenW(src->lpstrSchema);
5328 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5329 buffer += (len + 1) * sizeof(WCHAR);
5332 if (src->varkind == VAR_CONST)
5336 dest->u.lpvarValue = (VARIANT *)buffer;
5337 *dest->u.lpvarValue = *src->u.lpvarValue;
5338 buffer += sizeof(VARIANT);
5339 VariantInit(dest->u.lpvarValue);
5340 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5343 SysFreeString((BSTR)dest_ptr);
5347 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5350 if (src->varkind == VAR_CONST)
5351 VariantClear(dest->u.lpvarValue);
5352 SysFreeString((BSTR)dest);
5359 /* ITypeInfo::GetVarDesc
5361 * Retrieves a VARDESC structure that describes the specified variable.
5364 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5365 LPVARDESC *ppVarDesc)
5367 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5369 const TLBVarDesc *pVDesc;
5371 TRACE("(%p) index %d\n", This, index);
5373 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5377 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5379 return E_INVALIDARG;
5382 /* ITypeInfo_GetNames
5384 * Retrieves the variable with the specified member ID (or the name of the
5385 * property or method and its parameters) that correspond to the specified
5388 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5389 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5391 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5392 const TLBFuncDesc *pFDesc;
5393 const TLBVarDesc *pVDesc;
5395 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5396 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5399 /* function found, now return function and parameter names */
5400 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5403 *rgBstrNames=SysAllocString(pFDesc->Name);
5405 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5411 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5414 *rgBstrNames=SysAllocString(pVDesc->Name);
5419 if(This->impltypelist &&
5420 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5421 /* recursive search */
5424 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5426 if(SUCCEEDED(result))
5428 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5429 ITypeInfo_Release(pTInfo);
5432 WARN("Could not search inherited interface!\n");
5436 WARN("no names found\n");
5439 return TYPE_E_ELEMENTNOTFOUND;
5446 /* ITypeInfo::GetRefTypeOfImplType
5448 * If a type description describes a COM class, it retrieves the type
5449 * description of the implemented interface types. For an interface,
5450 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5454 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5459 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5462 const TLBImplType *pImpl = This->impltypelist;
5464 TRACE("(%p) index %d\n", This, index);
5465 if (TRACE_ON(ole)) dump_TypeInfo(This);
5469 /* only valid on dual interfaces;
5470 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5472 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5474 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5475 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5481 hr = TYPE_E_ELEMENTNOTFOUND;
5484 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5486 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5487 *pRefType = This->pTypeLib->dispatch_href;
5491 /* get element n from linked list */
5492 for(i=0; pImpl && i<index; i++)
5494 pImpl = pImpl->next;
5498 *pRefType = pImpl->hRef;
5500 hr = TYPE_E_ELEMENTNOTFOUND;
5506 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5508 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5514 /* ITypeInfo::GetImplTypeFlags
5516 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5517 * or base interface in a type description.
5519 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5520 UINT index, INT *pImplTypeFlags)
5522 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5526 TRACE("(%p) index %d\n", This, index);
5527 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5528 i++, pImpl=pImpl->next)
5530 if(i==index && pImpl){
5531 *pImplTypeFlags=pImpl->implflags;
5535 return TYPE_E_ELEMENTNOTFOUND;
5539 * Maps between member names and member IDs, and parameter names and
5542 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5543 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5545 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5546 const TLBFuncDesc *pFDesc;
5547 const TLBVarDesc *pVDesc;
5551 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5554 /* init out parameters in case of failure */
5555 for (i = 0; i < cNames; i++)
5556 pMemId[i] = MEMBERID_NIL;
5558 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5560 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5561 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5562 for(i=1; i < cNames; i++){
5563 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5564 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5566 if( j<pFDesc->funcdesc.cParams)
5569 ret=DISP_E_UNKNOWNNAME;
5571 TRACE("-- 0x%08x\n", ret);
5575 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5576 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5577 if(cNames) *pMemId=pVDesc->vardesc.memid;
5581 /* not found, see if it can be found in an inherited interface */
5582 if(This->impltypelist) {
5583 /* recursive search */
5585 ret=ITypeInfo_GetRefTypeInfo(iface,
5586 This->impltypelist->hRef, &pTInfo);
5588 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5589 ITypeInfo_Release(pTInfo);
5592 WARN("Could not search inherited interface!\n");
5594 WARN("no names found\n");
5595 return DISP_E_UNKNOWNNAME;
5598 /* ITypeInfo::Invoke
5600 * Invokes a method, or accesses a property of an object, that implements the
5601 * interface described by the type description.
5604 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5607 if (TRACE_ON(ole)) {
5609 TRACE("Calling %p(",func);
5610 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5622 res = func(args[0]);
5625 res = func(args[0],args[1]);
5628 res = func(args[0],args[1],args[2]);
5631 res = func(args[0],args[1],args[2],args[3]);
5634 res = func(args[0],args[1],args[2],args[3],args[4]);
5637 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5640 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5643 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5646 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5649 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5652 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5655 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11]);
5658 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12]);
5661 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13]);
5664 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14]);
5667 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15]);
5670 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16]);
5673 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17]);
5676 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18]);
5679 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19]);
5682 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20]);
5685 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21]);
5688 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22]);
5691 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23]);
5694 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24]);
5697 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25]);
5700 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26]);
5703 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27]);
5706 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28]);
5709 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10],args[11],args[12],args[13],args[14],args[15],args[16],args[17],args[18],args[19],args[20],args[21],args[22],args[23],args[24],args[25],args[26],args[27],args[28],args[29]);
5712 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5718 FIXME("unsupported calling convention %d\n",callconv);
5722 TRACE("returns %08x\n",res);
5726 /* The size of the argument on the stack in DWORD units (in all x86 call
5727 * convetions the arguments on the stack are DWORD-aligned)
5729 static int _dispargsize(VARTYPE vt)
5734 return 8/sizeof(DWORD);
5736 return sizeof(double)/sizeof(DWORD);
5738 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5740 return sizeof(CY)/sizeof(DWORD);
5742 return sizeof(DATE)/sizeof(DWORD);
5744 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5746 FIXME("VT_RECORD not implemented\n");
5753 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5756 ITypeInfo *tinfo2 = NULL;
5757 TYPEATTR *tattr = NULL;
5759 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5762 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5764 tdesc->u.hreftype, hr);
5767 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5770 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5771 ITypeInfo_Release(tinfo2);
5775 switch (tattr->typekind)
5782 tdesc = &tattr->tdescAlias;
5783 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5786 case TKIND_INTERFACE:
5787 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5793 case TKIND_DISPATCH:
5802 FIXME("TKIND_RECORD unhandled.\n");
5807 FIXME("TKIND_UNION unhandled.\n");
5812 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5816 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5817 ITypeInfo_Release(tinfo2);
5821 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5825 /* enforce only one level of pointer indirection */
5826 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5828 tdesc = tdesc->u.lptdesc;
5830 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5831 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5832 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5833 if ((tdesc->vt == VT_USERDEFINED) ||
5834 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5836 VARTYPE vt_userdefined = 0;
5837 const TYPEDESC *tdesc_userdefined = tdesc;
5838 if (tdesc->vt == VT_PTR)
5840 vt_userdefined = VT_BYREF;
5841 tdesc_userdefined = tdesc->u.lptdesc;
5843 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5845 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5846 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5848 *vt |= vt_userdefined;
5860 case VT_USERDEFINED:
5861 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5868 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5869 hr = DISP_E_BADVARTYPE;
5873 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5882 /***********************************************************************
5883 * DispCallFunc (OLEAUT32.@)
5885 * Invokes a function of the specified calling convention, passing the
5886 * specified arguments and returns the result.
5889 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5890 * oVft [I] The offset in the vtable. See notes.
5891 * cc [I] Calling convention of the function to call.
5892 * vtReturn [I] The return type of the function.
5893 * cActuals [I] Number of parameters.
5894 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5895 * prgpvarg [I] The arguments to pass.
5896 * pvargResult [O] The return value of the function. Can be NULL.
5900 * Failure: HRESULT code.
5903 * The HRESULT return value of this function is not affected by the return
5904 * value of the user supplied function, which is returned in pvargResult.
5906 * If pvInstance is NULL then a non-object function is to be called and oVft
5907 * is the address of the function to call.
5909 * The cc parameter can be one of the following values:
5922 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5923 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5925 int argsize, argspos;
5930 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5931 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5932 pvargResult, V_VT(pvargResult));
5936 argsize++; /* for This pointer */
5938 for (i=0;i<cActuals;i++)
5940 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5941 dump_Variant(prgpvarg[i]);
5942 argsize += _dispargsize(prgvt[i]);
5944 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5949 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5953 for (i=0;i<cActuals;i++)
5955 VARIANT *arg = prgpvarg[i];
5956 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5957 if (prgvt[i] == VT_VARIANT)
5958 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5960 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5961 argspos += _dispargsize(prgvt[i]);
5966 FARPROC *vtable = *(FARPROC**)pvInstance;
5967 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5970 /* if we aren't invoking an object then the function pointer is stored
5972 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5974 if (pvargResult && (vtReturn != VT_EMPTY))
5976 TRACE("Method returned 0x%08x\n",hres);
5977 V_VT(pvargResult) = vtReturn;
5978 V_UI4(pvargResult) = hres;
5981 HeapFree(GetProcessHeap(),0,args);
5985 #define INVBUF_ELEMENT_SIZE \
5986 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5987 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5988 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5989 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5990 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5991 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5992 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5993 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5995 static HRESULT WINAPI ITypeInfo_fnInvoke(
6000 DISPPARAMS *pDispParams,
6001 VARIANT *pVarResult,
6002 EXCEPINFO *pExcepInfo,
6005 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6007 unsigned int var_index;
6010 const TLBFuncDesc *pFuncInfo;
6012 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6013 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6018 ERR("NULL pDispParams not allowed\n");
6019 return E_INVALIDARG;
6022 dump_DispParms(pDispParams);
6024 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6026 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6027 pDispParams->cNamedArgs, pDispParams->cArgs);
6028 return E_INVALIDARG;
6031 /* we do this instead of using GetFuncDesc since it will return a fake
6032 * FUNCDESC for dispinterfaces and we want the real function description */
6033 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6034 if ((memid == pFuncInfo->funcdesc.memid) &&
6035 (wFlags & pFuncInfo->funcdesc.invkind))
6039 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6043 TRACE("invoking:\n");
6044 dump_TLBFuncDescOne(pFuncInfo);
6047 switch (func_desc->funckind) {
6048 case FUNC_PUREVIRTUAL:
6049 case FUNC_VIRTUAL: {
6050 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6052 VARIANT retval; /* pointer for storing byref retvals in */
6053 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6054 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6055 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6056 UINT cNamedArgs = pDispParams->cNamedArgs;
6057 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6061 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6063 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6065 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6066 hres = DISP_E_PARAMNOTFOUND;
6069 /* ignore the DISPID_PROPERTYPUT named argument from now on */
6071 rgdispidNamedArgs++;
6074 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6076 ERR("functions with the vararg attribute do not support named arguments\n");
6077 hres = DISP_E_NONAMEDARGS;
6081 for (i = 0; i < func_desc->cParams; i++)
6083 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6084 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6089 TRACE("changing args\n");
6090 for (i = 0; i < func_desc->cParams; i++)
6092 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6093 VARIANTARG *src_arg;
6099 for (j = 0; j < cNamedArgs; j++)
6100 if (rgdispidNamedArgs[j] == i)
6102 src_arg = &pDispParams->rgvarg[j];
6107 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
6109 if (wParamFlags & PARAMFLAG_FRETVAL)
6111 /* under most conditions the caller is not allowed to
6112 * pass in a dispparam arg in the index of what would be
6113 * the retval parameter. however, there is an exception
6114 * where the extra parameter is used in an extra
6115 * IDispatch::Invoke below */
6116 if ((i < pDispParams->cArgs) &&
6117 ((func_desc->cParams != 1) || !pVarResult ||
6118 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6120 hres = DISP_E_BADPARAMCOUNT;
6124 /* note: this check is placed so that if the caller passes
6125 * in a VARIANTARG for the retval we just ignore it, like
6127 if (i == func_desc->cParams - 1)
6130 arg = prgpvarg[i] = &rgvarg[i];
6131 memset(arg, 0, sizeof(*arg));
6132 V_VT(arg) = rgvt[i];
6133 memset(&retval, 0, sizeof(retval));
6134 V_BYREF(arg) = &retval;
6138 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6139 hres = E_UNEXPECTED;
6145 dump_Variant(src_arg);
6147 if (rgvt[i] == VT_VARIANT)
6148 hres = VariantCopy(&rgvarg[i], src_arg);
6149 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6151 if (rgvt[i] == V_VT(src_arg))
6152 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6155 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6156 hres = VariantCopy(&missing_arg[i], src_arg);
6157 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6159 V_VT(&rgvarg[i]) = rgvt[i];
6161 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6164 SAFEARRAYBOUND bound;
6168 bound.cElements = pDispParams->cArgs-i;
6169 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6171 ERR("SafeArrayCreate failed\n");
6174 hres = SafeArrayAccessData(a, (LPVOID)&v);
6177 ERR("SafeArrayAccessData failed with %x\n", hres);
6180 for (j = 0; j < bound.cElements; j++)
6181 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6182 hres = SafeArrayUnaccessData(a);
6185 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6188 V_ARRAY(&rgvarg[i]) = a;
6189 V_VT(&rgvarg[i]) = rgvt[i];
6191 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6193 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6194 V_VT(&missing_arg[i]) = V_VT(src_arg);
6195 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6196 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6197 V_VT(&rgvarg[i]) = rgvt[i];
6199 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6201 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6202 V_VT(&rgvarg[i]) = rgvt[i];
6206 /* FIXME: this doesn't work for VT_BYREF arguments if
6207 * they are not the same type as in the paramdesc */
6208 V_VT(&rgvarg[i]) = V_VT(src_arg);
6209 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6210 V_VT(&rgvarg[i]) = rgvt[i];
6215 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6216 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6217 debugstr_VT(src_arg), debugstr_VF(src_arg));
6220 prgpvarg[i] = &rgvarg[i];
6222 else if (wParamFlags & PARAMFLAG_FOPT)
6225 arg = prgpvarg[i] = &rgvarg[i];
6226 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6228 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6234 VARIANTARG *missing_arg;
6235 /* if the function wants a pointer to a variant then
6236 * set that up, otherwise just pass the VT_ERROR in
6237 * the argument by value */
6238 if (rgvt[i] & VT_BYREF)
6240 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6241 V_VT(arg) = VT_VARIANT | VT_BYREF;
6242 V_VARIANTREF(arg) = missing_arg;
6246 V_VT(missing_arg) = VT_ERROR;
6247 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6252 hres = DISP_E_BADPARAMCOUNT;
6256 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6258 /* VT_VOID is a special case for return types, so it is not
6259 * handled in the general function */
6260 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6261 V_VT(&varresult) = VT_EMPTY;
6264 V_VT(&varresult) = 0;
6265 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6266 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6269 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6270 V_VT(&varresult), func_desc->cParams, rgvt,
6271 prgpvarg, &varresult);
6273 for (i = 0; i < func_desc->cParams; i++)
6275 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6276 if (wParamFlags & PARAMFLAG_FRETVAL)
6280 TRACE("[retval] value: ");
6281 dump_Variant(prgpvarg[i]);
6286 VariantInit(pVarResult);
6287 /* deref return value */
6288 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6291 /* free data stored in varresult. Note that
6292 * VariantClear doesn't do what we want because we are
6293 * working with byref types. */
6294 /* FIXME: clear safearrays, bstrs, records and
6295 * variants here too */
6296 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6297 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6299 if(*V_UNKNOWNREF(prgpvarg[i]))
6300 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6304 else if (i < pDispParams->cArgs)
6306 if (wParamFlags & PARAMFLAG_FOUT)
6308 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6310 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6311 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6315 ERR("failed to convert param %d to vt %d\n", i,
6316 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6320 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6321 func_desc->cParamsOpt < 0 &&
6322 i == func_desc->cParams-1)
6324 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6327 hres = SafeArrayGetUBound(a, 1, &ubound);
6330 ERR("SafeArrayGetUBound failed with %x\n", hres);
6333 hres = SafeArrayAccessData(a, (LPVOID)&v);
6336 ERR("SafeArrayAccessData failed with %x\n", hres);
6339 for (j = 0; j <= ubound; j++)
6340 VariantClear(&v[j]);
6341 hres = SafeArrayUnaccessData(a);
6344 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6348 VariantClear(&rgvarg[i]);
6350 else if (wParamFlags & PARAMFLAG_FOPT)
6352 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6353 VariantClear(&rgvarg[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 (HIWORD(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 /* we use data structures from This, so we need to keep a reference
6663 * to it to stop it being destroyed and signal to the new instance to
6664 * not free its data structures when it is destroyed */
6665 pTypeInfoImpl->no_free_data = TRUE;
6666 pTypeInfoImpl->next = This;
6667 ITypeInfo_AddRef((ITypeInfo*) This);
6669 ITypeInfo_AddRef(*ppTInfo);
6673 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6674 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6675 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6677 HREFTYPE href_dispatch = hRefType;
6678 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6680 TLBRefType *ref_type;
6681 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6683 if(ref_type->reference == hRefType)
6686 if(&ref_type->entry == &This->pTypeLib->ref_list)
6688 FIXME("Can't find pRefType for ref %x\n", hRefType);
6691 if(hRefType != -1) {
6692 ITypeLib *pTLib = NULL;
6694 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6696 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6698 if(ref_type->pImpTLInfo->pImpTypeLib) {
6699 TRACE("typeinfo in imported typelib that is already loaded\n");
6700 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6701 ITypeLib2_AddRef(pTLib);
6704 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6705 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6706 ref_type->pImpTLInfo->wVersionMajor,
6707 ref_type->pImpTLInfo->wVersionMinor,
6708 ref_type->pImpTLInfo->lcid,
6711 if(FAILED(result)) {
6712 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6713 result=LoadTypeLib(libnam, &pTLib);
6714 SysFreeString(libnam);
6716 if(SUCCEEDED(result)) {
6717 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6718 ITypeLib2_AddRef(pTLib);
6722 if(SUCCEEDED(result)) {
6723 if(ref_type->index == TLB_REF_USE_GUID)
6724 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6728 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6732 ITypeLib2_Release(pTLib);
6737 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6738 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6742 /* ITypeInfo::AddressOfMember
6744 * Retrieves the addresses of static functions or variables, such as those
6747 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6748 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6750 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6756 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6758 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6762 module = LoadLibraryW(dll);
6765 ERR("couldn't load %s\n", debugstr_w(dll));
6767 SysFreeString(entry);
6768 return STG_E_FILENOTFOUND;
6770 /* FIXME: store library somewhere where we can free it */
6775 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6776 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6777 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6779 *ppv = GetProcAddress(module, entryA);
6781 ERR("function not found %s\n", debugstr_a(entryA));
6783 HeapFree(GetProcessHeap(), 0, entryA);
6787 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6789 ERR("function not found %d\n", ordinal);
6793 SysFreeString(entry);
6796 return TYPE_E_DLLFUNCTIONNOTFOUND;
6801 /* ITypeInfo::CreateInstance
6803 * Creates a new instance of a type that describes a component object class
6806 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6807 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6809 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6813 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6819 WARN("Not able to aggregate\n");
6820 return CLASS_E_NOAGGREGATION;
6823 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6824 if(FAILED(hr)) return hr;
6826 if(pTA->typekind != TKIND_COCLASS)
6828 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6834 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6837 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6838 TRACE("GetActiveObject rets %08x\n", hr);
6841 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6842 IUnknown_Release(pUnk);
6847 hr = CoCreateInstance(&pTA->guid, NULL,
6848 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6852 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6856 /* ITypeInfo::GetMops
6858 * Retrieves marshalling information.
6860 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6863 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6864 FIXME("(%p) stub!\n", This);
6868 /* ITypeInfo::GetContainingTypeLib
6870 * Retrieves the containing type library and the index of the type description
6871 * within that type library.
6873 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6874 ITypeLib * *ppTLib, UINT *pIndex)
6876 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6878 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6880 *pIndex=This->index;
6881 TRACE("returning pIndex=%d\n", *pIndex);
6885 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6886 ITypeLib2_AddRef(*ppTLib);
6887 TRACE("returning ppTLib=%p\n", *ppTLib);
6893 /* ITypeInfo::ReleaseTypeAttr
6895 * Releases a TYPEATTR previously returned by GetTypeAttr.
6898 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6899 TYPEATTR* pTypeAttr)
6901 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6902 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6903 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6906 /* ITypeInfo::ReleaseFuncDesc
6908 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6910 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6912 FUNCDESC *pFuncDesc)
6914 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6917 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6919 for (i = 0; i < pFuncDesc->cParams; i++)
6920 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6921 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6923 SysFreeString((BSTR)pFuncDesc);
6926 /* ITypeInfo::ReleaseVarDesc
6928 * Releases a VARDESC previously returned by GetVarDesc.
6930 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6933 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6934 TRACE("(%p)->(%p)\n", This, pVarDesc);
6936 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6937 if (pVarDesc->varkind == VAR_CONST)
6938 VariantClear(pVarDesc->u.lpvarValue);
6939 SysFreeString((BSTR)pVarDesc);
6942 /* ITypeInfo2::GetTypeKind
6944 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6947 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6948 TYPEKIND *pTypeKind)
6950 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6951 *pTypeKind=This->TypeAttr.typekind;
6952 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6956 /* ITypeInfo2::GetTypeFlags
6958 * Returns the type flags without any allocations. This returns a DWORD type
6959 * flag, which expands the type flags without growing the TYPEATTR (type
6963 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6965 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6966 *pTypeFlags=This->TypeAttr.wTypeFlags;
6967 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6971 /* ITypeInfo2::GetFuncIndexOfMemId
6972 * Binds to a specific member based on a known DISPID, where the member name
6973 * is not known (for example, when binding to a default member).
6976 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6977 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6979 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6980 const TLBFuncDesc *pFuncInfo;
6984 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6985 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6991 result = TYPE_E_ELEMENTNOTFOUND;
6993 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6994 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6998 /* TypeInfo2::GetVarIndexOfMemId
7000 * Binds to a specific member based on a known DISPID, where the member name
7001 * is not known (for example, when binding to a default member).
7004 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7005 MEMBERID memid, UINT *pVarIndex)
7007 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7008 TLBVarDesc *pVarInfo;
7011 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7012 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7018 result = TYPE_E_ELEMENTNOTFOUND;
7020 TRACE("(%p) memid 0x%08x -> %s\n", This,
7021 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7025 /* ITypeInfo2::GetCustData
7027 * Gets the custom data
7029 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7034 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7035 TLBCustData *pCData;
7037 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7038 if( IsEqualIID(guid, &pCData->guid)) break;
7040 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7044 VariantInit( pVarVal);
7045 VariantCopy( pVarVal, &pCData->data);
7048 return E_INVALIDARG; /* FIXME: correct? */
7051 /* ITypeInfo2::GetFuncCustData
7053 * Gets the custom data
7055 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7061 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7062 TLBCustData *pCData=NULL;
7063 TLBFuncDesc * pFDesc;
7065 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7066 pFDesc=pFDesc->next);
7069 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7070 if( IsEqualIID(guid, &pCData->guid)) break;
7072 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7075 VariantInit( pVarVal);
7076 VariantCopy( pVarVal, &pCData->data);
7079 return E_INVALIDARG; /* FIXME: correct? */
7082 /* ITypeInfo2::GetParamCustData
7084 * Gets the custom data
7086 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7093 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7094 TLBCustData *pCData=NULL;
7095 TLBFuncDesc * pFDesc;
7098 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7100 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7101 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7102 pCData = pCData->next)
7103 if( IsEqualIID(guid, &pCData->guid)) break;
7105 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7109 VariantInit( pVarVal);
7110 VariantCopy( pVarVal, &pCData->data);
7113 return E_INVALIDARG; /* FIXME: correct? */
7116 /* ITypeInfo2::GetVarCustData
7118 * Gets the custom data
7120 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7126 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7127 TLBCustData *pCData=NULL;
7128 TLBVarDesc * pVDesc;
7131 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7135 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7137 if( IsEqualIID(guid, &pCData->guid)) break;
7141 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7145 VariantInit( pVarVal);
7146 VariantCopy( pVarVal, &pCData->data);
7149 return E_INVALIDARG; /* FIXME: correct? */
7152 /* ITypeInfo2::GetImplCustData
7154 * Gets the custom data
7156 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7162 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7163 TLBCustData *pCData=NULL;
7164 TLBImplType * pRDesc;
7167 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7171 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7173 if( IsEqualIID(guid, &pCData->guid)) break;
7177 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7181 VariantInit( pVarVal);
7182 VariantCopy( pVarVal, &pCData->data);
7185 return E_INVALIDARG; /* FIXME: correct? */
7188 /* ITypeInfo2::GetDocumentation2
7190 * Retrieves the documentation string, the complete Help file name and path,
7191 * the localization context to use, and the context ID for the library Help
7192 * topic in the Help file.
7195 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7199 BSTR *pbstrHelpString,
7200 DWORD *pdwHelpStringContext,
7201 BSTR *pbstrHelpStringDll)
7203 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7204 const TLBFuncDesc *pFDesc;
7205 const TLBVarDesc *pVDesc;
7206 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7207 "HelpStringContext(%p) HelpStringDll(%p)\n",
7208 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7209 pbstrHelpStringDll );
7210 /* the help string should be obtained from the helpstringdll,
7211 * using the _DLLGetDocumentation function, based on the supplied
7212 * lcid. Nice to do sometime...
7214 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7216 *pbstrHelpString=SysAllocString(This->Name);
7217 if(pdwHelpStringContext)
7218 *pdwHelpStringContext=This->dwHelpStringContext;
7219 if(pbstrHelpStringDll)
7220 *pbstrHelpStringDll=
7221 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7223 }else {/* for a member */
7224 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7225 if(pFDesc->funcdesc.memid==memid){
7227 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7228 if(pdwHelpStringContext)
7229 *pdwHelpStringContext=pFDesc->HelpStringContext;
7230 if(pbstrHelpStringDll)
7231 *pbstrHelpStringDll=
7232 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7235 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7236 if(pVDesc->vardesc.memid==memid){
7238 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7239 if(pdwHelpStringContext)
7240 *pdwHelpStringContext=pVDesc->HelpStringContext;
7241 if(pbstrHelpStringDll)
7242 *pbstrHelpStringDll=
7243 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7247 return TYPE_E_ELEMENTNOTFOUND;
7250 /* ITypeInfo2::GetAllCustData
7252 * Gets all custom data items for the Type info.
7255 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7257 CUSTDATA *pCustData)
7259 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7260 TLBCustData *pCData;
7263 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7265 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7266 if(pCustData->prgCustData ){
7267 pCustData->cCustData=This->ctCustData;
7268 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7269 pCustData->prgCustData[i].guid=pCData->guid;
7270 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7273 ERR(" OUT OF MEMORY!\n");
7274 return E_OUTOFMEMORY;
7279 /* ITypeInfo2::GetAllFuncCustData
7281 * Gets all custom data items for the specified Function
7284 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7287 CUSTDATA *pCustData)
7289 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7290 TLBCustData *pCData;
7291 TLBFuncDesc * pFDesc;
7293 TRACE("(%p) index %d\n", This, index);
7294 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7295 pFDesc=pFDesc->next)
7298 pCustData->prgCustData =
7299 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7300 if(pCustData->prgCustData ){
7301 pCustData->cCustData=pFDesc->ctCustData;
7302 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7303 pCData = pCData->next){
7304 pCustData->prgCustData[i].guid=pCData->guid;
7305 VariantCopy(& pCustData->prgCustData[i].varValue,
7309 ERR(" OUT OF MEMORY!\n");
7310 return E_OUTOFMEMORY;
7314 return TYPE_E_ELEMENTNOTFOUND;
7317 /* ITypeInfo2::GetAllParamCustData
7319 * Gets all custom data items for the Functions
7322 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7323 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7325 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7326 TLBCustData *pCData=NULL;
7327 TLBFuncDesc * pFDesc;
7329 TRACE("(%p) index %d\n", This, indexFunc);
7330 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7331 pFDesc=pFDesc->next)
7333 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7334 pCustData->prgCustData =
7335 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7336 sizeof(CUSTDATAITEM));
7337 if(pCustData->prgCustData ){
7338 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7339 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7340 pCData; i++, pCData = pCData->next){
7341 pCustData->prgCustData[i].guid=pCData->guid;
7342 VariantCopy(& pCustData->prgCustData[i].varValue,
7346 ERR(" OUT OF MEMORY!\n");
7347 return E_OUTOFMEMORY;
7351 return TYPE_E_ELEMENTNOTFOUND;
7354 /* ITypeInfo2::GetAllVarCustData
7356 * Gets all custom data items for the specified Variable
7359 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7360 UINT index, CUSTDATA *pCustData)
7362 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7363 TLBCustData *pCData;
7364 TLBVarDesc * pVDesc;
7366 TRACE("(%p) index %d\n", This, index);
7367 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7368 pVDesc=pVDesc->next)
7371 pCustData->prgCustData =
7372 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7373 if(pCustData->prgCustData ){
7374 pCustData->cCustData=pVDesc->ctCustData;
7375 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7376 pCData = pCData->next){
7377 pCustData->prgCustData[i].guid=pCData->guid;
7378 VariantCopy(& pCustData->prgCustData[i].varValue,
7382 ERR(" OUT OF MEMORY!\n");
7383 return E_OUTOFMEMORY;
7387 return TYPE_E_ELEMENTNOTFOUND;
7390 /* ITypeInfo2::GetAllImplCustData
7392 * Gets all custom data items for the specified implementation type
7395 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7398 CUSTDATA *pCustData)
7400 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7401 TLBCustData *pCData;
7402 TLBImplType * pRDesc;
7404 TRACE("(%p) index %d\n", This, index);
7405 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7406 pRDesc=pRDesc->next)
7409 pCustData->prgCustData =
7410 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7411 if(pCustData->prgCustData ){
7412 pCustData->cCustData=pRDesc->ctCustData;
7413 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7414 pCData = pCData->next){
7415 pCustData->prgCustData[i].guid=pCData->guid;
7416 VariantCopy(& pCustData->prgCustData[i].varValue,
7420 ERR(" OUT OF MEMORY!\n");
7421 return E_OUTOFMEMORY;
7425 return TYPE_E_ELEMENTNOTFOUND;
7428 static const ITypeInfo2Vtbl tinfvt =
7431 ITypeInfo_fnQueryInterface,
7433 ITypeInfo_fnRelease,
7435 ITypeInfo_fnGetTypeAttr,
7436 ITypeInfo_fnGetTypeComp,
7437 ITypeInfo_fnGetFuncDesc,
7438 ITypeInfo_fnGetVarDesc,
7439 ITypeInfo_fnGetNames,
7440 ITypeInfo_fnGetRefTypeOfImplType,
7441 ITypeInfo_fnGetImplTypeFlags,
7442 ITypeInfo_fnGetIDsOfNames,
7444 ITypeInfo_fnGetDocumentation,
7445 ITypeInfo_fnGetDllEntry,
7446 ITypeInfo_fnGetRefTypeInfo,
7447 ITypeInfo_fnAddressOfMember,
7448 ITypeInfo_fnCreateInstance,
7449 ITypeInfo_fnGetMops,
7450 ITypeInfo_fnGetContainingTypeLib,
7451 ITypeInfo_fnReleaseTypeAttr,
7452 ITypeInfo_fnReleaseFuncDesc,
7453 ITypeInfo_fnReleaseVarDesc,
7455 ITypeInfo2_fnGetTypeKind,
7456 ITypeInfo2_fnGetTypeFlags,
7457 ITypeInfo2_fnGetFuncIndexOfMemId,
7458 ITypeInfo2_fnGetVarIndexOfMemId,
7459 ITypeInfo2_fnGetCustData,
7460 ITypeInfo2_fnGetFuncCustData,
7461 ITypeInfo2_fnGetParamCustData,
7462 ITypeInfo2_fnGetVarCustData,
7463 ITypeInfo2_fnGetImplTypeCustData,
7464 ITypeInfo2_fnGetDocumentation2,
7465 ITypeInfo2_fnGetAllCustData,
7466 ITypeInfo2_fnGetAllFuncCustData,
7467 ITypeInfo2_fnGetAllParamCustData,
7468 ITypeInfo2_fnGetAllVarCustData,
7469 ITypeInfo2_fnGetAllImplTypeCustData,
7472 /******************************************************************************
7473 * CreateDispTypeInfo [OLEAUT32.31]
7475 * Build type information for an object so it can be called through an
7476 * IDispatch interface.
7479 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7480 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7483 * This call allows an objects methods to be accessed through IDispatch, by
7484 * building an ITypeInfo object that IDispatch can use to call through.
7486 HRESULT WINAPI CreateDispTypeInfo(
7487 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7488 LCID lcid, /* [I] Locale Id */
7489 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7491 ITypeInfoImpl *pTIClass, *pTIIface;
7492 ITypeLibImpl *pTypeLibImpl;
7493 unsigned int param, func;
7494 TLBFuncDesc **ppFuncDesc;
7498 pTypeLibImpl = TypeLibImpl_Constructor();
7499 if (!pTypeLibImpl) return E_FAIL;
7501 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7502 pTIIface->pTypeLib = pTypeLibImpl;
7503 pTIIface->index = 0;
7504 pTIIface->Name = NULL;
7505 pTIIface->dwHelpContext = -1;
7506 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7507 pTIIface->TypeAttr.lcid = lcid;
7508 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7509 pTIIface->TypeAttr.wMajorVerNum = 0;
7510 pTIIface->TypeAttr.wMinorVerNum = 0;
7511 pTIIface->TypeAttr.cbAlignment = 2;
7512 pTIIface->TypeAttr.cbSizeInstance = -1;
7513 pTIIface->TypeAttr.cbSizeVft = -1;
7514 pTIIface->TypeAttr.cFuncs = 0;
7515 pTIIface->TypeAttr.cImplTypes = 0;
7516 pTIIface->TypeAttr.cVars = 0;
7517 pTIIface->TypeAttr.wTypeFlags = 0;
7519 ppFuncDesc = &pTIIface->funclist;
7520 for(func = 0; func < pidata->cMembers; func++) {
7521 METHODDATA *md = pidata->pmethdata + func;
7522 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7523 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7524 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7525 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7526 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7527 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7528 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7529 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7530 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7531 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7532 (*ppFuncDesc)->funcdesc.cScodes = 0;
7533 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7534 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7535 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7536 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7537 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7538 md->cArgs * sizeof(ELEMDESC));
7539 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7540 md->cArgs * sizeof(TLBParDesc));
7541 for(param = 0; param < md->cArgs; param++) {
7542 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7543 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7545 (*ppFuncDesc)->helpcontext = 0;
7546 (*ppFuncDesc)->HelpStringContext = 0;
7547 (*ppFuncDesc)->HelpString = NULL;
7548 (*ppFuncDesc)->Entry = NULL;
7549 (*ppFuncDesc)->ctCustData = 0;
7550 (*ppFuncDesc)->pCustData = NULL;
7551 (*ppFuncDesc)->next = NULL;
7552 pTIIface->TypeAttr.cFuncs++;
7553 ppFuncDesc = &(*ppFuncDesc)->next;
7556 dump_TypeInfo(pTIIface);
7558 pTypeLibImpl->pTypeInfo = pTIIface;
7559 pTypeLibImpl->TypeInfoCount++;
7561 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7562 pTIClass->pTypeLib = pTypeLibImpl;
7563 pTIClass->index = 1;
7564 pTIClass->Name = NULL;
7565 pTIClass->dwHelpContext = -1;
7566 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7567 pTIClass->TypeAttr.lcid = lcid;
7568 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7569 pTIClass->TypeAttr.wMajorVerNum = 0;
7570 pTIClass->TypeAttr.wMinorVerNum = 0;
7571 pTIClass->TypeAttr.cbAlignment = 2;
7572 pTIClass->TypeAttr.cbSizeInstance = -1;
7573 pTIClass->TypeAttr.cbSizeVft = -1;
7574 pTIClass->TypeAttr.cFuncs = 0;
7575 pTIClass->TypeAttr.cImplTypes = 1;
7576 pTIClass->TypeAttr.cVars = 0;
7577 pTIClass->TypeAttr.wTypeFlags = 0;
7579 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7580 pTIClass->impltypelist->hRef = 0;
7582 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7585 ref->pImpTLInfo = TLB_REF_INTERNAL;
7586 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7588 dump_TypeInfo(pTIClass);
7590 pTIIface->next = pTIClass;
7591 pTypeLibImpl->TypeInfoCount++;
7593 *pptinfo = (ITypeInfo*)pTIClass;
7595 ITypeInfo_AddRef(*pptinfo);
7596 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7602 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7604 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7606 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7609 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7611 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7613 return ITypeInfo_AddRef((ITypeInfo *)This);
7616 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7618 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7620 return ITypeInfo_Release((ITypeInfo *)This);
7623 static HRESULT WINAPI ITypeComp_fnBind(
7628 ITypeInfo ** ppTInfo,
7629 DESCKIND * pDescKind,
7632 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7633 const TLBFuncDesc *pFDesc;
7634 const TLBVarDesc *pVDesc;
7635 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7637 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7639 *pDescKind = DESCKIND_NONE;
7640 pBindPtr->lpfuncdesc = NULL;
7643 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7644 if (!strcmpiW(pFDesc->Name, szName)) {
7645 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7648 /* name found, but wrong flags */
7649 hr = TYPE_E_TYPEMISMATCH;
7654 HRESULT hr = TLB_AllocAndInitFuncDesc(
7656 &pBindPtr->lpfuncdesc,
7657 This->TypeAttr.typekind == TKIND_DISPATCH);
7660 *pDescKind = DESCKIND_FUNCDESC;
7661 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7662 ITypeInfo_AddRef(*ppTInfo);
7665 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7666 if (!strcmpiW(pVDesc->Name, szName)) {
7667 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7670 *pDescKind = DESCKIND_VARDESC;
7671 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7672 ITypeInfo_AddRef(*ppTInfo);
7677 /* FIXME: search each inherited interface, not just the first */
7678 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7679 /* recursive search */
7683 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7686 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7687 ITypeInfo_Release(pTInfo);
7691 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7692 ITypeComp_Release(pTComp);
7695 WARN("Could not search inherited interface!\n");
7697 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7701 static HRESULT WINAPI ITypeComp_fnBindType(
7705 ITypeInfo ** ppTInfo,
7706 ITypeComp ** ppTComp)
7708 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7710 /* strange behaviour (does nothing) but like the
7713 if (!ppTInfo || !ppTComp)
7722 static const ITypeCompVtbl tcompvt =
7725 ITypeComp_fnQueryInterface,
7727 ITypeComp_fnRelease,
7730 ITypeComp_fnBindType