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
68 #include "wine/unicode.h"
71 #include "wine/debug.h"
73 #include "wine/list.h"
75 WINE_DEFAULT_DEBUG_CHANNEL(ole);
76 WINE_DECLARE_DEBUG_CHANNEL(typelib);
78 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
79 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
81 /****************************************************************************
84 * Takes p_iVal (which is in little endian) and returns it
85 * in the host machine's byte order.
87 #ifdef WORDS_BIGENDIAN
88 static WORD FromLEWord(WORD p_iVal)
90 return (((p_iVal & 0x00FF) << 8) |
91 ((p_iVal & 0xFF00) >> 8));
95 static DWORD FromLEDWord(DWORD p_iVal)
97 return (((p_iVal & 0x000000FF) << 24) |
98 ((p_iVal & 0x0000FF00) << 8) |
99 ((p_iVal & 0x00FF0000) >> 8) |
100 ((p_iVal & 0xFF000000) >> 24));
103 #define FromLEWord(X) (X)
104 #define FromLEDWord(X) (X)
107 #define DISPATCH_HREF_OFFSET 0x01000000
108 #define DISPATCH_HREF_MASK 0xff000000
110 /****************************************************************************
113 * Fix byte order in any structure if necessary
115 #ifdef WORDS_BIGENDIAN
116 static void FromLEWords(void *p_Val, int p_iSize)
120 p_iSize /= sizeof(WORD);
123 *Val = FromLEWord(*Val);
130 static void FromLEDWords(void *p_Val, int p_iSize)
134 p_iSize /= sizeof(DWORD);
137 *Val = FromLEDWord(*Val);
143 #define FromLEWords(X,Y) /*nothing*/
144 #define FromLEDWords(X,Y) /*nothing*/
148 * Find a typelib key which matches a requested maj.min version.
150 static BOOL find_typelib_key( REFGUID guid, WORD wMaj, WORD *wMin )
152 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
159 memcpy( buffer, typelibW, sizeof(typelibW) );
160 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
162 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
165 len = sizeof(key_name);
167 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
171 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
173 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
180 break; /* exact match */
182 if (v_min > best_min) best_min = v_min;
185 len = sizeof(key_name);
196 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
197 /* buffer must be at least 60 characters long */
198 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
200 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
201 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
203 memcpy( buffer, TypelibW, sizeof(TypelibW) );
204 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
205 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
209 /* get the path of an interface key, in the form "Interface\\<guid>" */
210 /* buffer must be at least 50 characters long */
211 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
213 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
215 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
216 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
220 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
221 /* buffer must be at least 16 characters long */
222 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
224 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
225 static const WCHAR win16W[] = {'w','i','n','1','6',0};
226 static const WCHAR win32W[] = {'w','i','n','3','2',0};
228 sprintfW( buffer, LcidFormatW, lcid );
231 case SYS_WIN16: strcatW( buffer, win16W ); break;
232 case SYS_WIN32: strcatW( buffer, win32W ); break;
234 TRACE("Typelib is for unsupported syskind %i\n", syskind);
240 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
243 /****************************************************************************
244 * QueryPathOfRegTypeLib [OLEAUT32.164]
246 * Gets the path to a registered type library.
249 * guid [I] referenced guid
250 * wMaj [I] major version
251 * wMin [I] minor version
253 * path [O] path of typelib
257 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
258 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
261 HRESULT WINAPI QueryPathOfRegTypeLib(
268 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
272 WCHAR Path[MAX_PATH];
275 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
277 if (!find_typelib_key( guid, wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
278 get_typelib_key( guid, wMaj, wMin, buffer );
280 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
281 if (res == ERROR_FILE_NOT_FOUND)
283 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
284 return TYPE_E_LIBNOTREGISTERED;
286 else if (res != ERROR_SUCCESS)
288 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
289 return TYPE_E_REGISTRYACCESS;
294 LONG dwPathLen = sizeof(Path);
296 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
298 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
302 else if (myLCID == lcid)
304 /* try with sub-langid */
305 myLCID = SUBLANGID(lcid);
307 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
309 /* try with system langid */
319 *path = SysAllocString( Path );
324 TRACE_(typelib)("-- 0x%08x\n", hr);
328 /******************************************************************************
329 * CreateTypeLib [OLEAUT32.160] creates a typelib
335 HRESULT WINAPI CreateTypeLib(
336 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
338 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
342 /******************************************************************************
343 * LoadTypeLib [OLEAUT32.161]
345 * Loads a type library
348 * szFile [I] Name of file to load from.
349 * pptLib [O] Pointer that receives ITypeLib object on success.
356 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
358 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
360 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
361 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
364 /******************************************************************************
365 * LoadTypeLibEx [OLEAUT32.183]
367 * Loads and optionally registers a type library
373 HRESULT WINAPI LoadTypeLibEx(
374 LPCOLESTR szFile, /* [in] Name of file to load from */
375 REGKIND regkind, /* [in] Specify kind of registration */
376 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
378 WCHAR szPath[MAX_PATH+1];
381 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
385 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
390 case REGKIND_DEFAULT:
391 /* don't register typelibs supplied with full path. Experimentation confirms the following */
392 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
393 (szFile[0] && (szFile[1] == ':'))) break;
394 /* else fall-through */
396 case REGKIND_REGISTER:
397 if (FAILED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
399 IUnknown_Release(*pptLib);
407 TRACE(" returns %08x\n",res);
411 /******************************************************************************
412 * LoadRegTypeLib [OLEAUT32.162]
414 * Loads a registered type library.
417 * rguid [I] GUID of the registered type library.
418 * wVerMajor [I] major version.
419 * wVerMinor [I] minor version.
420 * lcid [I] locale ID.
421 * ppTLib [O] pointer that receives an ITypeLib object on success.
425 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
428 HRESULT WINAPI LoadRegTypeLib(
440 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
444 res= LoadTypeLib(bstr, ppTLib);
448 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
454 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
455 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
456 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
457 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
458 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
459 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
461 /******************************************************************************
462 * RegisterTypeLib [OLEAUT32.163]
463 * Adds information about a type library to the System Registry
465 * Docs: ITypeLib FAR * ptlib
466 * Docs: OLECHAR FAR* szFullPath
467 * Docs: OLECHAR FAR* szHelpDir
473 HRESULT WINAPI RegisterTypeLib(
474 ITypeLib * ptlib, /* [in] Pointer to the library*/
475 OLECHAR * szFullPath, /* [in] full Path of the library*/
476 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
479 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
480 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
481 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
491 if (ptlib == NULL || szFullPath == NULL)
494 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
497 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
500 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
501 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
505 /* Set the human-readable name of the typelib */
506 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
508 if (RegSetValueExW(key, NULL, 0, REG_SZ,
509 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
517 /* Make up the name of the typelib path subkey */
518 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
520 /* Create the typelib path subkey */
521 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
522 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
524 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
525 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
533 /* Create the flags subkey */
534 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
535 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
537 /* FIXME: is %u correct? */
538 static const WCHAR formatW[] = {'%','u',0};
540 sprintfW(buf, formatW, attr->wLibFlags);
541 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
542 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
550 /* create the helpdir subkey */
551 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
552 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
554 BOOL freeHelpDir = FALSE;
557 /* if we created a new key, and helpDir was null, set the helpdir
558 to the directory which contains the typelib. However,
559 if we just opened an existing key, we leave the helpdir alone */
560 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
561 szHelpDir = SysAllocString(szFullPath);
562 pIndexStr = strrchrW(szHelpDir, '\\');
569 /* if we have an szHelpDir, set it! */
570 if (szHelpDir != NULL) {
571 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
572 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
578 if (freeHelpDir) SysFreeString(szHelpDir);
590 /* register OLE Automation-compatible interfaces for this typelib */
591 types = ITypeLib_GetTypeInfoCount(ptlib);
592 for (tidx=0; tidx<types; tidx++) {
593 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
594 LPOLESTR name = NULL;
595 ITypeInfo *tinfo = NULL;
597 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
600 case TKIND_INTERFACE:
601 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
602 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
606 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
607 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
611 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
616 TYPEATTR *tattr = NULL;
617 ITypeInfo_GetTypeAttr(tinfo, &tattr);
620 TRACE_(typelib)("guid=%s, flags=%04x (",
621 debugstr_guid(&tattr->guid),
624 if (TRACE_ON(typelib)) {
625 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
645 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
647 /* register interface<->typelib coupling */
648 get_interface_key( &tattr->guid, keyName );
649 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
650 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
653 RegSetValueExW(key, NULL, 0, REG_SZ,
654 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
656 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
657 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
658 RegSetValueExW(subKey, NULL, 0, REG_SZ,
659 (const BYTE *)PSOA, sizeof PSOA);
663 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
664 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
665 RegSetValueExW(subKey, NULL, 0, REG_SZ,
666 (const BYTE *)PSOA, sizeof PSOA);
670 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
671 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
674 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
675 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
677 StringFromGUID2(&attr->guid, buffer, 40);
678 RegSetValueExW(subKey, NULL, 0, REG_SZ,
679 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
680 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
681 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
682 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
690 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
693 ITypeInfo_Release(tinfo);
700 ITypeLib_ReleaseTLibAttr(ptlib, attr);
706 /******************************************************************************
707 * UnRegisterTypeLib [OLEAUT32.186]
708 * Removes information about a type library from the System Registry
715 HRESULT WINAPI UnRegisterTypeLib(
716 REFGUID libid, /* [in] Guid of the library */
717 WORD wVerMajor, /* [in] major version */
718 WORD wVerMinor, /* [in] minor version */
719 LCID lcid, /* [in] locale id */
722 BSTR tlibPath = NULL;
725 WCHAR subKeyName[50];
728 BOOL deleteOtherStuff;
731 TYPEATTR* typeAttr = NULL;
733 ITypeInfo* typeInfo = NULL;
734 ITypeLib* typeLib = NULL;
737 TRACE("(IID: %s)\n",debugstr_guid(libid));
739 /* Create the path to the key */
740 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
742 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
744 TRACE("Unsupported syskind %i\n", syskind);
745 result = E_INVALIDARG;
749 /* get the path to the typelib on disk */
750 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
751 result = E_INVALIDARG;
755 /* Try and open the key to the type library. */
756 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
757 result = E_INVALIDARG;
761 /* Try and load the type library */
762 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
763 result = TYPE_E_INVALIDSTATE;
767 /* remove any types registered with this typelib */
768 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
769 for (i=0; i<numTypes; i++) {
770 /* get the kind of type */
771 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
775 /* skip non-interfaces, and get type info for the type */
776 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
779 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
782 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
786 /* the path to the type */
787 get_interface_key( &typeAttr->guid, subKeyName );
789 /* Delete its bits */
790 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS) {
793 RegDeleteKeyW(subKey, ProxyStubClsidW);
794 RegDeleteKeyW(subKey, ProxyStubClsid32W);
795 RegDeleteKeyW(subKey, TypeLibW);
798 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
801 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
803 if (typeInfo) ITypeInfo_Release(typeInfo);
807 /* Now, delete the type library path subkey */
808 get_lcid_subkey( lcid, syskind, subKeyName );
809 RegDeleteKeyW(key, subKeyName);
810 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
811 RegDeleteKeyW(key, subKeyName);
813 /* check if there is anything besides the FLAGS/HELPDIR keys.
814 If there is, we don't delete them */
815 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
816 deleteOtherStuff = TRUE;
818 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
819 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
821 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
822 if (!strcmpW(subKeyName, FLAGSW)) continue;
823 if (!strcmpW(subKeyName, HELPDIRW)) continue;
824 deleteOtherStuff = FALSE;
828 /* only delete the other parts of the key if we're absolutely sure */
829 if (deleteOtherStuff) {
830 RegDeleteKeyW(key, FLAGSW);
831 RegDeleteKeyW(key, HELPDIRW);
835 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
836 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
837 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
841 SysFreeString(tlibPath);
842 if (typeLib) ITypeLib_Release(typeLib);
843 if (subKey) RegCloseKey(subKey);
844 if (key) RegCloseKey(key);
848 /*======================= ITypeLib implementation =======================*/
850 typedef struct tagTLBCustData
854 struct tagTLBCustData* next;
857 /* data structure for import typelibs */
858 typedef struct tagTLBImpLib
860 int offset; /* offset in the file (MSFT)
861 offset in nametable (SLTG)
862 just used to identify library while reading
864 GUID guid; /* libid */
865 BSTR name; /* name */
867 LCID lcid; /* lcid of imported typelib */
869 WORD wVersionMajor; /* major version number */
870 WORD wVersionMinor; /* minor version number */
872 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
873 NULL if not yet loaded */
874 struct tagTLBImpLib * next;
877 /* internal ITypeLib data */
878 typedef struct tagITypeLibImpl
880 const ITypeLib2Vtbl *lpVtbl;
881 const ITypeCompVtbl *lpVtblTypeComp;
883 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
885 /* strings can be stored in tlb as multibyte strings BUT they are *always*
886 * exported to the application as a UNICODE string.
892 unsigned long dwHelpContext;
893 int TypeInfoCount; /* nr of typeinfo's in librarry */
894 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
895 int ctCustData; /* number of items in cust data list */
896 TLBCustData * pCustData; /* linked list to cust data */
897 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
898 int ctTypeDesc; /* number of items in type desc array */
899 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
900 library. Only used while reading MSFT
902 struct list ref_list; /* list of ref types in this typelib */
903 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
906 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
907 struct tagITypeLibImpl *next, *prev;
912 static const ITypeLib2Vtbl tlbvt;
913 static const ITypeCompVtbl tlbtcvt;
915 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
917 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
920 /* ITypeLib methods */
921 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
922 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
924 /*======================= ITypeInfo implementation =======================*/
926 /* data for referenced types */
927 typedef struct tagTLBRefType
929 INT index; /* Type index for internal ref or for external ref
930 it the format is SLTG. -2 indicates to
933 GUID guid; /* guid of the referenced type */
934 /* if index == TLB_REF_USE_GUID */
936 HREFTYPE reference; /* The href of this ref */
937 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
938 TLB_REF_INTERNAL for internal refs
939 TLB_REF_NOT_FOUND for broken refs */
944 #define TLB_REF_USE_GUID -2
946 #define TLB_REF_INTERNAL (void*)-2
947 #define TLB_REF_NOT_FOUND (void*)-1
949 /* internal Parameter data */
950 typedef struct tagTLBParDesc
954 TLBCustData * pCustData; /* linked list to cust data */
957 /* internal Function data */
958 typedef struct tagTLBFuncDesc
960 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
961 BSTR Name; /* the name of this function */
962 TLBParDesc *pParamDesc; /* array with param names and custom data */
964 int HelpStringContext;
966 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
968 TLBCustData * pCustData; /* linked list to cust data; */
969 struct tagTLBFuncDesc * next;
972 /* internal Variable data */
973 typedef struct tagTLBVarDesc
975 VARDESC vardesc; /* lots of info on the variable and its attributes. */
976 BSTR Name; /* the name of this variable */
978 int HelpStringContext; /* FIXME: where? */
981 TLBCustData * pCustData;/* linked list to cust data; */
982 struct tagTLBVarDesc * next;
985 /* internal implemented interface data */
986 typedef struct tagTLBImplType
988 HREFTYPE hRef; /* hRef of interface */
989 int implflags; /* IMPLFLAG_*s */
991 TLBCustData * pCustData;/* linked list to custom data; */
992 struct tagTLBImplType *next;
995 /* internal TypeInfo data */
996 typedef struct tagITypeInfoImpl
998 const ITypeInfo2Vtbl *lpVtbl;
999 const ITypeCompVtbl *lpVtblTypeComp;
1001 BOOL no_free_data; /* don't free data structures */
1002 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1003 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1004 int index; /* index in this typelib; */
1005 HREFTYPE hreftype; /* hreftype for app object binding */
1006 /* type libs seem to store the doc strings in ascii
1007 * so why should we do it in unicode?
1012 unsigned long dwHelpContext;
1013 unsigned long dwHelpStringContext;
1016 TLBFuncDesc * funclist; /* linked list with function descriptions */
1019 TLBVarDesc * varlist; /* linked list with variable descriptions */
1021 /* Implemented Interfaces */
1022 TLBImplType * impltypelist;
1025 TLBCustData * pCustData; /* linked list to cust data; */
1026 struct tagITypeInfoImpl * next;
1029 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1031 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1034 static const ITypeInfo2Vtbl tinfvt;
1035 static const ITypeCompVtbl tcompvt;
1037 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1039 typedef struct tagTLBContext
1041 unsigned int oStart; /* start of TLB in file */
1042 unsigned int pos; /* current pos */
1043 unsigned int length; /* total length */
1044 void *mapping; /* memory mapping */
1045 MSFT_SegDir * pTblDir;
1046 ITypeLibImpl* pLibInfo;
1050 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1055 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1056 if (pTD->vt & VT_RESERVED)
1057 szVarType += strlen(strcpy(szVarType, "reserved | "));
1058 if (pTD->vt & VT_BYREF)
1059 szVarType += strlen(strcpy(szVarType, "ref to "));
1060 if (pTD->vt & VT_ARRAY)
1061 szVarType += strlen(strcpy(szVarType, "array of "));
1062 if (pTD->vt & VT_VECTOR)
1063 szVarType += strlen(strcpy(szVarType, "vector of "));
1064 switch(pTD->vt & VT_TYPEMASK) {
1065 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1066 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1067 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1068 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1069 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1070 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1071 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1072 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1073 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1074 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1075 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1076 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1077 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1078 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1079 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1080 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1081 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1082 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1083 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1084 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1085 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1086 pTD->u.hreftype); break;
1087 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1088 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1089 case VT_PTR: sprintf(szVarType, "ptr to ");
1090 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1092 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1093 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1095 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1096 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1097 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1100 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1104 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1106 USHORT flags = edesc->u.paramdesc.wParamFlags;
1107 dump_TypeDesc(&edesc->tdesc,buf);
1108 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1109 MESSAGE("\t\tu.paramdesc.wParamFlags");
1110 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1111 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1112 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1113 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1114 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1115 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1116 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1117 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1118 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1120 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1122 MESSAGE("memid is %08x\n",funcdesc->memid);
1123 for (i=0;i<funcdesc->cParams;i++) {
1124 MESSAGE("Param %d:\n",i);
1125 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1127 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1128 switch (funcdesc->funckind) {
1129 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1130 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1131 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1132 case FUNC_STATIC: MESSAGE("static");break;
1133 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1134 default: MESSAGE("unknown");break;
1136 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1137 switch (funcdesc->invkind) {
1138 case INVOKE_FUNC: MESSAGE("func");break;
1139 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1140 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1141 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1143 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1144 switch (funcdesc->callconv) {
1145 case CC_CDECL: MESSAGE("cdecl");break;
1146 case CC_PASCAL: MESSAGE("pascal");break;
1147 case CC_STDCALL: MESSAGE("stdcall");break;
1148 case CC_SYSCALL: MESSAGE("syscall");break;
1151 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1152 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1153 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1155 MESSAGE("\telemdescFunc (return value type):\n");
1156 dump_ELEMDESC(&funcdesc->elemdescFunc);
1159 static const char * const typekind_desc[] =
1172 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1175 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1176 for (i=0;i<pfd->funcdesc.cParams;i++)
1177 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1180 dump_FUNCDESC(&(pfd->funcdesc));
1182 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1183 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1185 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1189 dump_TLBFuncDescOne(pfd);
1193 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1197 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1202 static void dump_TLBImpLib(const TLBImpLib *import)
1204 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1205 debugstr_w(import->name));
1206 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1207 import->wVersionMinor, import->lcid, import->offset);
1210 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1214 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1216 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1217 if(ref->index == -1)
1218 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1220 TRACE_(typelib)("type no: %d\n", ref->index);
1222 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1224 TRACE_(typelib)("in lib\n");
1225 dump_TLBImpLib(ref->pImpTLInfo);
1230 static void dump_TLBImplType(const TLBImplType * impl)
1234 "implementing/inheriting interface hRef = %x implflags %x\n",
1235 impl->hRef, impl->implflags);
1240 static void dump_Variant(const VARIANT * pvar)
1244 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1248 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1249 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1251 TRACE(",%p", V_BYREF(pvar));
1253 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1255 TRACE(",%p", V_ARRAY(pvar));
1257 else switch (V_TYPE(pvar))
1259 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1260 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1261 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1262 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1264 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1266 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1267 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1268 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1269 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1270 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1271 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1272 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1273 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1274 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1275 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1276 V_CY(pvar).s.Lo); break;
1278 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1279 TRACE(",<invalid>");
1281 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1282 st.wHour, st.wMinute, st.wSecond);
1286 case VT_USERDEFINED:
1288 case VT_NULL: break;
1289 default: TRACE(",?"); break;
1295 static void dump_DispParms(const DISPPARAMS * pdp)
1299 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1301 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1303 TRACE("named args:\n");
1304 for (index = 0; index < pdp->cNamedArgs; index++)
1305 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1308 if (pdp->cArgs && pdp->rgvarg)
1311 for (index = 0; index < pdp->cArgs; index++)
1312 dump_Variant( &pdp->rgvarg[index] );
1316 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1318 TRACE("%p ref=%u\n", pty, pty->ref);
1319 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1320 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1321 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1322 TRACE("fct:%u var:%u impl:%u\n",
1323 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1324 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1325 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1326 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1328 dump_TLBFuncDesc(pty->funclist);
1329 dump_TLBVarDesc(pty->varlist);
1330 dump_TLBImplType(pty->impltypelist);
1333 static void dump_VARDESC(const VARDESC *v)
1335 MESSAGE("memid %d\n",v->memid);
1336 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1337 MESSAGE("oInst %d\n",v->u.oInst);
1338 dump_ELEMDESC(&(v->elemdescVar));
1339 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1340 MESSAGE("varkind %d\n",v->varkind);
1343 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1345 /* VT_LPWSTR is largest type that */
1346 /* may appear in type description*/
1347 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1348 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1349 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1350 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1351 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1352 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1356 static void TLB_abort(void)
1361 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1362 static void * TLB_Alloc(unsigned size)
1365 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1367 ERR("cannot allocate memory\n");
1372 static void TLB_Free(void * ptr)
1374 HeapFree(GetProcessHeap(), 0, ptr);
1377 /* returns the size required for a deep copy of a typedesc into a
1379 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1383 if (alloc_initial_space)
1384 size += sizeof(TYPEDESC);
1390 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1393 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1394 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1400 /* deep copy a typedesc into a flat buffer */
1401 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1406 buffer = (char *)buffer + sizeof(TYPEDESC);
1415 dest->u.lptdesc = buffer;
1416 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1419 dest->u.lpadesc = buffer;
1420 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1421 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1422 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1428 /* free custom data allocated by MSFT_CustData */
1429 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1431 TLBCustData *pCustDataNext;
1432 for (; pCustData; pCustData = pCustDataNext)
1434 VariantClear(&pCustData->data);
1436 pCustDataNext = pCustData->next;
1437 TLB_Free(pCustData);
1441 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1446 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1447 ret = SysAllocStringLen(NULL, len - 1);
1448 if (!ret) return ret;
1449 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1453 /**********************************************************************
1455 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1457 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1462 static inline void MSFT_Seek(TLBContext *pcx, long where)
1464 if (where != DO_NOT_SEEK)
1466 where += pcx->oStart;
1467 if (where > pcx->length)
1470 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1478 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1480 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08lx\n",
1481 pcx->pos, count, pcx->oStart, pcx->length, where);
1483 MSFT_Seek(pcx, where);
1484 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1485 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1490 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1495 ret = MSFT_Read(buffer, count, pcx, where);
1496 FromLEDWords(buffer, ret);
1501 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1506 ret = MSFT_Read(buffer, count, pcx, where);
1507 FromLEWords(buffer, ret);
1512 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1514 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1515 memset(pGuid,0, sizeof(GUID));
1518 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1519 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1520 pGuid->Data2 = FromLEWord(pGuid->Data2);
1521 pGuid->Data3 = FromLEWord(pGuid->Data3);
1522 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1525 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1527 MSFT_NameIntro niName;
1531 ERR_(typelib)("bad offset %d\n", offset);
1535 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1536 pcx->pTblDir->pNametab.offset+offset);
1538 return niName.hreftype;
1541 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1544 MSFT_NameIntro niName;
1546 BSTR bstrName = NULL;
1550 ERR_(typelib)("bad offset %d\n", offset);
1553 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1554 pcx->pTblDir->pNametab.offset+offset);
1555 niName.namelen &= 0xFF; /* FIXME: correct ? */
1556 name=TLB_Alloc((niName.namelen & 0xff) +1);
1557 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1558 name[niName.namelen & 0xff]='\0';
1560 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1563 /* no invalid characters in string */
1566 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1568 /* don't check for invalid character since this has been done previously */
1569 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1573 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1577 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1584 if(offset<0) return NULL;
1585 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1586 if(length <= 0) return 0;
1587 string=TLB_Alloc(length +1);
1588 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1589 string[length]='\0';
1591 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1592 string, -1, NULL, 0);
1594 /* no invalid characters in string */
1597 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1599 /* don't check for invalid character since this has been done previously */
1600 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1604 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1608 * read a value and fill a VARIANT structure
1610 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1614 TRACE_(typelib)("\n");
1616 if(offset <0) { /* data are packed in here */
1617 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1618 V_I4(pVar) = offset & 0x3ffffff;
1621 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1622 pcx->pTblDir->pCustData.offset + offset );
1623 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1624 switch (V_VT(pVar)){
1625 case VT_EMPTY: /* FIXME: is this right? */
1626 case VT_NULL: /* FIXME: is this right? */
1627 case VT_I2 : /* this should not happen */
1638 case VT_VOID : /* FIXME: is this right? */
1646 case VT_DECIMAL : /* FIXME: is this right? */
1649 /* pointer types with known behaviour */
1652 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1655 DWORD origPos = MSFT_Tell(pcx), nullPos;
1658 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1660 nullPos = MSFT_Tell(pcx);
1661 size = nullPos - origPos;
1662 MSFT_Seek(pcx, origPos);
1664 ptr=TLB_Alloc(size);/* allocate temp buffer */
1665 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1666 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1667 /* FIXME: do we need a AtoW conversion here? */
1668 V_UNION(pVar, bstrVal[size])='\0';
1669 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1673 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1680 case VT_USERDEFINED :
1686 case VT_STREAMED_OBJECT :
1687 case VT_STORED_OBJECT :
1688 case VT_BLOB_OBJECT :
1693 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1697 if(size>0) /* (big|small) endian correct? */
1698 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1702 * create a linked list with custom data
1704 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1710 TRACE_(typelib)("\n");
1714 pNew=TLB_Alloc(sizeof(TLBCustData));
1715 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1716 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1717 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1718 /* add new custom data at head of the list */
1719 pNew->next=*ppCustData;
1721 offset = entry.next;
1726 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1730 pTd->vt=type & VT_TYPEMASK;
1732 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1734 if(pTd->vt == VT_USERDEFINED)
1735 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1737 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1740 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1742 /* resolve referenced type if any */
1745 switch (lpTypeDesc->vt)
1748 lpTypeDesc = lpTypeDesc->u.lptdesc;
1752 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1755 case VT_USERDEFINED:
1756 MSFT_DoRefType(pcx, pTI->pTypeLib,
1757 lpTypeDesc->u.hreftype);
1769 MSFT_DoFuncs(TLBContext* pcx,
1774 TLBFuncDesc** pptfd)
1777 * member information is stored in a data structure at offset
1778 * indicated by the memoffset field of the typeinfo structure
1779 * There are several distinctive parts.
1780 * The first part starts with a field that holds the total length
1781 * of this (first) part excluding this field. Then follow the records,
1782 * for each member there is one record.
1784 * The first entry is always the length of the record (including this
1786 * The rest of the record depends on the type of the member. If there is
1787 * a field indicating the member type (function, variable, interface, etc)
1788 * I have not found it yet. At this time we depend on the information
1789 * in the type info and the usual order how things are stored.
1791 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1794 * Third is an equal sized array with file offsets to the name entry
1797 * The fourth and last (?) part is an array with offsets to the records
1798 * in the first part of this file segment.
1801 int infolen, nameoffset, reclength, nrattributes, i;
1802 int recoffset = offset + sizeof(INT);
1804 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1805 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1806 TLBFuncDesc *ptfd_prev = NULL;
1808 TRACE_(typelib)("\n");
1810 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1812 for ( i = 0; i < cFuncs ; i++ )
1814 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1816 /* name, eventually add to a hash table */
1817 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1818 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1820 /* nameoffset is sometimes -1 on the second half of a propget/propput
1821 * pair of functions */
1822 if ((nameoffset == -1) && (i > 0))
1823 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1825 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1827 /* read the function information record */
1828 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1830 reclength &= 0xffff;
1832 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1834 /* do the attributes */
1835 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1838 if ( nrattributes > 0 )
1840 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1842 if ( nrattributes > 1 )
1844 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1845 pFuncRec->OptAttr[1]) ;
1847 if ( nrattributes > 2 )
1849 if ( pFuncRec->FKCCIC & 0x2000 )
1851 if (HIWORD(pFuncRec->OptAttr[2]) != 0)
1852 ERR("ordinal 0x%08x invalid, HIWORD != 0\n", pFuncRec->OptAttr[2]);
1853 (*pptfd)->Entry = (BSTR)pFuncRec->OptAttr[2];
1857 (*pptfd)->Entry = MSFT_ReadString(pcx,
1858 pFuncRec->OptAttr[2]);
1860 if( nrattributes > 5 )
1862 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1864 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1867 pFuncRec->OptAttr[6],
1868 &(*pptfd)->pCustData);
1874 (*pptfd)->Entry = (BSTR)-1;
1879 /* fill the FuncDesc Structure */
1880 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1881 offset + infolen + ( i + 1) * sizeof(INT));
1883 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1884 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1885 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1886 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1887 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1888 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1889 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1893 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1895 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1897 /* do the parameters/arguments */
1898 if(pFuncRec->nrargs)
1901 MSFT_ParameterInfo paraminfo;
1903 (*pptfd)->funcdesc.lprgelemdescParam =
1904 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1906 (*pptfd)->pParamDesc =
1907 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1909 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1910 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1912 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1914 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1921 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1924 if (paraminfo.oName == -1)
1925 /* this occurs for [propput] or [propget] methods, so
1926 * we should just set the name of the parameter to the
1927 * name of the method. */
1928 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1930 (*pptfd)->pParamDesc[j].Name =
1931 MSFT_ReadName( pcx, paraminfo.oName );
1932 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1934 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1937 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1938 (pFuncRec->FKCCIC & 0x1000) )
1940 INT* pInt = (INT *)((char *)pFuncRec +
1942 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1944 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1946 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1947 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1949 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1953 elemdesc->u.paramdesc.pparamdescex = NULL;
1955 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1958 pFuncRec->OptAttr[7+j],
1959 &(*pptfd)->pParamDesc[j].pCustData);
1962 /* SEEK value = jump to offset,
1963 * from there jump to the end of record,
1964 * go back by (j-1) arguments
1966 MSFT_ReadLEDWords( ¶minfo ,
1967 sizeof(MSFT_ParameterInfo), pcx,
1968 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1969 * sizeof(MSFT_ParameterInfo)));
1973 /* scode is not used: archaic win16 stuff FIXME: right? */
1974 (*pptfd)->funcdesc.cScodes = 0 ;
1975 (*pptfd)->funcdesc.lprgscode = NULL ;
1978 pptfd = & ((*pptfd)->next);
1979 recoffset += reclength;
1981 HeapFree(GetProcessHeap(), 0, recbuf);
1984 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1985 int cVars, int offset, TLBVarDesc ** pptvd)
1987 int infolen, nameoffset, reclength;
1989 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1993 TRACE_(typelib)("\n");
1995 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1996 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1997 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1998 recoffset += offset+sizeof(INT);
1999 for(i=0;i<cVars;i++){
2000 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2001 /* name, eventually add to a hash table */
2002 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2003 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2004 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2005 /* read the variable information record */
2006 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2008 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2010 if(reclength >(6*sizeof(INT)) )
2011 (*pptvd)->HelpContext=pVarRec->HelpContext;
2012 if(reclength >(7*sizeof(INT)) )
2013 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2014 if(reclength >(8*sizeof(INT)) )
2015 if(reclength >(9*sizeof(INT)) )
2016 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2017 /* fill the VarDesc Structure */
2018 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2019 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2020 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2021 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2022 MSFT_GetTdesc(pcx, pVarRec->DataType,
2023 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2024 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2025 if(pVarRec->VarKind == VAR_CONST ){
2026 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2027 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2028 pVarRec->OffsValue, pcx);
2030 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2031 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2032 pptvd=&((*pptvd)->next);
2033 recoffset += reclength;
2036 /* fill in data for a hreftype (offset). When the referenced type is contained
2037 * in the typelib, it's just an (file) offset in the type info base dir.
2038 * If comes from import, it's an offset+1 in the ImpInfo table
2040 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2045 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2047 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2049 if(ref->reference == offset) return;
2052 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2053 list_add_tail(&pTL->ref_list, &ref->entry);
2055 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2056 /* external typelib */
2057 MSFT_ImpInfo impinfo;
2058 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2060 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2062 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2063 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2064 while (pImpLib){ /* search the known offsets of all import libraries */
2065 if(pImpLib->offset==impinfo.oImpFile) break;
2066 pImpLib=pImpLib->next;
2069 ref->reference = offset;
2070 ref->pImpTLInfo = pImpLib;
2071 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2072 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2073 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2074 ref->index = TLB_REF_USE_GUID;
2076 ref->index = impinfo.oGuid;
2078 ERR("Cannot find a reference\n");
2079 ref->reference = -1;
2080 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2083 /* in this typelib */
2084 ref->index = MSFT_HREFTYPE_INDEX(offset);
2085 ref->reference = offset;
2086 ref->pImpTLInfo = TLB_REF_INTERNAL;
2090 /* process Implemented Interfaces of a com class */
2091 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2095 MSFT_RefRecord refrec;
2096 TLBImplType **ppImpl = &pTI->impltypelist;
2098 TRACE_(typelib)("\n");
2100 for(i=0;i<count;i++){
2101 if(offset<0) break; /* paranoia */
2102 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2103 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2104 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2105 (*ppImpl)->hRef = refrec.reftype;
2106 (*ppImpl)->implflags=refrec.flags;
2107 (*ppImpl)->ctCustData=
2108 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2109 offset=refrec.onext;
2110 ppImpl=&((*ppImpl)->next);
2114 * process a typeinfo record
2116 static ITypeInfoImpl * MSFT_DoTypeInfo(
2119 ITypeLibImpl * pLibInfo)
2121 MSFT_TypeInfoBase tiBase;
2122 ITypeInfoImpl *ptiRet;
2124 TRACE_(typelib)("count=%u\n", count);
2126 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2127 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2128 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2130 /* this is where we are coming from */
2131 ptiRet->pTypeLib = pLibInfo;
2132 ptiRet->index=count;
2133 /* fill in the typeattr fields */
2135 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2136 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2137 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2138 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2139 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2140 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2141 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2142 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2143 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2144 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2145 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2146 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2147 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2148 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2149 MSFT_GetTdesc(pcx, tiBase.datatype1,
2150 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2153 /* IDLDESC idldescType; *//* never saw this one != zero */
2155 /* name, eventually add to a hash table */
2156 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2157 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2158 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2160 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2161 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2162 ptiRet->dwHelpContext=tiBase.helpcontext;
2164 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2165 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2167 /* note: InfoType's Help file and HelpStringDll come from the containing
2168 * library. Further HelpString and Docstring appear to be the same thing :(
2171 if(ptiRet->TypeAttr.cFuncs >0 )
2172 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2173 ptiRet->TypeAttr.cVars,
2174 tiBase.memoffset, & ptiRet->funclist);
2176 if(ptiRet->TypeAttr.cVars >0 )
2177 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2178 ptiRet->TypeAttr.cVars,
2179 tiBase.memoffset, & ptiRet->varlist);
2180 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2181 switch(ptiRet->TypeAttr.typekind)
2184 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2187 case TKIND_DISPATCH:
2188 /* This is not -1 when the interface is a non-base dual interface or
2189 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2190 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2194 if (tiBase.datatype1 != -1)
2196 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2197 ptiRet->impltypelist->hRef = tiBase.datatype1;
2198 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2202 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2203 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2204 ptiRet->impltypelist->hRef = tiBase.datatype1;
2209 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2211 TRACE_(typelib)("%s guid: %s kind:%s\n",
2212 debugstr_w(ptiRet->Name),
2213 debugstr_guid(&ptiRet->TypeAttr.guid),
2214 typekind_desc[ptiRet->TypeAttr.typekind]);
2219 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2220 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2221 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2224 static ITypeLibImpl *tlb_cache_first;
2225 static CRITICAL_SECTION cache_section;
2226 static CRITICAL_SECTION_DEBUG cache_section_debug =
2228 0, 0, &cache_section,
2229 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2230 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2232 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2235 typedef struct TLB_PEFile
2237 const IUnknownVtbl *lpvtbl;
2240 HRSRC typelib_resource;
2241 HGLOBAL typelib_global;
2242 LPVOID typelib_base;
2245 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2247 if (IsEqualIID(riid, &IID_IUnknown))
2250 IUnknown_AddRef(iface);
2254 return E_NOINTERFACE;
2257 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2259 TLB_PEFile *This = (TLB_PEFile *)iface;
2260 return InterlockedIncrement(&This->refs);
2263 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2265 TLB_PEFile *This = (TLB_PEFile *)iface;
2266 ULONG refs = InterlockedDecrement(&This->refs);
2269 if (This->typelib_global)
2270 FreeResource(This->typelib_global);
2272 FreeLibrary(This->dll);
2273 HeapFree(GetProcessHeap(), 0, This);
2278 static const IUnknownVtbl TLB_PEFile_Vtable =
2280 TLB_PEFile_QueryInterface,
2285 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2289 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2291 return E_OUTOFMEMORY;
2293 This->lpvtbl = &TLB_PEFile_Vtable;
2296 This->typelib_resource = NULL;
2297 This->typelib_global = NULL;
2298 This->typelib_base = NULL;
2300 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2301 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2305 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2306 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2307 if (This->typelib_resource)
2309 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2310 if (This->typelib_global)
2312 This->typelib_base = LockResource(This->typelib_global);
2314 if (This->typelib_base)
2316 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2317 *ppBase = This->typelib_base;
2318 *ppFile = (IUnknown *)&This->lpvtbl;
2325 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2326 return TYPE_E_CANTLOADLIBRARY;
2330 typedef struct TLB_Mapping
2332 const IUnknownVtbl *lpvtbl;
2336 LPVOID typelib_base;
2339 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2341 if (IsEqualIID(riid, &IID_IUnknown))
2344 IUnknown_AddRef(iface);
2348 return E_NOINTERFACE;
2351 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2353 TLB_Mapping *This = (TLB_Mapping *)iface;
2354 return InterlockedIncrement(&This->refs);
2357 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2359 TLB_Mapping *This = (TLB_Mapping *)iface;
2360 ULONG refs = InterlockedDecrement(&This->refs);
2363 if (This->typelib_base)
2364 UnmapViewOfFile(This->typelib_base);
2366 CloseHandle(This->mapping);
2367 if (This->file != INVALID_HANDLE_VALUE)
2368 CloseHandle(This->file);
2369 HeapFree(GetProcessHeap(), 0, This);
2374 static const IUnknownVtbl TLB_Mapping_Vtable =
2376 TLB_Mapping_QueryInterface,
2381 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2385 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2387 return E_OUTOFMEMORY;
2389 This->lpvtbl = &TLB_Mapping_Vtable;
2391 This->file = INVALID_HANDLE_VALUE;
2392 This->mapping = NULL;
2393 This->typelib_base = NULL;
2395 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2396 if (INVALID_HANDLE_VALUE != This->file)
2398 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2401 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2402 if(This->typelib_base)
2404 /* retrieve file size */
2405 *pdwTLBLength = GetFileSize(This->file, NULL);
2406 *ppBase = This->typelib_base;
2407 *ppFile = (IUnknown *)&This->lpvtbl;
2413 IUnknown_Release((IUnknown *)&This->lpvtbl);
2414 return TYPE_E_CANTLOADLIBRARY;
2417 /****************************************************************************
2420 * find the type of the typelib file and map the typelib resource into
2423 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2424 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2425 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2427 ITypeLibImpl *entry;
2430 LPWSTR index_str, file = (LPWSTR)pszFileName;
2431 LPVOID pBase = NULL;
2432 DWORD dwTLBLength = 0;
2433 IUnknown *pFile = NULL;
2437 index_str = strrchrW(pszFileName, '\\');
2438 if(index_str && *++index_str != '\0')
2441 long idx = strtolW(index_str, &end_ptr, 10);
2442 if(*end_ptr == '\0')
2444 int str_len = index_str - pszFileName - 1;
2446 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2447 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2452 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2454 if(strchrW(file, '\\'))
2456 lstrcpyW(pszPath, file);
2460 int len = GetSystemDirectoryW(pszPath, cchPath);
2461 pszPath[len] = '\\';
2462 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2466 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2468 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2470 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2471 EnterCriticalSection(&cache_section);
2472 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2474 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2476 TRACE("cache hit\n");
2477 *ppTypeLib = (ITypeLib2*)entry;
2478 ITypeLib_AddRef(*ppTypeLib);
2479 LeaveCriticalSection(&cache_section);
2483 LeaveCriticalSection(&cache_section);
2485 /* now actually load and parse the typelib */
2487 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2488 if (ret == TYPE_E_CANTLOADLIBRARY)
2489 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2492 if (dwTLBLength >= 4)
2494 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2495 if (dwSignature == MSFT_SIGNATURE)
2496 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2497 else if (dwSignature == SLTG_SIGNATURE)
2498 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2501 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2502 ret = TYPE_E_CANTLOADLIBRARY;
2506 ret = TYPE_E_CANTLOADLIBRARY;
2507 IUnknown_Release(pFile);
2511 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2513 TRACE("adding to cache\n");
2514 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2515 lstrcpyW(impl->path, pszPath);
2516 /* We should really canonicalise the path here. */
2517 impl->index = index;
2519 /* FIXME: check if it has added already in the meantime */
2520 EnterCriticalSection(&cache_section);
2521 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2523 tlb_cache_first = impl;
2524 LeaveCriticalSection(&cache_section);
2527 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2532 /*================== ITypeLib(2) Methods ===================================*/
2534 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2536 ITypeLibImpl* pTypeLibImpl;
2538 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2539 if (!pTypeLibImpl) return NULL;
2541 pTypeLibImpl->lpVtbl = &tlbvt;
2542 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2543 pTypeLibImpl->ref = 1;
2545 list_init(&pTypeLibImpl->ref_list);
2546 pTypeLibImpl->dispatch_href = -1;
2548 return pTypeLibImpl;
2551 /****************************************************************************
2552 * ITypeLib2_Constructor_MSFT
2554 * loading an MSFT typelib from an in-memory image
2556 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2560 MSFT_Header tlbHeader;
2561 MSFT_SegDir tlbSegDir;
2562 ITypeLibImpl * pTypeLibImpl;
2564 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2566 pTypeLibImpl = TypeLibImpl_Constructor();
2567 if (!pTypeLibImpl) return NULL;
2569 /* get pointer to beginning of typelib data */
2573 cx.pLibInfo = pTypeLibImpl;
2574 cx.length = dwTLBLength;
2577 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2578 TRACE_(typelib)("header:\n");
2579 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2580 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2581 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2584 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2586 /* there is a small amount of information here until the next important
2588 * the segment directory . Try to calculate the amount of data */
2589 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2591 /* now read the segment directory */
2592 TRACE("read segment directory (at %ld)\n",lPSegDir);
2593 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2594 cx.pTblDir = &tlbSegDir;
2596 /* just check two entries */
2597 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2599 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2600 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2604 /* now fill our internal data */
2605 /* TLIBATTR fields */
2606 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2608 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2609 /* Windows seems to have zero here, is this correct? */
2610 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2611 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2613 pTypeLibImpl->LibAttr.lcid = 0;
2615 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2616 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2617 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2618 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2620 /* name, eventually add to a hash table */
2621 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2624 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2625 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2627 if( tlbHeader.varflags & HELPDLLFLAG)
2630 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2631 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2634 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2637 if(tlbHeader.CustomDataOffset >= 0)
2639 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2642 /* fill in type descriptions */
2643 if(tlbSegDir.pTypdescTab.length > 0)
2645 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2647 pTypeLibImpl->ctTypeDesc = cTD;
2648 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2649 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2652 /* FIXME: add several sanity checks here */
2653 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2654 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2656 /* FIXME: check safearray */
2658 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2660 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2662 else if(td[0] == VT_CARRAY)
2664 /* array descr table here */
2665 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2667 else if(td[0] == VT_USERDEFINED)
2669 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2671 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2674 /* second time around to fill the array subscript info */
2677 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2678 if(tlbSegDir.pArrayDescriptions.offset>0)
2680 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2681 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2684 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2686 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2688 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2690 for(j = 0; j<td[2]; j++)
2692 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2693 sizeof(INT), &cx, DO_NOT_SEEK);
2694 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2695 sizeof(INT), &cx, DO_NOT_SEEK);
2700 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2701 ERR("didn't find array description data\n");
2706 /* imported type libs */
2707 if(tlbSegDir.pImpFiles.offset>0)
2709 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2710 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2713 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2717 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2718 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2719 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2721 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2722 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2723 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2724 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2727 name = TLB_Alloc(size+1);
2728 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2729 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
2731 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2732 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2734 ppImpLib = &(*ppImpLib)->next;
2738 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
2739 if(pTypeLibImpl->dispatch_href != -1)
2740 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
2743 if(tlbHeader.nrtypeinfos >= 0 )
2745 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2746 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2749 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
2751 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2753 ppTI = &((*ppTI)->next);
2754 (pTypeLibImpl->TypeInfoCount)++;
2758 TRACE("(%p)\n", pTypeLibImpl);
2759 return (ITypeLib2*) pTypeLibImpl;
2763 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
2769 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2770 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2774 guid->Data4[0] = s >> 8;
2775 guid->Data4[1] = s & 0xff;
2778 for(i = 0; i < 6; i++) {
2779 memcpy(b, str + 24 + 2 * i, 2);
2780 guid->Data4[i + 2] = strtol(b, NULL, 16);
2785 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
2791 bytelen = *(const WORD*)ptr;
2792 if(bytelen == 0xffff) return 2;
2793 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2794 *pBstr = SysAllocStringLen(NULL, len - 1);
2796 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
2800 static WORD SLTG_ReadStringA(const char *ptr, char **str)
2805 bytelen = *(const WORD*)ptr;
2806 if(bytelen == 0xffff) return 2;
2807 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2808 memcpy(*str, ptr + 2, bytelen);
2809 (*str)[bytelen] = '\0';
2813 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2815 char *ptr = pLibBlk;
2818 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2819 FIXME("libblk magic = %04x\n", w);
2824 if((w = *(WORD*)ptr) != 0xffff) {
2825 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2830 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2832 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2834 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2837 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2840 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2841 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2843 pTypeLibImpl->LibAttr.lcid = 0;
2846 ptr += 4; /* skip res12 */
2848 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2851 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2854 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2857 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2858 ptr += sizeof(GUID);
2860 return ptr - (char*)pLibBlk;
2863 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
2868 } sltg_ref_lookup_t;
2870 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
2871 HREFTYPE *typelib_ref)
2873 if(typeinfo_ref < table->num)
2875 *typelib_ref = table->refs[typeinfo_ref];
2879 ERR_(typelib)("Unable to find reference\n");
2884 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
2889 if((*pType & 0xe00) == 0xe00) {
2891 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2893 pTD = pTD->u.lptdesc;
2895 switch(*pType & 0x3f) {
2898 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2900 pTD = pTD->u.lptdesc;
2903 case VT_USERDEFINED:
2904 pTD->vt = VT_USERDEFINED;
2905 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
2911 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2914 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2916 pTD->vt = VT_CARRAY;
2917 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2919 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2920 pTD->u.lpadesc->cDims = pSA->cDims;
2921 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2922 pSA->cDims * sizeof(SAFEARRAYBOUND));
2924 pTD = &pTD->u.lpadesc->tdescElem;
2930 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2934 pTD->vt = VT_SAFEARRAY;
2935 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2937 pTD = pTD->u.lptdesc;
2941 pTD->vt = *pType & 0x3f;
2950 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
2951 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
2953 /* Handle [in/out] first */
2954 if((*pType & 0xc000) == 0xc000)
2955 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2956 else if(*pType & 0x8000)
2957 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2958 else if(*pType & 0x4000)
2959 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2961 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2964 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2967 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2969 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
2973 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
2978 TLBRefType *ref_type;
2979 sltg_ref_lookup_t *table;
2980 HREFTYPE typelib_ref;
2982 if(pRef->magic != SLTG_REF_MAGIC) {
2983 FIXME("Ref magic = %x\n", pRef->magic);
2986 name = ( (char*)pRef->names + pRef->number);
2988 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
2989 table->num = pRef->number >> 3;
2991 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
2993 /* We don't want the first href to be 0 */
2994 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
2996 for(ref = 0; ref < pRef->number >> 3; ref++) {
2998 unsigned int lib_offs, type_num;
3000 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3002 name += SLTG_ReadStringA(name, &refname);
3003 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3004 FIXME_(typelib)("Can't sscanf ref\n");
3005 if(lib_offs != 0xffff) {
3006 TLBImpLib **import = &pTL->pImpLibs;
3009 if((*import)->offset == lib_offs)
3011 import = &(*import)->next;
3014 char fname[MAX_PATH+1];
3017 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3019 (*import)->offset = lib_offs;
3020 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3022 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3023 &(*import)->wVersionMajor,
3024 &(*import)->wVersionMinor,
3025 &(*import)->lcid, fname) != 4) {
3026 FIXME_(typelib)("can't sscanf ref %s\n",
3027 pNameTable + lib_offs + 40);
3029 len = strlen(fname);
3030 if(fname[len-1] != '#')
3031 FIXME("fname = %s\n", fname);
3032 fname[len-1] = '\0';
3033 (*import)->name = TLB_MultiByteToBSTR(fname);
3035 ref_type->pImpTLInfo = *import;
3037 /* Store a reference to IDispatch */
3038 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3039 pTL->dispatch_href = typelib_ref;
3041 } else { /* internal ref */
3042 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3044 ref_type->reference = typelib_ref;
3045 ref_type->index = type_num;
3047 HeapFree(GetProcessHeap(), 0, refname);
3048 list_add_tail(&pTL->ref_list, &ref_type->entry);
3050 table->refs[ref] = typelib_ref;
3053 if((BYTE)*name != SLTG_REF_MAGIC)
3054 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3055 dump_TLBRefType(pTL);
3059 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3060 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3062 SLTG_ImplInfo *info;
3063 TLBImplType **ppImplType = &pTI->impltypelist;
3064 /* I don't really get this structure, usually it's 0x16 bytes
3065 long, but iuser.tlb contains some that are 0x18 bytes long.
3066 That's ok because we can use the next ptr to jump to the next
3067 one. But how do we know the length of the last one? The WORD
3068 at offs 0x8 might be the clue. For now I'm just assuming that
3069 the last one is the regular 0x16 bytes. */
3071 info = (SLTG_ImplInfo*)pBlk;
3073 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3074 sizeof(**ppImplType));
3075 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3076 (*ppImplType)->implflags = info->impltypeflags;
3077 pTI->TypeAttr.cImplTypes++;
3078 ppImplType = &(*ppImplType)->next;
3080 if(info->next == 0xffff)
3083 FIXME_(typelib)("Interface inheriting more than one interface\n");
3084 info = (SLTG_ImplInfo*)(pBlk + info->next);
3086 info++; /* see comment at top of function */
3090 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3091 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3093 TLBVarDesc **ppVarDesc = &pTI->varlist;
3094 BSTR bstrPrevName = NULL;
3095 SLTG_Variable *pItem;
3099 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3100 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3102 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3103 sizeof(**ppVarDesc));
3104 (*ppVarDesc)->vardesc.memid = pItem->memid;
3106 if (pItem->magic != SLTG_VAR_MAGIC &&
3107 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3108 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3112 if (pItem->name == 0xfffe)
3113 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3115 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3117 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3118 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3119 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3121 if(pItem->flags & 0x02)
3122 pType = &pItem->type;
3124 pType = (WORD*)(pBlk + pItem->type);
3126 if (pItem->flags & ~0xda)
3127 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3129 SLTG_DoElem(pType, pBlk,
3130 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3132 if (TRACE_ON(typelib)) {
3134 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3135 TRACE_(typelib)("elemdescVar: %s\n", buf);
3138 if (pItem->flags & 0x40) {
3139 TRACE_(typelib)("VAR_DISPATCH\n");
3140 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3142 else if (pItem->flags & 0x10) {
3143 TRACE_(typelib)("VAR_CONST\n");
3144 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3145 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3147 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3148 if (pItem->flags & 0x08)
3149 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3151 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3157 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3159 TRACE_(typelib)("len = %u\n", len);
3160 if (len == 0xffff) {
3163 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3164 str = SysAllocStringLen(NULL, alloc_len);
3165 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3167 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3168 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3177 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3178 *(INT*)(pBlk + pItem->byte_offs);
3181 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3186 TRACE_(typelib)("VAR_PERINSTANCE\n");
3187 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3188 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3191 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3192 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3194 if (pItem->flags & 0x80)
3195 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3197 bstrPrevName = (*ppVarDesc)->Name;
3198 ppVarDesc = &((*ppVarDesc)->next);
3200 pTI->TypeAttr.cVars = cVars;
3203 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3204 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3206 SLTG_Function *pFunc;
3208 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3210 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3211 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3216 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3217 sizeof(**ppFuncDesc));
3219 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3220 case SLTG_FUNCTION_MAGIC:
3221 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3223 case SLTG_DISPATCH_FUNCTION_MAGIC:
3224 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3226 case SLTG_STATIC_FUNCTION_MAGIC:
3227 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3230 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3231 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3235 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3237 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3238 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3239 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3240 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3241 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3242 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3244 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3245 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3247 if(pFunc->retnextopt & 0x80)
3248 pType = &pFunc->rettype;
3250 pType = (WORD*)(pBlk + pFunc->rettype);
3252 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3254 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3255 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3256 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3257 (*ppFuncDesc)->pParamDesc =
3258 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3259 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3261 pArg = (WORD*)(pBlk + pFunc->arg_off);
3263 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3264 char *paramName = pNameTable + *pArg;
3266 /* If arg type follows then paramName points to the 2nd
3267 letter of the name, else the next WORD is an offset to
3268 the arg type and paramName points to the first letter.
3269 So let's take one char off paramName and see if we're
3270 pointing at an alpha-numeric char. However if *pArg is
3271 0xffff or 0xfffe then the param has no name, the former
3272 meaning that the next WORD is the type, the latter
3273 meaning that the next WORD is an offset to the type. */
3278 else if(*pArg == 0xfffe) {
3282 else if(paramName[-1] && !isalnum(paramName[-1]))
3287 if(HaveOffs) { /* the next word is an offset to type */
3288 pType = (WORD*)(pBlk + *pArg);
3289 SLTG_DoElem(pType, pBlk,
3290 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3295 pArg = SLTG_DoElem(pArg, pBlk,
3296 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3299 /* Are we an optional param ? */
3300 if((*ppFuncDesc)->funcdesc.cParams - param <=
3301 (*ppFuncDesc)->funcdesc.cParamsOpt)
3302 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3305 (*ppFuncDesc)->pParamDesc[param].Name =
3306 TLB_MultiByteToBSTR(paramName);
3308 (*ppFuncDesc)->pParamDesc[param].Name =
3309 SysAllocString((*ppFuncDesc)->Name);
3313 ppFuncDesc = &((*ppFuncDesc)->next);
3314 if(pFunc->next == 0xffff) break;
3316 pTI->TypeAttr.cFuncs = cFuncs;
3319 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3320 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3321 SLTG_TypeInfoTail *pTITail)
3324 sltg_ref_lookup_t *ref_lookup = NULL;
3326 if(pTIHeader->href_table != 0xffffffff) {
3327 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3333 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3334 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3336 HeapFree(GetProcessHeap(), 0, ref_lookup);
3340 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3341 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3342 const SLTG_TypeInfoTail *pTITail)
3345 sltg_ref_lookup_t *ref_lookup = NULL;
3347 if(pTIHeader->href_table != 0xffffffff) {
3348 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3354 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3355 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3358 if (pTITail->funcs_off != 0xffff)
3359 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3361 HeapFree(GetProcessHeap(), 0, ref_lookup);
3363 if (TRACE_ON(typelib))
3364 dump_TLBFuncDesc(pTI->funclist);
3367 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3368 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3369 const SLTG_TypeInfoTail *pTITail)
3371 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3374 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3375 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3376 const SLTG_TypeInfoTail *pTITail)
3379 sltg_ref_lookup_t *ref_lookup = NULL;
3381 if (pTITail->simple_alias) {
3382 /* if simple alias, no more processing required */
3383 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3387 if(pTIHeader->href_table != 0xffffffff) {
3388 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3392 /* otherwise it is an offset to a type */
3393 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3395 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3397 HeapFree(GetProcessHeap(), 0, ref_lookup);
3400 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3401 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3402 const SLTG_TypeInfoTail *pTITail)
3404 sltg_ref_lookup_t *ref_lookup = NULL;
3405 if (pTIHeader->href_table != 0xffffffff)
3406 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3409 if (pTITail->vars_off != 0xffff)
3410 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3412 if (pTITail->funcs_off != 0xffff)
3413 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3415 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3416 * of dispinterface functions including the IDispatch ones, so
3417 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3418 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3420 HeapFree(GetProcessHeap(), 0, ref_lookup);
3421 if (TRACE_ON(typelib))
3422 dump_TLBFuncDesc(pTI->funclist);
3425 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3426 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3427 const SLTG_TypeInfoTail *pTITail)
3429 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3432 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3433 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3434 const SLTG_TypeInfoTail *pTITail)
3436 sltg_ref_lookup_t *ref_lookup = NULL;
3437 if (pTIHeader->href_table != 0xffffffff)
3438 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3441 if (pTITail->vars_off != 0xffff)
3442 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3444 if (pTITail->funcs_off != 0xffff)
3445 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3446 HeapFree(GetProcessHeap(), 0, ref_lookup);
3447 if (TRACE_ON(typelib))
3451 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3452 managable copy of it into this */
3465 } SLTG_InternalOtherTypeInfo;
3467 /****************************************************************************
3468 * ITypeLib2_Constructor_SLTG
3470 * loading a SLTG typelib from an in-memory image
3472 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3474 ITypeLibImpl *pTypeLibImpl;
3475 SLTG_Header *pHeader;
3476 SLTG_BlkEntry *pBlkEntry;
3480 LPVOID pBlk, pFirstBlk;
3481 SLTG_LibBlk *pLibBlk;
3482 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3483 char *pAfterOTIBlks = NULL;
3484 char *pNameTable, *ptr;
3487 ITypeInfoImpl **ppTypeInfoImpl;
3489 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3492 pTypeLibImpl = TypeLibImpl_Constructor();
3493 if (!pTypeLibImpl) return NULL;
3497 TRACE_(typelib)("header:\n");
3498 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3499 pHeader->nrOfFileBlks );
3500 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3501 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3502 pHeader->SLTG_magic);
3506 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3507 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3509 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3510 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3512 /* Next we have a magic block */
3513 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3515 /* Let's see if we're still in sync */
3516 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3517 sizeof(SLTG_COMPOBJ_MAGIC))) {
3518 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3521 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3522 sizeof(SLTG_DIR_MAGIC))) {
3523 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3527 pIndex = (SLTG_Index*)(pMagic+1);
3529 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3531 pFirstBlk = (LPVOID)(pPad9 + 1);
3533 /* We'll set up a ptr to the main library block, which is the last one. */
3535 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3536 pBlkEntry[order].next != 0;
3537 order = pBlkEntry[order].next - 1, i++) {
3538 pBlk = (char*)pBlk + pBlkEntry[order].len;
3542 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3544 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3549 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3551 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3552 sizeof(*pOtherTypeInfoBlks) *
3553 pTypeLibImpl->TypeInfoCount);
3556 ptr = (char*)pLibBlk + len;
3558 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3562 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3564 w = *(WORD*)(ptr + 2);
3567 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3569 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3570 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3572 w = *(WORD*)(ptr + 4 + len);
3574 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3576 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3578 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3579 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3581 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3582 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3583 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3585 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3587 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3590 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3591 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3592 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3593 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3594 len += sizeof(SLTG_OtherTypeInfo);
3598 pAfterOTIBlks = ptr;
3600 /* Skip this WORD and get the next DWORD */
3601 len = *(DWORD*)(pAfterOTIBlks + 2);
3603 /* Now add this to pLibBLk look at what we're pointing at and
3604 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3605 dust and we should be pointing at the beginning of the name
3608 pNameTable = (char*)pLibBlk + len;
3610 switch(*(WORD*)pNameTable) {
3617 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3621 pNameTable += 0x216;
3625 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3627 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3630 /* Hopefully we now have enough ptrs set up to actually read in
3631 some TypeInfos. It's not clear which order to do them in, so
3632 I'll just follow the links along the BlkEntry chain and read
3633 them in the order in which they are in the file */
3635 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3637 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3638 pBlkEntry[order].next != 0;
3639 order = pBlkEntry[order].next - 1, i++) {
3641 SLTG_TypeInfoHeader *pTIHeader;
3642 SLTG_TypeInfoTail *pTITail;
3643 SLTG_MemberHeader *pMemHeader;
3645 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3646 pOtherTypeInfoBlks[i].index_name)) {
3647 FIXME_(typelib)("Index strings don't match\n");
3652 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3653 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3656 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3657 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3658 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3660 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3661 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3662 (*ppTypeInfoImpl)->index = i;
3663 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3664 pOtherTypeInfoBlks[i].name_offs +
3666 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3667 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3668 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3669 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3670 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3671 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3672 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3674 if((pTIHeader->typeflags1 & 7) != 2)
3675 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3676 if(pTIHeader->typeflags3 != 2)
3677 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3679 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3680 debugstr_w((*ppTypeInfoImpl)->Name),
3681 typekind_desc[pTIHeader->typekind],
3682 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3683 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3685 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3687 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3689 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3690 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3691 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3693 switch(pTIHeader->typekind) {
3695 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3696 pTIHeader, pTITail);
3700 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3701 pTIHeader, pTITail);
3704 case TKIND_INTERFACE:
3705 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3706 pTIHeader, pTITail);
3710 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3711 pTIHeader, pTITail);
3715 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3716 pTIHeader, pTITail);
3719 case TKIND_DISPATCH:
3720 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3721 pTIHeader, pTITail);
3725 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3726 pTIHeader, pTITail);
3730 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3735 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3736 but we've already set those */
3737 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3752 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3753 pBlk = (char*)pBlk + pBlkEntry[order].len;
3756 if(i != pTypeLibImpl->TypeInfoCount) {
3757 FIXME("Somehow processed %d TypeInfos\n", i);
3761 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3762 return (ITypeLib2*)pTypeLibImpl;
3765 /* ITypeLib::QueryInterface
3767 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3772 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3774 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3777 if(IsEqualIID(riid, &IID_IUnknown) ||
3778 IsEqualIID(riid,&IID_ITypeLib)||
3779 IsEqualIID(riid,&IID_ITypeLib2))
3786 ITypeLib2_AddRef(iface);
3787 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3790 TRACE("-- Interface: E_NOINTERFACE\n");
3791 return E_NOINTERFACE;
3796 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3798 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3799 ULONG ref = InterlockedIncrement(&This->ref);
3801 TRACE("(%p)->ref was %u\n",This, ref - 1);
3806 /* ITypeLib::Release
3808 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3810 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3811 ULONG ref = InterlockedDecrement(&This->ref);
3813 TRACE("(%p)->(%u)\n",This, ref);
3817 TLBImpLib *pImpLib, *pImpLibNext;
3818 TLBCustData *pCustData, *pCustDataNext;
3819 TLBRefType *ref_type;
3823 /* remove cache entry */
3826 TRACE("removing from cache list\n");
3827 EnterCriticalSection(&cache_section);
3828 if (This->next) This->next->prev = This->prev;
3829 if (This->prev) This->prev->next = This->next;
3830 else tlb_cache_first = This->next;
3831 LeaveCriticalSection(&cache_section);
3832 HeapFree(GetProcessHeap(), 0, This->path);
3834 TRACE(" destroying ITypeLib(%p)\n",This);
3836 SysFreeString(This->Name);
3839 SysFreeString(This->DocString);
3840 This->DocString = NULL;
3842 SysFreeString(This->HelpFile);
3843 This->HelpFile = NULL;
3845 SysFreeString(This->HelpStringDll);
3846 This->HelpStringDll = NULL;
3848 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
3850 VariantClear(&pCustData->data);
3852 pCustDataNext = pCustData->next;
3853 TLB_Free(pCustData);
3856 for (i = 0; i < This->ctTypeDesc; i++)
3857 if (This->pTypeDesc[i].vt == VT_CARRAY)
3858 TLB_Free(This->pTypeDesc[i].u.lpadesc);
3860 TLB_Free(This->pTypeDesc);
3862 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
3864 if (pImpLib->pImpTypeLib)
3865 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
3866 SysFreeString(pImpLib->name);
3868 pImpLibNext = pImpLib->next;
3872 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
3874 list_remove(&ref_type->entry);
3878 if (This->pTypeInfo) /* can be NULL */
3879 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3880 HeapFree(GetProcessHeap(),0,This);
3887 /* ITypeLib::GetTypeInfoCount
3889 * Returns the number of type descriptions in the type library
3891 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3893 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3894 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3895 return This->TypeInfoCount;
3898 /* ITypeLib::GetTypeInfo
3900 * retrieves the specified type description in the library.
3902 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3905 ITypeInfo **ppTInfo)
3909 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3910 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3912 TRACE("(%p)->(index=%d)\n", This, index);
3914 if (!ppTInfo) return E_INVALIDARG;
3916 /* search element n in list */
3917 for(i=0; i < index; i++)
3919 pTypeInfo = pTypeInfo->next;
3922 TRACE("-- element not found\n");
3923 return TYPE_E_ELEMENTNOTFOUND;
3927 *ppTInfo = (ITypeInfo *) pTypeInfo;
3929 ITypeInfo_AddRef(*ppTInfo);
3930 TRACE("-- found (%p)\n",*ppTInfo);
3935 /* ITypeLibs::GetTypeInfoType
3937 * Retrieves the type of a type description.
3939 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3944 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3946 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3948 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
3949 return TYPE_E_ELEMENTNOTFOUND;
3951 TRACE("(%p) index %d\n", This, index);
3953 if(!pTKind) return E_INVALIDARG;
3955 /* search element n in list */
3956 for(i=0; i < index; i++)
3960 TRACE("-- element not found\n");
3961 return TYPE_E_ELEMENTNOTFOUND;
3963 pTInfo = pTInfo->next;
3966 *pTKind = pTInfo->TypeAttr.typekind;
3967 TRACE("-- found Type (%d)\n", *pTKind);
3971 /* ITypeLib::GetTypeInfoOfGuid
3973 * Retrieves the type description that corresponds to the specified GUID.
3976 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3979 ITypeInfo **ppTInfo)
3981 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3982 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3984 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3988 WARN("-- element not found\n");
3989 return TYPE_E_ELEMENTNOTFOUND;
3992 /* search linked list for guid */
3993 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3995 pTypeInfo = pTypeInfo->next;
3999 /* end of list reached */
4000 WARN("-- element not found\n");
4001 return TYPE_E_ELEMENTNOTFOUND;
4005 TRACE("-- found (%p, %s)\n",
4007 debugstr_w(pTypeInfo->Name));
4009 *ppTInfo = (ITypeInfo*)pTypeInfo;
4010 ITypeInfo_AddRef(*ppTInfo);
4014 /* ITypeLib::GetLibAttr
4016 * Retrieves the structure that contains the library's attributes.
4019 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4021 LPTLIBATTR *ppTLibAttr)
4023 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4024 TRACE("(%p)\n",This);
4025 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4026 **ppTLibAttr = This->LibAttr;
4030 /* ITypeLib::GetTypeComp
4032 * Enables a client compiler to bind to a library's types, variables,
4033 * constants, and global functions.
4036 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4038 ITypeComp **ppTComp)
4040 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4042 TRACE("(%p)->(%p)\n",This,ppTComp);
4043 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4044 ITypeComp_AddRef(*ppTComp);
4049 /* ITypeLib::GetDocumentation
4051 * Retrieves the library's documentation string, the complete Help file name
4052 * and path, and the context identifier for the library Help topic in the Help
4055 * On a successful return all non-null BSTR pointers will have been set,
4058 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4062 BSTR *pBstrDocString,
4063 DWORD *pdwHelpContext,
4064 BSTR *pBstrHelpFile)
4066 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4068 HRESULT result = E_INVALIDARG;
4073 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4075 pBstrName, pBstrDocString,
4076 pdwHelpContext, pBstrHelpFile);
4080 /* documentation for the typelib */
4085 if(!(*pBstrName = SysAllocString(This->Name)))
4093 if (This->DocString)
4095 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4098 else if (This->Name)
4100 if(!(*pBstrDocString = SysAllocString(This->Name)))
4104 *pBstrDocString = NULL;
4108 *pdwHelpContext = This->dwHelpContext;
4114 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4118 *pBstrHelpFile = NULL;
4125 /* for a typeinfo */
4126 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4128 if(SUCCEEDED(result))
4130 result = ITypeInfo_GetDocumentation(pTInfo,
4134 pdwHelpContext, pBstrHelpFile);
4136 ITypeInfo_Release(pTInfo);
4141 if (pBstrDocString) SysFreeString (*pBstrDocString);
4143 if (pBstrName) SysFreeString (*pBstrName);
4145 return STG_E_INSUFFICIENTMEMORY;
4150 * Indicates whether a passed-in string contains the name of a type or member
4151 * described in the library.
4154 static HRESULT WINAPI ITypeLib2_fnIsName(
4160 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4161 ITypeInfoImpl *pTInfo;
4162 TLBFuncDesc *pFInfo;
4165 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4167 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4171 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4172 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4173 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4174 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4175 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4176 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4177 goto ITypeLib2_fnIsName_exit;
4179 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4180 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4185 ITypeLib2_fnIsName_exit:
4186 TRACE("(%p)slow! search for %s: %s found!\n", This,
4187 debugstr_w(szNameBuf), *pfName?"NOT":"");
4192 /* ITypeLib::FindName
4194 * Finds occurrences of a type description in a type library. This may be used
4195 * to quickly verify that a name exists in a type library.
4198 static HRESULT WINAPI ITypeLib2_fnFindName(
4202 ITypeInfo **ppTInfo,
4206 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4207 ITypeInfoImpl *pTInfo;
4208 TLBFuncDesc *pFInfo;
4211 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4213 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4214 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4215 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4216 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4217 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4218 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4219 goto ITypeLib2_fnFindName_exit;
4222 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4223 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4225 ITypeLib2_fnFindName_exit:
4226 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4227 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4230 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4231 This, *pcFound, debugstr_w(szNameBuf), j);
4238 /* ITypeLib::ReleaseTLibAttr
4240 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4243 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4245 TLIBATTR *pTLibAttr)
4247 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4248 TRACE("freeing (%p)\n",This);
4249 HeapFree(GetProcessHeap(),0,pTLibAttr);
4253 /* ITypeLib2::GetCustData
4255 * gets the custom data
4257 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4262 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4263 TLBCustData *pCData;
4265 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4267 if( IsEqualIID(guid, &pCData->guid)) break;
4270 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4274 VariantInit( pVarVal);
4275 VariantCopy( pVarVal, &pCData->data);
4278 return E_INVALIDARG; /* FIXME: correct? */
4281 /* ITypeLib2::GetLibStatistics
4283 * Returns statistics about a type library that are required for efficient
4284 * sizing of hash tables.
4287 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4289 ULONG *pcUniqueNames,
4290 ULONG *pcchUniqueNames)
4292 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4294 FIXME("(%p): stub!\n", This);
4296 if(pcUniqueNames) *pcUniqueNames=1;
4297 if(pcchUniqueNames) *pcchUniqueNames=1;
4301 /* ITypeLib2::GetDocumentation2
4303 * Retrieves the library's documentation string, the complete Help file name
4304 * and path, the localization context to use, and the context ID for the
4305 * library Help topic in the Help file.
4308 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4312 BSTR *pbstrHelpString,
4313 DWORD *pdwHelpStringContext,
4314 BSTR *pbstrHelpStringDll)
4316 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4320 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4322 /* the help string should be obtained from the helpstringdll,
4323 * using the _DLLGetDocumentation function, based on the supplied
4324 * lcid. Nice to do sometime...
4328 /* documentation for the typelib */
4330 *pbstrHelpString=SysAllocString(This->DocString);
4331 if(pdwHelpStringContext)
4332 *pdwHelpStringContext=This->dwHelpContext;
4333 if(pbstrHelpStringDll)
4334 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4340 /* for a typeinfo */
4341 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4343 if(SUCCEEDED(result))
4345 ITypeInfo2 * pTInfo2;
4346 result = ITypeInfo_QueryInterface(pTInfo,
4348 (LPVOID*) &pTInfo2);
4350 if(SUCCEEDED(result))
4352 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4356 pdwHelpStringContext,
4357 pbstrHelpStringDll);
4359 ITypeInfo2_Release(pTInfo2);
4362 ITypeInfo_Release(pTInfo);
4368 /* ITypeLib2::GetAllCustData
4370 * Gets all custom data items for the library.
4373 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4375 CUSTDATA *pCustData)
4377 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4378 TLBCustData *pCData;
4380 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4381 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4382 if(pCustData->prgCustData ){
4383 pCustData->cCustData=This->ctCustData;
4384 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4385 pCustData->prgCustData[i].guid=pCData->guid;
4386 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4389 ERR(" OUT OF MEMORY!\n");
4390 return E_OUTOFMEMORY;
4395 static const ITypeLib2Vtbl tlbvt = {
4396 ITypeLib2_fnQueryInterface,
4398 ITypeLib2_fnRelease,
4399 ITypeLib2_fnGetTypeInfoCount,
4400 ITypeLib2_fnGetTypeInfo,
4401 ITypeLib2_fnGetTypeInfoType,
4402 ITypeLib2_fnGetTypeInfoOfGuid,
4403 ITypeLib2_fnGetLibAttr,
4404 ITypeLib2_fnGetTypeComp,
4405 ITypeLib2_fnGetDocumentation,
4407 ITypeLib2_fnFindName,
4408 ITypeLib2_fnReleaseTLibAttr,
4410 ITypeLib2_fnGetCustData,
4411 ITypeLib2_fnGetLibStatistics,
4412 ITypeLib2_fnGetDocumentation2,
4413 ITypeLib2_fnGetAllCustData
4417 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4419 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4421 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4424 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4426 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4428 return ITypeLib2_AddRef((ITypeLib2 *)This);
4431 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4433 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4435 return ITypeLib2_Release((ITypeLib2 *)This);
4438 static HRESULT WINAPI ITypeLibComp_fnBind(
4443 ITypeInfo ** ppTInfo,
4444 DESCKIND * pDescKind,
4447 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4448 ITypeInfoImpl *pTypeInfo;
4450 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4452 *pDescKind = DESCKIND_NONE;
4453 pBindPtr->lptcomp = NULL;
4456 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4458 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4460 /* FIXME: check wFlags here? */
4461 /* FIXME: we should use a hash table to look this info up using lHash
4462 * instead of an O(n) search */
4463 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4464 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4466 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4468 *pDescKind = DESCKIND_TYPECOMP;
4469 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4470 ITypeComp_AddRef(pBindPtr->lptcomp);
4471 TRACE("module or enum: %s\n", debugstr_w(szName));
4476 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4477 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4479 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4482 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4483 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4485 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4490 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4491 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4493 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4495 ITypeInfo *subtypeinfo;
4497 DESCKIND subdesckind;
4499 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4500 &subtypeinfo, &subdesckind, &subbindptr);
4501 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4503 TYPEDESC tdesc_appobject =
4506 (TYPEDESC *)pTypeInfo->hreftype
4510 const VARDESC vardesc_appobject =
4513 NULL, /* lpstrSchema */
4528 VAR_STATIC /* varkind */
4531 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4533 /* cleanup things filled in by Bind call so we can put our
4534 * application object data in there instead */
4535 switch (subdesckind)
4537 case DESCKIND_FUNCDESC:
4538 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4540 case DESCKIND_VARDESC:
4541 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4546 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4548 if (pTypeInfo->hreftype == -1)
4549 FIXME("no hreftype for interface %p\n", pTypeInfo);
4551 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4555 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4556 *ppTInfo = (ITypeInfo *)pTypeInfo;
4557 ITypeInfo_AddRef(*ppTInfo);
4563 TRACE("name not found %s\n", debugstr_w(szName));
4567 static HRESULT WINAPI ITypeLibComp_fnBindType(
4571 ITypeInfo ** ppTInfo,
4572 ITypeComp ** ppTComp)
4574 FIXME("(%s, %x, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4578 static const ITypeCompVtbl tlbtcvt =
4581 ITypeLibComp_fnQueryInterface,
4582 ITypeLibComp_fnAddRef,
4583 ITypeLibComp_fnRelease,
4585 ITypeLibComp_fnBind,
4586 ITypeLibComp_fnBindType
4589 /*================== ITypeInfo(2) Methods ===================================*/
4590 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4592 ITypeInfoImpl * pTypeInfoImpl;
4594 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4597 pTypeInfoImpl->lpVtbl = &tinfvt;
4598 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4599 pTypeInfoImpl->ref=1;
4600 pTypeInfoImpl->hreftype = -1;
4601 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4602 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4604 TRACE("(%p)\n", pTypeInfoImpl);
4605 return (ITypeInfo2*) pTypeInfoImpl;
4608 /* ITypeInfo::QueryInterface
4610 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4615 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4617 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4620 if(IsEqualIID(riid, &IID_IUnknown) ||
4621 IsEqualIID(riid,&IID_ITypeInfo)||
4622 IsEqualIID(riid,&IID_ITypeInfo2))
4626 ITypeInfo_AddRef(iface);
4627 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4630 TRACE("-- Interface: E_NOINTERFACE\n");
4631 return E_NOINTERFACE;
4634 /* ITypeInfo::AddRef
4636 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4638 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4639 ULONG ref = InterlockedIncrement(&This->ref);
4641 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4643 TRACE("(%p)->ref is %u\n",This, ref);
4647 /* ITypeInfo::Release
4649 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4651 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4652 ULONG ref = InterlockedDecrement(&This->ref);
4654 TRACE("(%p)->(%u)\n",This, ref);
4657 /* We don't release ITypeLib when ref=0 because
4658 it means that function is called by ITypeLib2_Release */
4659 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4661 TLBFuncDesc *pFInfo, *pFInfoNext;
4662 TLBVarDesc *pVInfo, *pVInfoNext;
4663 TLBImplType *pImpl, *pImplNext;
4665 TRACE("destroying ITypeInfo(%p)\n",This);
4667 if (This->no_free_data)
4670 SysFreeString(This->Name);
4673 SysFreeString(This->DocString);
4674 This->DocString = NULL;
4676 SysFreeString(This->DllName);
4677 This->DllName = NULL;
4679 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4682 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4684 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4685 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4687 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4688 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4690 SysFreeString(pFInfo->pParamDesc[i].Name);
4692 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4693 TLB_Free(pFInfo->pParamDesc);
4694 TLB_FreeCustData(pFInfo->pCustData);
4695 if (HIWORD(pFInfo->Entry) != 0 && pFInfo->Entry != (BSTR)-1)
4696 SysFreeString(pFInfo->Entry);
4697 SysFreeString(pFInfo->HelpString);
4698 SysFreeString(pFInfo->Name);
4700 pFInfoNext = pFInfo->next;
4703 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
4705 if (pVInfo->vardesc.varkind == VAR_CONST)
4707 VariantClear(pVInfo->vardesc.u.lpvarValue);
4708 TLB_Free(pVInfo->vardesc.u.lpvarValue);
4710 TLB_FreeCustData(pVInfo->pCustData);
4711 SysFreeString(pVInfo->Name);
4712 pVInfoNext = pVInfo->next;
4715 for(pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
4717 TLB_FreeCustData(pImpl->pCustData);
4718 pImplNext = pImpl->next;
4721 TLB_FreeCustData(This->pCustData);
4726 ITypeInfo_Release((ITypeInfo*)This->next);
4729 HeapFree(GetProcessHeap(),0,This);
4735 /* ITypeInfo::GetTypeAttr
4737 * Retrieves a TYPEATTR structure that contains the attributes of the type
4741 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4742 LPTYPEATTR *ppTypeAttr)
4744 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4747 TRACE("(%p)\n",This);
4749 size = sizeof(**ppTypeAttr);
4750 if (This->TypeAttr.typekind == TKIND_ALIAS)
4751 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4753 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4755 return E_OUTOFMEMORY;
4757 **ppTypeAttr = This->TypeAttr;
4759 if (This->TypeAttr.typekind == TKIND_ALIAS)
4760 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4761 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4763 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4764 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4766 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4767 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4772 /* ITypeInfo::GetTypeComp
4774 * Retrieves the ITypeComp interface for the type description, which enables a
4775 * client compiler to bind to the type description's members.
4778 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4779 ITypeComp * *ppTComp)
4781 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4783 TRACE("(%p)->(%p)\n", This, ppTComp);
4785 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4786 ITypeComp_AddRef(*ppTComp);
4790 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4792 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4793 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4794 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4798 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4801 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4802 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4804 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4805 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4806 *buffer += sizeof(PARAMDESCEX);
4807 *pparamdescex_dest = *pparamdescex_src;
4808 VariantInit(&pparamdescex_dest->varDefaultValue);
4809 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4810 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4813 dest->u.paramdesc.pparamdescex = NULL;
4817 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4819 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4820 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4823 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4827 SIZE_T size = sizeof(*src);
4831 size += sizeof(*src->lprgscode) * src->cScodes;
4832 size += TLB_SizeElemDesc(&src->elemdescFunc);
4833 for (i = 0; i < src->cParams; i++)
4835 size += sizeof(ELEMDESC);
4836 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4839 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4840 if (!dest) return E_OUTOFMEMORY;
4843 if (dispinterface) /* overwrite funckind */
4844 dest->funckind = FUNC_DISPATCH;
4845 buffer = (char *)(dest + 1);
4847 dest->lprgscode = (SCODE *)buffer;
4848 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4849 buffer += sizeof(*src->lprgscode) * src->cScodes;
4851 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4854 SysFreeString((BSTR)dest);
4858 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4859 buffer += sizeof(ELEMDESC) * src->cParams;
4860 for (i = 0; i < src->cParams; i++)
4862 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4868 /* undo the above actions */
4869 for (i = i - 1; i >= 0; i--)
4870 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4871 TLB_FreeElemDesc(&dest->elemdescFunc);
4872 SysFreeString((BSTR)dest);
4876 /* special treatment for dispinterfaces: this makes functions appear
4877 * to return their [retval] value when it is really returning an
4879 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4881 if (dest->cParams &&
4882 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4884 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4885 if (elemdesc->tdesc.vt != VT_PTR)
4887 ERR("elemdesc should have started with VT_PTR instead of:\n");
4889 dump_ELEMDESC(elemdesc);
4890 return E_UNEXPECTED;
4893 /* copy last parameter to the return value. we are using a flat
4894 * buffer so there is no danger of leaking memory in
4896 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4898 /* remove the last parameter */
4902 /* otherwise this function is made to appear to have no return
4904 dest->elemdescFunc.tdesc.vt = VT_VOID;
4912 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4914 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4915 const TLBFuncDesc *pFDesc;
4918 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4923 *ppFuncDesc = &pFDesc->funcdesc;
4927 return TYPE_E_ELEMENTNOTFOUND;
4930 /* internal function to make the inherited interfaces' methods appear
4931 * part of the interface */
4932 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4933 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
4935 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4937 UINT implemented_funcs = 0;
4942 *hrefoffset = DISPATCH_HREF_OFFSET;
4944 if(This->impltypelist)
4946 ITypeInfo *pSubTypeInfo;
4949 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
4953 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4956 &sub_funcs, hrefoffset);
4957 implemented_funcs += sub_funcs;
4958 ITypeInfo_Release(pSubTypeInfo);
4961 *hrefoffset += DISPATCH_HREF_OFFSET;
4965 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4969 if (index < implemented_funcs)
4970 return E_INVALIDARG;
4971 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4975 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
4977 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
4980 switch (pTypeDesc->vt)
4982 case VT_USERDEFINED:
4983 pTypeDesc->u.hreftype += hrefoffset;
4987 pTypeDesc = pTypeDesc->u.lptdesc;
4990 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
4998 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5001 for (i = 0; i < pFuncDesc->cParams; i++)
5002 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5003 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5006 /* ITypeInfo::GetFuncDesc
5008 * Retrieves the FUNCDESC structure that contains information about a
5009 * specified function.
5012 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5013 LPFUNCDESC *ppFuncDesc)
5015 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5016 const FUNCDESC *internal_funcdesc;
5018 UINT hrefoffset = 0;
5020 TRACE("(%p) index %d\n", This, index);
5022 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5023 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5024 &internal_funcdesc, NULL,
5027 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5028 &internal_funcdesc);
5031 WARN("description for function %d not found\n", index);
5035 hr = TLB_AllocAndInitFuncDesc(
5038 This->TypeAttr.typekind == TKIND_DISPATCH);
5040 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5041 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5043 TRACE("-- 0x%08x\n", hr);
5047 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5051 SIZE_T size = sizeof(*src);
5054 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5055 if (src->varkind == VAR_CONST)
5056 size += sizeof(VARIANT);
5057 size += TLB_SizeElemDesc(&src->elemdescVar);
5059 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5060 if (!dest) return E_OUTOFMEMORY;
5063 buffer = (char *)(dest + 1);
5064 if (src->lpstrSchema)
5067 dest->lpstrSchema = (LPOLESTR)buffer;
5068 len = strlenW(src->lpstrSchema);
5069 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5070 buffer += (len + 1) * sizeof(WCHAR);
5073 if (src->varkind == VAR_CONST)
5077 dest->u.lpvarValue = (VARIANT *)buffer;
5078 *dest->u.lpvarValue = *src->u.lpvarValue;
5079 buffer += sizeof(VARIANT);
5080 VariantInit(dest->u.lpvarValue);
5081 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5084 SysFreeString((BSTR)dest_ptr);
5088 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5091 if (src->varkind == VAR_CONST)
5092 VariantClear(dest->u.lpvarValue);
5093 SysFreeString((BSTR)dest);
5100 /* ITypeInfo::GetVarDesc
5102 * Retrieves a VARDESC structure that describes the specified variable.
5105 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5106 LPVARDESC *ppVarDesc)
5108 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5110 const TLBVarDesc *pVDesc;
5112 TRACE("(%p) index %d\n", This, index);
5114 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5118 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5120 return E_INVALIDARG;
5123 /* ITypeInfo_GetNames
5125 * Retrieves the variable with the specified member ID (or the name of the
5126 * property or method and its parameters) that correspond to the specified
5129 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5130 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5132 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5133 const TLBFuncDesc *pFDesc;
5134 const TLBVarDesc *pVDesc;
5136 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5137 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5140 /* function found, now return function and parameter names */
5141 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5144 *rgBstrNames=SysAllocString(pFDesc->Name);
5146 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5152 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5155 *rgBstrNames=SysAllocString(pVDesc->Name);
5160 if(This->impltypelist &&
5161 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5162 /* recursive search */
5165 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5167 if(SUCCEEDED(result))
5169 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5170 ITypeInfo_Release(pTInfo);
5173 WARN("Could not search inherited interface!\n");
5177 WARN("no names found\n");
5180 return TYPE_E_ELEMENTNOTFOUND;
5187 /* ITypeInfo::GetRefTypeOfImplType
5189 * If a type description describes a COM class, it retrieves the type
5190 * description of the implemented interface types. For an interface,
5191 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5195 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5200 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5203 const TLBImplType *pImpl = This->impltypelist;
5205 TRACE("(%p) index %d\n", This, index);
5206 if (TRACE_ON(ole)) dump_TypeInfo(This);
5210 /* only valid on dual interfaces;
5211 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5213 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5215 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
5216 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
5222 hr = TYPE_E_ELEMENTNOTFOUND;
5225 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5227 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5228 *pRefType = This->pTypeLib->dispatch_href;
5232 /* get element n from linked list */
5233 for(i=0; pImpl && i<index; i++)
5235 pImpl = pImpl->next;
5239 *pRefType = pImpl->hRef;
5241 hr = TYPE_E_ELEMENTNOTFOUND;
5247 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5249 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5255 /* ITypeInfo::GetImplTypeFlags
5257 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5258 * or base interface in a type description.
5260 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5261 UINT index, INT *pImplTypeFlags)
5263 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5267 TRACE("(%p) index %d\n", This, index);
5268 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5269 i++, pImpl=pImpl->next)
5271 if(i==index && pImpl){
5272 *pImplTypeFlags=pImpl->implflags;
5276 return TYPE_E_ELEMENTNOTFOUND;
5280 * Maps between member names and member IDs, and parameter names and
5283 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5284 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5286 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5287 const TLBFuncDesc *pFDesc;
5288 const TLBVarDesc *pVDesc;
5292 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5295 /* init out parameters in case of failure */
5296 for (i = 0; i < cNames; i++)
5297 pMemId[i] = MEMBERID_NIL;
5299 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5301 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5302 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5303 for(i=1; i < cNames; i++){
5304 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5305 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5307 if( j<pFDesc->funcdesc.cParams)
5310 ret=DISP_E_UNKNOWNNAME;
5312 TRACE("-- 0x%08x\n", ret);
5316 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5317 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5318 if(cNames) *pMemId=pVDesc->vardesc.memid;
5322 /* not found, see if it can be found in an inherited interface */
5323 if(This->impltypelist) {
5324 /* recursive search */
5326 ret=ITypeInfo_GetRefTypeInfo(iface,
5327 This->impltypelist->hRef, &pTInfo);
5329 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5330 ITypeInfo_Release(pTInfo);
5333 WARN("Could not search inherited interface!\n");
5335 WARN("no names found\n");
5336 return DISP_E_UNKNOWNNAME;
5339 /* ITypeInfo::Invoke
5341 * Invokes a method, or accesses a property of an object, that implements the
5342 * interface described by the type description.
5345 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5348 if (TRACE_ON(ole)) {
5350 TRACE("Calling %p(",func);
5351 for (i=0;i<nrargs;i++) TRACE("%08x,",args[i]);
5363 res = func(args[0]);
5366 res = func(args[0],args[1]);
5369 res = func(args[0],args[1],args[2]);
5372 res = func(args[0],args[1],args[2],args[3]);
5375 res = func(args[0],args[1],args[2],args[3],args[4]);
5378 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
5381 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
5384 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
5387 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
5390 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
5393 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
5396 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]);
5399 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]);
5402 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]);
5405 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]);
5408 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]);
5411 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]);
5414 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]);
5417 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]);
5420 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]);
5423 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]);
5426 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]);
5429 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]);
5432 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]);
5435 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]);
5438 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]);
5441 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]);
5444 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]);
5447 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]);
5450 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]);
5453 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5459 FIXME("unsupported calling convention %d\n",callconv);
5463 TRACE("returns %08x\n",res);
5467 /* The size of the argument on the stack in DWORD units (in all x86 call
5468 * convetions the arguments on the stack are DWORD-aligned)
5470 int _dispargsize(VARTYPE vt)
5475 return 8/sizeof(DWORD);
5477 return sizeof(double)/sizeof(DWORD);
5479 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5481 return sizeof(CY)/sizeof(DWORD);
5483 return sizeof(DATE)/sizeof(DWORD);
5485 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5487 FIXME("VT_RECORD not implemented\n");
5494 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5497 ITypeInfo *tinfo2 = NULL;
5498 TYPEATTR *tattr = NULL;
5500 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5503 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5505 tdesc->u.hreftype, hr);
5508 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5511 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5512 ITypeInfo_Release(tinfo2);
5516 switch (tattr->typekind)
5523 tdesc = &tattr->tdescAlias;
5524 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5527 case TKIND_INTERFACE:
5528 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5534 case TKIND_DISPATCH:
5543 FIXME("TKIND_RECORD unhandled.\n");
5548 FIXME("TKIND_UNION unhandled.\n");
5553 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5557 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5558 ITypeInfo_Release(tinfo2);
5562 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5566 /* enforce only one level of pointer indirection */
5567 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5569 tdesc = tdesc->u.lptdesc;
5571 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5572 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5573 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5574 if ((tdesc->vt == VT_USERDEFINED) ||
5575 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5577 VARTYPE vt_userdefined = 0;
5578 const TYPEDESC *tdesc_userdefined = tdesc;
5579 if (tdesc->vt == VT_PTR)
5581 vt_userdefined = VT_BYREF;
5582 tdesc_userdefined = tdesc->u.lptdesc;
5584 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5586 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5587 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5589 *vt |= vt_userdefined;
5601 case VT_USERDEFINED:
5602 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5609 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5610 hr = DISP_E_BADVARTYPE;
5614 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5623 /***********************************************************************
5624 * DispCallFunc (OLEAUT32.@)
5626 * Invokes a function of the specified calling convention, passing the
5627 * specified arguments and returns the result.
5630 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5631 * oVft [I] The offset in the vtable. See notes.
5632 * cc [I] Calling convention of the function to call.
5633 * vtReturn [I] The return type of the function.
5634 * cActuals [I] Number of parameters.
5635 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5636 * prgpvarg [I] The arguments to pass.
5637 * pvargResult [O] The return value of the function. Can be NULL.
5641 * Failure: HRESULT code.
5644 * The HRESULT return value of this function is not affected by the return
5645 * value of the user supplied function, which is returned in pvargResult.
5647 * If pvInstance is NULL then a non-object function is to be called and oVft
5648 * is the address of the function to call.
5650 * The cc parameter can be one of the following values:
5663 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5664 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5666 int argsize, argspos;
5671 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5672 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5673 pvargResult, V_VT(pvargResult));
5677 argsize++; /* for This pointer */
5679 for (i=0;i<cActuals;i++)
5681 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5682 dump_Variant(prgpvarg[i]);
5683 argsize += _dispargsize(prgvt[i]);
5685 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5690 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5694 for (i=0;i<cActuals;i++)
5696 VARIANT *arg = prgpvarg[i];
5697 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5698 if (prgvt[i] == VT_VARIANT)
5699 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5701 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5702 argspos += _dispargsize(prgvt[i]);
5707 FARPROC *vtable = *(FARPROC**)pvInstance;
5708 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5711 /* if we aren't invoking an object then the function pointer is stored
5713 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5715 if (pvargResult && (vtReturn != VT_EMPTY))
5717 TRACE("Method returned 0x%08x\n",hres);
5718 V_VT(pvargResult) = vtReturn;
5719 V_UI4(pvargResult) = hres;
5722 HeapFree(GetProcessHeap(),0,args);
5726 #define INVBUF_ELEMENT_SIZE \
5727 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5728 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5729 ((VARIANTARG *)(buffer))
5730 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5731 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5732 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5733 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5734 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5735 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5737 static HRESULT WINAPI ITypeInfo_fnInvoke(
5742 DISPPARAMS *pDispParams,
5743 VARIANT *pVarResult,
5744 EXCEPINFO *pExcepInfo,
5747 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5749 unsigned int var_index;
5752 const TLBFuncDesc *pFuncInfo;
5754 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
5755 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5760 ERR("NULL pDispParams not allowed\n");
5761 return E_INVALIDARG;
5764 dump_DispParms(pDispParams);
5766 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5768 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5769 pDispParams->cNamedArgs, pDispParams->cArgs);
5770 return E_INVALIDARG;
5773 /* we do this instead of using GetFuncDesc since it will return a fake
5774 * FUNCDESC for dispinterfaces and we want the real function description */
5775 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5776 if ((memid == pFuncInfo->funcdesc.memid) &&
5777 (wFlags & pFuncInfo->funcdesc.invkind))
5781 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5785 TRACE("invoking:\n");
5786 dump_TLBFuncDescOne(pFuncInfo);
5789 switch (func_desc->funckind) {
5790 case FUNC_PUREVIRTUAL:
5791 case FUNC_VIRTUAL: {
5792 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5794 VARIANT retval; /* pointer for storing byref retvals in */
5795 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5796 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5797 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5798 UINT cNamedArgs = pDispParams->cNamedArgs;
5799 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
5803 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
5805 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
5807 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
5808 hres = DISP_E_PARAMNOTFOUND;
5811 /* ignore the DISPID_PROPERTYPUT named argument from now on */
5813 rgdispidNamedArgs++;
5816 if (func_desc->cParamsOpt < 0 && cNamedArgs)
5818 ERR("functions with the vararg attribute do not support named arguments\n");
5819 hres = DISP_E_NONAMEDARGS;
5823 for (i = 0; i < func_desc->cParams; i++)
5825 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5826 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5831 TRACE("changing args\n");
5832 for (i = 0; i < func_desc->cParams; i++)
5834 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5835 VARIANTARG *src_arg;
5841 for (j = 0; j < cNamedArgs; j++)
5842 if (rgdispidNamedArgs[j] == i)
5844 src_arg = &pDispParams->rgvarg[j];
5849 src_arg = i < pDispParams->cArgs ? &pDispParams->rgvarg[pDispParams->cArgs - 1 - i] : NULL;
5851 if (wParamFlags & PARAMFLAG_FRETVAL)
5853 /* under most conditions the caller is not allowed to
5854 * pass in a dispparam arg in the index of what would be
5855 * the retval parameter. however, there is an exception
5856 * where the extra parameter is used in an extra
5857 * IDispatch::Invoke below */
5858 if ((i < pDispParams->cArgs) &&
5859 ((func_desc->cParams != 1) || !pVarResult ||
5860 !(func_desc->invkind & INVOKE_PROPERTYGET)))
5862 hres = DISP_E_BADPARAMCOUNT;
5866 /* note: this check is placed so that if the caller passes
5867 * in a VARIANTARG for the retval we just ignore it, like
5869 if (i == func_desc->cParams - 1)
5872 arg = prgpvarg[i] = &rgvarg[i];
5873 memset(arg, 0, sizeof(*arg));
5874 V_VT(arg) = rgvt[i];
5875 memset(&retval, 0, sizeof(retval));
5876 V_BYREF(arg) = &retval;
5880 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5881 hres = E_UNEXPECTED;
5887 dump_Variant(src_arg);
5889 if (rgvt[i] == VT_VARIANT)
5890 hres = VariantCopy(&rgvarg[i], src_arg);
5891 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5893 if (rgvt[i] == V_VT(src_arg))
5894 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5897 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5898 hres = VariantCopy(&missing_arg[i], src_arg);
5899 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5901 V_VT(&rgvarg[i]) = rgvt[i];
5903 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
5906 SAFEARRAYBOUND bound;
5910 bound.cElements = pDispParams->cArgs-i;
5911 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
5913 ERR("SafeArrayCreate failed\n");
5916 hres = SafeArrayAccessData(a, (LPVOID)&v);
5919 ERR("SafeArrayAccessData failed with %x\n", hres);
5922 for (j = 0; j < bound.cElements; j++)
5923 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
5924 hres = SafeArrayUnaccessData(a);
5927 ERR("SafeArrayUnaccessData failed with %x\n", hres);
5930 V_ARRAY(&rgvarg[i]) = a;
5931 V_VT(&rgvarg[i]) = rgvt[i];
5933 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5935 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5936 V_VT(&missing_arg[i]) = V_VT(src_arg);
5937 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5938 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5939 V_VT(&rgvarg[i]) = rgvt[i];
5941 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5943 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5944 V_VT(&rgvarg[i]) = rgvt[i];
5948 /* FIXME: this doesn't work for VT_BYREF arguments if
5949 * they are not the same type as in the paramdesc */
5950 V_VT(&rgvarg[i]) = V_VT(src_arg);
5951 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5952 V_VT(&rgvarg[i]) = rgvt[i];
5957 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5958 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5959 debugstr_VT(src_arg), debugstr_VF(src_arg));
5962 prgpvarg[i] = &rgvarg[i];
5964 else if (wParamFlags & PARAMFLAG_FOPT)
5967 arg = prgpvarg[i] = &rgvarg[i];
5968 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5970 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5976 VARIANTARG *missing_arg;
5977 /* if the function wants a pointer to a variant then
5978 * set that up, otherwise just pass the VT_ERROR in
5979 * the argument by value */
5980 if (rgvt[i] & VT_BYREF)
5982 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
5983 V_VT(arg) = VT_VARIANT | VT_BYREF;
5984 V_VARIANTREF(arg) = missing_arg;
5988 V_VT(missing_arg) = VT_ERROR;
5989 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
5994 hres = DISP_E_BADPARAMCOUNT;
5998 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6000 /* VT_VOID is a special case for return types, so it is not
6001 * handled in the general function */
6002 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6003 V_VT(&varresult) = VT_EMPTY;
6006 V_VT(&varresult) = 0;
6007 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6008 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6011 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6012 V_VT(&varresult), func_desc->cParams, rgvt,
6013 prgpvarg, &varresult);
6015 for (i = 0; i < func_desc->cParams; i++)
6017 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6018 if (wParamFlags & PARAMFLAG_FRETVAL)
6022 TRACE("[retval] value: ");
6023 dump_Variant(prgpvarg[i]);
6028 VariantInit(pVarResult);
6029 /* deref return value */
6030 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6033 /* free data stored in varresult. Note that
6034 * VariantClear doesn't do what we want because we are
6035 * working with byref types. */
6036 /* FIXME: clear safearrays, bstrs, records and
6037 * variants here too */
6038 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
6039 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
6041 if(*V_UNKNOWNREF(prgpvarg[i]))
6042 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
6046 else if (i < pDispParams->cArgs)
6048 if (wParamFlags & PARAMFLAG_FOUT)
6050 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
6052 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
6053 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6057 ERR("failed to convert param %d to vt %d\n", i,
6058 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
6062 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6063 func_desc->cParamsOpt < 0 &&
6064 i == func_desc->cParams-1)
6066 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6069 hres = SafeArrayGetUBound(a, 1, &ubound);
6072 ERR("SafeArrayGetUBound failed with %x\n", hres);
6075 hres = SafeArrayAccessData(a, (LPVOID)&v);
6078 ERR("SafeArrayAccessData failed with %x\n", hres);
6081 for (j = 0; j <= ubound; j++)
6082 VariantClear(&v[j]);
6083 hres = SafeArrayUnaccessData(a);
6086 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6090 VariantClear(&rgvarg[i]);
6092 else if (wParamFlags & PARAMFLAG_FOPT)
6094 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6095 VariantClear(&rgvarg[i]);
6099 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6101 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6102 hres = DISP_E_EXCEPTION;
6105 IErrorInfo *pErrorInfo;
6106 pExcepInfo->scode = V_ERROR(&varresult);
6107 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6109 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6110 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6111 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6112 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6114 IErrorInfo_Release(pErrorInfo);
6118 if (V_VT(&varresult) != VT_ERROR)
6120 TRACE("varresult value: ");
6121 dump_Variant(&varresult);
6125 VariantClear(pVarResult);
6126 *pVarResult = varresult;
6129 VariantClear(&varresult);
6132 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6133 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6134 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6135 (pDispParams->cArgs != 0))
6137 if (V_VT(pVarResult) == VT_DISPATCH)
6139 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6140 /* Note: not VariantClear; we still need the dispatch
6141 * pointer to be valid */
6142 VariantInit(pVarResult);
6143 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6144 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6145 pDispParams, pVarResult, pExcepInfo, pArgErr);
6146 IDispatch_Release(pDispatch);
6150 VariantClear(pVarResult);
6151 hres = DISP_E_NOTACOLLECTION;
6156 HeapFree(GetProcessHeap(), 0, buffer);
6159 case FUNC_DISPATCH: {
6162 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6163 if (SUCCEEDED(hres)) {
6164 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6165 hres = IDispatch_Invoke(
6166 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6167 pVarResult,pExcepInfo,pArgErr
6170 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6171 IDispatch_Release(disp);
6173 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6177 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6182 TRACE("-- 0x%08x\n", hres);
6185 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6188 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6189 if(FAILED(hres)) return hres;
6191 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6192 dump_VARDESC(var_desc);
6193 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6197 /* not found, look for it in inherited interfaces */
6198 ITypeInfo2_GetTypeKind(iface, &type_kind);
6199 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6200 if(This->impltypelist) {
6201 /* recursive search */
6203 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6204 if(SUCCEEDED(hres)){
6205 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6206 ITypeInfo_Release(pTInfo);
6209 WARN("Could not search inherited interface!\n");
6212 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6213 return DISP_E_MEMBERNOTFOUND;
6216 /* ITypeInfo::GetDocumentation
6218 * Retrieves the documentation string, the complete Help file name and path,
6219 * and the context ID for the Help topic for a specified type description.
6221 * (Can be tested by the Visual Basic Editor in Word for instance.)
6223 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6224 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6225 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6227 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6228 const TLBFuncDesc *pFDesc;
6229 const TLBVarDesc *pVDesc;
6230 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6231 " HelpContext(%p) HelpFile(%p)\n",
6232 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6233 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6235 *pBstrName=SysAllocString(This->Name);
6237 *pBstrDocString=SysAllocString(This->DocString);
6239 *pdwHelpContext=This->dwHelpContext;
6241 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6243 }else {/* for a member */
6244 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6245 if(pFDesc->funcdesc.memid==memid){
6247 *pBstrName = SysAllocString(pFDesc->Name);
6249 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6251 *pdwHelpContext=pFDesc->helpcontext;
6254 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6255 if(pVDesc->vardesc.memid==memid){
6257 *pBstrName = SysAllocString(pVDesc->Name);
6259 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6261 *pdwHelpContext=pVDesc->HelpContext;
6266 if(This->impltypelist &&
6267 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6268 /* recursive search */
6271 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6273 if(SUCCEEDED(result)) {
6274 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6275 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6276 ITypeInfo_Release(pTInfo);
6279 WARN("Could not search inherited interface!\n");
6282 WARN("member %d not found\n", memid);
6283 return TYPE_E_ELEMENTNOTFOUND;
6286 /* ITypeInfo::GetDllEntry
6288 * Retrieves a description or specification of an entry point for a function
6291 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6292 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6295 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6296 const TLBFuncDesc *pFDesc;
6298 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6300 if (pBstrDllName) *pBstrDllName = NULL;
6301 if (pBstrName) *pBstrName = NULL;
6302 if (pwOrdinal) *pwOrdinal = 0;
6304 if (This->TypeAttr.typekind != TKIND_MODULE)
6305 return TYPE_E_BADMODULEKIND;
6307 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6308 if(pFDesc->funcdesc.memid==memid){
6309 dump_TypeInfo(This);
6311 dump_TLBFuncDescOne(pFDesc);
6314 *pBstrDllName = SysAllocString(This->DllName);
6316 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6318 *pBstrName = SysAllocString(pFDesc->Entry);
6326 *pwOrdinal = (DWORD)pFDesc->Entry;
6329 return TYPE_E_ELEMENTNOTFOUND;
6332 /* internal function to make the inherited interfaces' methods appear
6333 * part of the interface */
6334 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6335 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6337 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6340 TRACE("%p, 0x%x\n", iface, *hRefType);
6342 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6344 ITypeInfo *pSubTypeInfo;
6346 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6350 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6352 ITypeInfo_Release(pSubTypeInfo);
6356 *hRefType -= DISPATCH_HREF_OFFSET;
6358 if (!(*hRefType & DISPATCH_HREF_MASK))
6359 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6364 /* ITypeInfo::GetRefTypeInfo
6366 * If a type description references other type descriptions, it retrieves
6367 * the referenced type descriptions.
6369 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6372 ITypeInfo **ppTInfo)
6374 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6375 HRESULT result = E_FAIL;
6377 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6379 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6380 ITypeInfo_AddRef(*ppTInfo);
6383 else if (hRefType == -1 &&
6384 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6385 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6387 /* when we meet a DUAL dispinterface, we must create the interface
6390 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6393 /* the interface version contains the same information as the dispinterface
6394 * copy the contents of the structs.
6396 *pTypeInfoImpl = *This;
6397 pTypeInfoImpl->ref = 0;
6399 /* change the type to interface */
6400 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6402 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6404 /* we use data structures from This, so we need to keep a reference
6405 * to it to stop it being destroyed and signal to the new instance to
6406 * not free its data structures when it is destroyed */
6407 pTypeInfoImpl->no_free_data = TRUE;
6408 pTypeInfoImpl->next = This;
6409 ITypeInfo_AddRef((ITypeInfo*) This);
6411 ITypeInfo_AddRef(*ppTInfo);
6415 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6416 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6417 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6419 HREFTYPE href_dispatch = hRefType;
6420 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6422 TLBRefType *ref_type;
6423 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6425 if(ref_type->reference == hRefType)
6428 if(&ref_type->entry == &This->pTypeLib->ref_list)
6430 FIXME("Can't find pRefType for ref %x\n", hRefType);
6433 if(hRefType != -1) {
6434 ITypeLib *pTLib = NULL;
6436 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6438 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6440 if(ref_type->pImpTLInfo->pImpTypeLib) {
6441 TRACE("typeinfo in imported typelib that is already loaded\n");
6442 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6443 ITypeLib2_AddRef(pTLib);
6446 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6447 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6448 ref_type->pImpTLInfo->wVersionMajor,
6449 ref_type->pImpTLInfo->wVersionMinor,
6450 ref_type->pImpTLInfo->lcid,
6453 if(FAILED(result)) {
6454 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6455 result=LoadTypeLib(libnam, &pTLib);
6456 SysFreeString(libnam);
6458 if(SUCCEEDED(result)) {
6459 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6460 ITypeLib2_AddRef(pTLib);
6464 if(SUCCEEDED(result)) {
6465 if(ref_type->index == TLB_REF_USE_GUID)
6466 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6470 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6474 ITypeLib2_Release(pTLib);
6479 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6480 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6484 /* ITypeInfo::AddressOfMember
6486 * Retrieves the addresses of static functions or variables, such as those
6489 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6490 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6492 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6498 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6500 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6504 module = LoadLibraryW(dll);
6507 ERR("couldn't load %s\n", debugstr_w(dll));
6509 SysFreeString(entry);
6510 return STG_E_FILENOTFOUND;
6512 /* FIXME: store library somewhere where we can free it */
6517 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6518 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6519 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6521 *ppv = GetProcAddress(module, entryA);
6523 ERR("function not found %s\n", debugstr_a(entryA));
6525 HeapFree(GetProcessHeap(), 0, entryA);
6529 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6531 ERR("function not found %d\n", ordinal);
6535 SysFreeString(entry);
6538 return TYPE_E_DLLFUNCTIONNOTFOUND;
6543 /* ITypeInfo::CreateInstance
6545 * Creates a new instance of a type that describes a component object class
6548 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6549 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6551 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6555 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6561 WARN("Not able to aggregate\n");
6562 return CLASS_E_NOAGGREGATION;
6565 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6566 if(FAILED(hr)) return hr;
6568 if(pTA->typekind != TKIND_COCLASS)
6570 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6576 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6579 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6580 TRACE("GetActiveObject rets %08x\n", hr);
6583 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6584 IUnknown_Release(pUnk);
6589 hr = CoCreateInstance(&pTA->guid, NULL,
6590 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6594 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6598 /* ITypeInfo::GetMops
6600 * Retrieves marshalling information.
6602 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6605 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6606 FIXME("(%p) stub!\n", This);
6610 /* ITypeInfo::GetContainingTypeLib
6612 * Retrieves the containing type library and the index of the type description
6613 * within that type library.
6615 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6616 ITypeLib * *ppTLib, UINT *pIndex)
6618 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6620 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6622 *pIndex=This->index;
6623 TRACE("returning pIndex=%d\n", *pIndex);
6627 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6628 ITypeLib2_AddRef(*ppTLib);
6629 TRACE("returning ppTLib=%p\n", *ppTLib);
6635 /* ITypeInfo::ReleaseTypeAttr
6637 * Releases a TYPEATTR previously returned by GetTypeAttr.
6640 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6641 TYPEATTR* pTypeAttr)
6643 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6644 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6645 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6648 /* ITypeInfo::ReleaseFuncDesc
6650 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6652 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6654 FUNCDESC *pFuncDesc)
6656 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6659 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6661 for (i = 0; i < pFuncDesc->cParams; i++)
6662 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6663 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6665 SysFreeString((BSTR)pFuncDesc);
6668 /* ITypeInfo::ReleaseVarDesc
6670 * Releases a VARDESC previously returned by GetVarDesc.
6672 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6675 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6676 TRACE("(%p)->(%p)\n", This, pVarDesc);
6678 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6679 if (pVarDesc->varkind == VAR_CONST)
6680 VariantClear(pVarDesc->u.lpvarValue);
6681 SysFreeString((BSTR)pVarDesc);
6684 /* ITypeInfo2::GetTypeKind
6686 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6689 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6690 TYPEKIND *pTypeKind)
6692 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6693 *pTypeKind=This->TypeAttr.typekind;
6694 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6698 /* ITypeInfo2::GetTypeFlags
6700 * Returns the type flags without any allocations. This returns a DWORD type
6701 * flag, which expands the type flags without growing the TYPEATTR (type
6705 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6707 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6708 *pTypeFlags=This->TypeAttr.wTypeFlags;
6709 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6713 /* ITypeInfo2::GetFuncIndexOfMemId
6714 * Binds to a specific member based on a known DISPID, where the member name
6715 * is not known (for example, when binding to a default member).
6718 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6719 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6721 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6722 const TLBFuncDesc *pFuncInfo;
6726 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6727 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6733 result = TYPE_E_ELEMENTNOTFOUND;
6735 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
6736 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6740 /* TypeInfo2::GetVarIndexOfMemId
6742 * Binds to a specific member based on a known DISPID, where the member name
6743 * is not known (for example, when binding to a default member).
6746 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6747 MEMBERID memid, UINT *pVarIndex)
6749 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6750 TLBVarDesc *pVarInfo;
6753 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6754 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6760 result = TYPE_E_ELEMENTNOTFOUND;
6762 TRACE("(%p) memid 0x%08x -> %s\n", This,
6763 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6767 /* ITypeInfo2::GetCustData
6769 * Gets the custom data
6771 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6776 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6777 TLBCustData *pCData;
6779 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6780 if( IsEqualIID(guid, &pCData->guid)) break;
6782 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6786 VariantInit( pVarVal);
6787 VariantCopy( pVarVal, &pCData->data);
6790 return E_INVALIDARG; /* FIXME: correct? */
6793 /* ITypeInfo2::GetFuncCustData
6795 * Gets the custom data
6797 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6803 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6804 TLBCustData *pCData=NULL;
6805 TLBFuncDesc * pFDesc;
6807 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6808 pFDesc=pFDesc->next);
6811 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6812 if( IsEqualIID(guid, &pCData->guid)) break;
6814 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6817 VariantInit( pVarVal);
6818 VariantCopy( pVarVal, &pCData->data);
6821 return E_INVALIDARG; /* FIXME: correct? */
6824 /* ITypeInfo2::GetParamCustData
6826 * Gets the custom data
6828 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6835 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6836 TLBCustData *pCData=NULL;
6837 TLBFuncDesc * pFDesc;
6840 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6842 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
6843 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6844 pCData = pCData->next)
6845 if( IsEqualIID(guid, &pCData->guid)) break;
6847 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6851 VariantInit( pVarVal);
6852 VariantCopy( pVarVal, &pCData->data);
6855 return E_INVALIDARG; /* FIXME: correct? */
6858 /* ITypeInfo2::GetVarCustData
6860 * Gets the custom data
6862 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6868 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6869 TLBCustData *pCData=NULL;
6870 TLBVarDesc * pVDesc;
6873 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6877 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6879 if( IsEqualIID(guid, &pCData->guid)) break;
6883 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6887 VariantInit( pVarVal);
6888 VariantCopy( pVarVal, &pCData->data);
6891 return E_INVALIDARG; /* FIXME: correct? */
6894 /* ITypeInfo2::GetImplCustData
6896 * Gets the custom data
6898 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6904 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6905 TLBCustData *pCData=NULL;
6906 TLBImplType * pRDesc;
6909 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6913 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6915 if( IsEqualIID(guid, &pCData->guid)) break;
6919 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6923 VariantInit( pVarVal);
6924 VariantCopy( pVarVal, &pCData->data);
6927 return E_INVALIDARG; /* FIXME: correct? */
6930 /* ITypeInfo2::GetDocumentation2
6932 * Retrieves the documentation string, the complete Help file name and path,
6933 * the localization context to use, and the context ID for the library Help
6934 * topic in the Help file.
6937 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6941 BSTR *pbstrHelpString,
6942 DWORD *pdwHelpStringContext,
6943 BSTR *pbstrHelpStringDll)
6945 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6946 const TLBFuncDesc *pFDesc;
6947 const TLBVarDesc *pVDesc;
6948 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
6949 "HelpStringContext(%p) HelpStringDll(%p)\n",
6950 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6951 pbstrHelpStringDll );
6952 /* the help string should be obtained from the helpstringdll,
6953 * using the _DLLGetDocumentation function, based on the supplied
6954 * lcid. Nice to do sometime...
6956 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6958 *pbstrHelpString=SysAllocString(This->Name);
6959 if(pdwHelpStringContext)
6960 *pdwHelpStringContext=This->dwHelpStringContext;
6961 if(pbstrHelpStringDll)
6962 *pbstrHelpStringDll=
6963 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6965 }else {/* for a member */
6966 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6967 if(pFDesc->funcdesc.memid==memid){
6969 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6970 if(pdwHelpStringContext)
6971 *pdwHelpStringContext=pFDesc->HelpStringContext;
6972 if(pbstrHelpStringDll)
6973 *pbstrHelpStringDll=
6974 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6977 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6978 if(pVDesc->vardesc.memid==memid){
6980 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6981 if(pdwHelpStringContext)
6982 *pdwHelpStringContext=pVDesc->HelpStringContext;
6983 if(pbstrHelpStringDll)
6984 *pbstrHelpStringDll=
6985 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6989 return TYPE_E_ELEMENTNOTFOUND;
6992 /* ITypeInfo2::GetAllCustData
6994 * Gets all custom data items for the Type info.
6997 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6999 CUSTDATA *pCustData)
7001 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7002 TLBCustData *pCData;
7005 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7007 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7008 if(pCustData->prgCustData ){
7009 pCustData->cCustData=This->ctCustData;
7010 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7011 pCustData->prgCustData[i].guid=pCData->guid;
7012 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7015 ERR(" OUT OF MEMORY!\n");
7016 return E_OUTOFMEMORY;
7021 /* ITypeInfo2::GetAllFuncCustData
7023 * Gets all custom data items for the specified Function
7026 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7029 CUSTDATA *pCustData)
7031 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7032 TLBCustData *pCData;
7033 TLBFuncDesc * pFDesc;
7035 TRACE("(%p) index %d\n", This, index);
7036 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7037 pFDesc=pFDesc->next)
7040 pCustData->prgCustData =
7041 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7042 if(pCustData->prgCustData ){
7043 pCustData->cCustData=pFDesc->ctCustData;
7044 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7045 pCData = pCData->next){
7046 pCustData->prgCustData[i].guid=pCData->guid;
7047 VariantCopy(& pCustData->prgCustData[i].varValue,
7051 ERR(" OUT OF MEMORY!\n");
7052 return E_OUTOFMEMORY;
7056 return TYPE_E_ELEMENTNOTFOUND;
7059 /* ITypeInfo2::GetAllParamCustData
7061 * Gets all custom data items for the Functions
7064 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7065 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7067 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7068 TLBCustData *pCData=NULL;
7069 TLBFuncDesc * pFDesc;
7071 TRACE("(%p) index %d\n", This, indexFunc);
7072 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7073 pFDesc=pFDesc->next)
7075 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7076 pCustData->prgCustData =
7077 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7078 sizeof(CUSTDATAITEM));
7079 if(pCustData->prgCustData ){
7080 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7081 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7082 pCData; i++, pCData = pCData->next){
7083 pCustData->prgCustData[i].guid=pCData->guid;
7084 VariantCopy(& pCustData->prgCustData[i].varValue,
7088 ERR(" OUT OF MEMORY!\n");
7089 return E_OUTOFMEMORY;
7093 return TYPE_E_ELEMENTNOTFOUND;
7096 /* ITypeInfo2::GetAllVarCustData
7098 * Gets all custom data items for the specified Variable
7101 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7102 UINT index, CUSTDATA *pCustData)
7104 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7105 TLBCustData *pCData;
7106 TLBVarDesc * pVDesc;
7108 TRACE("(%p) index %d\n", This, index);
7109 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7110 pVDesc=pVDesc->next)
7113 pCustData->prgCustData =
7114 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7115 if(pCustData->prgCustData ){
7116 pCustData->cCustData=pVDesc->ctCustData;
7117 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7118 pCData = pCData->next){
7119 pCustData->prgCustData[i].guid=pCData->guid;
7120 VariantCopy(& pCustData->prgCustData[i].varValue,
7124 ERR(" OUT OF MEMORY!\n");
7125 return E_OUTOFMEMORY;
7129 return TYPE_E_ELEMENTNOTFOUND;
7132 /* ITypeInfo2::GetAllImplCustData
7134 * Gets all custom data items for the specified implementation type
7137 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7140 CUSTDATA *pCustData)
7142 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7143 TLBCustData *pCData;
7144 TLBImplType * pRDesc;
7146 TRACE("(%p) index %d\n", This, index);
7147 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7148 pRDesc=pRDesc->next)
7151 pCustData->prgCustData =
7152 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7153 if(pCustData->prgCustData ){
7154 pCustData->cCustData=pRDesc->ctCustData;
7155 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7156 pCData = pCData->next){
7157 pCustData->prgCustData[i].guid=pCData->guid;
7158 VariantCopy(& pCustData->prgCustData[i].varValue,
7162 ERR(" OUT OF MEMORY!\n");
7163 return E_OUTOFMEMORY;
7167 return TYPE_E_ELEMENTNOTFOUND;
7170 static const ITypeInfo2Vtbl tinfvt =
7173 ITypeInfo_fnQueryInterface,
7175 ITypeInfo_fnRelease,
7177 ITypeInfo_fnGetTypeAttr,
7178 ITypeInfo_fnGetTypeComp,
7179 ITypeInfo_fnGetFuncDesc,
7180 ITypeInfo_fnGetVarDesc,
7181 ITypeInfo_fnGetNames,
7182 ITypeInfo_fnGetRefTypeOfImplType,
7183 ITypeInfo_fnGetImplTypeFlags,
7184 ITypeInfo_fnGetIDsOfNames,
7186 ITypeInfo_fnGetDocumentation,
7187 ITypeInfo_fnGetDllEntry,
7188 ITypeInfo_fnGetRefTypeInfo,
7189 ITypeInfo_fnAddressOfMember,
7190 ITypeInfo_fnCreateInstance,
7191 ITypeInfo_fnGetMops,
7192 ITypeInfo_fnGetContainingTypeLib,
7193 ITypeInfo_fnReleaseTypeAttr,
7194 ITypeInfo_fnReleaseFuncDesc,
7195 ITypeInfo_fnReleaseVarDesc,
7197 ITypeInfo2_fnGetTypeKind,
7198 ITypeInfo2_fnGetTypeFlags,
7199 ITypeInfo2_fnGetFuncIndexOfMemId,
7200 ITypeInfo2_fnGetVarIndexOfMemId,
7201 ITypeInfo2_fnGetCustData,
7202 ITypeInfo2_fnGetFuncCustData,
7203 ITypeInfo2_fnGetParamCustData,
7204 ITypeInfo2_fnGetVarCustData,
7205 ITypeInfo2_fnGetImplTypeCustData,
7206 ITypeInfo2_fnGetDocumentation2,
7207 ITypeInfo2_fnGetAllCustData,
7208 ITypeInfo2_fnGetAllFuncCustData,
7209 ITypeInfo2_fnGetAllParamCustData,
7210 ITypeInfo2_fnGetAllVarCustData,
7211 ITypeInfo2_fnGetAllImplTypeCustData,
7214 /******************************************************************************
7215 * CreateDispTypeInfo [OLEAUT32.31]
7217 * Build type information for an object so it can be called through an
7218 * IDispatch interface.
7221 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7222 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7225 * This call allows an objects methods to be accessed through IDispatch, by
7226 * building an ITypeInfo object that IDispatch can use to call through.
7228 HRESULT WINAPI CreateDispTypeInfo(
7229 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7230 LCID lcid, /* [I] Locale Id */
7231 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7233 ITypeInfoImpl *pTIClass, *pTIIface;
7234 ITypeLibImpl *pTypeLibImpl;
7235 unsigned int param, func;
7236 TLBFuncDesc **ppFuncDesc;
7240 pTypeLibImpl = TypeLibImpl_Constructor();
7241 if (!pTypeLibImpl) return E_FAIL;
7243 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7244 pTIIface->pTypeLib = pTypeLibImpl;
7245 pTIIface->index = 0;
7246 pTIIface->Name = NULL;
7247 pTIIface->dwHelpContext = -1;
7248 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7249 pTIIface->TypeAttr.lcid = lcid;
7250 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7251 pTIIface->TypeAttr.wMajorVerNum = 0;
7252 pTIIface->TypeAttr.wMinorVerNum = 0;
7253 pTIIface->TypeAttr.cbAlignment = 2;
7254 pTIIface->TypeAttr.cbSizeInstance = -1;
7255 pTIIface->TypeAttr.cbSizeVft = -1;
7256 pTIIface->TypeAttr.cFuncs = 0;
7257 pTIIface->TypeAttr.cImplTypes = 0;
7258 pTIIface->TypeAttr.cVars = 0;
7259 pTIIface->TypeAttr.wTypeFlags = 0;
7261 ppFuncDesc = &pTIIface->funclist;
7262 for(func = 0; func < pidata->cMembers; func++) {
7263 METHODDATA *md = pidata->pmethdata + func;
7264 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7265 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7266 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7267 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7268 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7269 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7270 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7271 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7272 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7273 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
7274 (*ppFuncDesc)->funcdesc.cScodes = 0;
7275 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7276 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7277 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7278 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7279 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7280 md->cArgs * sizeof(ELEMDESC));
7281 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7282 md->cArgs * sizeof(TLBParDesc));
7283 for(param = 0; param < md->cArgs; param++) {
7284 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7285 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7287 (*ppFuncDesc)->helpcontext = 0;
7288 (*ppFuncDesc)->HelpStringContext = 0;
7289 (*ppFuncDesc)->HelpString = NULL;
7290 (*ppFuncDesc)->Entry = NULL;
7291 (*ppFuncDesc)->ctCustData = 0;
7292 (*ppFuncDesc)->pCustData = NULL;
7293 (*ppFuncDesc)->next = NULL;
7294 pTIIface->TypeAttr.cFuncs++;
7295 ppFuncDesc = &(*ppFuncDesc)->next;
7298 dump_TypeInfo(pTIIface);
7300 pTypeLibImpl->pTypeInfo = pTIIface;
7301 pTypeLibImpl->TypeInfoCount++;
7303 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7304 pTIClass->pTypeLib = pTypeLibImpl;
7305 pTIClass->index = 1;
7306 pTIClass->Name = NULL;
7307 pTIClass->dwHelpContext = -1;
7308 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7309 pTIClass->TypeAttr.lcid = lcid;
7310 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7311 pTIClass->TypeAttr.wMajorVerNum = 0;
7312 pTIClass->TypeAttr.wMinorVerNum = 0;
7313 pTIClass->TypeAttr.cbAlignment = 2;
7314 pTIClass->TypeAttr.cbSizeInstance = -1;
7315 pTIClass->TypeAttr.cbSizeVft = -1;
7316 pTIClass->TypeAttr.cFuncs = 0;
7317 pTIClass->TypeAttr.cImplTypes = 1;
7318 pTIClass->TypeAttr.cVars = 0;
7319 pTIClass->TypeAttr.wTypeFlags = 0;
7321 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7322 pTIClass->impltypelist->hRef = 0;
7324 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7327 ref->pImpTLInfo = TLB_REF_INTERNAL;
7328 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7330 dump_TypeInfo(pTIClass);
7332 pTIIface->next = pTIClass;
7333 pTypeLibImpl->TypeInfoCount++;
7335 *pptinfo = (ITypeInfo*)pTIClass;
7337 ITypeInfo_AddRef(*pptinfo);
7338 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7344 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7346 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7348 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7351 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7353 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7355 return ITypeInfo_AddRef((ITypeInfo *)This);
7358 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7360 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7362 return ITypeInfo_Release((ITypeInfo *)This);
7365 static HRESULT WINAPI ITypeComp_fnBind(
7370 ITypeInfo ** ppTInfo,
7371 DESCKIND * pDescKind,
7374 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7375 const TLBFuncDesc *pFDesc;
7376 const TLBVarDesc *pVDesc;
7377 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7379 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7381 *pDescKind = DESCKIND_NONE;
7382 pBindPtr->lpfuncdesc = NULL;
7385 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7386 if (!strcmpiW(pFDesc->Name, szName)) {
7387 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7390 /* name found, but wrong flags */
7391 hr = TYPE_E_TYPEMISMATCH;
7396 HRESULT hr = TLB_AllocAndInitFuncDesc(
7398 &pBindPtr->lpfuncdesc,
7399 This->TypeAttr.typekind == TKIND_DISPATCH);
7402 *pDescKind = DESCKIND_FUNCDESC;
7403 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7404 ITypeInfo_AddRef(*ppTInfo);
7407 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7408 if (!strcmpiW(pVDesc->Name, szName)) {
7409 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7412 *pDescKind = DESCKIND_VARDESC;
7413 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7414 ITypeInfo_AddRef(*ppTInfo);
7419 /* FIXME: search each inherited interface, not just the first */
7420 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7421 /* recursive search */
7425 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7428 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7429 ITypeInfo_Release(pTInfo);
7433 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7434 ITypeComp_Release(pTComp);
7437 WARN("Could not search inherited interface!\n");
7439 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7443 static HRESULT WINAPI ITypeComp_fnBindType(
7447 ITypeInfo ** ppTInfo,
7448 ITypeComp ** ppTComp)
7450 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7452 /* strange behaviour (does nothing) but like the
7455 if (!ppTInfo || !ppTComp)
7464 static const ITypeCompVtbl tcompvt =
7467 ITypeComp_fnQueryInterface,
7469 ITypeComp_fnRelease,
7472 ITypeComp_fnBindType