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);
2213 FreeLibrary(hinstDLL);
2217 LeaveCriticalSection(&cache_section);
2219 /* now actually load and parse the typelib */
2222 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2223 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2226 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2229 LPVOID pBase = LockResource(hGlobal);
2230 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2234 /* try to load as incore resource */
2235 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2236 if (dwSignature == MSFT_SIGNATURE)
2237 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2238 else if (dwSignature == SLTG_SIGNATURE)
2239 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2241 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2243 FreeResource( hGlobal );
2246 FreeLibrary(hinstDLL);
2250 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2251 if (INVALID_HANDLE_VALUE != hFile)
2253 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2256 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2259 /* retrieve file size */
2260 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2261 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2263 if (dwSignature == MSFT_SIGNATURE)
2264 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2265 else if (dwSignature == SLTG_SIGNATURE)
2266 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2268 UnmapViewOfFile(pBase);
2270 CloseHandle(hMapping);
2277 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2279 TRACE("adding to cache\n");
2280 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2281 lstrcpyW(impl->path, pszPath);
2282 /* We should really canonicalise the path here. */
2283 impl->index = index;
2285 /* FIXME: check if it has added already in the meantime */
2286 EnterCriticalSection(&cache_section);
2287 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2289 tlb_cache_first = impl;
2290 LeaveCriticalSection(&cache_section);
2293 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2298 /*================== ITypeLib(2) Methods ===================================*/
2300 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2302 ITypeLibImpl* pTypeLibImpl;
2304 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2305 if (!pTypeLibImpl) return NULL;
2307 pTypeLibImpl->lpVtbl = &tlbvt;
2308 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2309 pTypeLibImpl->ref = 1;
2311 return pTypeLibImpl;
2314 /****************************************************************************
2315 * ITypeLib2_Constructor_MSFT
2317 * loading an MSFT typelib from an in-memory image
2319 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2323 MSFT_Header tlbHeader;
2324 MSFT_SegDir tlbSegDir;
2325 ITypeLibImpl * pTypeLibImpl;
2327 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2329 pTypeLibImpl = TypeLibImpl_Constructor();
2330 if (!pTypeLibImpl) return NULL;
2332 /* get pointer to beginning of typelib data */
2336 cx.pLibInfo = pTypeLibImpl;
2337 cx.length = dwTLBLength;
2340 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2341 TRACE_(typelib)("header:\n");
2342 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2343 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2344 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2347 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2349 /* there is a small amount of information here until the next important
2351 * the segment directory . Try to calculate the amount of data */
2352 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2354 /* now read the segment directory */
2355 TRACE("read segment directory (at %ld)\n",lPSegDir);
2356 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2357 cx.pTblDir = &tlbSegDir;
2359 /* just check two entries */
2360 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2362 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2363 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2367 /* now fill our internal data */
2368 /* TLIBATTR fields */
2369 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2371 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2372 /* Windows seems to have zero here, is this correct? */
2373 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2374 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2376 pTypeLibImpl->LibAttr.lcid = 0;
2378 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2379 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2380 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2381 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2383 /* name, eventually add to a hash table */
2384 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2387 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2388 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2390 if( tlbHeader.varflags & HELPDLLFLAG)
2393 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2394 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2397 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2400 if(tlbHeader.CustomDataOffset >= 0)
2402 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2405 /* fill in typedescriptions */
2406 if(tlbSegDir.pTypdescTab.length > 0)
2408 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2410 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2411 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2414 /* FIXME: add several sanity checks here */
2415 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2416 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2418 /* FIXME: check safearray */
2420 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2422 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2424 else if(td[0] == VT_CARRAY)
2426 /* array descr table here */
2427 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2429 else if(td[0] == VT_USERDEFINED)
2431 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2433 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2436 /* second time around to fill the array subscript info */
2439 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2440 if(tlbSegDir.pArrayDescriptions.offset>0)
2442 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2443 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2446 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2448 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2450 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2452 for(j = 0; j<td[2]; j++)
2454 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2455 sizeof(INT), &cx, DO_NOT_SEEK);
2456 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2457 sizeof(INT), &cx, DO_NOT_SEEK);
2462 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2463 ERR("didn't find array description data\n");
2468 /* imported type libs */
2469 if(tlbSegDir.pImpFiles.offset>0)
2471 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2472 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2475 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2480 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2481 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2482 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2484 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2485 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2486 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2487 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2490 name = TLB_Alloc(size+1);
2491 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2492 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2493 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2494 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2497 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2498 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2500 ppImpLib = &(*ppImpLib)->next;
2505 if(tlbHeader.nrtypeinfos >= 0 )
2507 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2508 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2511 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2513 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2515 ppTI = &((*ppTI)->next);
2516 (pTypeLibImpl->TypeInfoCount)++;
2520 TRACE("(%p)\n", pTypeLibImpl);
2521 return (ITypeLib2*) pTypeLibImpl;
2525 static BSTR TLB_MultiByteToBSTR(char *ptr)
2531 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2532 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2533 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2534 ret = SysAllocString(nameW);
2535 HeapFree(GetProcessHeap(), 0, nameW);
2539 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2545 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2546 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2550 guid->Data4[0] = s >> 8;
2551 guid->Data4[1] = s & 0xff;
2554 for(i = 0; i < 6; i++) {
2555 memcpy(b, str + 24 + 2 * i, 2);
2556 guid->Data4[i + 2] = strtol(b, NULL, 16);
2561 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2568 bytelen = *(WORD*)ptr;
2569 if(bytelen == 0xffff) return 2;
2570 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2571 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2572 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2573 *pBstr = SysAllocStringLen(nameW, len);
2574 HeapFree(GetProcessHeap(), 0, nameW);
2578 static WORD SLTG_ReadStringA(char *ptr, char **str)
2583 bytelen = *(WORD*)ptr;
2584 if(bytelen == 0xffff) return 2;
2585 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2586 memcpy(*str, ptr + 2, bytelen);
2587 (*str)[bytelen] = '\0';
2591 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2593 char *ptr = pLibBlk;
2596 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2597 FIXME("libblk magic = %04x\n", w);
2602 if((w = *(WORD*)ptr) != 0xffff) {
2603 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2608 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2610 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2612 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2615 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2618 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2619 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2621 pTypeLibImpl->LibAttr.lcid = 0;
2624 ptr += 4; /* skip res12 */
2626 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2629 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2632 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2635 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2636 ptr += sizeof(GUID);
2638 return ptr - (char*)pLibBlk;
2641 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2646 if((*pType & 0xe00) == 0xe00) {
2648 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2650 pTD = pTD->u.lptdesc;
2652 switch(*pType & 0x3f) {
2655 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2657 pTD = pTD->u.lptdesc;
2660 case VT_USERDEFINED:
2661 pTD->vt = VT_USERDEFINED;
2662 pTD->u.hreftype = *(++pType) / 4;
2668 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2671 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2673 pTD->vt = VT_CARRAY;
2674 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2676 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2677 pTD->u.lpadesc->cDims = pSA->cDims;
2678 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2679 pSA->cDims * sizeof(SAFEARRAYBOUND));
2681 pTD = &pTD->u.lpadesc->tdescElem;
2687 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2691 pTD->vt = VT_SAFEARRAY;
2692 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2694 pTD = pTD->u.lptdesc;
2698 pTD->vt = *pType & 0x3f;
2707 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2709 /* Handle [in/out] first */
2710 if((*pType & 0xc000) == 0xc000)
2711 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2712 else if(*pType & 0x8000)
2713 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2714 else if(*pType & 0x4000)
2715 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2717 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2720 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2723 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2725 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2729 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2734 TLBRefType **ppRefType;
2736 if(pRef->magic != SLTG_REF_MAGIC) {
2737 FIXME("Ref magic = %x\n", pRef->magic);
2740 name = ( (char*)(&pRef->names) + pRef->number);
2742 ppRefType = &pTI->reflist;
2743 for(ref = 0; ref < pRef->number >> 3; ref++) {
2745 unsigned int lib_offs, type_num;
2747 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2748 sizeof(**ppRefType));
2750 name += SLTG_ReadStringA(name, &refname);
2751 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2752 FIXME("Can't sscanf ref\n");
2753 if(lib_offs != 0xffff) {
2754 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2757 if((*import)->offset == lib_offs)
2759 import = &(*import)->next;
2762 char fname[MAX_PATH+1];
2765 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2767 (*import)->offset = lib_offs;
2768 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2770 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2771 &(*import)->wVersionMajor,
2772 &(*import)->wVersionMinor,
2773 &(*import)->lcid, fname) != 4) {
2774 FIXME("can't sscanf ref %s\n",
2775 pNameTable + lib_offs + 40);
2777 len = strlen(fname);
2778 if(fname[len-1] != '#')
2779 FIXME("fname = %s\n", fname);
2780 fname[len-1] = '\0';
2781 (*import)->name = TLB_MultiByteToBSTR(fname);
2783 (*ppRefType)->pImpTLInfo = *import;
2784 } else { /* internal ref */
2785 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2787 (*ppRefType)->reference = ref;
2788 (*ppRefType)->index = type_num;
2790 HeapFree(GetProcessHeap(), 0, refname);
2791 ppRefType = &(*ppRefType)->next;
2793 if((BYTE)*name != SLTG_REF_MAGIC)
2794 FIXME("End of ref block magic = %x\n", *name);
2795 dump_TLBRefType(pTI->reflist);
2798 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2801 SLTG_ImplInfo *info;
2802 TLBImplType **ppImplType = &pTI->impltypelist;
2803 /* I don't really get this structure, usually it's 0x16 bytes
2804 long, but iuser.tlb contains some that are 0x18 bytes long.
2805 That's ok because we can use the next ptr to jump to the next
2806 one. But how do we know the length of the last one? The WORD
2807 at offs 0x8 might be the clue. For now I'm just assuming that
2808 the last one is the regular 0x16 bytes. */
2810 info = (SLTG_ImplInfo*)pBlk;
2812 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2813 sizeof(**ppImplType));
2814 (*ppImplType)->hRef = info->ref;
2815 (*ppImplType)->implflags = info->impltypeflags;
2816 pTI->TypeAttr.cImplTypes++;
2817 ppImplType = &(*ppImplType)->next;
2819 if(info->next == 0xffff)
2822 FIXME("Interface inheriting more than one interface\n");
2823 info = (SLTG_ImplInfo*)(pBlk + info->next);
2825 info++; /* see comment at top of function */
2829 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2831 TLBVarDesc **ppVarDesc = &pTI->varlist;
2832 BSTR bstrPrevName = NULL;
2833 SLTG_Variable *pItem;
2838 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2839 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2841 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2842 sizeof(**ppVarDesc));
2843 (*ppVarDesc)->vardesc.memid = pItem->memid;
2845 if (pItem->magic != SLTG_VAR_MAGIC &&
2846 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2847 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2851 if (pItem->name == 0xfffe)
2852 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2854 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2856 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2857 TRACE_(typelib)("memid = 0x%lx\n", pItem->memid);
2859 if (pItem->flags & 0x40) {
2860 TRACE_(typelib)("VAR_DISPATCH\n");
2861 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2863 else if (pItem->flags & 0x10) {
2864 TRACE_(typelib)("VAR_CONST\n");
2865 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2866 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2868 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2869 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2870 *(INT*)(pBlk + pItem->byte_offs);
2873 TRACE_(typelib)("VAR_PERINSTANCE\n");
2874 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2875 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2878 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2879 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2881 if (pItem->flags & 0x80)
2882 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2884 if(pItem->flags & 0x02)
2885 pType = &pItem->type;
2887 pType = (WORD*)(pBlk + pItem->type);
2889 if (pItem->flags & ~0xd2)
2890 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2892 SLTG_DoElem(pType, pBlk,
2893 &(*ppVarDesc)->vardesc.elemdescVar);
2895 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2897 bstrPrevName = (*ppVarDesc)->Name;
2898 ppVarDesc = &((*ppVarDesc)->next);
2900 pTI->TypeAttr.cVars = cVars;
2903 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2905 SLTG_Function *pFunc;
2907 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2909 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2910 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2915 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2916 sizeof(**ppFuncDesc));
2918 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2919 case SLTG_FUNCTION_MAGIC:
2920 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2922 case SLTG_DISPATCH_FUNCTION_MAGIC:
2923 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2925 case SLTG_STATIC_FUNCTION_MAGIC:
2926 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2929 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2930 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2934 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2936 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2937 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2938 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2939 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2940 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2941 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2943 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2944 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2946 if(pFunc->retnextopt & 0x80)
2947 pType = &pFunc->rettype;
2949 pType = (WORD*)(pBlk + pFunc->rettype);
2951 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2953 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2954 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2955 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2956 (*ppFuncDesc)->pParamDesc =
2957 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2958 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2960 pArg = (WORD*)(pBlk + pFunc->arg_off);
2962 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2963 char *paramName = pNameTable + *pArg;
2965 /* If arg type follows then paramName points to the 2nd
2966 letter of the name, else the next WORD is an offset to
2967 the arg type and paramName points to the first letter.
2968 So let's take one char off paramName and see if we're
2969 pointing at an alpha-numeric char. However if *pArg is
2970 0xffff or 0xfffe then the param has no name, the former
2971 meaning that the next WORD is the type, the latter
2972 meaning the the next WORD is an offset to the type. */
2977 else if(*pArg == 0xfffe) {
2981 else if(paramName[-1] && !isalnum(paramName[-1]))
2986 if(HaveOffs) { /* the next word is an offset to type */
2987 pType = (WORD*)(pBlk + *pArg);
2988 SLTG_DoElem(pType, pBlk,
2989 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2994 pArg = SLTG_DoElem(pArg, pBlk,
2995 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2998 /* Are we an optional param ? */
2999 if((*ppFuncDesc)->funcdesc.cParams - param <=
3000 (*ppFuncDesc)->funcdesc.cParamsOpt)
3001 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3004 (*ppFuncDesc)->pParamDesc[param].Name =
3005 TLB_MultiByteToBSTR(paramName);
3009 ppFuncDesc = &((*ppFuncDesc)->next);
3010 if(pFunc->next == 0xffff) break;
3012 pTI->TypeAttr.cFuncs = cFuncs;
3015 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3016 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3017 SLTG_TypeInfoTail *pTITail)
3019 char *pFirstItem, *pNextItem;
3021 if(pTIHeader->href_table != 0xffffffff) {
3022 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3026 pFirstItem = pNextItem = pBlk;
3028 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3029 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3034 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3035 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3036 SLTG_TypeInfoTail *pTITail)
3038 char *pFirstItem, *pNextItem;
3040 if(pTIHeader->href_table != 0xffffffff) {
3041 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3045 pFirstItem = pNextItem = pBlk;
3047 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3048 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3051 if (pTITail->funcs_off != 0xffff)
3052 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3054 if (TRACE_ON(typelib))
3055 dump_TLBFuncDesc(pTI->funclist);
3058 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3059 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3060 SLTG_TypeInfoTail *pTITail)
3062 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3065 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3066 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3067 SLTG_TypeInfoTail *pTITail)
3071 if (pTITail->simple_alias) {
3072 /* if simple alias, no more processing required */
3073 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3077 if(pTIHeader->href_table != 0xffffffff) {
3078 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3082 /* otherwise it is an offset to a type */
3083 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3085 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3088 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3089 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3090 SLTG_TypeInfoTail *pTITail)
3092 if (pTIHeader->href_table != 0xffffffff)
3093 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3096 if (pTITail->vars_off != 0xffff)
3097 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3099 if (pTITail->funcs_off != 0xffff)
3100 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3102 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3103 * of dispinterface functons including the IDispatch ones, so
3104 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3105 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3107 if (TRACE_ON(typelib))
3108 dump_TLBFuncDesc(pTI->funclist);
3111 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3112 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3113 SLTG_TypeInfoTail *pTITail)
3115 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3118 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3119 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3120 SLTG_TypeInfoTail *pTITail)
3122 if (pTIHeader->href_table != 0xffffffff)
3123 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3126 if (pTITail->vars_off != 0xffff)
3127 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3129 if (pTITail->funcs_off != 0xffff)
3130 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3133 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3134 managable copy of it into this */
3147 } SLTG_InternalOtherTypeInfo;
3149 /****************************************************************************
3150 * ITypeLib2_Constructor_SLTG
3152 * loading a SLTG typelib from an in-memory image
3154 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3156 ITypeLibImpl *pTypeLibImpl;
3157 SLTG_Header *pHeader;
3158 SLTG_BlkEntry *pBlkEntry;
3162 LPVOID pBlk, pFirstBlk;
3163 SLTG_LibBlk *pLibBlk;
3164 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3165 char *pAfterOTIBlks = NULL;
3166 char *pNameTable, *ptr;
3169 ITypeInfoImpl **ppTypeInfoImpl;
3171 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3174 pTypeLibImpl = TypeLibImpl_Constructor();
3175 if (!pTypeLibImpl) return NULL;
3179 TRACE_(typelib)("header:\n");
3180 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3181 pHeader->nrOfFileBlks );
3182 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3183 FIXME("Header type magic 0x%08lx not supported.\n",
3184 pHeader->SLTG_magic);
3188 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3189 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3191 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3192 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3194 /* Next we have a magic block */
3195 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3197 /* Let's see if we're still in sync */
3198 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3199 sizeof(SLTG_COMPOBJ_MAGIC))) {
3200 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3203 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3204 sizeof(SLTG_DIR_MAGIC))) {
3205 FIXME("dir magic = %s\n", pMagic->dir_magic);
3209 pIndex = (SLTG_Index*)(pMagic+1);
3211 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3213 pFirstBlk = (LPVOID)(pPad9 + 1);
3215 /* We'll set up a ptr to the main library block, which is the last one. */
3217 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3218 pBlkEntry[order].next != 0;
3219 order = pBlkEntry[order].next - 1, i++) {
3220 pBlk = (char*)pBlk + pBlkEntry[order].len;
3224 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3226 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3231 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3233 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3234 sizeof(*pOtherTypeInfoBlks) *
3235 pTypeLibImpl->TypeInfoCount);
3238 ptr = (char*)pLibBlk + len;
3240 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3244 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3246 w = *(WORD*)(ptr + 2);
3249 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3251 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3252 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3254 w = *(WORD*)(ptr + 4 + len);
3256 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3258 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3260 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3261 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3263 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3264 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3265 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3267 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3269 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3272 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3273 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3274 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3275 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3276 len += sizeof(SLTG_OtherTypeInfo);
3280 pAfterOTIBlks = ptr;
3282 /* Skip this WORD and get the next DWORD */
3283 len = *(DWORD*)(pAfterOTIBlks + 2);
3285 /* Now add this to pLibBLk look at what we're pointing at and
3286 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3287 dust and we should be pointing at the beginning of the name
3290 pNameTable = (char*)pLibBlk + len;
3292 switch(*(WORD*)pNameTable) {
3299 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3303 pNameTable += 0x216;
3307 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3309 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3312 /* Hopefully we now have enough ptrs set up to actually read in
3313 some TypeInfos. It's not clear which order to do them in, so
3314 I'll just follow the links along the BlkEntry chain and read
3315 them in in the order in which they're in the file */
3317 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3319 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3320 pBlkEntry[order].next != 0;
3321 order = pBlkEntry[order].next - 1, i++) {
3323 SLTG_TypeInfoHeader *pTIHeader;
3324 SLTG_TypeInfoTail *pTITail;
3325 SLTG_MemberHeader *pMemHeader;
3327 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3328 pOtherTypeInfoBlks[i].index_name)) {
3329 FIXME("Index strings don't match\n");
3334 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3335 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3338 TRACE("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
3339 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3341 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3342 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3343 (*ppTypeInfoImpl)->index = i;
3344 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3345 pOtherTypeInfoBlks[i].name_offs +
3347 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3348 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3350 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3351 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3352 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3353 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3354 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3356 if((pTIHeader->typeflags1 & 7) != 2)
3357 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3358 if(pTIHeader->typeflags3 != 2)
3359 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3361 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3362 debugstr_w((*ppTypeInfoImpl)->Name),
3363 typekind_desc[pTIHeader->typekind],
3364 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3365 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3367 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3369 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3371 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3372 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3373 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3375 switch(pTIHeader->typekind) {
3377 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3378 pTIHeader, pTITail);
3382 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3383 pTIHeader, pTITail);
3386 case TKIND_INTERFACE:
3387 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3388 pTIHeader, pTITail);
3392 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3393 pTIHeader, pTITail);
3397 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3398 pTIHeader, pTITail);
3401 case TKIND_DISPATCH:
3402 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3403 pTIHeader, pTITail);
3407 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3408 pTIHeader, pTITail);
3412 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3417 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3418 but we've already set those */
3419 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3434 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3435 pBlk = (char*)pBlk + pBlkEntry[order].len;
3438 if(i != pTypeLibImpl->TypeInfoCount) {
3439 FIXME("Somehow processed %d TypeInfos\n", i);
3443 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3444 return (ITypeLib2*)pTypeLibImpl;
3447 /* ITypeLib::QueryInterface
3449 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3454 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3456 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3459 if(IsEqualIID(riid, &IID_IUnknown) ||
3460 IsEqualIID(riid,&IID_ITypeLib)||
3461 IsEqualIID(riid,&IID_ITypeLib2))
3468 ITypeLib2_AddRef(iface);
3469 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3472 TRACE("-- Interface: E_NOINTERFACE\n");
3473 return E_NOINTERFACE;
3478 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3480 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3481 ULONG ref = InterlockedIncrement(&This->ref);
3483 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3488 /* ITypeLib::Release
3490 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3492 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3493 ULONG ref = InterlockedDecrement(&This->ref);
3495 TRACE("(%p)->(%lu)\n",This, ref);
3499 /* remove cache entry */
3502 TRACE("removing from cache list\n");
3503 EnterCriticalSection(&cache_section);
3504 if (This->next) This->next->prev = This->prev;
3505 if (This->prev) This->prev->next = This->next;
3506 else tlb_cache_first = This->next;
3507 LeaveCriticalSection(&cache_section);
3508 HeapFree(GetProcessHeap(), 0, This->path);
3510 /* FIXME destroy child objects */
3511 TRACE(" destroying ITypeLib(%p)\n",This);
3515 SysFreeString(This->Name);
3519 if (This->DocString)
3521 SysFreeString(This->DocString);
3522 This->DocString = NULL;
3527 SysFreeString(This->HelpFile);
3528 This->HelpFile = NULL;
3531 if (This->HelpStringDll)
3533 SysFreeString(This->HelpStringDll);
3534 This->HelpStringDll = NULL;
3537 if (This->pTypeInfo) /* can be NULL */
3538 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3539 HeapFree(GetProcessHeap(),0,This);
3546 /* ITypeLib::GetTypeInfoCount
3548 * Returns the number of type descriptions in the type library
3550 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3552 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3553 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3554 return This->TypeInfoCount;
3557 /* ITypeLib::GetTypeInfo
3559 * retrieves the specified type description in the library.
3561 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3564 ITypeInfo **ppTInfo)
3568 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3569 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3571 TRACE("(%p)->(index=%d)\n", This, index);
3573 if (!ppTInfo) return E_INVALIDARG;
3575 /* search element n in list */
3576 for(i=0; i < index; i++)
3578 pTypeInfo = pTypeInfo->next;
3581 TRACE("-- element not found\n");
3582 return TYPE_E_ELEMENTNOTFOUND;
3586 *ppTInfo = (ITypeInfo *) pTypeInfo;
3588 ITypeInfo_AddRef(*ppTInfo);
3589 TRACE("-- found (%p)\n",*ppTInfo);
3594 /* ITypeLibs::GetTypeInfoType
3596 * Retrieves the type of a type description.
3598 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3603 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3605 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3607 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3608 return TYPE_E_ELEMENTNOTFOUND;
3610 TRACE("(%p) index %d\n", This, index);
3612 if(!pTKind) return E_INVALIDARG;
3614 /* search element n in list */
3615 for(i=0; i < index; i++)
3619 TRACE("-- element not found\n");
3620 return TYPE_E_ELEMENTNOTFOUND;
3622 pTInfo = pTInfo->next;
3625 *pTKind = pTInfo->TypeAttr.typekind;
3626 TRACE("-- found Type (%d)\n", *pTKind);
3630 /* ITypeLib::GetTypeInfoOfGuid
3632 * Retrieves the type description that corresponds to the specified GUID.
3635 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3638 ITypeInfo **ppTInfo)
3640 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3641 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3643 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3647 WARN("-- element not found\n");
3648 return TYPE_E_ELEMENTNOTFOUND;
3651 /* search linked list for guid */
3652 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3654 pTypeInfo = pTypeInfo->next;
3658 /* end of list reached */
3659 WARN("-- element not found\n");
3660 return TYPE_E_ELEMENTNOTFOUND;
3664 TRACE("-- found (%p, %s)\n",
3666 debugstr_w(pTypeInfo->Name));
3668 *ppTInfo = (ITypeInfo*)pTypeInfo;
3669 ITypeInfo_AddRef(*ppTInfo);
3673 /* ITypeLib::GetLibAttr
3675 * Retrieves the structure that contains the library's attributes.
3678 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3680 LPTLIBATTR *ppTLibAttr)
3682 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3683 TRACE("(%p)\n",This);
3684 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3685 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3689 /* ITypeLib::GetTypeComp
3691 * Enables a client compiler to bind to a library's types, variables,
3692 * constants, and global functions.
3695 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3697 ITypeComp **ppTComp)
3699 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3701 TRACE("(%p)->(%p)\n",This,ppTComp);
3702 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3703 ITypeComp_AddRef(*ppTComp);
3708 /* ITypeLib::GetDocumentation
3710 * Retrieves the library's documentation string, the complete Help file name
3711 * and path, and the context identifier for the library Help topic in the Help
3714 * On a successful return all non-null BSTR pointers will have been set,
3717 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3721 BSTR *pBstrDocString,
3722 DWORD *pdwHelpContext,
3723 BSTR *pBstrHelpFile)
3725 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3727 HRESULT result = E_INVALIDARG;
3732 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3734 pBstrName, pBstrDocString,
3735 pdwHelpContext, pBstrHelpFile);
3739 /* documentation for the typelib */
3744 if(!(*pBstrName = SysAllocString(This->Name)))
3752 if (This->DocString)
3754 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3757 else if (This->Name)
3759 if(!(*pBstrDocString = SysAllocString(This->Name)))
3763 *pBstrDocString = NULL;
3767 *pdwHelpContext = This->dwHelpContext;
3773 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3777 *pBstrHelpFile = NULL;
3784 /* for a typeinfo */
3785 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3787 if(SUCCEEDED(result))
3789 result = ITypeInfo_GetDocumentation(pTInfo,
3793 pdwHelpContext, pBstrHelpFile);
3795 ITypeInfo_Release(pTInfo);
3800 if (pBstrDocString) SysFreeString (*pBstrDocString);
3802 if (pBstrName) SysFreeString (*pBstrName);
3804 return STG_E_INSUFFICIENTMEMORY;
3809 * Indicates whether a passed-in string contains the name of a type or member
3810 * described in the library.
3813 static HRESULT WINAPI ITypeLib2_fnIsName(
3819 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3820 ITypeInfoImpl *pTInfo;
3821 TLBFuncDesc *pFInfo;
3824 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3826 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3830 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3831 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3832 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3833 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3834 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3835 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3836 goto ITypeLib2_fnIsName_exit;
3838 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3839 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3844 ITypeLib2_fnIsName_exit:
3845 TRACE("(%p)slow! search for %s: %s found!\n", This,
3846 debugstr_w(szNameBuf), *pfName?"NOT":"");
3851 /* ITypeLib::FindName
3853 * Finds occurrences of a type description in a type library. This may be used
3854 * to quickly verify that a name exists in a type library.
3857 static HRESULT WINAPI ITypeLib2_fnFindName(
3861 ITypeInfo **ppTInfo,
3865 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3866 ITypeInfoImpl *pTInfo;
3867 TLBFuncDesc *pFInfo;
3870 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3872 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3873 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3874 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3875 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3876 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3877 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3878 goto ITypeLib2_fnFindName_exit;
3881 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3882 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3884 ITypeLib2_fnFindName_exit:
3885 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3886 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3889 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3890 This, *pcFound, debugstr_w(szNameBuf), j);
3897 /* ITypeLib::ReleaseTLibAttr
3899 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3902 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3904 TLIBATTR *pTLibAttr)
3906 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3907 TRACE("freeing (%p)\n",This);
3908 HeapFree(GetProcessHeap(),0,pTLibAttr);
3912 /* ITypeLib2::GetCustData
3914 * gets the custom data
3916 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3921 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3922 TLBCustData *pCData;
3924 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3926 if( IsEqualIID(guid, &pCData->guid)) break;
3929 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3933 VariantInit( pVarVal);
3934 VariantCopy( pVarVal, &pCData->data);
3937 return E_INVALIDARG; /* FIXME: correct? */
3940 /* ITypeLib2::GetLibStatistics
3942 * Returns statistics about a type library that are required for efficient
3943 * sizing of hash tables.
3946 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3948 ULONG *pcUniqueNames,
3949 ULONG *pcchUniqueNames)
3951 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3953 FIXME("(%p): stub!\n", This);
3955 if(pcUniqueNames) *pcUniqueNames=1;
3956 if(pcchUniqueNames) *pcchUniqueNames=1;
3960 /* ITypeLib2::GetDocumentation2
3962 * Retrieves the library's documentation string, the complete Help file name
3963 * and path, the localization context to use, and the context ID for the
3964 * library Help topic in the Help file.
3967 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3971 BSTR *pbstrHelpString,
3972 DWORD *pdwHelpStringContext,
3973 BSTR *pbstrHelpStringDll)
3975 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3979 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3981 /* the help string should be obtained from the helpstringdll,
3982 * using the _DLLGetDocumentation function, based on the supplied
3983 * lcid. Nice to do sometime...
3987 /* documentation for the typelib */
3989 *pbstrHelpString=SysAllocString(This->DocString);
3990 if(pdwHelpStringContext)
3991 *pdwHelpStringContext=This->dwHelpContext;
3992 if(pbstrHelpStringDll)
3993 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3999 /* for a typeinfo */
4000 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4002 if(SUCCEEDED(result))
4004 ITypeInfo2 * pTInfo2;
4005 result = ITypeInfo_QueryInterface(pTInfo,
4007 (LPVOID*) &pTInfo2);
4009 if(SUCCEEDED(result))
4011 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4015 pdwHelpStringContext,
4016 pbstrHelpStringDll);
4018 ITypeInfo2_Release(pTInfo2);
4021 ITypeInfo_Release(pTInfo);
4027 /* ITypeLib2::GetAllCustData
4029 * Gets all custom data items for the library.
4032 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4034 CUSTDATA *pCustData)
4036 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4037 TLBCustData *pCData;
4039 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4040 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4041 if(pCustData->prgCustData ){
4042 pCustData->cCustData=This->ctCustData;
4043 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4044 pCustData->prgCustData[i].guid=pCData->guid;
4045 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4048 ERR(" OUT OF MEMORY!\n");
4049 return E_OUTOFMEMORY;
4054 static const ITypeLib2Vtbl tlbvt = {
4055 ITypeLib2_fnQueryInterface,
4057 ITypeLib2_fnRelease,
4058 ITypeLib2_fnGetTypeInfoCount,
4059 ITypeLib2_fnGetTypeInfo,
4060 ITypeLib2_fnGetTypeInfoType,
4061 ITypeLib2_fnGetTypeInfoOfGuid,
4062 ITypeLib2_fnGetLibAttr,
4063 ITypeLib2_fnGetTypeComp,
4064 ITypeLib2_fnGetDocumentation,
4066 ITypeLib2_fnFindName,
4067 ITypeLib2_fnReleaseTLibAttr,
4069 ITypeLib2_fnGetCustData,
4070 ITypeLib2_fnGetLibStatistics,
4071 ITypeLib2_fnGetDocumentation2,
4072 ITypeLib2_fnGetAllCustData
4076 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4078 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4080 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4083 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4085 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4087 return ITypeLib2_AddRef((ITypeLib2 *)This);
4090 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4092 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4094 return ITypeLib2_Release((ITypeLib2 *)This);
4097 static HRESULT WINAPI ITypeLibComp_fnBind(
4102 ITypeInfo ** ppTInfo,
4103 DESCKIND * pDescKind,
4106 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4107 ITypeInfoImpl *pTypeInfo;
4109 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4111 *pDescKind = DESCKIND_NONE;
4112 pBindPtr->lptcomp = NULL;
4115 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4117 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4119 /* FIXME: check wFlags here? */
4120 /* FIXME: we should use a hash table to look this info up using lHash
4121 * instead of an O(n) search */
4122 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4123 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4125 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4127 *pDescKind = DESCKIND_TYPECOMP;
4128 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4129 ITypeComp_AddRef(pBindPtr->lptcomp);
4130 TRACE("module or enum: %s\n", debugstr_w(szName));
4135 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4136 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4138 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4141 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4142 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4144 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4149 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4150 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4152 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4154 ITypeInfo *subtypeinfo;
4156 DESCKIND subdesckind;
4158 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4159 &subtypeinfo, &subdesckind, &subbindptr);
4160 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4162 TYPEDESC tdesc_appobject =
4165 (TYPEDESC *)pTypeInfo->hreftype
4169 const VARDESC vardesc_appobject =
4172 NULL, /* lpstrSchema */
4187 VAR_STATIC /* varkind */
4190 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4192 /* cleanup things filled in by Bind call so we can put our
4193 * application object data in there instead */
4194 switch (subdesckind)
4196 case DESCKIND_FUNCDESC:
4197 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4199 case DESCKIND_VARDESC:
4200 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4205 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4207 if (pTypeInfo->hreftype == -1)
4208 FIXME("no hreftype for interface %p\n", pTypeInfo);
4210 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4214 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4215 *ppTInfo = (ITypeInfo *)pTypeInfo;
4216 ITypeInfo_AddRef(*ppTInfo);
4222 TRACE("name not found %s\n", debugstr_w(szName));
4226 static HRESULT WINAPI ITypeLibComp_fnBindType(
4230 ITypeInfo ** ppTInfo,
4231 ITypeComp ** ppTComp)
4233 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4237 static const ITypeCompVtbl tlbtcvt =
4240 ITypeLibComp_fnQueryInterface,
4241 ITypeLibComp_fnAddRef,
4242 ITypeLibComp_fnRelease,
4244 ITypeLibComp_fnBind,
4245 ITypeLibComp_fnBindType
4248 /*================== ITypeInfo(2) Methods ===================================*/
4249 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4251 ITypeInfoImpl * pTypeInfoImpl;
4253 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4256 pTypeInfoImpl->lpVtbl = &tinfvt;
4257 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4258 pTypeInfoImpl->ref=1;
4259 pTypeInfoImpl->hreftype = -1;
4260 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4261 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4263 TRACE("(%p)\n", pTypeInfoImpl);
4264 return (ITypeInfo2*) pTypeInfoImpl;
4267 /* ITypeInfo::QueryInterface
4269 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4274 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4276 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4279 if(IsEqualIID(riid, &IID_IUnknown) ||
4280 IsEqualIID(riid,&IID_ITypeInfo)||
4281 IsEqualIID(riid,&IID_ITypeInfo2))
4285 ITypeInfo_AddRef(iface);
4286 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4289 TRACE("-- Interface: E_NOINTERFACE\n");
4290 return E_NOINTERFACE;
4293 /* ITypeInfo::AddRef
4295 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4297 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4298 ULONG ref = InterlockedIncrement(&This->ref);
4300 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4302 TRACE("(%p)->ref is %lu\n",This, ref);
4306 /* ITypeInfo::Release
4308 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4310 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4311 ULONG ref = InterlockedDecrement(&This->ref);
4313 TRACE("(%p)->(%lu)\n",This, ref);
4316 /* We don't release ITypeLib when ref=0 because
4317 it means that function is called by ITypeLib2_Release */
4318 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4320 static int once = 0;
4324 FIXME("destroy child objects\n");
4327 TRACE("destroying ITypeInfo(%p)\n",This);
4330 SysFreeString(This->Name);
4334 if (This->DocString)
4336 SysFreeString(This->DocString);
4337 This->DocString = 0;
4342 SysFreeString(This->DllName);
4348 ITypeInfo_Release((ITypeInfo*)This->next);
4351 HeapFree(GetProcessHeap(),0,This);
4357 /* ITypeInfo::GetTypeAttr
4359 * Retrieves a TYPEATTR structure that contains the attributes of the type
4363 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4364 LPTYPEATTR *ppTypeAttr)
4366 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4369 TRACE("(%p)\n",This);
4371 size = sizeof(**ppTypeAttr);
4372 if (This->TypeAttr.typekind == TKIND_ALIAS)
4373 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4375 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4377 return E_OUTOFMEMORY;
4379 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4381 if (This->TypeAttr.typekind == TKIND_ALIAS)
4382 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4383 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4385 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4386 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4388 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4389 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4394 /* ITypeInfo::GetTypeComp
4396 * Retrieves the ITypeComp interface for the type description, which enables a
4397 * client compiler to bind to the type description's members.
4400 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4401 ITypeComp * *ppTComp)
4403 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4405 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4407 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4408 ITypeComp_AddRef(*ppTComp);
4412 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4414 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4415 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4416 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4420 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4422 memcpy(dest, src, sizeof(ELEMDESC));
4423 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4424 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4426 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4427 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4428 *buffer += sizeof(PARAMDESCEX);
4429 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4430 VariantInit(&pparamdescex_dest->varDefaultValue);
4431 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4432 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4435 dest->u.paramdesc.pparamdescex = NULL;
4439 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4441 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4442 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4445 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4449 SIZE_T size = sizeof(*src);
4453 size += sizeof(*src->lprgscode) * src->cScodes;
4454 size += TLB_SizeElemDesc(&src->elemdescFunc);
4455 for (i = 0; i < src->cParams; i++)
4457 size += sizeof(ELEMDESC);
4458 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4461 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4462 if (!dest) return E_OUTOFMEMORY;
4464 memcpy(dest, src, sizeof(FUNCDESC));
4465 buffer = (char *)(dest + 1);
4467 dest->lprgscode = (SCODE *)buffer;
4468 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4469 buffer += sizeof(*src->lprgscode) * src->cScodes;
4471 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4474 SysFreeString((BSTR)dest);
4478 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4479 buffer += sizeof(ELEMDESC) * src->cParams;
4480 for (i = 0; i < src->cParams; i++)
4482 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4488 /* undo the above actions */
4489 for (i = i - 1; i >= 0; i--)
4490 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4491 TLB_FreeElemDesc(&dest->elemdescFunc);
4492 SysFreeString((BSTR)dest);
4496 /* special treatment for dispinterfaces: this makes functions appear
4497 * to return their [retval] value when it is really returning an
4499 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4501 if (dest->cParams &&
4502 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4504 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4505 if (elemdesc->tdesc.vt != VT_PTR)
4507 ERR("elemdesc should have started with VT_PTR instead of:\n");
4509 dump_ELEMDESC(elemdesc);
4510 return E_UNEXPECTED;
4513 /* copy last parameter to the return value. we are using a flat
4514 * buffer so there is no danger of leaking memory in
4516 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4518 /* remove the last parameter */
4522 /* otherwise this function is made to appear to have no return
4524 dest->elemdescFunc.tdesc.vt = VT_VOID;
4532 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4534 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4535 const TLBFuncDesc *pFDesc;
4538 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4543 *ppFuncDesc = &pFDesc->funcdesc;
4547 return E_INVALIDARG;
4550 /* ITypeInfo::GetFuncDesc
4552 * Retrieves the FUNCDESC structure that contains information about a
4553 * specified function.
4556 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4557 LPFUNCDESC *ppFuncDesc)
4559 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4560 const FUNCDESC *internal_funcdesc;
4563 TRACE("(%p) index %d\n", This, index);
4565 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4569 return TLB_AllocAndInitFuncDesc(
4572 This->TypeAttr.typekind == TKIND_DISPATCH);
4575 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4579 SIZE_T size = sizeof(*src);
4582 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4583 if (src->varkind == VAR_CONST)
4584 size += sizeof(VARIANT);
4585 size += TLB_SizeElemDesc(&src->elemdescVar);
4587 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4588 if (!dest) return E_OUTOFMEMORY;
4591 buffer = (char *)(dest + 1);
4592 if (src->lpstrSchema)
4595 dest->lpstrSchema = (LPOLESTR)buffer;
4596 len = strlenW(src->lpstrSchema);
4597 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4598 buffer += (len + 1) * sizeof(WCHAR);
4601 if (src->varkind == VAR_CONST)
4605 dest->u.lpvarValue = (VARIANT *)buffer;
4606 *dest->u.lpvarValue = *src->u.lpvarValue;
4607 buffer += sizeof(VARIANT);
4608 VariantInit(dest->u.lpvarValue);
4609 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4612 SysFreeString((BSTR)dest_ptr);
4616 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4619 if (src->varkind == VAR_CONST)
4620 VariantClear(dest->u.lpvarValue);
4621 SysFreeString((BSTR)dest);
4628 /* ITypeInfo::GetVarDesc
4630 * Retrieves a VARDESC structure that describes the specified variable.
4633 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4634 LPVARDESC *ppVarDesc)
4636 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4638 const TLBVarDesc *pVDesc;
4640 TRACE("(%p) index %d\n", This, index);
4642 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4646 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4648 return E_INVALIDARG;
4651 /* ITypeInfo_GetNames
4653 * Retrieves the variable with the specified member ID (or the name of the
4654 * property or method and its parameters) that correspond to the specified
4657 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4658 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4660 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4661 const TLBFuncDesc *pFDesc;
4662 const TLBVarDesc *pVDesc;
4664 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4665 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4668 /* function found, now return function and parameter names */
4669 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4672 *rgBstrNames=SysAllocString(pFDesc->Name);
4674 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4680 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4683 *rgBstrNames=SysAllocString(pVDesc->Name);
4688 if(This->TypeAttr.cImplTypes &&
4689 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4690 /* recursive search */
4693 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4695 if(SUCCEEDED(result))
4697 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4698 ITypeInfo_Release(pTInfo);
4701 WARN("Could not search inherited interface!\n");
4705 WARN("no names found\n");
4708 return TYPE_E_ELEMENTNOTFOUND;
4715 /* ITypeInfo::GetRefTypeOfImplType
4717 * If a type description describes a COM class, it retrieves the type
4718 * description of the implemented interface types. For an interface,
4719 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4723 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4728 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4731 const TLBImplType *pImpl = This->impltypelist;
4733 TRACE("(%p) index %d\n", This, index);
4734 if (TRACE_ON(ole)) dump_TypeInfo(This);
4738 /* only valid on dual interfaces;
4739 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4741 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4743 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4744 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4750 hr = TYPE_E_ELEMENTNOTFOUND;
4755 /* get element n from linked list */
4756 for(i=0; pImpl && i<index; i++)
4758 pImpl = pImpl->next;
4762 *pRefType = pImpl->hRef;
4764 hr = TYPE_E_ELEMENTNOTFOUND;
4770 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4772 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4778 /* ITypeInfo::GetImplTypeFlags
4780 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4781 * or base interface in a type description.
4783 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4784 UINT index, INT *pImplTypeFlags)
4786 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4790 TRACE("(%p) index %d\n", This, index);
4791 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4792 i++, pImpl=pImpl->next)
4794 if(i==index && pImpl){
4795 *pImplTypeFlags=pImpl->implflags;
4799 return TYPE_E_ELEMENTNOTFOUND;
4803 * Maps between member names and member IDs, and parameter names and
4806 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4807 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4809 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4810 const TLBFuncDesc *pFDesc;
4811 const TLBVarDesc *pVDesc;
4815 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4818 /* init out parameters in case of failure */
4819 for (i = 0; i < cNames; i++)
4820 pMemId[i] = MEMBERID_NIL;
4822 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4824 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4825 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4826 for(i=1; i < cNames; i++){
4827 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4828 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4830 if( j<pFDesc->funcdesc.cParams)
4833 ret=DISP_E_UNKNOWNNAME;
4835 TRACE("-- 0x%08lx\n", ret);
4839 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4840 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4841 if(cNames) *pMemId=pVDesc->vardesc.memid;
4845 /* not found, see if it can be found in an inherited interface */
4846 if(This->TypeAttr.cImplTypes) {
4847 /* recursive search */
4849 ret=ITypeInfo_GetRefTypeInfo(iface,
4850 This->impltypelist->hRef, &pTInfo);
4852 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4853 ITypeInfo_Release(pTInfo);
4856 WARN("Could not search inherited interface!\n");
4858 WARN("no names found\n");
4859 return DISP_E_UNKNOWNNAME;
4862 /* ITypeInfo::Invoke
4864 * Invokes a method, or accesses a property of an object, that implements the
4865 * interface described by the type description.
4868 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4871 if (TRACE_ON(ole)) {
4873 TRACE("Calling %p(",func);
4874 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4886 res = func(args[0]);
4889 res = func(args[0],args[1]);
4892 res = func(args[0],args[1],args[2]);
4895 res = func(args[0],args[1],args[2],args[3]);
4898 res = func(args[0],args[1],args[2],args[3],args[4]);
4901 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4904 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4907 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4910 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4913 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4916 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4919 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]);
4922 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]);
4925 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]);
4928 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]);
4931 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]);
4934 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]);
4937 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]);
4940 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]);
4943 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]);
4946 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]);
4949 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]);
4952 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]);
4955 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4961 FIXME("unsupported calling convention %d\n",callconv);
4965 TRACE("returns %08lx\n",res);
4969 extern int _argsize(DWORD vt);
4971 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4974 ITypeInfo *tinfo2 = NULL;
4975 TYPEATTR *tattr = NULL;
4977 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4980 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4982 tdesc->u.hreftype, hr);
4985 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4988 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4989 ITypeInfo_Release(tinfo2);
4993 switch (tattr->typekind)
5000 tdesc = &tattr->tdescAlias;
5001 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5004 case TKIND_INTERFACE:
5005 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5011 case TKIND_DISPATCH:
5020 FIXME("TKIND_RECORD unhandled.\n");
5025 FIXME("TKIND_UNION unhandled.\n");
5030 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5034 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5035 ITypeInfo_Release(tinfo2);
5039 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5043 /* enforce only one level of pointer indirection */
5044 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5046 tdesc = tdesc->u.lptdesc;
5048 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5049 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5050 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5051 if ((tdesc->vt == VT_USERDEFINED) ||
5052 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5054 VARTYPE vt_userdefined = 0;
5055 const TYPEDESC *tdesc_userdefined = tdesc;
5056 if (tdesc->vt == VT_PTR)
5058 vt_userdefined = VT_BYREF;
5059 tdesc_userdefined = tdesc->u.lptdesc;
5061 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5063 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5064 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5066 *vt |= vt_userdefined;
5078 case VT_USERDEFINED:
5079 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5086 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5087 hr = DISP_E_BADVARTYPE;
5091 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5100 /***********************************************************************
5101 * DispCallFunc (OLEAUT32.@)
5103 * Invokes a function of the specifed calling convention, passing the
5104 * specified arguments and returns the result.
5107 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5108 * oVft [I] The offset in the vtable. See notes.
5109 * cc [I] Calling convention of the function to call.
5110 * vtReturn [I] The return type of the function.
5111 * cActuals [I] Number of parameters.
5112 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5113 * prgpvarg [I] The arguments to pass.
5114 * pvargResult [O] The return value of the function. Can be NULL.
5118 * Failure: HRESULT code.
5121 * The HRESULT return value of this function is not affected by the return
5122 * value of the user supplied function, which is returned in pvargResult.
5124 * If pvInstance is NULL then a non-object function is to be called and oVft
5125 * is the address of the function to call.
5127 * The cc parameter can be one of the following values:
5140 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5141 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5143 int i, argsize, argspos;
5147 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5148 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5149 pvargResult, V_VT(pvargResult));
5153 argsize++; /* for This pointer */
5155 for (i=0;i<cActuals;i++)
5157 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5158 dump_Variant(prgpvarg[i]);
5159 argsize += _argsize(prgvt[i]);
5161 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5166 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5170 for (i=0;i<cActuals;i++)
5172 VARIANT *arg = prgpvarg[i];
5173 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5174 if (prgvt[i] == VT_VARIANT)
5175 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5177 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5178 argspos += _argsize(prgvt[i]);
5183 FARPROC *vtable = *(FARPROC**)pvInstance;
5184 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5187 /* if we aren't invoking an object then the function pointer is stored
5189 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5191 if (pvargResult && (vtReturn != VT_EMPTY))
5193 TRACE("Method returned 0x%08lx\n",hres);
5194 V_VT(pvargResult) = vtReturn;
5195 V_UI4(pvargResult) = hres;
5198 HeapFree(GetProcessHeap(),0,args);
5202 #define INVBUF_ELEMENT_SIZE \
5203 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5204 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5205 ((VARIANTARG *)(buffer))
5206 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5207 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5208 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5209 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5210 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5211 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5213 static HRESULT WINAPI ITypeInfo_fnInvoke(
5218 DISPPARAMS *pDispParams,
5219 VARIANT *pVarResult,
5220 EXCEPINFO *pExcepInfo,
5223 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5225 unsigned int var_index;
5228 const TLBFuncDesc *pFuncInfo;
5230 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5231 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5236 ERR("NULL pDispParams not allowed\n");
5237 return E_INVALIDARG;
5240 dump_DispParms(pDispParams);
5242 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5244 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5245 pDispParams->cNamedArgs, pDispParams->cArgs);
5246 return E_INVALIDARG;
5249 /* we do this instead of using GetFuncDesc since it will return a fake
5250 * FUNCDESC for dispinterfaces and we want the real function description */
5251 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5252 if ((memid == pFuncInfo->funcdesc.memid) &&
5253 (wFlags & pFuncInfo->funcdesc.invkind))
5257 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5261 TRACE("invoking:\n");
5262 dump_TLBFuncDescOne(pFuncInfo);
5265 switch (func_desc->funckind) {
5266 case FUNC_PUREVIRTUAL:
5267 case FUNC_VIRTUAL: {
5268 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5270 VARIANT retval; /* pointer for storing byref retvals in */
5271 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5272 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5273 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5276 for (i = 0; i < func_desc->cParams; i++)
5278 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5279 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5284 TRACE("changing args\n");
5285 for (i = 0; i < func_desc->cParams; i++)
5287 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5289 if (wParamFlags & PARAMFLAG_FRETVAL)
5291 /* note: this check is placed so that if the caller passes
5292 * in a VARIANTARG for the retval we just ignore it, like
5294 if (i == func_desc->cParams - 1)
5297 arg = prgpvarg[i] = &rgvarg[i];
5298 memset(arg, 0, sizeof(*arg));
5299 V_VT(arg) = rgvt[i];
5300 memset(&retval, 0, sizeof(retval));
5301 V_BYREF(arg) = &retval;
5305 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5306 hres = E_UNEXPECTED;
5310 else if (i < pDispParams->cArgs)
5312 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5313 dump_Variant(src_arg);
5315 if (rgvt[i] == VT_VARIANT)
5316 hres = VariantCopy(&rgvarg[i], src_arg);
5317 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5319 if (rgvt[i] == V_VT(src_arg))
5320 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5323 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5324 hres = VariantCopy(&missing_arg[i], src_arg);
5325 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5327 V_VT(&rgvarg[i]) = rgvt[i];
5329 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5331 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5332 V_VT(&missing_arg[i]) = V_VT(src_arg);
5333 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5334 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5335 V_VT(&rgvarg[i]) = rgvt[i];
5337 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5339 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5340 V_VT(&rgvarg[i]) = rgvt[i];
5344 /* FIXME: this doesn't work for VT_BYREF arguments if
5345 * they are not the same type as in the paramdesc */
5346 V_VT(&rgvarg[i]) = V_VT(src_arg);
5347 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5348 V_VT(&rgvarg[i]) = rgvt[i];
5353 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5354 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5355 debugstr_VT(src_arg), debugstr_VF(src_arg));
5358 prgpvarg[i] = &rgvarg[i];
5360 else if (wParamFlags & PARAMFLAG_FOPT)
5363 arg = prgpvarg[i] = &rgvarg[i];
5364 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5366 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5372 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5373 V_VT(arg) = VT_VARIANT | VT_BYREF;
5374 V_VARIANTREF(arg) = &missing_arg[i];
5375 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5376 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5381 hres = DISP_E_BADPARAMCOUNT;
5385 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5386 if (func_desc->cParamsOpt < 0)
5388 FIXME("Does not support safearray optional parameters\n");
5389 hres = DISP_E_BADPARAMCOUNT;
5390 goto func_fail; /* FIXME: we don't free changed types here */
5393 /* VT_VOID is a special case for return types, so it is not
5394 * handled in the general function */
5395 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5396 V_VT(&varresult) = VT_EMPTY;
5399 V_VT(&varresult) = 0;
5400 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5401 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5404 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5405 V_VT(&varresult), func_desc->cParams, rgvt,
5406 prgpvarg, &varresult);
5408 for (i = 0; i < func_desc->cParams; i++)
5410 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5411 if (wParamFlags & PARAMFLAG_FRETVAL)
5415 TRACE("[retval] value: ");
5416 dump_Variant(prgpvarg[i]);
5421 VariantInit(pVarResult);
5422 /* deref return value */
5423 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5426 /* free data stored in varresult. Note that
5427 * VariantClear doesn't do what we want because we are
5428 * working with byref types. */
5429 /* FIXME: clear safearrays, bstrs, records and
5430 * variants here too */
5431 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5432 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5434 if(*V_UNKNOWNREF(prgpvarg[i]))
5435 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5439 else if (i < pDispParams->cArgs)
5441 if (wParamFlags & PARAMFLAG_FOUT)
5443 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5445 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5446 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5450 ERR("failed to convert param %d to vt %d\n", i,
5451 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5455 VariantClear(&rgvarg[i]);
5457 else if (wParamFlags & PARAMFLAG_FOPT)
5459 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5460 VariantClear(&rgvarg[i]);
5464 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5466 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5467 hres = DISP_E_EXCEPTION;
5468 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5472 HeapFree(GetProcessHeap(), 0, buffer);
5475 case FUNC_DISPATCH: {
5478 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5479 if (SUCCEEDED(hres)) {
5480 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5481 hres = IDispatch_Invoke(
5482 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5483 pVarResult,pExcepInfo,pArgErr
5486 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5487 IDispatch_Release(disp);
5489 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5493 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5498 TRACE("-- 0x%08lx\n", hres);
5501 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5504 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5505 if(FAILED(hres)) return hres;
5507 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5508 dump_VARDESC(var_desc);
5509 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5513 /* not found, look for it in inherited interfaces */
5514 ITypeInfo2_GetTypeKind(iface, &type_kind);
5515 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5517 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5518 /* recursive search */
5520 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5521 if(SUCCEEDED(hres)){
5522 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5523 ITypeInfo_Release(pTInfo);
5526 WARN("Could not search inherited interface!\n");
5529 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5530 return DISP_E_MEMBERNOTFOUND;
5533 /* ITypeInfo::GetDocumentation
5535 * Retrieves the documentation string, the complete Help file name and path,
5536 * and the context ID for the Help topic for a specified type description.
5538 * (Can be tested by the Visual Basic Editor in Word for instance.)
5540 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5541 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5542 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5544 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5545 const TLBFuncDesc *pFDesc;
5546 const TLBVarDesc *pVDesc;
5547 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5548 " HelpContext(%p) HelpFile(%p)\n",
5549 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5550 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5552 *pBstrName=SysAllocString(This->Name);
5554 *pBstrDocString=SysAllocString(This->DocString);
5556 *pdwHelpContext=This->dwHelpContext;
5558 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5560 }else {/* for a member */
5561 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5562 if(pFDesc->funcdesc.memid==memid){
5564 *pBstrName = SysAllocString(pFDesc->Name);
5566 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5568 *pdwHelpContext=pFDesc->helpcontext;
5571 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5572 if(pVDesc->vardesc.memid==memid){
5574 *pBstrName = SysAllocString(pVDesc->Name);
5576 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5578 *pdwHelpContext=pVDesc->HelpContext;
5582 WARN("member %ld not found\n", memid);
5583 return TYPE_E_ELEMENTNOTFOUND;
5586 /* ITypeInfo::GetDllEntry
5588 * Retrieves a description or specification of an entry point for a function
5591 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5592 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5595 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5596 const TLBFuncDesc *pFDesc;
5598 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5600 if (pBstrDllName) *pBstrDllName = NULL;
5601 if (pBstrName) *pBstrName = NULL;
5602 if (pwOrdinal) *pwOrdinal = 0;
5604 if (This->TypeAttr.typekind != TKIND_MODULE)
5605 return TYPE_E_BADMODULEKIND;
5607 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5608 if(pFDesc->funcdesc.memid==memid){
5609 dump_TypeInfo(This);
5611 dump_TLBFuncDescOne(pFDesc);
5614 *pBstrDllName = SysAllocString(This->DllName);
5616 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5618 *pBstrName = SysAllocString(pFDesc->Entry);
5626 *pwOrdinal = (DWORD)pFDesc->Entry;
5629 return TYPE_E_ELEMENTNOTFOUND;
5632 /* ITypeInfo::GetRefTypeInfo
5634 * If a type description references other type descriptions, it retrieves
5635 * the referenced type descriptions.
5637 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5640 ITypeInfo **ppTInfo)
5642 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5643 HRESULT result = E_FAIL;
5645 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5647 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5648 ITypeInfo_AddRef(*ppTInfo);
5651 else if (hRefType == -1 &&
5652 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5653 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5655 /* when we meet a DUAL dispinterface, we must create the interface
5658 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5661 /* the interface version contains the same information as the dispinterface
5662 * copy the contents of the structs.
5664 *pTypeInfoImpl = *This;
5665 pTypeInfoImpl->ref = 1;
5667 /* change the type to interface */
5668 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5670 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5672 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5677 TLBRefType *pRefType;
5678 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5679 if(pRefType->reference == hRefType)
5683 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5684 if(pRefType && hRefType != -1) {
5685 ITypeLib *pTLib = NULL;
5687 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5689 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5691 if(pRefType->pImpTLInfo->pImpTypeLib) {
5692 TRACE("typeinfo in imported typelib that is already loaded\n");
5693 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5694 ITypeLib2_AddRef((ITypeLib*) pTLib);
5697 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5698 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5699 pRefType->pImpTLInfo->wVersionMajor,
5700 pRefType->pImpTLInfo->wVersionMinor,
5701 pRefType->pImpTLInfo->lcid,
5704 if(!SUCCEEDED(result)) {
5705 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5706 result=LoadTypeLib(libnam, &pTLib);
5707 SysFreeString(libnam);
5709 if(SUCCEEDED(result)) {
5710 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5711 ITypeLib2_AddRef(pTLib);
5715 if(SUCCEEDED(result)) {
5716 if(pRefType->index == TLB_REF_USE_GUID)
5717 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5721 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5725 ITypeLib2_Release(pTLib);
5729 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5730 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5734 /* ITypeInfo::AddressOfMember
5736 * Retrieves the addresses of static functions or variables, such as those
5739 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5740 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5742 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5748 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5750 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5754 module = LoadLibraryW(dll);
5757 ERR("couldn't load %s\n", debugstr_w(dll));
5759 if (entry) SysFreeString(entry);
5760 return STG_E_FILENOTFOUND;
5762 /* FIXME: store library somewhere where we can free it */
5767 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5768 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5769 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5771 *ppv = GetProcAddress(module, entryA);
5773 ERR("function not found %s\n", debugstr_a(entryA));
5775 HeapFree(GetProcessHeap(), 0, entryA);
5779 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5781 ERR("function not found %d\n", ordinal);
5785 if (entry) SysFreeString(entry);
5788 return TYPE_E_DLLFUNCTIONNOTFOUND;
5793 /* ITypeInfo::CreateInstance
5795 * Creates a new instance of a type that describes a component object class
5798 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5799 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5801 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5802 FIXME("(%p) stub!\n", This);
5806 /* ITypeInfo::GetMops
5808 * Retrieves marshalling information.
5810 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5813 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5814 FIXME("(%p) stub!\n", This);
5818 /* ITypeInfo::GetContainingTypeLib
5820 * Retrieves the containing type library and the index of the type description
5821 * within that type library.
5823 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5824 ITypeLib * *ppTLib, UINT *pIndex)
5826 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5828 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5830 *pIndex=This->index;
5831 TRACE("returning pIndex=%d\n", *pIndex);
5835 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5836 ITypeLib2_AddRef(*ppTLib);
5837 TRACE("returning ppTLib=%p\n", *ppTLib);
5843 /* ITypeInfo::ReleaseTypeAttr
5845 * Releases a TYPEATTR previously returned by GetTypeAttr.
5848 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5849 TYPEATTR* pTypeAttr)
5851 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5852 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5853 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5856 /* ITypeInfo::ReleaseFuncDesc
5858 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5860 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5862 FUNCDESC *pFuncDesc)
5864 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5867 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5869 for (i = 0; i < pFuncDesc->cParams; i++)
5870 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5871 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5873 SysFreeString((BSTR)pFuncDesc);
5876 /* ITypeInfo::ReleaseVarDesc
5878 * Releases a VARDESC previously returned by GetVarDesc.
5880 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5883 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5884 TRACE("(%p)->(%p)\n", This, pVarDesc);
5886 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5887 if (pVarDesc->varkind == VAR_CONST)
5888 VariantClear(pVarDesc->u.lpvarValue);
5889 SysFreeString((BSTR)pVarDesc);
5892 /* ITypeInfo2::GetTypeKind
5894 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5897 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5898 TYPEKIND *pTypeKind)
5900 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5901 *pTypeKind=This->TypeAttr.typekind;
5902 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5906 /* ITypeInfo2::GetTypeFlags
5908 * Returns the type flags without any allocations. This returns a DWORD type
5909 * flag, which expands the type flags without growing the TYPEATTR (type
5913 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5915 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5916 *pTypeFlags=This->TypeAttr.wTypeFlags;
5917 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5921 /* ITypeInfo2::GetFuncIndexOfMemId
5922 * Binds to a specific member based on a known DISPID, where the member name
5923 * is not known (for example, when binding to a default member).
5926 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5927 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5929 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5930 const TLBFuncDesc *pFuncInfo;
5934 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5935 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5941 result = TYPE_E_ELEMENTNOTFOUND;
5943 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5944 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5948 /* TypeInfo2::GetVarIndexOfMemId
5950 * Binds to a specific member based on a known DISPID, where the member name
5951 * is not known (for example, when binding to a default member).
5954 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5955 MEMBERID memid, UINT *pVarIndex)
5957 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5958 TLBVarDesc *pVarInfo;
5961 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5962 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5968 result = TYPE_E_ELEMENTNOTFOUND;
5970 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5971 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5975 /* ITypeInfo2::GetCustData
5977 * Gets the custom data
5979 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5984 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5985 TLBCustData *pCData;
5987 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5988 if( IsEqualIID(guid, &pCData->guid)) break;
5990 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5994 VariantInit( pVarVal);
5995 VariantCopy( pVarVal, &pCData->data);
5998 return E_INVALIDARG; /* FIXME: correct? */
6001 /* ITypeInfo2::GetFuncCustData
6003 * Gets the custom data
6005 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6011 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6012 TLBCustData *pCData=NULL;
6013 TLBFuncDesc * pFDesc;
6015 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6016 pFDesc=pFDesc->next);
6019 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6020 if( IsEqualIID(guid, &pCData->guid)) break;
6022 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6025 VariantInit( pVarVal);
6026 VariantCopy( pVarVal, &pCData->data);
6029 return E_INVALIDARG; /* FIXME: correct? */
6032 /* ITypeInfo2::GetParamCustData
6034 * Gets the custom data
6036 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6043 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6044 TLBCustData *pCData=NULL;
6045 TLBFuncDesc * pFDesc;
6048 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6050 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6051 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6052 pCData = pCData->next)
6053 if( IsEqualIID(guid, &pCData->guid)) break;
6055 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6059 VariantInit( pVarVal);
6060 VariantCopy( pVarVal, &pCData->data);
6063 return E_INVALIDARG; /* FIXME: correct? */
6066 /* ITypeInfo2::GetVarCustData
6068 * Gets the custom data
6070 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6076 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6077 TLBCustData *pCData=NULL;
6078 TLBVarDesc * pVDesc;
6081 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6085 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6087 if( IsEqualIID(guid, &pCData->guid)) break;
6091 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6095 VariantInit( pVarVal);
6096 VariantCopy( pVarVal, &pCData->data);
6099 return E_INVALIDARG; /* FIXME: correct? */
6102 /* ITypeInfo2::GetImplCustData
6104 * Gets the custom data
6106 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6112 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6113 TLBCustData *pCData=NULL;
6114 TLBImplType * pRDesc;
6117 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6121 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6123 if( IsEqualIID(guid, &pCData->guid)) break;
6127 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6131 VariantInit( pVarVal);
6132 VariantCopy( pVarVal, &pCData->data);
6135 return E_INVALIDARG; /* FIXME: correct? */
6138 /* ITypeInfo2::GetDocumentation2
6140 * Retrieves the documentation string, the complete Help file name and path,
6141 * the localization context to use, and the context ID for the library Help
6142 * topic in the Help file.
6145 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6149 BSTR *pbstrHelpString,
6150 DWORD *pdwHelpStringContext,
6151 BSTR *pbstrHelpStringDll)
6153 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6154 const TLBFuncDesc *pFDesc;
6155 const TLBVarDesc *pVDesc;
6156 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6157 "HelpStringContext(%p) HelpStringDll(%p)\n",
6158 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6159 pbstrHelpStringDll );
6160 /* the help string should be obtained from the helpstringdll,
6161 * using the _DLLGetDocumentation function, based on the supplied
6162 * lcid. Nice to do sometime...
6164 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6166 *pbstrHelpString=SysAllocString(This->Name);
6167 if(pdwHelpStringContext)
6168 *pdwHelpStringContext=This->dwHelpStringContext;
6169 if(pbstrHelpStringDll)
6170 *pbstrHelpStringDll=
6171 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6173 }else {/* for a member */
6174 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6175 if(pFDesc->funcdesc.memid==memid){
6177 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6178 if(pdwHelpStringContext)
6179 *pdwHelpStringContext=pFDesc->HelpStringContext;
6180 if(pbstrHelpStringDll)
6181 *pbstrHelpStringDll=
6182 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6185 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6186 if(pVDesc->vardesc.memid==memid){
6188 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6189 if(pdwHelpStringContext)
6190 *pdwHelpStringContext=pVDesc->HelpStringContext;
6191 if(pbstrHelpStringDll)
6192 *pbstrHelpStringDll=
6193 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6197 return TYPE_E_ELEMENTNOTFOUND;
6200 /* ITypeInfo2::GetAllCustData
6202 * Gets all custom data items for the Type info.
6205 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6207 CUSTDATA *pCustData)
6209 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6210 TLBCustData *pCData;
6213 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6215 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6216 if(pCustData->prgCustData ){
6217 pCustData->cCustData=This->ctCustData;
6218 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6219 pCustData->prgCustData[i].guid=pCData->guid;
6220 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6223 ERR(" OUT OF MEMORY!\n");
6224 return E_OUTOFMEMORY;
6229 /* ITypeInfo2::GetAllFuncCustData
6231 * Gets all custom data items for the specified Function
6234 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6237 CUSTDATA *pCustData)
6239 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6240 TLBCustData *pCData;
6241 TLBFuncDesc * pFDesc;
6243 TRACE("(%p) index %d\n", This, index);
6244 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6245 pFDesc=pFDesc->next)
6248 pCustData->prgCustData =
6249 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6250 if(pCustData->prgCustData ){
6251 pCustData->cCustData=pFDesc->ctCustData;
6252 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6253 pCData = pCData->next){
6254 pCustData->prgCustData[i].guid=pCData->guid;
6255 VariantCopy(& pCustData->prgCustData[i].varValue,
6259 ERR(" OUT OF MEMORY!\n");
6260 return E_OUTOFMEMORY;
6264 return TYPE_E_ELEMENTNOTFOUND;
6267 /* ITypeInfo2::GetAllParamCustData
6269 * Gets all custom data items for the Functions
6272 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6273 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6275 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6276 TLBCustData *pCData=NULL;
6277 TLBFuncDesc * pFDesc;
6279 TRACE("(%p) index %d\n", This, indexFunc);
6280 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6281 pFDesc=pFDesc->next)
6283 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6284 pCustData->prgCustData =
6285 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6286 sizeof(CUSTDATAITEM));
6287 if(pCustData->prgCustData ){
6288 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6289 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6290 pCData; i++, pCData = pCData->next){
6291 pCustData->prgCustData[i].guid=pCData->guid;
6292 VariantCopy(& pCustData->prgCustData[i].varValue,
6296 ERR(" OUT OF MEMORY!\n");
6297 return E_OUTOFMEMORY;
6301 return TYPE_E_ELEMENTNOTFOUND;
6304 /* ITypeInfo2::GetAllVarCustData
6306 * Gets all custom data items for the specified Variable
6309 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6310 UINT index, CUSTDATA *pCustData)
6312 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6313 TLBCustData *pCData;
6314 TLBVarDesc * pVDesc;
6316 TRACE("(%p) index %d\n", This, index);
6317 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6318 pVDesc=pVDesc->next)
6321 pCustData->prgCustData =
6322 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6323 if(pCustData->prgCustData ){
6324 pCustData->cCustData=pVDesc->ctCustData;
6325 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6326 pCData = pCData->next){
6327 pCustData->prgCustData[i].guid=pCData->guid;
6328 VariantCopy(& pCustData->prgCustData[i].varValue,
6332 ERR(" OUT OF MEMORY!\n");
6333 return E_OUTOFMEMORY;
6337 return TYPE_E_ELEMENTNOTFOUND;
6340 /* ITypeInfo2::GetAllImplCustData
6342 * Gets all custom data items for the specified implementation type
6345 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6348 CUSTDATA *pCustData)
6350 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6351 TLBCustData *pCData;
6352 TLBImplType * pRDesc;
6354 TRACE("(%p) index %d\n", This, index);
6355 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6356 pRDesc=pRDesc->next)
6359 pCustData->prgCustData =
6360 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6361 if(pCustData->prgCustData ){
6362 pCustData->cCustData=pRDesc->ctCustData;
6363 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6364 pCData = pCData->next){
6365 pCustData->prgCustData[i].guid=pCData->guid;
6366 VariantCopy(& pCustData->prgCustData[i].varValue,
6370 ERR(" OUT OF MEMORY!\n");
6371 return E_OUTOFMEMORY;
6375 return TYPE_E_ELEMENTNOTFOUND;
6378 static const ITypeInfo2Vtbl tinfvt =
6381 ITypeInfo_fnQueryInterface,
6383 ITypeInfo_fnRelease,
6385 ITypeInfo_fnGetTypeAttr,
6386 ITypeInfo_fnGetTypeComp,
6387 ITypeInfo_fnGetFuncDesc,
6388 ITypeInfo_fnGetVarDesc,
6389 ITypeInfo_fnGetNames,
6390 ITypeInfo_fnGetRefTypeOfImplType,
6391 ITypeInfo_fnGetImplTypeFlags,
6392 ITypeInfo_fnGetIDsOfNames,
6394 ITypeInfo_fnGetDocumentation,
6395 ITypeInfo_fnGetDllEntry,
6396 ITypeInfo_fnGetRefTypeInfo,
6397 ITypeInfo_fnAddressOfMember,
6398 ITypeInfo_fnCreateInstance,
6399 ITypeInfo_fnGetMops,
6400 ITypeInfo_fnGetContainingTypeLib,
6401 ITypeInfo_fnReleaseTypeAttr,
6402 ITypeInfo_fnReleaseFuncDesc,
6403 ITypeInfo_fnReleaseVarDesc,
6405 ITypeInfo2_fnGetTypeKind,
6406 ITypeInfo2_fnGetTypeFlags,
6407 ITypeInfo2_fnGetFuncIndexOfMemId,
6408 ITypeInfo2_fnGetVarIndexOfMemId,
6409 ITypeInfo2_fnGetCustData,
6410 ITypeInfo2_fnGetFuncCustData,
6411 ITypeInfo2_fnGetParamCustData,
6412 ITypeInfo2_fnGetVarCustData,
6413 ITypeInfo2_fnGetImplTypeCustData,
6414 ITypeInfo2_fnGetDocumentation2,
6415 ITypeInfo2_fnGetAllCustData,
6416 ITypeInfo2_fnGetAllFuncCustData,
6417 ITypeInfo2_fnGetAllParamCustData,
6418 ITypeInfo2_fnGetAllVarCustData,
6419 ITypeInfo2_fnGetAllImplTypeCustData,
6422 /******************************************************************************
6423 * CreateDispTypeInfo [OLEAUT32.31]
6425 * Build type information for an object so it can be called through an
6426 * IDispatch interface.
6429 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6430 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6433 * This call allows an objects methods to be accessed through IDispatch, by
6434 * building an ITypeInfo object that IDispatch can use to call through.
6436 HRESULT WINAPI CreateDispTypeInfo(
6437 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6438 LCID lcid, /* [I] Locale Id */
6439 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6441 ITypeInfoImpl *pTIClass, *pTIIface;
6442 ITypeLibImpl *pTypeLibImpl;
6444 TLBFuncDesc **ppFuncDesc;
6447 pTypeLibImpl = TypeLibImpl_Constructor();
6448 if (!pTypeLibImpl) return E_FAIL;
6450 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6451 pTIIface->pTypeLib = pTypeLibImpl;
6452 pTIIface->index = 0;
6453 pTIIface->Name = NULL;
6454 pTIIface->dwHelpContext = -1;
6455 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6456 pTIIface->TypeAttr.lcid = lcid;
6457 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6458 pTIIface->TypeAttr.wMajorVerNum = 0;
6459 pTIIface->TypeAttr.wMinorVerNum = 0;
6460 pTIIface->TypeAttr.cbAlignment = 2;
6461 pTIIface->TypeAttr.cbSizeInstance = -1;
6462 pTIIface->TypeAttr.cbSizeVft = -1;
6463 pTIIface->TypeAttr.cFuncs = 0;
6464 pTIIface->TypeAttr.cImplTypes = 0;
6465 pTIIface->TypeAttr.cVars = 0;
6466 pTIIface->TypeAttr.wTypeFlags = 0;
6468 ppFuncDesc = &pTIIface->funclist;
6469 for(func = 0; func < pidata->cMembers; func++) {
6470 METHODDATA *md = pidata->pmethdata + func;
6471 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6472 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6473 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6474 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6475 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6476 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6477 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6478 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6479 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6480 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6481 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6482 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6483 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6484 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6485 md->cArgs * sizeof(ELEMDESC));
6486 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6487 md->cArgs * sizeof(TLBParDesc));
6488 for(param = 0; param < md->cArgs; param++) {
6489 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6490 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6492 (*ppFuncDesc)->helpcontext = 0;
6493 (*ppFuncDesc)->HelpStringContext = 0;
6494 (*ppFuncDesc)->HelpString = NULL;
6495 (*ppFuncDesc)->Entry = NULL;
6496 (*ppFuncDesc)->ctCustData = 0;
6497 (*ppFuncDesc)->pCustData = NULL;
6498 (*ppFuncDesc)->next = NULL;
6499 ppFuncDesc = &(*ppFuncDesc)->next;
6502 dump_TypeInfo(pTIIface);
6504 pTypeLibImpl->pTypeInfo = pTIIface;
6505 pTypeLibImpl->TypeInfoCount++;
6507 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6508 pTIClass->pTypeLib = pTypeLibImpl;
6509 pTIClass->index = 1;
6510 pTIClass->Name = NULL;
6511 pTIClass->dwHelpContext = -1;
6512 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6513 pTIClass->TypeAttr.lcid = lcid;
6514 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6515 pTIClass->TypeAttr.wMajorVerNum = 0;
6516 pTIClass->TypeAttr.wMinorVerNum = 0;
6517 pTIClass->TypeAttr.cbAlignment = 2;
6518 pTIClass->TypeAttr.cbSizeInstance = -1;
6519 pTIClass->TypeAttr.cbSizeVft = -1;
6520 pTIClass->TypeAttr.cFuncs = 0;
6521 pTIClass->TypeAttr.cImplTypes = 1;
6522 pTIClass->TypeAttr.cVars = 0;
6523 pTIClass->TypeAttr.wTypeFlags = 0;
6525 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6526 pTIClass->impltypelist->hRef = 1;
6528 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6529 pTIClass->reflist->index = 0;
6530 pTIClass->reflist->reference = 1;
6531 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6533 dump_TypeInfo(pTIClass);
6535 pTIIface->next = pTIClass;
6536 pTypeLibImpl->TypeInfoCount++;
6538 *pptinfo = (ITypeInfo*)pTIClass;
6543 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6545 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6547 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6550 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6552 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6554 return ITypeInfo_AddRef((ITypeInfo *)This);
6557 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6559 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6561 return ITypeInfo_Release((ITypeInfo *)This);
6564 static HRESULT WINAPI ITypeComp_fnBind(
6569 ITypeInfo ** ppTInfo,
6570 DESCKIND * pDescKind,
6573 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6574 const TLBFuncDesc *pFDesc;
6575 const TLBVarDesc *pVDesc;
6576 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6578 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6580 *pDescKind = DESCKIND_NONE;
6581 pBindPtr->lpfuncdesc = NULL;
6584 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6585 if (!strcmpiW(pFDesc->Name, szName)) {
6586 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6589 /* name found, but wrong flags */
6590 hr = TYPE_E_TYPEMISMATCH;
6595 HRESULT hr = TLB_AllocAndInitFuncDesc(
6597 &pBindPtr->lpfuncdesc,
6598 This->TypeAttr.typekind == TKIND_DISPATCH);
6601 *pDescKind = DESCKIND_FUNCDESC;
6602 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6603 ITypeInfo_AddRef(*ppTInfo);
6606 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6607 if (!strcmpiW(pVDesc->Name, szName)) {
6608 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6611 *pDescKind = DESCKIND_VARDESC;
6612 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6613 ITypeInfo_AddRef(*ppTInfo);
6618 /* FIXME: search each inherited interface, not just the first */
6619 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6620 /* recursive search */
6624 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6627 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6628 ITypeInfo_Release(pTInfo);
6632 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6633 ITypeComp_Release(pTComp);
6636 WARN("Could not search inherited interface!\n");
6638 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6642 static HRESULT WINAPI ITypeComp_fnBindType(
6646 ITypeInfo ** ppTInfo,
6647 ITypeComp ** ppTComp)
6649 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6651 /* strange behaviour (does nothing) but like the
6654 if (!ppTInfo || !ppTComp)
6663 static const ITypeCompVtbl tcompvt =
6666 ITypeComp_fnQueryInterface,
6668 ITypeComp_fnRelease,
6671 ITypeComp_fnBindType