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.
32 * So when you release the dispinterface, you delete the vtable-interface structures
33 * as well... fortunately, clean up of structures is not implemented.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
38 * - some garbage is read from function names on some very rare occasions.
40 * --------------------------------------------------------------------------------------
41 * Known problems left from previous implementation (1999, Rein Klazes) :
43 * -. Data structures are straightforward, but slow for look-ups.
44 * -. (related) nothing is hashed
45 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
46 * of them I don't know yet how to implement them.
47 * -. Most error return values are just guessed not checked with windows
49 * -. didn't bother with a c++ interface
50 * -. lousy fatal error handling
51 * -. some methods just return pointers to internal data structures, this is
52 * partly laziness, partly I want to check how windows does it.
57 #include "wine/port.h"
66 #define NONAMELESSUNION
67 #define NONAMELESSSTRUCT
76 #include "wine/unicode.h"
79 #include "wine/debug.h"
82 WINE_DEFAULT_DEBUG_CHANNEL(ole);
83 WINE_DECLARE_DEBUG_CHANNEL(typelib);
85 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
86 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
88 /****************************************************************************
91 * Takes p_iVal (which is in little endian) and returns it
92 * in the host machine's byte order.
94 #ifdef WORDS_BIGENDIAN
95 static WORD FromLEWord(WORD p_iVal)
97 return (((p_iVal & 0x00FF) << 8) |
98 ((p_iVal & 0xFF00) >> 8));
102 static DWORD FromLEDWord(DWORD p_iVal)
104 return (((p_iVal & 0x000000FF) << 24) |
105 ((p_iVal & 0x0000FF00) << 8) |
106 ((p_iVal & 0x00FF0000) >> 8) |
107 ((p_iVal & 0xFF000000) >> 24));
110 #define FromLEWord(X) (X)
111 #define FromLEDWord(X) (X)
115 /****************************************************************************
118 * Fix byte order in any structure if necessary
120 #ifdef WORDS_BIGENDIAN
121 static void FromLEWords(void *p_Val, int p_iSize)
125 p_iSize /= sizeof(WORD);
128 *Val = FromLEWord(*Val);
135 static void FromLEDWords(void *p_Val, int p_iSize)
139 p_iSize /= sizeof(DWORD);
142 *Val = FromLEDWord(*Val);
148 #define FromLEWords(X,Y) /*nothing*/
149 #define FromLEDWords(X,Y) /*nothing*/
152 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
153 /* buffer must be at least 60 characters long */
154 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
156 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
157 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
159 memcpy( buffer, TypelibW, sizeof(TypelibW) );
160 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
161 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
165 /* get the path of an interface key, in the form "Interface\\<guid>" */
166 /* buffer must be at least 50 characters long */
167 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
169 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
171 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
172 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
176 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
177 /* buffer must be at least 16 characters long */
178 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
180 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
181 static const WCHAR win16W[] = {'w','i','n','1','6',0};
182 static const WCHAR win32W[] = {'w','i','n','3','2',0};
184 sprintfW( buffer, LcidFormatW, lcid );
187 case SYS_WIN16: strcatW( buffer, win16W ); break;
188 case SYS_WIN32: strcatW( buffer, win32W ); break;
190 TRACE("Typelib is for unsupported syskind %i\n", syskind);
196 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
199 /****************************************************************************
200 * QueryPathOfRegTypeLib [OLEAUT32.164]
202 * Gets the path to a registered type library.
205 * guid [I] referenced guid
206 * wMaj [I] major version
207 * wMin [I] minor version
209 * path [O] path of typelib
213 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
214 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
217 HRESULT WINAPI QueryPathOfRegTypeLib(
224 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
228 WCHAR Path[MAX_PATH];
231 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
233 get_typelib_key( guid, wMaj, wMin, buffer );
235 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
236 if (res == ERROR_FILE_NOT_FOUND)
238 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
239 return TYPE_E_LIBNOTREGISTERED;
241 else if (res != ERROR_SUCCESS)
243 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
244 return TYPE_E_REGISTRYACCESS;
249 LONG dwPathLen = sizeof(Path);
251 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
253 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
257 else if (myLCID == lcid)
259 /* try with sub-langid */
260 myLCID = SUBLANGID(lcid);
262 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
264 /* try with system langid */
274 *path = SysAllocString( Path );
279 TRACE_(typelib)("-- 0x%08lx\n", hr);
283 /******************************************************************************
284 * CreateTypeLib [OLEAUT32.160] creates a typelib
290 HRESULT WINAPI CreateTypeLib(
291 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
293 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
297 /******************************************************************************
298 * LoadTypeLib [OLEAUT32.161]
300 * Loads a type library
303 * szFile [I] Name of file to load from.
304 * pptLib [O] Pointer that receives ITypeLib object on success.
311 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
313 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
315 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
316 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
319 /******************************************************************************
320 * LoadTypeLibEx [OLEAUT32.183]
322 * Loads and optionally registers a type library
328 HRESULT WINAPI LoadTypeLibEx(
329 LPCOLESTR szFile, /* [in] Name of file to load from */
330 REGKIND regkind, /* [in] Specify kind of registration */
331 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
333 WCHAR szPath[MAX_PATH+1];
336 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
340 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
345 case REGKIND_DEFAULT:
346 /* don't register typelibs supplied with full path. Experimentation confirms the following */
347 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
348 (szFile[0] && (szFile[1] == ':'))) break;
349 /* else fall-through */
351 case REGKIND_REGISTER:
352 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
354 IUnknown_Release(*pptLib);
362 TRACE(" returns %08lx\n",res);
366 /******************************************************************************
367 * LoadRegTypeLib [OLEAUT32.162]
369 * Loads a registered type library.
372 * rguid [I] GUID of the registered type library.
373 * wVerMajor [I] major version.
374 * wVerMinor [I] minor version.
375 * lcid [I] locale ID.
376 * ppTLib [O] pointer that receives an ITypeLib object on success.
380 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
383 HRESULT WINAPI LoadRegTypeLib(
395 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
399 res= LoadTypeLib(bstr, ppTLib);
403 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
409 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
410 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
411 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
412 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
413 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
414 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
416 /******************************************************************************
417 * RegisterTypeLib [OLEAUT32.163]
418 * Adds information about a type library to the System Registry
420 * Docs: ITypeLib FAR * ptlib
421 * Docs: OLECHAR FAR* szFullPath
422 * Docs: OLECHAR FAR* szHelpDir
428 HRESULT WINAPI RegisterTypeLib(
429 ITypeLib * ptlib, /* [in] Pointer to the library*/
430 OLECHAR * szFullPath, /* [in] full Path of the library*/
431 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
434 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
435 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
436 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
446 if (ptlib == NULL || szFullPath == NULL)
449 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
452 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
455 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
456 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
460 /* Set the human-readable name of the typelib */
461 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
463 if (RegSetValueExW(key, NULL, 0, REG_SZ,
464 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
472 /* Make up the name of the typelib path subkey */
473 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
475 /* Create the typelib path subkey */
476 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
477 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
479 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
480 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
488 /* Create the flags subkey */
489 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
490 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
492 /* FIXME: is %u correct? */
493 static const WCHAR formatW[] = {'%','u',0};
495 sprintfW(buf, formatW, attr->wLibFlags);
496 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
497 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
505 /* create the helpdir subkey */
506 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
507 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
509 BOOL freeHelpDir = FALSE;
512 /* if we created a new key, and helpDir was null, set the helpdir
513 to the directory which contains the typelib. However,
514 if we just opened an existing key, we leave the helpdir alone */
515 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
516 szHelpDir = SysAllocString(szFullPath);
517 pIndexStr = strrchrW(szHelpDir, '\\');
524 /* if we have an szHelpDir, set it! */
525 if (szHelpDir != NULL) {
526 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
527 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
533 if (freeHelpDir) SysFreeString(szHelpDir);
545 /* register OLE Automation-compatible interfaces for this typelib */
546 types = ITypeLib_GetTypeInfoCount(ptlib);
547 for (tidx=0; tidx<types; tidx++) {
548 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
549 LPOLESTR name = NULL;
550 ITypeInfo *tinfo = NULL;
552 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
555 case TKIND_INTERFACE:
556 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
557 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
561 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
562 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
566 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
571 TYPEATTR *tattr = NULL;
572 ITypeInfo_GetTypeAttr(tinfo, &tattr);
575 TRACE_(typelib)("guid=%s, flags=%04x (",
576 debugstr_guid(&tattr->guid),
579 if (TRACE_ON(typelib)) {
580 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
600 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL|TYPEFLAG_FDISPATCHABLE))
602 /* register interface<->typelib coupling */
603 get_interface_key( &tattr->guid, keyName );
604 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
605 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
608 RegSetValueExW(key, NULL, 0, REG_SZ,
609 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
611 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
612 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
613 RegSetValueExW(subKey, NULL, 0, REG_SZ,
614 (BYTE*)PSOA, sizeof PSOA);
618 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
619 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
620 RegSetValueExW(subKey, NULL, 0, REG_SZ,
621 (BYTE*)PSOA, sizeof PSOA);
625 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
626 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
629 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
630 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
632 StringFromGUID2(&attr->guid, buffer, 40);
633 RegSetValueExW(subKey, NULL, 0, REG_SZ,
634 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
635 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
636 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
637 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
645 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
648 ITypeInfo_Release(tinfo);
655 ITypeLib_ReleaseTLibAttr(ptlib, attr);
661 /******************************************************************************
662 * UnRegisterTypeLib [OLEAUT32.186]
663 * Removes information about a type library from the System Registry
670 HRESULT WINAPI UnRegisterTypeLib(
671 REFGUID libid, /* [in] Guid of the library */
672 WORD wVerMajor, /* [in] major version */
673 WORD wVerMinor, /* [in] minor version */
674 LCID lcid, /* [in] locale id */
677 BSTR tlibPath = NULL;
680 WCHAR subKeyName[50];
683 BOOL deleteOtherStuff;
686 TYPEATTR* typeAttr = NULL;
688 ITypeInfo* typeInfo = NULL;
689 ITypeLib* typeLib = NULL;
692 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
694 /* Create the path to the key */
695 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
697 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
699 TRACE("Unsupported syskind %i\n", syskind);
700 result = E_INVALIDARG;
704 /* get the path to the typelib on disk */
705 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
706 result = E_INVALIDARG;
710 /* Try and open the key to the type library. */
711 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
712 result = E_INVALIDARG;
716 /* Try and load the type library */
717 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
718 result = TYPE_E_INVALIDSTATE;
722 /* remove any types registered with this typelib */
723 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
724 for (i=0; i<numTypes; i++) {
725 /* get the kind of type */
726 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
730 /* skip non-interfaces, and get type info for the type */
731 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
734 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
737 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
741 /* the path to the type */
742 get_interface_key( &typeAttr->guid, subKeyName );
744 /* Delete its bits */
745 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
748 RegDeleteKeyW(subKey, ProxyStubClsidW);
749 RegDeleteKeyW(subKey, ProxyStubClsid32W);
750 RegDeleteKeyW(subKey, TypeLibW);
753 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
756 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
758 if (typeInfo) ITypeInfo_Release(typeInfo);
762 /* Now, delete the type library path subkey */
763 get_lcid_subkey( lcid, syskind, subKeyName );
764 RegDeleteKeyW(key, subKeyName);
765 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
766 RegDeleteKeyW(key, subKeyName);
768 /* check if there is anything besides the FLAGS/HELPDIR keys.
769 If there is, we don't delete them */
770 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
771 deleteOtherStuff = TRUE;
773 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
774 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
776 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
777 if (!strcmpW(subKeyName, FLAGSW)) continue;
778 if (!strcmpW(subKeyName, HELPDIRW)) continue;
779 deleteOtherStuff = FALSE;
783 /* only delete the other parts of the key if we're absolutely sure */
784 if (deleteOtherStuff) {
785 RegDeleteKeyW(key, FLAGSW);
786 RegDeleteKeyW(key, HELPDIRW);
790 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
791 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
792 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
796 if (tlibPath) SysFreeString(tlibPath);
797 if (typeLib) ITypeLib_Release(typeLib);
798 if (subKey) RegCloseKey(subKey);
799 if (key) RegCloseKey(key);
803 /*======================= ITypeLib implementation =======================*/
805 typedef struct tagTLBCustData
809 struct tagTLBCustData* next;
812 /* data structure for import typelibs */
813 typedef struct tagTLBImpLib
815 int offset; /* offset in the file (MSFT)
816 offset in nametable (SLTG)
817 just used to identify library while reading
819 GUID guid; /* libid */
820 BSTR name; /* name */
822 LCID lcid; /* lcid of imported typelib */
824 WORD wVersionMajor; /* major version number */
825 WORD wVersionMinor; /* minor version number */
827 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
828 NULL if not yet loaded */
829 struct tagTLBImpLib * next;
832 /* internal ITypeLib data */
833 typedef struct tagITypeLibImpl
835 const ITypeLib2Vtbl *lpVtbl;
836 const ITypeCompVtbl *lpVtblTypeComp;
838 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
840 /* strings can be stored in tlb as multibyte strings BUT they are *always*
841 * exported to the application as a UNICODE string.
847 unsigned long dwHelpContext;
848 int TypeInfoCount; /* nr of typeinfo's in librarry */
849 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
850 int ctCustData; /* number of items in cust data list */
851 TLBCustData * pCustData; /* linked list to cust data */
852 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
853 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
854 libary. Only used while read MSFT
857 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
858 struct tagITypeLibImpl *next, *prev;
863 static const ITypeLib2Vtbl tlbvt;
864 static const ITypeCompVtbl tlbtcvt;
866 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
868 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
871 /* ITypeLib methods */
872 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
873 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
875 /*======================= ITypeInfo implementation =======================*/
877 /* data for referenced types */
878 typedef struct tagTLBRefType
880 INT index; /* Type index for internal ref or for external ref
881 it the format is SLTG. -2 indicates to
884 GUID guid; /* guid of the referenced type */
885 /* if index == TLB_REF_USE_GUID */
887 HREFTYPE reference; /* The href of this ref */
888 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
889 TLB_REF_INTERNAL for internal refs
890 TLB_REF_NOT_FOUND for broken refs */
892 struct tagTLBRefType * next;
895 #define TLB_REF_USE_GUID -2
897 #define TLB_REF_INTERNAL (void*)-2
898 #define TLB_REF_NOT_FOUND (void*)-1
900 /* internal Parameter data */
901 typedef struct tagTLBParDesc
905 TLBCustData * pCustData; /* linked list to cust data */
908 /* internal Function data */
909 typedef struct tagTLBFuncDesc
911 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
912 BSTR Name; /* the name of this function */
913 TLBParDesc *pParamDesc; /* array with param names and custom data */
915 int HelpStringContext;
917 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
919 TLBCustData * pCustData; /* linked list to cust data; */
920 struct tagTLBFuncDesc * next;
923 /* internal Variable data */
924 typedef struct tagTLBVarDesc
926 VARDESC vardesc; /* lots of info on the variable and its attributes. */
927 BSTR Name; /* the name of this variable */
929 int HelpStringContext; /* FIXME: where? */
932 TLBCustData * pCustData;/* linked list to cust data; */
933 struct tagTLBVarDesc * next;
936 /* internal implemented interface data */
937 typedef struct tagTLBImplType
939 HREFTYPE hRef; /* hRef of interface */
940 int implflags; /* IMPLFLAG_*s */
942 TLBCustData * pCustData;/* linked list to custom data; */
943 struct tagTLBImplType *next;
946 /* internal TypeInfo data */
947 typedef struct tagITypeInfoImpl
949 const ITypeInfo2Vtbl *lpVtbl;
950 const ITypeCompVtbl *lpVtblTypeComp;
952 TYPEATTR TypeAttr ; /* _lots_ of type information. */
953 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
954 int index; /* index in this typelib; */
955 HREFTYPE hreftype; /* hreftype for app object binding */
956 /* type libs seem to store the doc strings in ascii
957 * so why should we do it in unicode?
962 unsigned long dwHelpContext;
963 unsigned long dwHelpStringContext;
966 TLBFuncDesc * funclist; /* linked list with function descriptions */
969 TLBVarDesc * varlist; /* linked list with variable descriptions */
971 /* Implemented Interfaces */
972 TLBImplType * impltypelist;
974 TLBRefType * reflist;
976 TLBCustData * pCustData; /* linked list to cust data; */
977 struct tagITypeInfoImpl * next;
980 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
982 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
985 static const ITypeInfo2Vtbl tinfvt;
986 static const ITypeCompVtbl tcompvt;
988 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
990 typedef struct tagTLBContext
992 unsigned int oStart; /* start of TLB in file */
993 unsigned int pos; /* current pos */
994 unsigned int length; /* total length */
995 void *mapping; /* memory mapping */
996 MSFT_SegDir * pTblDir;
997 ITypeLibImpl* pLibInfo;
1001 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1006 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1007 if (pTD->vt & VT_RESERVED)
1008 szVarType += strlen(strcpy(szVarType, "reserved | "));
1009 if (pTD->vt & VT_BYREF)
1010 szVarType += strlen(strcpy(szVarType, "ref to "));
1011 if (pTD->vt & VT_ARRAY)
1012 szVarType += strlen(strcpy(szVarType, "array of "));
1013 if (pTD->vt & VT_VECTOR)
1014 szVarType += strlen(strcpy(szVarType, "vector of "));
1015 switch(pTD->vt & VT_TYPEMASK) {
1016 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1017 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1018 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1019 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1020 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1021 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1022 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1023 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1024 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1025 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1026 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1027 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1028 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1029 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1030 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1031 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1032 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1033 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1034 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1035 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1036 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1037 pTD->u.hreftype); break;
1038 case VT_PTR: sprintf(szVarType, "ptr to ");
1039 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1041 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1042 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1044 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1045 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1046 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1049 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1053 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1055 USHORT flags = edesc->u.paramdesc.wParamFlags;
1056 dump_TypeDesc(&edesc->tdesc,buf);
1057 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1058 MESSAGE("\t\tu.paramdesc.wParamFlags");
1059 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1060 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1061 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1062 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1063 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1064 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1065 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1066 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1067 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1069 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1071 MESSAGE("memid is %08lx\n",funcdesc->memid);
1072 for (i=0;i<funcdesc->cParams;i++) {
1073 MESSAGE("Param %d:\n",i);
1074 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1076 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1077 switch (funcdesc->funckind) {
1078 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1079 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1080 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1081 case FUNC_STATIC: MESSAGE("static");break;
1082 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1083 default: MESSAGE("unknown");break;
1085 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1086 switch (funcdesc->invkind) {
1087 case INVOKE_FUNC: MESSAGE("func");break;
1088 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1089 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1090 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1092 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1093 switch (funcdesc->callconv) {
1094 case CC_CDECL: MESSAGE("cdecl");break;
1095 case CC_PASCAL: MESSAGE("pascal");break;
1096 case CC_STDCALL: MESSAGE("stdcall");break;
1097 case CC_SYSCALL: MESSAGE("syscall");break;
1100 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1101 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1102 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1104 MESSAGE("\telemdescFunc (return value type):\n");
1105 dump_ELEMDESC(&funcdesc->elemdescFunc);
1108 static const char * typekind_desc[] =
1121 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1124 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1125 for (i=0;i<pfd->funcdesc.cParams;i++)
1126 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1129 dump_FUNCDESC(&(pfd->funcdesc));
1131 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1132 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1134 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1138 dump_TLBFuncDescOne(pfd);
1142 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1146 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1151 static void dump_TLBImpLib(const TLBImpLib *import)
1153 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1154 debugstr_w(import->name));
1155 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1156 import->wVersionMinor, import->lcid, import->offset);
1159 static void dump_TLBRefType(const TLBRefType * prt)
1163 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1164 if(prt->index == -1)
1165 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1167 TRACE_(typelib)("type no: %d\n", prt->index);
1169 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1170 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1171 TRACE_(typelib)("in lib\n");
1172 dump_TLBImpLib(prt->pImpTLInfo);
1178 static void dump_TLBImplType(const TLBImplType * impl)
1182 "implementing/inheriting interface hRef = %lx implflags %x\n",
1183 impl->hRef, impl->implflags);
1188 void dump_Variant(const VARIANT * pvar)
1192 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1196 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1197 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1199 TRACE(",%p", V_BYREF(pvar));
1201 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1203 TRACE(",%p", V_ARRAY(pvar));
1205 else switch (V_TYPE(pvar))
1207 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1208 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1209 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1210 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1212 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1214 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1215 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1216 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1217 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1218 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1219 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1220 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1221 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1222 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1223 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1224 V_CY(pvar).s.Lo); break;
1226 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1227 TRACE(",<invalid>");
1229 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1230 st.wHour, st.wMinute, st.wSecond);
1234 case VT_USERDEFINED:
1236 case VT_NULL: break;
1237 default: TRACE(",?"); break;
1243 static void dump_DispParms(const DISPPARAMS * pdp)
1247 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1249 if (pdp->cNamedArgs)
1250 TRACE("named args:\n");
1251 for (index = 0; index < pdp->cNamedArgs; index++)
1252 TRACE( "\t0x%lx\n", pdp->rgdispidNamedArgs[index] );
1256 for (index = 0; index < pdp->cArgs; index++)
1257 dump_Variant( &pdp->rgvarg[index] );
1260 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1262 TRACE("%p ref=%lu\n", pty, pty->ref);
1263 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1264 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1265 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1266 TRACE("fct:%u var:%u impl:%u\n",
1267 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1268 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1269 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1270 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1272 dump_TLBFuncDesc(pty->funclist);
1273 dump_TLBVarDesc(pty->varlist);
1274 dump_TLBImplType(pty->impltypelist);
1277 static void dump_VARDESC(const VARDESC *v)
1279 MESSAGE("memid %ld\n",v->memid);
1280 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1281 MESSAGE("oInst %ld\n",v->u.oInst);
1282 dump_ELEMDESC(&(v->elemdescVar));
1283 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1284 MESSAGE("varkind %d\n",v->varkind);
1287 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1289 /* VT_LPWSTR is largest type that */
1290 /* may appear in type description*/
1291 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1292 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1293 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1294 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1295 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1296 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1300 static void TLB_abort(void)
1304 static void * TLB_Alloc(unsigned size)
1307 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1309 ERR("cannot allocate memory\n");
1314 static void TLB_Free(void * ptr)
1316 HeapFree(GetProcessHeap(), 0, ptr);
1319 /* returns the size required for a deep copy of a typedesc into a
1321 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1325 if (alloc_initial_space)
1326 size += sizeof(TYPEDESC);
1332 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1335 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1336 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1342 /* deep copy a typedesc into a flat buffer */
1343 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1348 buffer = (char *)buffer + sizeof(TYPEDESC);
1357 dest->u.lptdesc = buffer;
1358 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1361 dest->u.lpadesc = buffer;
1362 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1363 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1364 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1370 /**********************************************************************
1372 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1374 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1379 static inline void MSFT_Seek(TLBContext *pcx, long where)
1381 if (where != DO_NOT_SEEK)
1383 where += pcx->oStart;
1384 if (where > pcx->length)
1387 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1395 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1397 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1398 pcx->pos, count, pcx->oStart, pcx->length, where);
1400 MSFT_Seek(pcx, where);
1401 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1402 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1407 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1412 ret = MSFT_Read(buffer, count, pcx, where);
1413 FromLEDWords(buffer, ret);
1418 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1423 ret = MSFT_Read(buffer, count, pcx, where);
1424 FromLEWords(buffer, ret);
1429 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1431 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1432 memset(pGuid,0, sizeof(GUID));
1435 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1436 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1437 pGuid->Data2 = FromLEWord(pGuid->Data2);
1438 pGuid->Data3 = FromLEWord(pGuid->Data3);
1439 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1442 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1444 MSFT_NameIntro niName;
1448 ERR_(typelib)("bad offset %d\n", offset);
1452 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1453 pcx->pTblDir->pNametab.offset+offset);
1455 return niName.hreftype;
1458 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1461 MSFT_NameIntro niName;
1463 WCHAR* pwstring = NULL;
1464 BSTR bstrName = NULL;
1468 ERR_(typelib)("bad offset %d\n", offset);
1471 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1472 pcx->pTblDir->pNametab.offset+offset);
1473 niName.namelen &= 0xFF; /* FIXME: correct ? */
1474 name=TLB_Alloc((niName.namelen & 0xff) +1);
1475 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1476 name[niName.namelen & 0xff]='\0';
1478 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1481 /* no invalid characters in string */
1484 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1486 /* don't check for invalid character since this has been done previously */
1487 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1489 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1490 lengthInChars = SysStringLen(bstrName);
1491 HeapFree(GetProcessHeap(), 0, pwstring);
1494 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1498 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1505 if(offset<0) return NULL;
1506 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1507 if(length <= 0) return 0;
1508 string=TLB_Alloc(length +1);
1509 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1510 string[length]='\0';
1512 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1513 string, -1, NULL, 0);
1515 /* no invalid characters in string */
1518 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1520 /* don't check for invalid character since this has been done previously */
1521 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1523 bstr = SysAllocStringLen(pwstring, lengthInChars);
1524 lengthInChars = SysStringLen(bstr);
1525 HeapFree(GetProcessHeap(), 0, pwstring);
1528 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1532 * read a value and fill a VARIANT structure
1534 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1538 TRACE_(typelib)("\n");
1540 if(offset <0) { /* data are packed in here */
1541 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1542 V_I4(pVar) = offset & 0x3ffffff;
1545 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1546 pcx->pTblDir->pCustData.offset + offset );
1547 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1548 switch (V_VT(pVar)){
1549 case VT_EMPTY: /* FIXME: is this right? */
1550 case VT_NULL: /* FIXME: is this right? */
1551 case VT_I2 : /* this should not happen */
1562 case VT_VOID : /* FIXME: is this right? */
1570 case VT_DECIMAL : /* FIXME: is this right? */
1573 /* pointer types with known behaviour */
1576 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1579 DWORD origPos = MSFT_Tell(pcx), nullPos;
1582 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1584 nullPos = MSFT_Tell(pcx);
1585 size = nullPos - origPos;
1586 MSFT_Seek(pcx, origPos);
1588 ptr=TLB_Alloc(size);/* allocate temp buffer */
1589 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1590 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1591 /* FIXME: do we need a AtoW conversion here? */
1592 V_UNION(pVar, bstrVal[size])=L'\0';
1593 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1597 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1604 case VT_USERDEFINED :
1610 case VT_STREAMED_OBJECT :
1611 case VT_STORED_OBJECT :
1612 case VT_BLOB_OBJECT :
1617 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1621 if(size>0) /* (big|small) endian correct? */
1622 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1626 * create a linked list with custom data
1628 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1634 TRACE_(typelib)("\n");
1638 pNew=TLB_Alloc(sizeof(TLBCustData));
1639 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1640 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1641 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1642 /* add new custom data at head of the list */
1643 pNew->next=*ppCustData;
1645 offset = entry.next;
1650 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1654 pTd->vt=type & VT_TYPEMASK;
1656 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1658 if(pTd->vt == VT_USERDEFINED)
1659 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1661 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1664 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1666 /* resolve referenced type if any */
1669 switch (lpTypeDesc->vt)
1672 lpTypeDesc = lpTypeDesc->u.lptdesc;
1676 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1679 case VT_USERDEFINED:
1680 MSFT_DoRefType(pcx, pTI,
1681 lpTypeDesc->u.hreftype);
1693 MSFT_DoFuncs(TLBContext* pcx,
1698 TLBFuncDesc** pptfd)
1701 * member information is stored in a data structure at offset
1702 * indicated by the memoffset field of the typeinfo structure
1703 * There are several distinctive parts.
1704 * The first part starts with a field that holds the total length
1705 * of this (first) part excluding this field. Then follow the records,
1706 * for each member there is one record.
1708 * The first entry is always the length of the record (including this
1710 * The rest of the record depends on the type of the member. If there is
1711 * a field indicating the member type (function, variable, interface, etc)
1712 * I have not found it yet. At this time we depend on the information
1713 * in the type info and the usual order how things are stored.
1715 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1718 * Third is an equal sized array with file offsets to the name entry
1721 * The fourth and last (?) part is an array with offsets to the records
1722 * in the first part of this file segment.
1725 int infolen, nameoffset, reclength, nrattributes, i;
1726 int recoffset = offset + sizeof(INT);
1728 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1729 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1730 TLBFuncDesc *ptfd_prev = NULL;
1732 TRACE_(typelib)("\n");
1734 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1736 for ( i = 0; i < cFuncs ; i++ )
1738 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1740 /* name, eventually add to a hash table */
1741 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1742 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1744 /* nameoffset is sometimes -1 on the second half of a propget/propput
1745 * pair of functions */
1746 if ((nameoffset == -1) && (i > 0))
1747 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1749 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1751 /* read the function information record */
1752 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1754 reclength &= 0xffff;
1756 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1758 /* do the attributes */
1759 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1762 if ( nrattributes > 0 )
1764 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1766 if ( nrattributes > 1 )
1768 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1769 pFuncRec->OptAttr[1]) ;
1771 if ( nrattributes > 2 )
1773 if ( pFuncRec->FKCCIC & 0x2000 )
1775 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1779 (*pptfd)->Entry = MSFT_ReadString(pcx,
1780 pFuncRec->OptAttr[2]);
1782 if( nrattributes > 5 )
1784 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1786 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1789 pFuncRec->OptAttr[6],
1790 &(*pptfd)->pCustData);
1797 /* fill the FuncDesc Structure */
1798 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1799 offset + infolen + ( i + 1) * sizeof(INT));
1801 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1802 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1803 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1804 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1805 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1806 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1807 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1811 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1813 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1815 /* do the parameters/arguments */
1816 if(pFuncRec->nrargs)
1819 MSFT_ParameterInfo paraminfo;
1821 (*pptfd)->funcdesc.lprgelemdescParam =
1822 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1824 (*pptfd)->pParamDesc =
1825 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1827 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1828 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1830 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1832 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1839 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1842 if (paraminfo.oName == -1)
1843 /* this occurs for [propput] or [propget] methods, so
1844 * we should just set the name of the parameter to the
1845 * name of the method. */
1846 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1848 (*pptfd)->pParamDesc[j].Name =
1849 MSFT_ReadName( pcx, paraminfo.oName );
1850 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1852 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1855 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1856 (pFuncRec->FKCCIC & 0x1000) )
1858 INT* pInt = (INT *)((char *)pFuncRec +
1860 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1862 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1864 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1865 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1867 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1871 elemdesc->u.paramdesc.pparamdescex = NULL;
1873 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1876 pFuncRec->OptAttr[7+j],
1877 &(*pptfd)->pParamDesc[j].pCustData);
1880 /* SEEK value = jump to offset,
1881 * from there jump to the end of record,
1882 * go back by (j-1) arguments
1884 MSFT_ReadLEDWords( ¶minfo ,
1885 sizeof(MSFT_ParameterInfo), pcx,
1886 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1887 * sizeof(MSFT_ParameterInfo)));
1891 /* scode is not used: archaic win16 stuff FIXME: right? */
1892 (*pptfd)->funcdesc.cScodes = 0 ;
1893 (*pptfd)->funcdesc.lprgscode = NULL ;
1896 pptfd = & ((*pptfd)->next);
1897 recoffset += reclength;
1899 HeapFree(GetProcessHeap(), 0, recbuf);
1902 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1903 int cVars, int offset, TLBVarDesc ** pptvd)
1905 int infolen, nameoffset, reclength;
1907 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1911 TRACE_(typelib)("\n");
1913 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1914 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1915 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1916 recoffset += offset+sizeof(INT);
1917 for(i=0;i<cVars;i++){
1918 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1919 /* name, eventually add to a hash table */
1920 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1921 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1922 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1923 /* read the variable information record */
1924 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1926 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1928 if(reclength >(6*sizeof(INT)) )
1929 (*pptvd)->HelpContext=pVarRec->HelpContext;
1930 if(reclength >(7*sizeof(INT)) )
1931 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1932 if(reclength >(8*sizeof(INT)) )
1933 if(reclength >(9*sizeof(INT)) )
1934 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1935 /* fill the VarDesc Structure */
1936 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1937 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1938 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1939 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1940 MSFT_GetTdesc(pcx, pVarRec->DataType,
1941 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1942 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1943 if(pVarRec->VarKind == VAR_CONST ){
1944 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1945 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1946 pVarRec->OffsValue, pcx);
1948 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1949 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1950 pptvd=&((*pptvd)->next);
1951 recoffset += reclength;
1954 /* fill in data for a hreftype (offset). When the referenced type is contained
1955 * in the typelib, it's just an (file) offset in the type info base dir.
1956 * If comes from import, it's an offset+1 in the ImpInfo table
1958 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1962 TLBRefType **ppRefType = &pTI->reflist;
1964 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1967 if((*ppRefType)->reference == offset)
1969 ppRefType = &(*ppRefType)->next;
1972 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1973 sizeof(**ppRefType));
1975 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1976 /* external typelib */
1977 MSFT_ImpInfo impinfo;
1978 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1980 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1982 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1983 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1984 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1985 if(pImpLib->offset==impinfo.oImpFile) break;
1986 pImpLib=pImpLib->next;
1989 (*ppRefType)->reference=offset;
1990 (*ppRefType)->pImpTLInfo = pImpLib;
1991 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1992 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1993 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
1994 (*ppRefType)->index = TLB_REF_USE_GUID;
1996 (*ppRefType)->index = impinfo.oGuid;
1998 ERR("Cannot find a reference\n");
1999 (*ppRefType)->reference=-1;
2000 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2003 /* in this typelib */
2004 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2005 (*ppRefType)->reference=offset;
2006 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2010 /* process Implemented Interfaces of a com class */
2011 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2015 MSFT_RefRecord refrec;
2016 TLBImplType **ppImpl = &pTI->impltypelist;
2018 TRACE_(typelib)("\n");
2020 for(i=0;i<count;i++){
2021 if(offset<0) break; /* paranoia */
2022 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2023 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2024 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2025 (*ppImpl)->hRef = refrec.reftype;
2026 (*ppImpl)->implflags=refrec.flags;
2027 (*ppImpl)->ctCustData=
2028 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2029 offset=refrec.onext;
2030 ppImpl=&((*ppImpl)->next);
2034 * process a typeinfo record
2036 static ITypeInfoImpl * MSFT_DoTypeInfo(
2040 ITypeLibImpl * pLibInfo)
2042 MSFT_TypeInfoBase tiBase;
2043 ITypeInfoImpl *ptiRet;
2045 TRACE_(typelib)("count=%u\n", count);
2047 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2048 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2049 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2051 /* this is where we are coming from */
2052 ptiRet->pTypeLib = pLibInfo;
2053 ptiRet->index=count;
2054 /* fill in the typeattr fields */
2056 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2057 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2058 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2059 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2060 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2061 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2062 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2063 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2064 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2065 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2066 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2067 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2068 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2069 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2070 MSFT_GetTdesc(pcx, tiBase.datatype1,
2071 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2074 /* IDLDESC idldescType; *//* never saw this one != zero */
2076 /* name, eventually add to a hash table */
2077 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2078 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2079 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2081 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2082 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2083 ptiRet->dwHelpContext=tiBase.helpcontext;
2085 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2086 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2088 /* note: InfoType's Help file and HelpStringDll come from the containing
2089 * library. Further HelpString and Docstring appear to be the same thing :(
2092 if(ptiRet->TypeAttr.cFuncs >0 )
2093 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2094 ptiRet->TypeAttr.cVars,
2095 tiBase.memoffset, & ptiRet->funclist);
2097 if(ptiRet->TypeAttr.cVars >0 )
2098 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2099 ptiRet->TypeAttr.cVars,
2100 tiBase.memoffset, & ptiRet->varlist);
2101 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2102 switch(ptiRet->TypeAttr.typekind)
2105 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2108 case TKIND_DISPATCH:
2109 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2111 if (tiBase.datatype1 != -1)
2113 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2114 ptiRet->impltypelist->hRef = tiBase.datatype1;
2118 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2119 ptiRet->impltypelist->hRef = dispatch_href;
2123 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2124 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2125 ptiRet->impltypelist->hRef = tiBase.datatype1;
2130 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2132 TRACE_(typelib)("%s guid: %s kind:%s\n",
2133 debugstr_w(ptiRet->Name),
2134 debugstr_guid(&ptiRet->TypeAttr.guid),
2135 typekind_desc[ptiRet->TypeAttr.typekind]);
2140 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2141 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2142 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2145 static ITypeLibImpl *tlb_cache_first;
2146 static CRITICAL_SECTION cache_section;
2147 static CRITICAL_SECTION_DEBUG cache_section_debug =
2149 0, 0, &cache_section,
2150 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2151 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2153 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2156 /****************************************************************************
2159 * find the type of the typelib file and map the typelib resource into
2162 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2163 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2164 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2166 ITypeLibImpl *entry;
2167 int ret = TYPE_E_CANTLOADLIBRARY;
2173 lstrcpynW(pszPath, pszFileName, cchPath);
2175 /* first try loading as a dll and access the typelib as a resource */
2176 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2177 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2180 /* it may have been specified with resource index appended to the
2181 * path, so remove it and try again */
2182 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2183 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2185 index = atoiW(pIndexStr);
2186 pszPath[pIndexStr - pszFileName - 1] = '\0';
2188 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2189 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2193 /* get the path to the specified typelib file */
2196 /* otherwise, try loading as a regular file */
2197 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2198 return TYPE_E_CANTLOADLIBRARY;
2201 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2203 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2204 EnterCriticalSection(&cache_section);
2205 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2207 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2209 TRACE("cache hit\n");
2210 *ppTypeLib = (ITypeLib2*)entry;
2211 ITypeLib_AddRef(*ppTypeLib);
2212 LeaveCriticalSection(&cache_section);
2216 LeaveCriticalSection(&cache_section);
2218 /* now actually load and parse the typelib */
2221 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2222 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2225 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2228 LPVOID pBase = LockResource(hGlobal);
2229 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2233 /* try to load as incore resource */
2234 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2235 if (dwSignature == MSFT_SIGNATURE)
2236 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2237 else if (dwSignature == SLTG_SIGNATURE)
2238 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2240 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2242 FreeResource( hGlobal );
2245 FreeLibrary(hinstDLL);
2249 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2250 if (INVALID_HANDLE_VALUE != hFile)
2252 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2255 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2258 /* retrieve file size */
2259 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2260 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2262 if (dwSignature == MSFT_SIGNATURE)
2263 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2264 else if (dwSignature == SLTG_SIGNATURE)
2265 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2267 UnmapViewOfFile(pBase);
2269 CloseHandle(hMapping);
2276 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2278 TRACE("adding to cache\n");
2279 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2280 lstrcpyW(impl->path, pszPath);
2281 /* We should really canonicalise the path here. */
2282 impl->index = index;
2284 /* FIXME: check if it has added already in the meantime */
2285 EnterCriticalSection(&cache_section);
2286 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2288 tlb_cache_first = impl;
2289 LeaveCriticalSection(&cache_section);
2292 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2297 /*================== ITypeLib(2) Methods ===================================*/
2299 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2301 ITypeLibImpl* pTypeLibImpl;
2303 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2304 if (!pTypeLibImpl) return NULL;
2306 pTypeLibImpl->lpVtbl = &tlbvt;
2307 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2308 pTypeLibImpl->ref = 1;
2310 return pTypeLibImpl;
2313 /****************************************************************************
2314 * ITypeLib2_Constructor_MSFT
2316 * loading an MSFT typelib from an in-memory image
2318 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2322 MSFT_Header tlbHeader;
2323 MSFT_SegDir tlbSegDir;
2324 ITypeLibImpl * pTypeLibImpl;
2326 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2328 pTypeLibImpl = TypeLibImpl_Constructor();
2329 if (!pTypeLibImpl) return NULL;
2331 /* get pointer to beginning of typelib data */
2335 cx.pLibInfo = pTypeLibImpl;
2336 cx.length = dwTLBLength;
2339 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2340 TRACE_(typelib)("header:\n");
2341 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2342 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2343 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2346 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2348 /* there is a small amount of information here until the next important
2350 * the segment directory . Try to calculate the amount of data */
2351 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2353 /* now read the segment directory */
2354 TRACE("read segment directory (at %ld)\n",lPSegDir);
2355 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2356 cx.pTblDir = &tlbSegDir;
2358 /* just check two entries */
2359 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2361 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2362 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2366 /* now fill our internal data */
2367 /* TLIBATTR fields */
2368 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2370 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2371 /* Windows seems to have zero here, is this correct? */
2372 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2373 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2375 pTypeLibImpl->LibAttr.lcid = 0;
2377 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2378 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2379 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2380 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2382 /* name, eventually add to a hash table */
2383 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2386 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2387 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2389 if( tlbHeader.varflags & HELPDLLFLAG)
2392 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2393 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2396 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2399 if(tlbHeader.CustomDataOffset >= 0)
2401 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2404 /* fill in typedescriptions */
2405 if(tlbSegDir.pTypdescTab.length > 0)
2407 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2409 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2410 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2413 /* FIXME: add several sanity checks here */
2414 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2415 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2417 /* FIXME: check safearray */
2419 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2421 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2423 else if(td[0] == VT_CARRAY)
2425 /* array descr table here */
2426 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2428 else if(td[0] == VT_USERDEFINED)
2430 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2432 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2435 /* second time around to fill the array subscript info */
2438 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2439 if(tlbSegDir.pArrayDescriptions.offset>0)
2441 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2442 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2445 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2447 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2449 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2451 for(j = 0; j<td[2]; j++)
2453 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2454 sizeof(INT), &cx, DO_NOT_SEEK);
2455 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2456 sizeof(INT), &cx, DO_NOT_SEEK);
2461 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2462 ERR("didn't find array description data\n");
2467 /* imported type libs */
2468 if(tlbSegDir.pImpFiles.offset>0)
2470 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2471 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2474 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2479 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2480 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2481 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2483 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2484 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2485 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2486 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2489 name = TLB_Alloc(size+1);
2490 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2491 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2492 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2493 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2496 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2497 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2499 ppImpLib = &(*ppImpLib)->next;
2504 if(tlbHeader.nrtypeinfos >= 0 )
2506 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2507 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2510 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2512 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2514 ppTI = &((*ppTI)->next);
2515 (pTypeLibImpl->TypeInfoCount)++;
2519 TRACE("(%p)\n", pTypeLibImpl);
2520 return (ITypeLib2*) pTypeLibImpl;
2524 static BSTR TLB_MultiByteToBSTR(char *ptr)
2530 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2531 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2532 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2533 ret = SysAllocString(nameW);
2534 HeapFree(GetProcessHeap(), 0, nameW);
2538 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2544 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2545 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2549 guid->Data4[0] = s >> 8;
2550 guid->Data4[1] = s & 0xff;
2553 for(i = 0; i < 6; i++) {
2554 memcpy(b, str + 24 + 2 * i, 2);
2555 guid->Data4[i + 2] = strtol(b, NULL, 16);
2560 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2567 bytelen = *(WORD*)ptr;
2568 if(bytelen == 0xffff) return 2;
2569 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2570 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2571 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2572 *pBstr = SysAllocStringLen(nameW, len);
2573 HeapFree(GetProcessHeap(), 0, nameW);
2577 static WORD SLTG_ReadStringA(char *ptr, char **str)
2582 bytelen = *(WORD*)ptr;
2583 if(bytelen == 0xffff) return 2;
2584 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2585 memcpy(*str, ptr + 2, bytelen);
2586 (*str)[bytelen] = '\0';
2590 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2592 char *ptr = pLibBlk;
2595 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2596 FIXME("libblk magic = %04x\n", w);
2601 if((w = *(WORD*)ptr) != 0xffff) {
2602 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2607 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2609 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2611 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2614 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2617 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2618 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2620 pTypeLibImpl->LibAttr.lcid = 0;
2623 ptr += 4; /* skip res12 */
2625 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2628 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2631 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2634 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2635 ptr += sizeof(GUID);
2637 return ptr - (char*)pLibBlk;
2640 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2645 if((*pType & 0xe00) == 0xe00) {
2647 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2649 pTD = pTD->u.lptdesc;
2651 switch(*pType & 0x3f) {
2654 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2656 pTD = pTD->u.lptdesc;
2659 case VT_USERDEFINED:
2660 pTD->vt = VT_USERDEFINED;
2661 pTD->u.hreftype = *(++pType) / 4;
2667 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2670 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2672 pTD->vt = VT_CARRAY;
2673 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2675 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2676 pTD->u.lpadesc->cDims = pSA->cDims;
2677 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2678 pSA->cDims * sizeof(SAFEARRAYBOUND));
2680 pTD = &pTD->u.lpadesc->tdescElem;
2686 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2690 pTD->vt = VT_SAFEARRAY;
2691 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2693 pTD = pTD->u.lptdesc;
2697 pTD->vt = *pType & 0x3f;
2706 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2708 /* Handle [in/out] first */
2709 if((*pType & 0xc000) == 0xc000)
2710 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2711 else if(*pType & 0x8000)
2712 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2713 else if(*pType & 0x4000)
2714 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2716 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2719 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2722 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2724 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2728 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2733 TLBRefType **ppRefType;
2735 if(pRef->magic != SLTG_REF_MAGIC) {
2736 FIXME("Ref magic = %x\n", pRef->magic);
2739 name = ( (char*)(&pRef->names) + pRef->number);
2741 ppRefType = &pTI->reflist;
2742 for(ref = 0; ref < pRef->number >> 3; ref++) {
2744 unsigned int lib_offs, type_num;
2746 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2747 sizeof(**ppRefType));
2749 name += SLTG_ReadStringA(name, &refname);
2750 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2751 FIXME("Can't sscanf ref\n");
2752 if(lib_offs != 0xffff) {
2753 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2756 if((*import)->offset == lib_offs)
2758 import = &(*import)->next;
2761 char fname[MAX_PATH+1];
2764 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2766 (*import)->offset = lib_offs;
2767 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2769 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2770 &(*import)->wVersionMajor,
2771 &(*import)->wVersionMinor,
2772 &(*import)->lcid, fname) != 4) {
2773 FIXME("can't sscanf ref %s\n",
2774 pNameTable + lib_offs + 40);
2776 len = strlen(fname);
2777 if(fname[len-1] != '#')
2778 FIXME("fname = %s\n", fname);
2779 fname[len-1] = '\0';
2780 (*import)->name = TLB_MultiByteToBSTR(fname);
2782 (*ppRefType)->pImpTLInfo = *import;
2783 } else { /* internal ref */
2784 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2786 (*ppRefType)->reference = ref;
2787 (*ppRefType)->index = type_num;
2789 HeapFree(GetProcessHeap(), 0, refname);
2790 ppRefType = &(*ppRefType)->next;
2792 if((BYTE)*name != SLTG_REF_MAGIC)
2793 FIXME("End of ref block magic = %x\n", *name);
2794 dump_TLBRefType(pTI->reflist);
2797 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2800 SLTG_ImplInfo *info;
2801 TLBImplType **ppImplType = &pTI->impltypelist;
2802 /* I don't really get this structure, usually it's 0x16 bytes
2803 long, but iuser.tlb contains some that are 0x18 bytes long.
2804 That's ok because we can use the next ptr to jump to the next
2805 one. But how do we know the length of the last one? The WORD
2806 at offs 0x8 might be the clue. For now I'm just assuming that
2807 the last one is the regular 0x16 bytes. */
2809 info = (SLTG_ImplInfo*)pBlk;
2811 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2812 sizeof(**ppImplType));
2813 (*ppImplType)->hRef = info->ref;
2814 (*ppImplType)->implflags = info->impltypeflags;
2815 pTI->TypeAttr.cImplTypes++;
2816 ppImplType = &(*ppImplType)->next;
2818 if(info->next == 0xffff)
2821 FIXME("Interface inheriting more than one interface\n");
2822 info = (SLTG_ImplInfo*)(pBlk + info->next);
2824 info++; /* see comment at top of function */
2828 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2830 TLBVarDesc **ppVarDesc = &pTI->varlist;
2831 BSTR bstrPrevName = NULL;
2832 SLTG_Variable *pItem;
2837 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2838 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2840 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2841 sizeof(**ppVarDesc));
2842 (*ppVarDesc)->vardesc.memid = pItem->memid;
2844 if (pItem->magic != SLTG_VAR_MAGIC &&
2845 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2846 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2850 if (pItem->name == 0xfffe)
2851 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2853 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2855 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2856 TRACE_(typelib)("memid = 0x%lx\n", pItem->memid);
2858 if (pItem->flags & 0x40) {
2859 TRACE_(typelib)("VAR_DISPATCH\n");
2860 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2862 else if (pItem->flags & 0x10) {
2863 TRACE_(typelib)("VAR_CONST\n");
2864 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2865 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2867 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2868 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2869 *(INT*)(pBlk + pItem->byte_offs);
2872 TRACE_(typelib)("VAR_PERINSTANCE\n");
2873 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2874 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2877 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2878 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2880 if (pItem->flags & 0x80)
2881 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2883 if(pItem->flags & 0x02)
2884 pType = &pItem->type;
2886 pType = (WORD*)(pBlk + pItem->type);
2888 if (pItem->flags & ~0xd2)
2889 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2891 SLTG_DoElem(pType, pBlk,
2892 &(*ppVarDesc)->vardesc.elemdescVar);
2894 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2896 bstrPrevName = (*ppVarDesc)->Name;
2897 ppVarDesc = &((*ppVarDesc)->next);
2899 pTI->TypeAttr.cVars = cVars;
2902 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2904 SLTG_Function *pFunc;
2906 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2908 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2909 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2914 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2915 sizeof(**ppFuncDesc));
2917 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2918 case SLTG_FUNCTION_MAGIC:
2919 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2921 case SLTG_DISPATCH_FUNCTION_MAGIC:
2922 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2924 case SLTG_STATIC_FUNCTION_MAGIC:
2925 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2928 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2929 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2933 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2935 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2936 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2937 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2938 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2939 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2940 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2942 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2943 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2945 if(pFunc->retnextopt & 0x80)
2946 pType = &pFunc->rettype;
2948 pType = (WORD*)(pBlk + pFunc->rettype);
2950 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2952 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2953 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2954 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2955 (*ppFuncDesc)->pParamDesc =
2956 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2957 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2959 pArg = (WORD*)(pBlk + pFunc->arg_off);
2961 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2962 char *paramName = pNameTable + *pArg;
2964 /* If arg type follows then paramName points to the 2nd
2965 letter of the name, else the next WORD is an offset to
2966 the arg type and paramName points to the first letter.
2967 So let's take one char off paramName and see if we're
2968 pointing at an alpha-numeric char. However if *pArg is
2969 0xffff or 0xfffe then the param has no name, the former
2970 meaning that the next WORD is the type, the latter
2971 meaning the the next WORD is an offset to the type. */
2976 else if(*pArg == 0xfffe) {
2980 else if(paramName[-1] && !isalnum(paramName[-1]))
2985 if(HaveOffs) { /* the next word is an offset to type */
2986 pType = (WORD*)(pBlk + *pArg);
2987 SLTG_DoElem(pType, pBlk,
2988 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2993 pArg = SLTG_DoElem(pArg, pBlk,
2994 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2997 /* Are we an optional param ? */
2998 if((*ppFuncDesc)->funcdesc.cParams - param <=
2999 (*ppFuncDesc)->funcdesc.cParamsOpt)
3000 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3003 (*ppFuncDesc)->pParamDesc[param].Name =
3004 TLB_MultiByteToBSTR(paramName);
3008 ppFuncDesc = &((*ppFuncDesc)->next);
3009 if(pFunc->next == 0xffff) break;
3011 pTI->TypeAttr.cFuncs = cFuncs;
3014 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3015 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3016 SLTG_TypeInfoTail *pTITail)
3018 char *pFirstItem, *pNextItem;
3020 if(pTIHeader->href_table != 0xffffffff) {
3021 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3025 pFirstItem = pNextItem = pBlk;
3027 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3028 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3033 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3034 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3035 SLTG_TypeInfoTail *pTITail)
3037 char *pFirstItem, *pNextItem;
3039 if(pTIHeader->href_table != 0xffffffff) {
3040 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3044 pFirstItem = pNextItem = pBlk;
3046 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3047 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3050 if (pTITail->funcs_off != 0xffff)
3051 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3053 if (TRACE_ON(typelib))
3054 dump_TLBFuncDesc(pTI->funclist);
3057 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3058 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3059 SLTG_TypeInfoTail *pTITail)
3061 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3064 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3065 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3066 SLTG_TypeInfoTail *pTITail)
3070 if (pTITail->simple_alias) {
3071 /* if simple alias, no more processing required */
3072 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3076 if(pTIHeader->href_table != 0xffffffff) {
3077 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3081 /* otherwise it is an offset to a type */
3082 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3084 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3087 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3088 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3089 SLTG_TypeInfoTail *pTITail)
3091 if (pTIHeader->href_table != 0xffffffff)
3092 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3095 if (pTITail->vars_off != 0xffff)
3096 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3098 if (pTITail->funcs_off != 0xffff)
3099 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3101 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3102 * of dispinterface functons including the IDispatch ones, so
3103 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3104 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3106 if (TRACE_ON(typelib))
3107 dump_TLBFuncDesc(pTI->funclist);
3110 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3111 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3112 SLTG_TypeInfoTail *pTITail)
3114 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3117 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3118 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3119 SLTG_TypeInfoTail *pTITail)
3121 if (pTIHeader->href_table != 0xffffffff)
3122 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3125 if (pTITail->vars_off != 0xffff)
3126 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3128 if (pTITail->funcs_off != 0xffff)
3129 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3132 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3133 managable copy of it into this */
3146 } SLTG_InternalOtherTypeInfo;
3148 /****************************************************************************
3149 * ITypeLib2_Constructor_SLTG
3151 * loading a SLTG typelib from an in-memory image
3153 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3155 ITypeLibImpl *pTypeLibImpl;
3156 SLTG_Header *pHeader;
3157 SLTG_BlkEntry *pBlkEntry;
3161 LPVOID pBlk, pFirstBlk;
3162 SLTG_LibBlk *pLibBlk;
3163 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3164 char *pAfterOTIBlks = NULL;
3165 char *pNameTable, *ptr;
3168 ITypeInfoImpl **ppTypeInfoImpl;
3170 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3173 pTypeLibImpl = TypeLibImpl_Constructor();
3174 if (!pTypeLibImpl) return NULL;
3178 TRACE_(typelib)("header:\n");
3179 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3180 pHeader->nrOfFileBlks );
3181 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3182 FIXME("Header type magic 0x%08lx not supported.\n",
3183 pHeader->SLTG_magic);
3187 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3188 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3190 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3191 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3193 /* Next we have a magic block */
3194 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3196 /* Let's see if we're still in sync */
3197 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3198 sizeof(SLTG_COMPOBJ_MAGIC))) {
3199 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3202 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3203 sizeof(SLTG_DIR_MAGIC))) {
3204 FIXME("dir magic = %s\n", pMagic->dir_magic);
3208 pIndex = (SLTG_Index*)(pMagic+1);
3210 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3212 pFirstBlk = (LPVOID)(pPad9 + 1);
3214 /* We'll set up a ptr to the main library block, which is the last one. */
3216 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3217 pBlkEntry[order].next != 0;
3218 order = pBlkEntry[order].next - 1, i++) {
3219 pBlk = (char*)pBlk + pBlkEntry[order].len;
3223 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3225 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3230 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3232 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3233 sizeof(*pOtherTypeInfoBlks) *
3234 pTypeLibImpl->TypeInfoCount);
3237 ptr = (char*)pLibBlk + len;
3239 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3243 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3245 w = *(WORD*)(ptr + 2);
3248 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3250 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3251 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3253 w = *(WORD*)(ptr + 4 + len);
3255 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3257 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3259 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3260 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3262 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3263 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3264 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3266 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3268 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3271 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3272 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3273 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3274 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3275 len += sizeof(SLTG_OtherTypeInfo);
3279 pAfterOTIBlks = ptr;
3281 /* Skip this WORD and get the next DWORD */
3282 len = *(DWORD*)(pAfterOTIBlks + 2);
3284 /* Now add this to pLibBLk look at what we're pointing at and
3285 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3286 dust and we should be pointing at the beginning of the name
3289 pNameTable = (char*)pLibBlk + len;
3291 switch(*(WORD*)pNameTable) {
3298 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3302 pNameTable += 0x216;
3306 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3308 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3311 /* Hopefully we now have enough ptrs set up to actually read in
3312 some TypeInfos. It's not clear which order to do them in, so
3313 I'll just follow the links along the BlkEntry chain and read
3314 them in in the order in which they're in the file */
3316 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3318 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3319 pBlkEntry[order].next != 0;
3320 order = pBlkEntry[order].next - 1, i++) {
3322 SLTG_TypeInfoHeader *pTIHeader;
3323 SLTG_TypeInfoTail *pTITail;
3324 SLTG_MemberHeader *pMemHeader;
3326 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3327 pOtherTypeInfoBlks[i].index_name)) {
3328 FIXME("Index strings don't match\n");
3333 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3334 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3337 TRACE("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
3338 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3340 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3341 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3342 (*ppTypeInfoImpl)->index = i;
3343 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3344 pOtherTypeInfoBlks[i].name_offs +
3346 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3347 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3349 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3350 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3351 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3352 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3353 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3355 if((pTIHeader->typeflags1 & 7) != 2)
3356 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3357 if(pTIHeader->typeflags3 != 2)
3358 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3360 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3361 debugstr_w((*ppTypeInfoImpl)->Name),
3362 typekind_desc[pTIHeader->typekind],
3363 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3364 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3366 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3368 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3370 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3371 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3372 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3374 switch(pTIHeader->typekind) {
3376 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3377 pTIHeader, pTITail);
3381 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3382 pTIHeader, pTITail);
3385 case TKIND_INTERFACE:
3386 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3387 pTIHeader, pTITail);
3391 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3392 pTIHeader, pTITail);
3396 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3397 pTIHeader, pTITail);
3400 case TKIND_DISPATCH:
3401 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3402 pTIHeader, pTITail);
3406 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3407 pTIHeader, pTITail);
3411 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3416 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3417 but we've already set those */
3418 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3433 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3434 pBlk = (char*)pBlk + pBlkEntry[order].len;
3437 if(i != pTypeLibImpl->TypeInfoCount) {
3438 FIXME("Somehow processed %d TypeInfos\n", i);
3442 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3443 return (ITypeLib2*)pTypeLibImpl;
3446 /* ITypeLib::QueryInterface
3448 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3453 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3455 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3458 if(IsEqualIID(riid, &IID_IUnknown) ||
3459 IsEqualIID(riid,&IID_ITypeLib)||
3460 IsEqualIID(riid,&IID_ITypeLib2))
3467 ITypeLib2_AddRef(iface);
3468 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3471 TRACE("-- Interface: E_NOINTERFACE\n");
3472 return E_NOINTERFACE;
3477 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3479 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3480 ULONG ref = InterlockedIncrement(&This->ref);
3482 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3487 /* ITypeLib::Release
3489 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3491 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3492 ULONG ref = InterlockedDecrement(&This->ref);
3494 TRACE("(%p)->(%lu)\n",This, ref);
3498 /* remove cache entry */
3501 TRACE("removing from cache list\n");
3502 EnterCriticalSection(&cache_section);
3503 if (This->next) This->next->prev = This->prev;
3504 if (This->prev) This->prev->next = This->next;
3505 else tlb_cache_first = This->next;
3506 LeaveCriticalSection(&cache_section);
3507 HeapFree(GetProcessHeap(), 0, This->path);
3509 /* FIXME destroy child objects */
3510 TRACE(" destroying ITypeLib(%p)\n",This);
3514 SysFreeString(This->Name);
3518 if (This->DocString)
3520 SysFreeString(This->DocString);
3521 This->DocString = NULL;
3526 SysFreeString(This->HelpFile);
3527 This->HelpFile = NULL;
3530 if (This->HelpStringDll)
3532 SysFreeString(This->HelpStringDll);
3533 This->HelpStringDll = NULL;
3536 if (This->pTypeInfo) /* can be NULL */
3537 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3538 HeapFree(GetProcessHeap(),0,This);
3545 /* ITypeLib::GetTypeInfoCount
3547 * Returns the number of type descriptions in the type library
3549 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3551 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3552 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3553 return This->TypeInfoCount;
3556 /* ITypeLib::GetTypeInfo
3558 * retrieves the specified type description in the library.
3560 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3563 ITypeInfo **ppTInfo)
3567 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3568 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3570 TRACE("(%p)->(index=%d)\n", This, index);
3572 if (!ppTInfo) return E_INVALIDARG;
3574 /* search element n in list */
3575 for(i=0; i < index; i++)
3577 pTypeInfo = pTypeInfo->next;
3580 TRACE("-- element not found\n");
3581 return TYPE_E_ELEMENTNOTFOUND;
3585 *ppTInfo = (ITypeInfo *) pTypeInfo;
3587 ITypeInfo_AddRef(*ppTInfo);
3588 TRACE("-- found (%p)\n",*ppTInfo);
3593 /* ITypeLibs::GetTypeInfoType
3595 * Retrieves the type of a type description.
3597 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3602 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3604 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3606 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3607 return TYPE_E_ELEMENTNOTFOUND;
3609 TRACE("(%p) index %d\n", This, index);
3611 if(!pTKind) return E_INVALIDARG;
3613 /* search element n in list */
3614 for(i=0; i < index; i++)
3618 TRACE("-- element not found\n");
3619 return TYPE_E_ELEMENTNOTFOUND;
3621 pTInfo = pTInfo->next;
3624 *pTKind = pTInfo->TypeAttr.typekind;
3625 TRACE("-- found Type (%d)\n", *pTKind);
3629 /* ITypeLib::GetTypeInfoOfGuid
3631 * Retrieves the type description that corresponds to the specified GUID.
3634 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3637 ITypeInfo **ppTInfo)
3639 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3640 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3642 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3646 WARN("-- element not found\n");
3647 return TYPE_E_ELEMENTNOTFOUND;
3650 /* search linked list for guid */
3651 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3653 pTypeInfo = pTypeInfo->next;
3657 /* end of list reached */
3658 WARN("-- element not found\n");
3659 return TYPE_E_ELEMENTNOTFOUND;
3663 TRACE("-- found (%p, %s)\n",
3665 debugstr_w(pTypeInfo->Name));
3667 *ppTInfo = (ITypeInfo*)pTypeInfo;
3668 ITypeInfo_AddRef(*ppTInfo);
3672 /* ITypeLib::GetLibAttr
3674 * Retrieves the structure that contains the library's attributes.
3677 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3679 LPTLIBATTR *ppTLibAttr)
3681 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3682 TRACE("(%p)\n",This);
3683 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3684 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3688 /* ITypeLib::GetTypeComp
3690 * Enables a client compiler to bind to a library's types, variables,
3691 * constants, and global functions.
3694 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3696 ITypeComp **ppTComp)
3698 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3700 TRACE("(%p)->(%p)\n",This,ppTComp);
3701 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3702 ITypeComp_AddRef(*ppTComp);
3707 /* ITypeLib::GetDocumentation
3709 * Retrieves the library's documentation string, the complete Help file name
3710 * and path, and the context identifier for the library Help topic in the Help
3713 * On a successful return all non-null BSTR pointers will have been set,
3716 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3720 BSTR *pBstrDocString,
3721 DWORD *pdwHelpContext,
3722 BSTR *pBstrHelpFile)
3724 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3726 HRESULT result = E_INVALIDARG;
3731 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3733 pBstrName, pBstrDocString,
3734 pdwHelpContext, pBstrHelpFile);
3738 /* documentation for the typelib */
3743 if(!(*pBstrName = SysAllocString(This->Name)))
3751 if (This->DocString)
3753 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3756 else if (This->Name)
3758 if(!(*pBstrDocString = SysAllocString(This->Name)))
3762 *pBstrDocString = NULL;
3766 *pdwHelpContext = This->dwHelpContext;
3772 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3776 *pBstrHelpFile = NULL;
3783 /* for a typeinfo */
3784 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3786 if(SUCCEEDED(result))
3788 result = ITypeInfo_GetDocumentation(pTInfo,
3792 pdwHelpContext, pBstrHelpFile);
3794 ITypeInfo_Release(pTInfo);
3799 if (pBstrDocString) SysFreeString (*pBstrDocString);
3801 if (pBstrName) SysFreeString (*pBstrName);
3803 return STG_E_INSUFFICIENTMEMORY;
3808 * Indicates whether a passed-in string contains the name of a type or member
3809 * described in the library.
3812 static HRESULT WINAPI ITypeLib2_fnIsName(
3818 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3819 ITypeInfoImpl *pTInfo;
3820 TLBFuncDesc *pFInfo;
3823 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3825 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3829 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3830 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3831 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3832 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3833 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3834 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3835 goto ITypeLib2_fnIsName_exit;
3837 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3838 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3843 ITypeLib2_fnIsName_exit:
3844 TRACE("(%p)slow! search for %s: %s found!\n", This,
3845 debugstr_w(szNameBuf), *pfName?"NOT":"");
3850 /* ITypeLib::FindName
3852 * Finds occurrences of a type description in a type library. This may be used
3853 * to quickly verify that a name exists in a type library.
3856 static HRESULT WINAPI ITypeLib2_fnFindName(
3860 ITypeInfo **ppTInfo,
3864 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3865 ITypeInfoImpl *pTInfo;
3866 TLBFuncDesc *pFInfo;
3869 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3871 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3872 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3873 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3874 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3875 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3876 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3877 goto ITypeLib2_fnFindName_exit;
3880 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3881 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3883 ITypeLib2_fnFindName_exit:
3884 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3885 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3888 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3889 This, *pcFound, debugstr_w(szNameBuf), j);
3896 /* ITypeLib::ReleaseTLibAttr
3898 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3901 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3903 TLIBATTR *pTLibAttr)
3905 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3906 TRACE("freeing (%p)\n",This);
3907 HeapFree(GetProcessHeap(),0,pTLibAttr);
3911 /* ITypeLib2::GetCustData
3913 * gets the custom data
3915 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3920 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3921 TLBCustData *pCData;
3923 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3925 if( IsEqualIID(guid, &pCData->guid)) break;
3928 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3932 VariantInit( pVarVal);
3933 VariantCopy( pVarVal, &pCData->data);
3936 return E_INVALIDARG; /* FIXME: correct? */
3939 /* ITypeLib2::GetLibStatistics
3941 * Returns statistics about a type library that are required for efficient
3942 * sizing of hash tables.
3945 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3947 ULONG *pcUniqueNames,
3948 ULONG *pcchUniqueNames)
3950 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3952 FIXME("(%p): stub!\n", This);
3954 if(pcUniqueNames) *pcUniqueNames=1;
3955 if(pcchUniqueNames) *pcchUniqueNames=1;
3959 /* ITypeLib2::GetDocumentation2
3961 * Retrieves the library's documentation string, the complete Help file name
3962 * and path, the localization context to use, and the context ID for the
3963 * library Help topic in the Help file.
3966 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3970 BSTR *pbstrHelpString,
3971 DWORD *pdwHelpStringContext,
3972 BSTR *pbstrHelpStringDll)
3974 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3978 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3980 /* the help string should be obtained from the helpstringdll,
3981 * using the _DLLGetDocumentation function, based on the supplied
3982 * lcid. Nice to do sometime...
3986 /* documentation for the typelib */
3988 *pbstrHelpString=SysAllocString(This->DocString);
3989 if(pdwHelpStringContext)
3990 *pdwHelpStringContext=This->dwHelpContext;
3991 if(pbstrHelpStringDll)
3992 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3998 /* for a typeinfo */
3999 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4001 if(SUCCEEDED(result))
4003 ITypeInfo2 * pTInfo2;
4004 result = ITypeInfo_QueryInterface(pTInfo,
4006 (LPVOID*) &pTInfo2);
4008 if(SUCCEEDED(result))
4010 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4014 pdwHelpStringContext,
4015 pbstrHelpStringDll);
4017 ITypeInfo2_Release(pTInfo2);
4020 ITypeInfo_Release(pTInfo);
4026 /* ITypeLib2::GetAllCustData
4028 * Gets all custom data items for the library.
4031 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4033 CUSTDATA *pCustData)
4035 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4036 TLBCustData *pCData;
4038 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4039 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4040 if(pCustData->prgCustData ){
4041 pCustData->cCustData=This->ctCustData;
4042 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4043 pCustData->prgCustData[i].guid=pCData->guid;
4044 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4047 ERR(" OUT OF MEMORY!\n");
4048 return E_OUTOFMEMORY;
4053 static const ITypeLib2Vtbl tlbvt = {
4054 ITypeLib2_fnQueryInterface,
4056 ITypeLib2_fnRelease,
4057 ITypeLib2_fnGetTypeInfoCount,
4058 ITypeLib2_fnGetTypeInfo,
4059 ITypeLib2_fnGetTypeInfoType,
4060 ITypeLib2_fnGetTypeInfoOfGuid,
4061 ITypeLib2_fnGetLibAttr,
4062 ITypeLib2_fnGetTypeComp,
4063 ITypeLib2_fnGetDocumentation,
4065 ITypeLib2_fnFindName,
4066 ITypeLib2_fnReleaseTLibAttr,
4068 ITypeLib2_fnGetCustData,
4069 ITypeLib2_fnGetLibStatistics,
4070 ITypeLib2_fnGetDocumentation2,
4071 ITypeLib2_fnGetAllCustData
4075 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4077 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4079 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4082 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4084 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4086 return ITypeLib2_AddRef((ITypeLib2 *)This);
4089 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4091 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4093 return ITypeLib2_Release((ITypeLib2 *)This);
4096 static HRESULT WINAPI ITypeLibComp_fnBind(
4101 ITypeInfo ** ppTInfo,
4102 DESCKIND * pDescKind,
4105 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4106 ITypeInfoImpl *pTypeInfo;
4108 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4110 *pDescKind = DESCKIND_NONE;
4111 pBindPtr->lptcomp = NULL;
4114 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4116 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4118 /* FIXME: check wFlags here? */
4119 /* FIXME: we should use a hash table to look this info up using lHash
4120 * instead of an O(n) search */
4121 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4122 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4124 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4126 *pDescKind = DESCKIND_TYPECOMP;
4127 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4128 ITypeComp_AddRef(pBindPtr->lptcomp);
4129 TRACE("module or enum: %s\n", debugstr_w(szName));
4134 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4135 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4137 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4140 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4141 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4143 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4148 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4149 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4151 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4153 ITypeInfo *subtypeinfo;
4155 DESCKIND subdesckind;
4157 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4158 &subtypeinfo, &subdesckind, &subbindptr);
4159 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4161 TYPEDESC tdesc_appobject =
4164 (TYPEDESC *)pTypeInfo->hreftype
4168 const VARDESC vardesc_appobject =
4171 NULL, /* lpstrSchema */
4186 VAR_STATIC /* varkind */
4189 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4191 /* cleanup things filled in by Bind call so we can put our
4192 * application object data in there instead */
4193 switch (subdesckind)
4195 case DESCKIND_FUNCDESC:
4196 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4198 case DESCKIND_VARDESC:
4199 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4204 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4206 if (pTypeInfo->hreftype == -1)
4207 FIXME("no hreftype for interface %p\n", pTypeInfo);
4209 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4213 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4214 *ppTInfo = (ITypeInfo *)pTypeInfo;
4215 ITypeInfo_AddRef(*ppTInfo);
4221 TRACE("name not found %s\n", debugstr_w(szName));
4225 static HRESULT WINAPI ITypeLibComp_fnBindType(
4229 ITypeInfo ** ppTInfo,
4230 ITypeComp ** ppTComp)
4232 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4236 static const ITypeCompVtbl tlbtcvt =
4239 ITypeLibComp_fnQueryInterface,
4240 ITypeLibComp_fnAddRef,
4241 ITypeLibComp_fnRelease,
4243 ITypeLibComp_fnBind,
4244 ITypeLibComp_fnBindType
4247 /*================== ITypeInfo(2) Methods ===================================*/
4248 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4250 ITypeInfoImpl * pTypeInfoImpl;
4252 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4255 pTypeInfoImpl->lpVtbl = &tinfvt;
4256 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4257 pTypeInfoImpl->ref=1;
4258 pTypeInfoImpl->hreftype = -1;
4259 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4260 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4262 TRACE("(%p)\n", pTypeInfoImpl);
4263 return (ITypeInfo2*) pTypeInfoImpl;
4266 /* ITypeInfo::QueryInterface
4268 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4273 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4275 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4278 if(IsEqualIID(riid, &IID_IUnknown) ||
4279 IsEqualIID(riid,&IID_ITypeInfo)||
4280 IsEqualIID(riid,&IID_ITypeInfo2))
4284 ITypeInfo_AddRef(iface);
4285 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4288 TRACE("-- Interface: E_NOINTERFACE\n");
4289 return E_NOINTERFACE;
4292 /* ITypeInfo::AddRef
4294 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4296 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4297 ULONG ref = InterlockedIncrement(&This->ref);
4299 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4301 TRACE("(%p)->ref is %lu\n",This, ref);
4305 /* ITypeInfo::Release
4307 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4309 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4310 ULONG ref = InterlockedDecrement(&This->ref);
4312 TRACE("(%p)->(%lu)\n",This, ref);
4315 /* We don't release ITypeLib when ref=0 because
4316 it means that function is called by ITypeLib2_Release */
4317 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4319 static int once = 0;
4323 FIXME("destroy child objects\n");
4326 TRACE("destroying ITypeInfo(%p)\n",This);
4329 SysFreeString(This->Name);
4333 if (This->DocString)
4335 SysFreeString(This->DocString);
4336 This->DocString = 0;
4341 SysFreeString(This->DllName);
4347 ITypeInfo_Release((ITypeInfo*)This->next);
4350 HeapFree(GetProcessHeap(),0,This);
4356 /* ITypeInfo::GetTypeAttr
4358 * Retrieves a TYPEATTR structure that contains the attributes of the type
4362 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4363 LPTYPEATTR *ppTypeAttr)
4365 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4368 TRACE("(%p)\n",This);
4370 size = sizeof(**ppTypeAttr);
4371 if (This->TypeAttr.typekind == TKIND_ALIAS)
4372 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4374 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4376 return E_OUTOFMEMORY;
4378 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4380 if (This->TypeAttr.typekind == TKIND_ALIAS)
4381 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4382 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4384 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4385 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4387 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4388 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4393 /* ITypeInfo::GetTypeComp
4395 * Retrieves the ITypeComp interface for the type description, which enables a
4396 * client compiler to bind to the type description's members.
4399 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4400 ITypeComp * *ppTComp)
4402 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4404 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4406 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4407 ITypeComp_AddRef(*ppTComp);
4411 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4413 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4414 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4415 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4419 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4421 memcpy(dest, src, sizeof(ELEMDESC));
4422 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4423 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4425 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4426 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4427 *buffer += sizeof(PARAMDESCEX);
4428 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4429 VariantInit(&pparamdescex_dest->varDefaultValue);
4430 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4431 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4434 dest->u.paramdesc.pparamdescex = NULL;
4438 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4440 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4441 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4444 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4448 SIZE_T size = sizeof(*src);
4452 size += sizeof(*src->lprgscode) * src->cScodes;
4453 size += TLB_SizeElemDesc(&src->elemdescFunc);
4454 for (i = 0; i < src->cParams; i++)
4456 size += sizeof(ELEMDESC);
4457 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4460 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4461 if (!dest) return E_OUTOFMEMORY;
4463 memcpy(dest, src, sizeof(FUNCDESC));
4464 buffer = (char *)(dest + 1);
4466 dest->lprgscode = (SCODE *)buffer;
4467 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4468 buffer += sizeof(*src->lprgscode) * src->cScodes;
4470 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4473 SysFreeString((BSTR)dest);
4477 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4478 buffer += sizeof(ELEMDESC) * src->cParams;
4479 for (i = 0; i < src->cParams; i++)
4481 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4487 /* undo the above actions */
4488 for (i = i - 1; i >= 0; i--)
4489 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4490 TLB_FreeElemDesc(&dest->elemdescFunc);
4491 SysFreeString((BSTR)dest);
4495 /* special treatment for dispinterfaces: this makes functions appear
4496 * to return their [retval] value when it is really returning an
4498 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4500 if (dest->cParams &&
4501 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4503 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4504 if (elemdesc->tdesc.vt != VT_PTR)
4506 ERR("elemdesc should have started with VT_PTR instead of:\n");
4508 dump_ELEMDESC(elemdesc);
4509 return E_UNEXPECTED;
4512 /* copy last parameter to the return value. we are using a flat
4513 * buffer so there is no danger of leaking memory in
4515 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4517 /* remove the last parameter */
4521 /* otherwise this function is made to appear to have no return
4523 dest->elemdescFunc.tdesc.vt = VT_VOID;
4531 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4533 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4534 const TLBFuncDesc *pFDesc;
4537 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4542 *ppFuncDesc = &pFDesc->funcdesc;
4546 return E_INVALIDARG;
4549 /* ITypeInfo::GetFuncDesc
4551 * Retrieves the FUNCDESC structure that contains information about a
4552 * specified function.
4555 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4556 LPFUNCDESC *ppFuncDesc)
4558 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4559 const FUNCDESC *internal_funcdesc;
4562 TRACE("(%p) index %d\n", This, index);
4564 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4568 return TLB_AllocAndInitFuncDesc(
4571 This->TypeAttr.typekind == TKIND_DISPATCH);
4574 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4578 SIZE_T size = sizeof(*src);
4581 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4582 if (src->varkind == VAR_CONST)
4583 size += sizeof(VARIANT);
4584 size += TLB_SizeElemDesc(&src->elemdescVar);
4586 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4587 if (!dest) return E_OUTOFMEMORY;
4590 buffer = (char *)(dest + 1);
4591 if (src->lpstrSchema)
4594 dest->lpstrSchema = (LPOLESTR)buffer;
4595 len = strlenW(src->lpstrSchema);
4596 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4597 buffer += (len + 1) * sizeof(WCHAR);
4600 if (src->varkind == VAR_CONST)
4604 dest->u.lpvarValue = (VARIANT *)buffer;
4605 *dest->u.lpvarValue = *src->u.lpvarValue;
4606 buffer += sizeof(VARIANT);
4607 VariantInit(dest->u.lpvarValue);
4608 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4611 SysFreeString((BSTR)dest_ptr);
4615 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4618 if (src->varkind == VAR_CONST)
4619 VariantClear(dest->u.lpvarValue);
4620 SysFreeString((BSTR)dest);
4627 /* ITypeInfo::GetVarDesc
4629 * Retrieves a VARDESC structure that describes the specified variable.
4632 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4633 LPVARDESC *ppVarDesc)
4635 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4637 const TLBVarDesc *pVDesc;
4639 TRACE("(%p) index %d\n", This, index);
4641 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4645 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4647 return E_INVALIDARG;
4650 /* ITypeInfo_GetNames
4652 * Retrieves the variable with the specified member ID (or the name of the
4653 * property or method and its parameters) that correspond to the specified
4656 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4657 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4659 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4660 const TLBFuncDesc *pFDesc;
4661 const TLBVarDesc *pVDesc;
4663 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4664 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4667 /* function found, now return function and parameter names */
4668 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4671 *rgBstrNames=SysAllocString(pFDesc->Name);
4673 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4679 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4682 *rgBstrNames=SysAllocString(pVDesc->Name);
4687 if(This->TypeAttr.cImplTypes &&
4688 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4689 /* recursive search */
4692 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4694 if(SUCCEEDED(result))
4696 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4697 ITypeInfo_Release(pTInfo);
4700 WARN("Could not search inherited interface!\n");
4704 WARN("no names found\n");
4707 return TYPE_E_ELEMENTNOTFOUND;
4714 /* ITypeInfo::GetRefTypeOfImplType
4716 * If a type description describes a COM class, it retrieves the type
4717 * description of the implemented interface types. For an interface,
4718 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4722 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4727 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4730 const TLBImplType *pImpl = This->impltypelist;
4732 TRACE("(%p) index %d\n", This, index);
4733 if (TRACE_ON(ole)) dump_TypeInfo(This);
4737 /* only valid on dual interfaces;
4738 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4740 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4742 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4743 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4749 hr = TYPE_E_ELEMENTNOTFOUND;
4754 /* get element n from linked list */
4755 for(i=0; pImpl && i<index; i++)
4757 pImpl = pImpl->next;
4761 *pRefType = pImpl->hRef;
4763 hr = TYPE_E_ELEMENTNOTFOUND;
4769 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4771 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4777 /* ITypeInfo::GetImplTypeFlags
4779 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4780 * or base interface in a type description.
4782 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4783 UINT index, INT *pImplTypeFlags)
4785 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4789 TRACE("(%p) index %d\n", This, index);
4790 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4791 i++, pImpl=pImpl->next)
4793 if(i==index && pImpl){
4794 *pImplTypeFlags=pImpl->implflags;
4798 return TYPE_E_ELEMENTNOTFOUND;
4802 * Maps between member names and member IDs, and parameter names and
4805 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4806 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4808 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4809 const TLBFuncDesc *pFDesc;
4810 const TLBVarDesc *pVDesc;
4814 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4817 /* init out parameters in case of failure */
4818 for (i = 0; i < cNames; i++)
4819 pMemId[i] = MEMBERID_NIL;
4821 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4823 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4824 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4825 for(i=1; i < cNames; i++){
4826 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4827 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4829 if( j<pFDesc->funcdesc.cParams)
4832 ret=DISP_E_UNKNOWNNAME;
4834 TRACE("-- 0x%08lx\n", ret);
4838 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4839 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4840 if(cNames) *pMemId=pVDesc->vardesc.memid;
4844 /* not found, see if it can be found in an inherited interface */
4845 if(This->TypeAttr.cImplTypes) {
4846 /* recursive search */
4848 ret=ITypeInfo_GetRefTypeInfo(iface,
4849 This->impltypelist->hRef, &pTInfo);
4851 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4852 ITypeInfo_Release(pTInfo);
4855 WARN("Could not search inherited interface!\n");
4857 WARN("no names found\n");
4858 return DISP_E_UNKNOWNNAME;
4861 /* ITypeInfo::Invoke
4863 * Invokes a method, or accesses a property of an object, that implements the
4864 * interface described by the type description.
4867 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4870 if (TRACE_ON(ole)) {
4872 TRACE("Calling %p(",func);
4873 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4885 res = func(args[0]);
4888 res = func(args[0],args[1]);
4891 res = func(args[0],args[1],args[2]);
4894 res = func(args[0],args[1],args[2],args[3]);
4897 res = func(args[0],args[1],args[2],args[3],args[4]);
4900 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4903 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4906 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4909 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4912 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4915 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4918 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]);
4921 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]);
4924 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]);
4927 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]);
4930 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]);
4933 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]);
4936 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]);
4939 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]);
4942 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]);
4945 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]);
4948 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]);
4951 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]);
4954 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4960 FIXME("unsupported calling convention %d\n",callconv);
4964 TRACE("returns %08lx\n",res);
4968 extern int _argsize(DWORD vt);
4970 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4973 ITypeInfo *tinfo2 = NULL;
4974 TYPEATTR *tattr = NULL;
4976 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4979 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4981 tdesc->u.hreftype, hr);
4984 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4987 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4988 ITypeInfo_Release(tinfo2);
4992 switch (tattr->typekind)
4999 tdesc = &tattr->tdescAlias;
5000 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5003 case TKIND_INTERFACE:
5004 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5010 case TKIND_DISPATCH:
5015 FIXME("TKIND_RECORD unhandled.\n");
5020 FIXME("TKIND_UNION unhandled.\n");
5025 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5029 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5030 ITypeInfo_Release(tinfo2);
5034 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5038 /* enforce only one level of pointer indirection */
5039 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5041 tdesc = tdesc->u.lptdesc;
5043 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5044 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5045 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5046 if ((tdesc->vt == VT_USERDEFINED) ||
5047 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5049 VARTYPE vt_userdefined = 0;
5050 const TYPEDESC *tdesc_userdefined = tdesc;
5051 if (tdesc->vt == VT_PTR)
5053 vt_userdefined = VT_BYREF;
5054 tdesc_userdefined = tdesc->u.lptdesc;
5056 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5058 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5059 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5061 *vt |= vt_userdefined;
5073 case VT_USERDEFINED:
5074 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5081 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5082 hr = DISP_E_BADVARTYPE;
5086 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5095 /***********************************************************************
5096 * DispCallFunc (OLEAUT32.@)
5098 * Invokes a function of the specifed calling convention, passing the
5099 * specified arguments and returns the result.
5102 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5103 * oVft [I] The offset in the vtable. See notes.
5104 * cc [I] Calling convention of the function to call.
5105 * vtReturn [I] The return type of the function.
5106 * cActuals [I] Number of parameters.
5107 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5108 * prgpvarg [I] The arguments to pass.
5109 * pvargResult [O] The return value of the function. Can be NULL.
5113 * Failure: HRESULT code.
5116 * The HRESULT return value of this function is not affected by the return
5117 * value of the user supplied function, which is returned in pvargResult.
5119 * If pvInstance is NULL then a non-object function is to be called and oVft
5120 * is the address of the function to call.
5122 * The cc parameter can be one of the following values:
5135 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5136 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5138 int i, argsize, argspos;
5142 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5143 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5144 pvargResult, V_VT(pvargResult));
5148 argsize++; /* for This pointer */
5150 for (i=0;i<cActuals;i++)
5152 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5153 dump_Variant(prgpvarg[i]);
5154 argsize += _argsize(prgvt[i]);
5156 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5161 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5165 for (i=0;i<cActuals;i++)
5167 VARIANT *arg = prgpvarg[i];
5168 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5169 if (prgvt[i] == VT_VARIANT)
5170 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5172 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5173 argspos += _argsize(prgvt[i]);
5178 FARPROC *vtable = *(FARPROC**)pvInstance;
5179 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5182 /* if we aren't invoking an object then the function pointer is stored
5184 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5186 if (pvargResult && (vtReturn != VT_EMPTY))
5188 TRACE("Method returned 0x%08lx\n",hres);
5189 V_VT(pvargResult) = vtReturn;
5190 V_UI4(pvargResult) = hres;
5193 HeapFree(GetProcessHeap(),0,args);
5197 #define INVBUF_ELEMENT_SIZE \
5198 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5199 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5200 ((VARIANTARG *)(buffer))
5201 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5202 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5203 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5204 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5205 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5206 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5208 static HRESULT WINAPI ITypeInfo_fnInvoke(
5213 DISPPARAMS *pDispParams,
5214 VARIANT *pVarResult,
5215 EXCEPINFO *pExcepInfo,
5218 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5220 unsigned int var_index;
5223 const TLBFuncDesc *pFuncInfo;
5225 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5226 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5231 ERR("NULL pDispParams not allowed\n");
5232 return E_INVALIDARG;
5235 dump_DispParms(pDispParams);
5237 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5239 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5240 pDispParams->cNamedArgs, pDispParams->cArgs);
5241 return E_INVALIDARG;
5244 /* we do this instead of using GetFuncDesc since it will return a fake
5245 * FUNCDESC for dispinterfaces and we want the real function description */
5246 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5247 if ((memid == pFuncInfo->funcdesc.memid) &&
5248 (wFlags & pFuncInfo->funcdesc.invkind))
5252 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5256 TRACE("invoking:\n");
5257 dump_TLBFuncDescOne(pFuncInfo);
5260 switch (func_desc->funckind) {
5261 case FUNC_PUREVIRTUAL:
5262 case FUNC_VIRTUAL: {
5263 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5265 VARIANT retval; /* pointer for storing byref retvals in */
5266 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5267 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5268 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5271 for (i = 0; i < func_desc->cParams; i++)
5273 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5274 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5279 TRACE("changing args\n");
5280 for (i = 0; i < func_desc->cParams; i++)
5282 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5284 if (wParamFlags & PARAMFLAG_FRETVAL)
5286 /* note: this check is placed so that if the caller passes
5287 * in a VARIANTARG for the retval we just ignore it, like
5289 if (i == func_desc->cParams - 1)
5292 arg = prgpvarg[i] = &rgvarg[i];
5293 memset(arg, 0, sizeof(*arg));
5294 V_VT(arg) = rgvt[i];
5295 memset(&retval, 0, sizeof(retval));
5296 V_BYREF(arg) = &retval;
5300 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5301 hres = E_UNEXPECTED;
5305 else if (i < pDispParams->cArgs)
5307 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5308 dump_Variant(src_arg);
5310 if (rgvt[i] == VT_VARIANT)
5311 hres = VariantCopy(&rgvarg[i], src_arg);
5312 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5314 if (rgvt[i] == V_VT(src_arg))
5315 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5318 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5319 hres = VariantCopy(&missing_arg[i], src_arg);
5320 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5322 V_VT(&rgvarg[i]) = rgvt[i];
5324 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5326 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5327 V_VT(&missing_arg[i]) = V_VT(src_arg);
5328 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5329 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5330 V_VT(&rgvarg[i]) = rgvt[i];
5332 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5334 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5335 V_VT(&rgvarg[i]) = rgvt[i];
5339 /* FIXME: this doesn't work for VT_BYREF arguments if
5340 * they are not the same type as in the paramdesc */
5341 V_VT(&rgvarg[i]) = V_VT(src_arg);
5342 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5343 V_VT(&rgvarg[i]) = rgvt[i];
5348 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5349 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5350 debugstr_VT(src_arg), debugstr_VF(src_arg));
5353 prgpvarg[i] = &rgvarg[i];
5355 else if (wParamFlags & PARAMFLAG_FOPT)
5358 arg = prgpvarg[i] = &rgvarg[i];
5359 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5361 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5367 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5368 V_VT(arg) = VT_VARIANT | VT_BYREF;
5369 V_VARIANTREF(arg) = &missing_arg[i];
5370 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5371 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5376 hres = DISP_E_BADPARAMCOUNT;
5380 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5381 if (func_desc->cParamsOpt < 0)
5383 FIXME("Does not support safearray optional parameters\n");
5384 hres = DISP_E_BADPARAMCOUNT;
5385 goto func_fail; /* FIXME: we don't free changed types here */
5388 /* VT_VOID is a special case for return types, so it is not
5389 * handled in the general function */
5390 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5391 V_VT(&varresult) = VT_EMPTY;
5394 V_VT(&varresult) = 0;
5395 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5396 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5399 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5400 V_VT(&varresult), func_desc->cParams, rgvt,
5401 prgpvarg, &varresult);
5403 for (i = 0; i < func_desc->cParams; i++)
5405 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5406 if (wParamFlags & PARAMFLAG_FRETVAL)
5410 TRACE("[retval] value: ");
5411 dump_Variant(prgpvarg[i]);
5416 VariantInit(pVarResult);
5417 /* deref return value */
5418 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5421 /* free data stored in varresult. Note that
5422 * VariantClear doesn't do what we want because we are
5423 * working with byref types. */
5424 /* FIXME: clear safearrays, bstrs, records and
5425 * variants here too */
5426 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5427 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5429 if(*V_UNKNOWNREF(prgpvarg[i]))
5430 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5434 else if (i < pDispParams->cArgs)
5436 if (wParamFlags & PARAMFLAG_FOUT)
5438 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5440 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5441 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5445 ERR("failed to convert param %d to vt %d\n", i,
5446 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5450 VariantClear(&rgvarg[i]);
5452 else if (wParamFlags & PARAMFLAG_FOPT)
5454 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5455 VariantClear(&rgvarg[i]);
5459 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5461 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5462 hres = DISP_E_EXCEPTION;
5463 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5467 HeapFree(GetProcessHeap(), 0, buffer);
5470 case FUNC_DISPATCH: {
5473 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5474 if (SUCCEEDED(hres)) {
5475 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5476 hres = IDispatch_Invoke(
5477 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5478 pVarResult,pExcepInfo,pArgErr
5481 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5482 IDispatch_Release(disp);
5484 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5488 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5493 TRACE("-- 0x%08lx\n", hres);
5496 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5499 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5500 if(FAILED(hres)) return hres;
5502 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5503 dump_VARDESC(var_desc);
5504 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5508 /* not found, look for it in inherited interfaces */
5509 ITypeInfo2_GetTypeKind(iface, &type_kind);
5510 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5512 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5513 /* recursive search */
5515 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5516 if(SUCCEEDED(hres)){
5517 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5518 ITypeInfo_Release(pTInfo);
5521 WARN("Could not search inherited interface!\n");
5524 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5525 return DISP_E_MEMBERNOTFOUND;
5528 /* ITypeInfo::GetDocumentation
5530 * Retrieves the documentation string, the complete Help file name and path,
5531 * and the context ID for the Help topic for a specified type description.
5533 * (Can be tested by the Visual Basic Editor in Word for instance.)
5535 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5536 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5537 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5539 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5540 const TLBFuncDesc *pFDesc;
5541 const TLBVarDesc *pVDesc;
5542 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5543 " HelpContext(%p) HelpFile(%p)\n",
5544 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5545 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5547 *pBstrName=SysAllocString(This->Name);
5549 *pBstrDocString=SysAllocString(This->DocString);
5551 *pdwHelpContext=This->dwHelpContext;
5553 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5555 }else {/* for a member */
5556 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5557 if(pFDesc->funcdesc.memid==memid){
5559 *pBstrName = SysAllocString(pFDesc->Name);
5561 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5563 *pdwHelpContext=pFDesc->helpcontext;
5566 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5567 if(pVDesc->vardesc.memid==memid){
5569 *pBstrName = SysAllocString(pVDesc->Name);
5571 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5573 *pdwHelpContext=pVDesc->HelpContext;
5577 WARN("member %ld not found\n", memid);
5578 return TYPE_E_ELEMENTNOTFOUND;
5581 /* ITypeInfo::GetDllEntry
5583 * Retrieves a description or specification of an entry point for a function
5586 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5587 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5590 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5591 const TLBFuncDesc *pFDesc;
5593 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5595 if (pBstrDllName) *pBstrDllName = NULL;
5596 if (pBstrName) *pBstrName = NULL;
5597 if (pwOrdinal) *pwOrdinal = 0;
5599 if (This->TypeAttr.typekind != TKIND_MODULE)
5600 return TYPE_E_BADMODULEKIND;
5602 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5603 if(pFDesc->funcdesc.memid==memid){
5604 dump_TypeInfo(This);
5606 dump_TLBFuncDescOne(pFDesc);
5609 *pBstrDllName = SysAllocString(This->DllName);
5611 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5613 *pBstrName = SysAllocString(pFDesc->Entry);
5621 *pwOrdinal = (DWORD)pFDesc->Entry;
5624 return TYPE_E_ELEMENTNOTFOUND;
5627 /* ITypeInfo::GetRefTypeInfo
5629 * If a type description references other type descriptions, it retrieves
5630 * the referenced type descriptions.
5632 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5635 ITypeInfo **ppTInfo)
5637 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5638 HRESULT result = E_FAIL;
5640 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5642 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5643 ITypeInfo_AddRef(*ppTInfo);
5646 else if (hRefType == -1 &&
5647 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5648 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5650 /* when we meet a DUAL dispinterface, we must create the interface
5653 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5656 /* the interface version contains the same information as the dispinterface
5657 * copy the contents of the structs.
5659 *pTypeInfoImpl = *This;
5660 pTypeInfoImpl->ref = 1;
5662 /* change the type to interface */
5663 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5665 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5667 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5672 TLBRefType *pRefType;
5673 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5674 if(pRefType->reference == hRefType)
5678 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5679 if(pRefType && hRefType != -1) {
5680 ITypeLib *pTLib = NULL;
5682 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5684 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5686 if(pRefType->pImpTLInfo->pImpTypeLib) {
5687 TRACE("typeinfo in imported typelib that is already loaded\n");
5688 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5689 ITypeLib2_AddRef((ITypeLib*) pTLib);
5692 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5693 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5694 pRefType->pImpTLInfo->wVersionMajor,
5695 pRefType->pImpTLInfo->wVersionMinor,
5696 pRefType->pImpTLInfo->lcid,
5699 if(!SUCCEEDED(result)) {
5700 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5701 result=LoadTypeLib(libnam, &pTLib);
5702 SysFreeString(libnam);
5704 if(SUCCEEDED(result)) {
5705 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5706 ITypeLib2_AddRef(pTLib);
5710 if(SUCCEEDED(result)) {
5711 if(pRefType->index == TLB_REF_USE_GUID)
5712 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5716 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5720 ITypeLib2_Release(pTLib);
5724 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5725 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5729 /* ITypeInfo::AddressOfMember
5731 * Retrieves the addresses of static functions or variables, such as those
5734 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5735 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5737 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5743 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5745 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5749 module = LoadLibraryW(dll);
5752 ERR("couldn't load %s\n", debugstr_w(dll));
5754 if (entry) SysFreeString(entry);
5755 return STG_E_FILENOTFOUND;
5757 /* FIXME: store library somewhere where we can free it */
5762 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5763 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5764 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5766 *ppv = GetProcAddress(module, entryA);
5768 ERR("function not found %s\n", debugstr_a(entryA));
5770 HeapFree(GetProcessHeap(), 0, entryA);
5774 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5776 ERR("function not found %d\n", ordinal);
5780 if (entry) SysFreeString(entry);
5783 return TYPE_E_DLLFUNCTIONNOTFOUND;
5788 /* ITypeInfo::CreateInstance
5790 * Creates a new instance of a type that describes a component object class
5793 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5794 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5796 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5797 FIXME("(%p) stub!\n", This);
5801 /* ITypeInfo::GetMops
5803 * Retrieves marshalling information.
5805 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5808 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5809 FIXME("(%p) stub!\n", This);
5813 /* ITypeInfo::GetContainingTypeLib
5815 * Retrieves the containing type library and the index of the type description
5816 * within that type library.
5818 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5819 ITypeLib * *ppTLib, UINT *pIndex)
5821 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5823 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5825 *pIndex=This->index;
5826 TRACE("returning pIndex=%d\n", *pIndex);
5830 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5831 ITypeLib2_AddRef(*ppTLib);
5832 TRACE("returning ppTLib=%p\n", *ppTLib);
5838 /* ITypeInfo::ReleaseTypeAttr
5840 * Releases a TYPEATTR previously returned by GetTypeAttr.
5843 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5844 TYPEATTR* pTypeAttr)
5846 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5847 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5848 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5851 /* ITypeInfo::ReleaseFuncDesc
5853 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5855 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5857 FUNCDESC *pFuncDesc)
5859 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5862 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5864 for (i = 0; i < pFuncDesc->cParams; i++)
5865 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5866 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5868 SysFreeString((BSTR)pFuncDesc);
5871 /* ITypeInfo::ReleaseVarDesc
5873 * Releases a VARDESC previously returned by GetVarDesc.
5875 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5878 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5879 TRACE("(%p)->(%p)\n", This, pVarDesc);
5881 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5882 if (pVarDesc->varkind == VAR_CONST)
5883 VariantClear(pVarDesc->u.lpvarValue);
5884 SysFreeString((BSTR)pVarDesc);
5887 /* ITypeInfo2::GetTypeKind
5889 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5892 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5893 TYPEKIND *pTypeKind)
5895 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5896 *pTypeKind=This->TypeAttr.typekind;
5897 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5901 /* ITypeInfo2::GetTypeFlags
5903 * Returns the type flags without any allocations. This returns a DWORD type
5904 * flag, which expands the type flags without growing the TYPEATTR (type
5908 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5910 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5911 *pTypeFlags=This->TypeAttr.wTypeFlags;
5912 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5916 /* ITypeInfo2::GetFuncIndexOfMemId
5917 * Binds to a specific member based on a known DISPID, where the member name
5918 * is not known (for example, when binding to a default member).
5921 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5922 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5924 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5925 const TLBFuncDesc *pFuncInfo;
5929 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5930 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5936 result = TYPE_E_ELEMENTNOTFOUND;
5938 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5939 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5943 /* TypeInfo2::GetVarIndexOfMemId
5945 * Binds to a specific member based on a known DISPID, where the member name
5946 * is not known (for example, when binding to a default member).
5949 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5950 MEMBERID memid, UINT *pVarIndex)
5952 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5953 TLBVarDesc *pVarInfo;
5956 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5957 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5963 result = TYPE_E_ELEMENTNOTFOUND;
5965 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5966 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5970 /* ITypeInfo2::GetCustData
5972 * Gets the custom data
5974 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5979 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5980 TLBCustData *pCData;
5982 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5983 if( IsEqualIID(guid, &pCData->guid)) break;
5985 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5989 VariantInit( pVarVal);
5990 VariantCopy( pVarVal, &pCData->data);
5993 return E_INVALIDARG; /* FIXME: correct? */
5996 /* ITypeInfo2::GetFuncCustData
5998 * Gets the custom data
6000 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6006 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6007 TLBCustData *pCData=NULL;
6008 TLBFuncDesc * pFDesc;
6010 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6011 pFDesc=pFDesc->next);
6014 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6015 if( IsEqualIID(guid, &pCData->guid)) break;
6017 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6020 VariantInit( pVarVal);
6021 VariantCopy( pVarVal, &pCData->data);
6024 return E_INVALIDARG; /* FIXME: correct? */
6027 /* ITypeInfo2::GetParamCustData
6029 * Gets the custom data
6031 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6038 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6039 TLBCustData *pCData=NULL;
6040 TLBFuncDesc * pFDesc;
6043 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6045 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6046 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6047 pCData = pCData->next)
6048 if( IsEqualIID(guid, &pCData->guid)) break;
6050 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6054 VariantInit( pVarVal);
6055 VariantCopy( pVarVal, &pCData->data);
6058 return E_INVALIDARG; /* FIXME: correct? */
6061 /* ITypeInfo2::GetVarCustData
6063 * Gets the custom data
6065 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6071 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6072 TLBCustData *pCData=NULL;
6073 TLBVarDesc * pVDesc;
6076 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6080 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6082 if( IsEqualIID(guid, &pCData->guid)) break;
6086 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6090 VariantInit( pVarVal);
6091 VariantCopy( pVarVal, &pCData->data);
6094 return E_INVALIDARG; /* FIXME: correct? */
6097 /* ITypeInfo2::GetImplCustData
6099 * Gets the custom data
6101 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6107 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6108 TLBCustData *pCData=NULL;
6109 TLBImplType * pRDesc;
6112 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6116 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6118 if( IsEqualIID(guid, &pCData->guid)) break;
6122 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6126 VariantInit( pVarVal);
6127 VariantCopy( pVarVal, &pCData->data);
6130 return E_INVALIDARG; /* FIXME: correct? */
6133 /* ITypeInfo2::GetDocumentation2
6135 * Retrieves the documentation string, the complete Help file name and path,
6136 * the localization context to use, and the context ID for the library Help
6137 * topic in the Help file.
6140 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6144 BSTR *pbstrHelpString,
6145 DWORD *pdwHelpStringContext,
6146 BSTR *pbstrHelpStringDll)
6148 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6149 const TLBFuncDesc *pFDesc;
6150 const TLBVarDesc *pVDesc;
6151 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6152 "HelpStringContext(%p) HelpStringDll(%p)\n",
6153 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6154 pbstrHelpStringDll );
6155 /* the help string should be obtained from the helpstringdll,
6156 * using the _DLLGetDocumentation function, based on the supplied
6157 * lcid. Nice to do sometime...
6159 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6161 *pbstrHelpString=SysAllocString(This->Name);
6162 if(pdwHelpStringContext)
6163 *pdwHelpStringContext=This->dwHelpStringContext;
6164 if(pbstrHelpStringDll)
6165 *pbstrHelpStringDll=
6166 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6168 }else {/* for a member */
6169 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6170 if(pFDesc->funcdesc.memid==memid){
6172 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6173 if(pdwHelpStringContext)
6174 *pdwHelpStringContext=pFDesc->HelpStringContext;
6175 if(pbstrHelpStringDll)
6176 *pbstrHelpStringDll=
6177 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6180 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6181 if(pVDesc->vardesc.memid==memid){
6183 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6184 if(pdwHelpStringContext)
6185 *pdwHelpStringContext=pVDesc->HelpStringContext;
6186 if(pbstrHelpStringDll)
6187 *pbstrHelpStringDll=
6188 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6192 return TYPE_E_ELEMENTNOTFOUND;
6195 /* ITypeInfo2::GetAllCustData
6197 * Gets all custom data items for the Type info.
6200 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6202 CUSTDATA *pCustData)
6204 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6205 TLBCustData *pCData;
6208 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6210 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6211 if(pCustData->prgCustData ){
6212 pCustData->cCustData=This->ctCustData;
6213 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6214 pCustData->prgCustData[i].guid=pCData->guid;
6215 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6218 ERR(" OUT OF MEMORY!\n");
6219 return E_OUTOFMEMORY;
6224 /* ITypeInfo2::GetAllFuncCustData
6226 * Gets all custom data items for the specified Function
6229 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6232 CUSTDATA *pCustData)
6234 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6235 TLBCustData *pCData;
6236 TLBFuncDesc * pFDesc;
6238 TRACE("(%p) index %d\n", This, index);
6239 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6240 pFDesc=pFDesc->next)
6243 pCustData->prgCustData =
6244 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6245 if(pCustData->prgCustData ){
6246 pCustData->cCustData=pFDesc->ctCustData;
6247 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6248 pCData = pCData->next){
6249 pCustData->prgCustData[i].guid=pCData->guid;
6250 VariantCopy(& pCustData->prgCustData[i].varValue,
6254 ERR(" OUT OF MEMORY!\n");
6255 return E_OUTOFMEMORY;
6259 return TYPE_E_ELEMENTNOTFOUND;
6262 /* ITypeInfo2::GetAllParamCustData
6264 * Gets all custom data items for the Functions
6267 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6268 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6270 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6271 TLBCustData *pCData=NULL;
6272 TLBFuncDesc * pFDesc;
6274 TRACE("(%p) index %d\n", This, indexFunc);
6275 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6276 pFDesc=pFDesc->next)
6278 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6279 pCustData->prgCustData =
6280 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6281 sizeof(CUSTDATAITEM));
6282 if(pCustData->prgCustData ){
6283 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6284 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6285 pCData; i++, pCData = pCData->next){
6286 pCustData->prgCustData[i].guid=pCData->guid;
6287 VariantCopy(& pCustData->prgCustData[i].varValue,
6291 ERR(" OUT OF MEMORY!\n");
6292 return E_OUTOFMEMORY;
6296 return TYPE_E_ELEMENTNOTFOUND;
6299 /* ITypeInfo2::GetAllVarCustData
6301 * Gets all custom data items for the specified Variable
6304 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6305 UINT index, CUSTDATA *pCustData)
6307 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6308 TLBCustData *pCData;
6309 TLBVarDesc * pVDesc;
6311 TRACE("(%p) index %d\n", This, index);
6312 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6313 pVDesc=pVDesc->next)
6316 pCustData->prgCustData =
6317 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6318 if(pCustData->prgCustData ){
6319 pCustData->cCustData=pVDesc->ctCustData;
6320 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6321 pCData = pCData->next){
6322 pCustData->prgCustData[i].guid=pCData->guid;
6323 VariantCopy(& pCustData->prgCustData[i].varValue,
6327 ERR(" OUT OF MEMORY!\n");
6328 return E_OUTOFMEMORY;
6332 return TYPE_E_ELEMENTNOTFOUND;
6335 /* ITypeInfo2::GetAllImplCustData
6337 * Gets all custom data items for the specified implementation type
6340 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6343 CUSTDATA *pCustData)
6345 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6346 TLBCustData *pCData;
6347 TLBImplType * pRDesc;
6349 TRACE("(%p) index %d\n", This, index);
6350 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6351 pRDesc=pRDesc->next)
6354 pCustData->prgCustData =
6355 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6356 if(pCustData->prgCustData ){
6357 pCustData->cCustData=pRDesc->ctCustData;
6358 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6359 pCData = pCData->next){
6360 pCustData->prgCustData[i].guid=pCData->guid;
6361 VariantCopy(& pCustData->prgCustData[i].varValue,
6365 ERR(" OUT OF MEMORY!\n");
6366 return E_OUTOFMEMORY;
6370 return TYPE_E_ELEMENTNOTFOUND;
6373 static const ITypeInfo2Vtbl tinfvt =
6376 ITypeInfo_fnQueryInterface,
6378 ITypeInfo_fnRelease,
6380 ITypeInfo_fnGetTypeAttr,
6381 ITypeInfo_fnGetTypeComp,
6382 ITypeInfo_fnGetFuncDesc,
6383 ITypeInfo_fnGetVarDesc,
6384 ITypeInfo_fnGetNames,
6385 ITypeInfo_fnGetRefTypeOfImplType,
6386 ITypeInfo_fnGetImplTypeFlags,
6387 ITypeInfo_fnGetIDsOfNames,
6389 ITypeInfo_fnGetDocumentation,
6390 ITypeInfo_fnGetDllEntry,
6391 ITypeInfo_fnGetRefTypeInfo,
6392 ITypeInfo_fnAddressOfMember,
6393 ITypeInfo_fnCreateInstance,
6394 ITypeInfo_fnGetMops,
6395 ITypeInfo_fnGetContainingTypeLib,
6396 ITypeInfo_fnReleaseTypeAttr,
6397 ITypeInfo_fnReleaseFuncDesc,
6398 ITypeInfo_fnReleaseVarDesc,
6400 ITypeInfo2_fnGetTypeKind,
6401 ITypeInfo2_fnGetTypeFlags,
6402 ITypeInfo2_fnGetFuncIndexOfMemId,
6403 ITypeInfo2_fnGetVarIndexOfMemId,
6404 ITypeInfo2_fnGetCustData,
6405 ITypeInfo2_fnGetFuncCustData,
6406 ITypeInfo2_fnGetParamCustData,
6407 ITypeInfo2_fnGetVarCustData,
6408 ITypeInfo2_fnGetImplTypeCustData,
6409 ITypeInfo2_fnGetDocumentation2,
6410 ITypeInfo2_fnGetAllCustData,
6411 ITypeInfo2_fnGetAllFuncCustData,
6412 ITypeInfo2_fnGetAllParamCustData,
6413 ITypeInfo2_fnGetAllVarCustData,
6414 ITypeInfo2_fnGetAllImplTypeCustData,
6417 /******************************************************************************
6418 * CreateDispTypeInfo [OLEAUT32.31]
6420 * Build type information for an object so it can be called through an
6421 * IDispatch interface.
6424 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6425 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6428 * This call allows an objects methods to be accessed through IDispatch, by
6429 * building an ITypeInfo object that IDispatch can use to call through.
6431 HRESULT WINAPI CreateDispTypeInfo(
6432 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6433 LCID lcid, /* [I] Locale Id */
6434 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6436 ITypeInfoImpl *pTIClass, *pTIIface;
6437 ITypeLibImpl *pTypeLibImpl;
6439 TLBFuncDesc **ppFuncDesc;
6442 pTypeLibImpl = TypeLibImpl_Constructor();
6443 if (!pTypeLibImpl) return E_FAIL;
6445 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6446 pTIIface->pTypeLib = pTypeLibImpl;
6447 pTIIface->index = 0;
6448 pTIIface->Name = NULL;
6449 pTIIface->dwHelpContext = -1;
6450 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6451 pTIIface->TypeAttr.lcid = lcid;
6452 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6453 pTIIface->TypeAttr.wMajorVerNum = 0;
6454 pTIIface->TypeAttr.wMinorVerNum = 0;
6455 pTIIface->TypeAttr.cbAlignment = 2;
6456 pTIIface->TypeAttr.cbSizeInstance = -1;
6457 pTIIface->TypeAttr.cbSizeVft = -1;
6458 pTIIface->TypeAttr.cFuncs = 0;
6459 pTIIface->TypeAttr.cImplTypes = 0;
6460 pTIIface->TypeAttr.cVars = 0;
6461 pTIIface->TypeAttr.wTypeFlags = 0;
6463 ppFuncDesc = &pTIIface->funclist;
6464 for(func = 0; func < pidata->cMembers; func++) {
6465 METHODDATA *md = pidata->pmethdata + func;
6466 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6467 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6468 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6469 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6470 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6471 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6472 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6473 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6474 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6475 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6476 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6477 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6478 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6479 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6480 md->cArgs * sizeof(ELEMDESC));
6481 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6482 md->cArgs * sizeof(TLBParDesc));
6483 for(param = 0; param < md->cArgs; param++) {
6484 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6485 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6487 (*ppFuncDesc)->helpcontext = 0;
6488 (*ppFuncDesc)->HelpStringContext = 0;
6489 (*ppFuncDesc)->HelpString = NULL;
6490 (*ppFuncDesc)->Entry = NULL;
6491 (*ppFuncDesc)->ctCustData = 0;
6492 (*ppFuncDesc)->pCustData = NULL;
6493 (*ppFuncDesc)->next = NULL;
6494 ppFuncDesc = &(*ppFuncDesc)->next;
6497 dump_TypeInfo(pTIIface);
6499 pTypeLibImpl->pTypeInfo = pTIIface;
6500 pTypeLibImpl->TypeInfoCount++;
6502 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6503 pTIClass->pTypeLib = pTypeLibImpl;
6504 pTIClass->index = 1;
6505 pTIClass->Name = NULL;
6506 pTIClass->dwHelpContext = -1;
6507 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6508 pTIClass->TypeAttr.lcid = lcid;
6509 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6510 pTIClass->TypeAttr.wMajorVerNum = 0;
6511 pTIClass->TypeAttr.wMinorVerNum = 0;
6512 pTIClass->TypeAttr.cbAlignment = 2;
6513 pTIClass->TypeAttr.cbSizeInstance = -1;
6514 pTIClass->TypeAttr.cbSizeVft = -1;
6515 pTIClass->TypeAttr.cFuncs = 0;
6516 pTIClass->TypeAttr.cImplTypes = 1;
6517 pTIClass->TypeAttr.cVars = 0;
6518 pTIClass->TypeAttr.wTypeFlags = 0;
6520 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6521 pTIClass->impltypelist->hRef = 1;
6523 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6524 pTIClass->reflist->index = 0;
6525 pTIClass->reflist->reference = 1;
6526 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6528 dump_TypeInfo(pTIClass);
6530 pTIIface->next = pTIClass;
6531 pTypeLibImpl->TypeInfoCount++;
6533 *pptinfo = (ITypeInfo*)pTIClass;
6538 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6540 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6542 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6545 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6547 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6549 return ITypeInfo_AddRef((ITypeInfo *)This);
6552 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6554 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6556 return ITypeInfo_Release((ITypeInfo *)This);
6559 static HRESULT WINAPI ITypeComp_fnBind(
6564 ITypeInfo ** ppTInfo,
6565 DESCKIND * pDescKind,
6568 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6569 const TLBFuncDesc *pFDesc;
6570 const TLBVarDesc *pVDesc;
6571 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6573 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6575 *pDescKind = DESCKIND_NONE;
6576 pBindPtr->lpfuncdesc = NULL;
6579 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6580 if (!strcmpiW(pFDesc->Name, szName)) {
6581 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6584 /* name found, but wrong flags */
6585 hr = TYPE_E_TYPEMISMATCH;
6590 HRESULT hr = TLB_AllocAndInitFuncDesc(
6592 &pBindPtr->lpfuncdesc,
6593 This->TypeAttr.typekind == TKIND_DISPATCH);
6596 *pDescKind = DESCKIND_FUNCDESC;
6597 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6598 ITypeInfo_AddRef(*ppTInfo);
6601 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6602 if (!strcmpiW(pVDesc->Name, szName)) {
6603 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6606 *pDescKind = DESCKIND_VARDESC;
6607 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6608 ITypeInfo_AddRef(*ppTInfo);
6613 /* FIXME: search each inherited interface, not just the first */
6614 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6615 /* recursive search */
6619 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6622 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6623 ITypeInfo_Release(pTInfo);
6627 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6628 ITypeComp_Release(pTComp);
6631 WARN("Could not search inherited interface!\n");
6633 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6637 static HRESULT WINAPI ITypeComp_fnBindType(
6641 ITypeInfo ** ppTInfo,
6642 ITypeComp ** ppTComp)
6644 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6646 /* strange behaviour (does nothing) but like the
6649 if (!ppTInfo || !ppTComp)
6658 static const ITypeCompVtbl tcompvt =
6661 ITypeComp_fnQueryInterface,
6663 ITypeComp_fnRelease,
6666 ITypeComp_fnBindType