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 while (index < pdp->cArgs)
1251 dump_Variant( &pdp->rgvarg[index] );
1256 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1258 TRACE("%p ref=%lu\n", pty, pty->ref);
1259 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1260 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1261 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1262 TRACE("fct:%u var:%u impl:%u\n",
1263 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1264 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1265 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1266 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1268 dump_TLBFuncDesc(pty->funclist);
1269 dump_TLBVarDesc(pty->varlist);
1270 dump_TLBImplType(pty->impltypelist);
1273 static void dump_VARDESC(const VARDESC *v)
1275 MESSAGE("memid %ld\n",v->memid);
1276 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1277 MESSAGE("oInst %ld\n",v->u.oInst);
1278 dump_ELEMDESC(&(v->elemdescVar));
1279 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1280 MESSAGE("varkind %d\n",v->varkind);
1283 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1285 /* VT_LPWSTR is largest type that */
1286 /* may appear in type description*/
1287 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1288 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1289 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1290 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1291 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1292 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1296 static void TLB_abort(void)
1300 static void * TLB_Alloc(unsigned size)
1303 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1305 ERR("cannot allocate memory\n");
1310 static void TLB_Free(void * ptr)
1312 HeapFree(GetProcessHeap(), 0, ptr);
1315 /* returns the size required for a deep copy of a typedesc into a
1317 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1321 if (alloc_initial_space)
1322 size += sizeof(TYPEDESC);
1328 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1331 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1332 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1338 /* deep copy a typedesc into a flat buffer */
1339 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1344 buffer = (char *)buffer + sizeof(TYPEDESC);
1353 dest->u.lptdesc = buffer;
1354 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1357 dest->u.lpadesc = buffer;
1358 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1359 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1360 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1366 /**********************************************************************
1368 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1370 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1375 static inline void MSFT_Seek(TLBContext *pcx, long where)
1377 if (where != DO_NOT_SEEK)
1379 where += pcx->oStart;
1380 if (where > pcx->length)
1383 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1391 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1393 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1394 pcx->pos, count, pcx->oStart, pcx->length, where);
1396 MSFT_Seek(pcx, where);
1397 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1398 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1403 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1408 ret = MSFT_Read(buffer, count, pcx, where);
1409 FromLEDWords(buffer, ret);
1414 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1419 ret = MSFT_Read(buffer, count, pcx, where);
1420 FromLEWords(buffer, ret);
1425 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1427 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1428 memset(pGuid,0, sizeof(GUID));
1431 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1432 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1433 pGuid->Data2 = FromLEWord(pGuid->Data2);
1434 pGuid->Data3 = FromLEWord(pGuid->Data3);
1435 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1438 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1440 MSFT_NameIntro niName;
1444 ERR_(typelib)("bad offset %d\n", offset);
1448 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1449 pcx->pTblDir->pNametab.offset+offset);
1451 return niName.hreftype;
1454 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1457 MSFT_NameIntro niName;
1459 WCHAR* pwstring = NULL;
1460 BSTR bstrName = NULL;
1464 ERR_(typelib)("bad offset %d\n", offset);
1467 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1468 pcx->pTblDir->pNametab.offset+offset);
1469 niName.namelen &= 0xFF; /* FIXME: correct ? */
1470 name=TLB_Alloc((niName.namelen & 0xff) +1);
1471 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1472 name[niName.namelen & 0xff]='\0';
1474 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1477 /* no invalid characters in string */
1480 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1482 /* don't check for invalid character since this has been done previously */
1483 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1485 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1486 lengthInChars = SysStringLen(bstrName);
1487 HeapFree(GetProcessHeap(), 0, pwstring);
1490 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1494 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1501 if(offset<0) return NULL;
1502 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1503 if(length <= 0) return 0;
1504 string=TLB_Alloc(length +1);
1505 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1506 string[length]='\0';
1508 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1509 string, -1, NULL, 0);
1511 /* no invalid characters in string */
1514 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1516 /* don't check for invalid character since this has been done previously */
1517 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1519 bstr = SysAllocStringLen(pwstring, lengthInChars);
1520 lengthInChars = SysStringLen(bstr);
1521 HeapFree(GetProcessHeap(), 0, pwstring);
1524 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1528 * read a value and fill a VARIANT structure
1530 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1534 TRACE_(typelib)("\n");
1536 if(offset <0) { /* data are packed in here */
1537 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1538 V_I4(pVar) = offset & 0x3ffffff;
1541 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1542 pcx->pTblDir->pCustData.offset + offset );
1543 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1544 switch (V_VT(pVar)){
1545 case VT_EMPTY: /* FIXME: is this right? */
1546 case VT_NULL: /* FIXME: is this right? */
1547 case VT_I2 : /* this should not happen */
1558 case VT_VOID : /* FIXME: is this right? */
1566 case VT_DECIMAL : /* FIXME: is this right? */
1569 /* pointer types with known behaviour */
1572 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1575 DWORD origPos = MSFT_Tell(pcx), nullPos;
1578 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1580 nullPos = MSFT_Tell(pcx);
1581 size = nullPos - origPos;
1582 MSFT_Seek(pcx, origPos);
1584 ptr=TLB_Alloc(size);/* allocate temp buffer */
1585 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1586 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1587 /* FIXME: do we need a AtoW conversion here? */
1588 V_UNION(pVar, bstrVal[size])=L'\0';
1589 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1593 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1600 case VT_USERDEFINED :
1606 case VT_STREAMED_OBJECT :
1607 case VT_STORED_OBJECT :
1608 case VT_BLOB_OBJECT :
1613 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1617 if(size>0) /* (big|small) endian correct? */
1618 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1622 * create a linked list with custom data
1624 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1630 TRACE_(typelib)("\n");
1634 pNew=TLB_Alloc(sizeof(TLBCustData));
1635 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1636 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1637 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1638 /* add new custom data at head of the list */
1639 pNew->next=*ppCustData;
1641 offset = entry.next;
1646 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1650 pTd->vt=type & VT_TYPEMASK;
1652 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1654 if(pTd->vt == VT_USERDEFINED)
1655 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1657 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1660 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1662 /* resolve referenced type if any */
1665 switch (lpTypeDesc->vt)
1668 lpTypeDesc = lpTypeDesc->u.lptdesc;
1672 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1675 case VT_USERDEFINED:
1676 MSFT_DoRefType(pcx, pTI,
1677 lpTypeDesc->u.hreftype);
1689 MSFT_DoFuncs(TLBContext* pcx,
1694 TLBFuncDesc** pptfd)
1697 * member information is stored in a data structure at offset
1698 * indicated by the memoffset field of the typeinfo structure
1699 * There are several distinctive parts.
1700 * The first part starts with a field that holds the total length
1701 * of this (first) part excluding this field. Then follow the records,
1702 * for each member there is one record.
1704 * The first entry is always the length of the record (including this
1706 * The rest of the record depends on the type of the member. If there is
1707 * a field indicating the member type (function, variable, interface, etc)
1708 * I have not found it yet. At this time we depend on the information
1709 * in the type info and the usual order how things are stored.
1711 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1714 * Third is an equal sized array with file offsets to the name entry
1717 * The fourth and last (?) part is an array with offsets to the records
1718 * in the first part of this file segment.
1721 int infolen, nameoffset, reclength, nrattributes, i;
1722 int recoffset = offset + sizeof(INT);
1724 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1725 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1726 TLBFuncDesc *ptfd_prev = NULL;
1728 TRACE_(typelib)("\n");
1730 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1732 for ( i = 0; i < cFuncs ; i++ )
1734 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1736 /* name, eventually add to a hash table */
1737 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1738 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1740 /* nameoffset is sometimes -1 on the second half of a propget/propput
1741 * pair of functions */
1742 if ((nameoffset == -1) && (i > 0))
1743 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1745 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1747 /* read the function information record */
1748 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1750 reclength &= 0xffff;
1752 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1754 /* do the attributes */
1755 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1758 if ( nrattributes > 0 )
1760 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1762 if ( nrattributes > 1 )
1764 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1765 pFuncRec->OptAttr[1]) ;
1767 if ( nrattributes > 2 )
1769 if ( pFuncRec->FKCCIC & 0x2000 )
1771 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1775 (*pptfd)->Entry = MSFT_ReadString(pcx,
1776 pFuncRec->OptAttr[2]);
1778 if( nrattributes > 5 )
1780 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1782 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1785 pFuncRec->OptAttr[6],
1786 &(*pptfd)->pCustData);
1793 /* fill the FuncDesc Structure */
1794 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1795 offset + infolen + ( i + 1) * sizeof(INT));
1797 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1798 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1799 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1800 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1801 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1802 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1803 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1807 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1809 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1811 /* do the parameters/arguments */
1812 if(pFuncRec->nrargs)
1815 MSFT_ParameterInfo paraminfo;
1817 (*pptfd)->funcdesc.lprgelemdescParam =
1818 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1820 (*pptfd)->pParamDesc =
1821 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1823 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1824 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1826 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1828 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1835 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1838 if (paraminfo.oName == -1)
1839 /* this occurs for [propput] or [propget] methods, so
1840 * we should just set the name of the parameter to the
1841 * name of the method. */
1842 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1844 (*pptfd)->pParamDesc[j].Name =
1845 MSFT_ReadName( pcx, paraminfo.oName );
1846 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1848 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1851 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1852 (pFuncRec->FKCCIC & 0x1000) )
1854 INT* pInt = (INT *)((char *)pFuncRec +
1856 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1858 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1860 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1861 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1863 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1867 elemdesc->u.paramdesc.pparamdescex = NULL;
1869 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1872 pFuncRec->OptAttr[7+j],
1873 &(*pptfd)->pParamDesc[j].pCustData);
1876 /* SEEK value = jump to offset,
1877 * from there jump to the end of record,
1878 * go back by (j-1) arguments
1880 MSFT_ReadLEDWords( ¶minfo ,
1881 sizeof(MSFT_ParameterInfo), pcx,
1882 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1883 * sizeof(MSFT_ParameterInfo)));
1887 /* scode is not used: archaic win16 stuff FIXME: right? */
1888 (*pptfd)->funcdesc.cScodes = 0 ;
1889 (*pptfd)->funcdesc.lprgscode = NULL ;
1892 pptfd = & ((*pptfd)->next);
1893 recoffset += reclength;
1895 HeapFree(GetProcessHeap(), 0, recbuf);
1898 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1899 int cVars, int offset, TLBVarDesc ** pptvd)
1901 int infolen, nameoffset, reclength;
1903 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1907 TRACE_(typelib)("\n");
1909 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1910 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1911 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1912 recoffset += offset+sizeof(INT);
1913 for(i=0;i<cVars;i++){
1914 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1915 /* name, eventually add to a hash table */
1916 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1917 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1918 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1919 /* read the variable information record */
1920 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1922 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1924 if(reclength >(6*sizeof(INT)) )
1925 (*pptvd)->HelpContext=pVarRec->HelpContext;
1926 if(reclength >(7*sizeof(INT)) )
1927 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1928 if(reclength >(8*sizeof(INT)) )
1929 if(reclength >(9*sizeof(INT)) )
1930 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1931 /* fill the VarDesc Structure */
1932 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1933 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1934 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1935 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1936 MSFT_GetTdesc(pcx, pVarRec->DataType,
1937 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1938 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1939 if(pVarRec->VarKind == VAR_CONST ){
1940 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1941 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1942 pVarRec->OffsValue, pcx);
1944 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1945 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1946 pptvd=&((*pptvd)->next);
1947 recoffset += reclength;
1950 /* fill in data for a hreftype (offset). When the referenced type is contained
1951 * in the typelib, it's just an (file) offset in the type info base dir.
1952 * If comes from import, it's an offset+1 in the ImpInfo table
1954 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1958 TLBRefType **ppRefType = &pTI->reflist;
1960 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1963 if((*ppRefType)->reference == offset)
1965 ppRefType = &(*ppRefType)->next;
1968 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1969 sizeof(**ppRefType));
1971 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1972 /* external typelib */
1973 MSFT_ImpInfo impinfo;
1974 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1976 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1978 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1979 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1980 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1981 if(pImpLib->offset==impinfo.oImpFile) break;
1982 pImpLib=pImpLib->next;
1985 (*ppRefType)->reference=offset;
1986 (*ppRefType)->pImpTLInfo = pImpLib;
1987 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1988 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1989 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
1990 (*ppRefType)->index = TLB_REF_USE_GUID;
1992 (*ppRefType)->index = impinfo.oGuid;
1994 ERR("Cannot find a reference\n");
1995 (*ppRefType)->reference=-1;
1996 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1999 /* in this typelib */
2000 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2001 (*ppRefType)->reference=offset;
2002 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2006 /* process Implemented Interfaces of a com class */
2007 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2011 MSFT_RefRecord refrec;
2012 TLBImplType **ppImpl = &pTI->impltypelist;
2014 TRACE_(typelib)("\n");
2016 for(i=0;i<count;i++){
2017 if(offset<0) break; /* paranoia */
2018 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2019 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2020 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2021 (*ppImpl)->hRef = refrec.reftype;
2022 (*ppImpl)->implflags=refrec.flags;
2023 (*ppImpl)->ctCustData=
2024 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2025 offset=refrec.onext;
2026 ppImpl=&((*ppImpl)->next);
2030 * process a typeinfo record
2032 static ITypeInfoImpl * MSFT_DoTypeInfo(
2036 ITypeLibImpl * pLibInfo)
2038 MSFT_TypeInfoBase tiBase;
2039 ITypeInfoImpl *ptiRet;
2041 TRACE_(typelib)("count=%u\n", count);
2043 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2044 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2045 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2047 /* this is where we are coming from */
2048 ptiRet->pTypeLib = pLibInfo;
2049 ptiRet->index=count;
2050 /* fill in the typeattr fields */
2052 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2053 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2054 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2055 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2056 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2057 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2058 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2059 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2060 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2061 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2062 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2063 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2064 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2065 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2066 MSFT_GetTdesc(pcx, tiBase.datatype1,
2067 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2070 /* IDLDESC idldescType; *//* never saw this one != zero */
2072 /* name, eventually add to a hash table */
2073 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2074 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2075 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2077 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2078 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2079 ptiRet->dwHelpContext=tiBase.helpcontext;
2081 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2082 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2084 /* note: InfoType's Help file and HelpStringDll come from the containing
2085 * library. Further HelpString and Docstring appear to be the same thing :(
2088 if(ptiRet->TypeAttr.cFuncs >0 )
2089 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2090 ptiRet->TypeAttr.cVars,
2091 tiBase.memoffset, & ptiRet->funclist);
2093 if(ptiRet->TypeAttr.cVars >0 )
2094 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2095 ptiRet->TypeAttr.cVars,
2096 tiBase.memoffset, & ptiRet->varlist);
2097 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2098 switch(ptiRet->TypeAttr.typekind)
2101 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2104 case TKIND_DISPATCH:
2105 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2107 if (tiBase.datatype1 != -1)
2109 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2110 ptiRet->impltypelist->hRef = tiBase.datatype1;
2114 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2115 ptiRet->impltypelist->hRef = dispatch_href;
2119 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2120 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2121 ptiRet->impltypelist->hRef = tiBase.datatype1;
2126 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2128 TRACE_(typelib)("%s guid: %s kind:%s\n",
2129 debugstr_w(ptiRet->Name),
2130 debugstr_guid(&ptiRet->TypeAttr.guid),
2131 typekind_desc[ptiRet->TypeAttr.typekind]);
2136 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2137 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2138 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2141 static ITypeLibImpl *tlb_cache_first;
2142 static CRITICAL_SECTION cache_section;
2143 static CRITICAL_SECTION_DEBUG cache_section_debug =
2145 0, 0, &cache_section,
2146 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2147 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2149 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2152 /****************************************************************************
2155 * find the type of the typelib file and map the typelib resource into
2158 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2159 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2160 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2162 ITypeLibImpl *entry;
2163 int ret = TYPE_E_CANTLOADLIBRARY;
2169 lstrcpynW(pszPath, pszFileName, cchPath);
2171 /* first try loading as a dll and access the typelib as a resource */
2172 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2173 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2176 /* it may have been specified with resource index appended to the
2177 * path, so remove it and try again */
2178 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2179 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2181 index = atoiW(pIndexStr);
2182 pszPath[pIndexStr - pszFileName - 1] = '\0';
2184 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2185 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2189 /* get the path to the specified typelib file */
2192 /* otherwise, try loading as a regular file */
2193 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2194 return TYPE_E_CANTLOADLIBRARY;
2197 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2199 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2200 EnterCriticalSection(&cache_section);
2201 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2203 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2205 TRACE("cache hit\n");
2206 *ppTypeLib = (ITypeLib2*)entry;
2207 ITypeLib_AddRef(*ppTypeLib);
2208 LeaveCriticalSection(&cache_section);
2212 LeaveCriticalSection(&cache_section);
2214 /* now actually load and parse the typelib */
2217 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2218 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2221 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2224 LPVOID pBase = LockResource(hGlobal);
2225 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2229 /* try to load as incore resource */
2230 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2231 if (dwSignature == MSFT_SIGNATURE)
2232 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2233 else if (dwSignature == SLTG_SIGNATURE)
2234 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2236 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2238 FreeResource( hGlobal );
2241 FreeLibrary(hinstDLL);
2245 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2246 if (INVALID_HANDLE_VALUE != hFile)
2248 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2251 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2254 /* retrieve file size */
2255 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2256 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2258 if (dwSignature == MSFT_SIGNATURE)
2259 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2260 else if (dwSignature == SLTG_SIGNATURE)
2261 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2263 UnmapViewOfFile(pBase);
2265 CloseHandle(hMapping);
2272 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2274 TRACE("adding to cache\n");
2275 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2276 lstrcpyW(impl->path, pszPath);
2277 /* We should really canonicalise the path here. */
2278 impl->index = index;
2280 /* FIXME: check if it has added already in the meantime */
2281 EnterCriticalSection(&cache_section);
2282 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2284 tlb_cache_first = impl;
2285 LeaveCriticalSection(&cache_section);
2288 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2293 /*================== ITypeLib(2) Methods ===================================*/
2295 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2297 ITypeLibImpl* pTypeLibImpl;
2299 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2300 if (!pTypeLibImpl) return NULL;
2302 pTypeLibImpl->lpVtbl = &tlbvt;
2303 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2304 pTypeLibImpl->ref = 1;
2306 return pTypeLibImpl;
2309 /****************************************************************************
2310 * ITypeLib2_Constructor_MSFT
2312 * loading an MSFT typelib from an in-memory image
2314 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2318 MSFT_Header tlbHeader;
2319 MSFT_SegDir tlbSegDir;
2320 ITypeLibImpl * pTypeLibImpl;
2322 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2324 pTypeLibImpl = TypeLibImpl_Constructor();
2325 if (!pTypeLibImpl) return NULL;
2327 /* get pointer to beginning of typelib data */
2331 cx.pLibInfo = pTypeLibImpl;
2332 cx.length = dwTLBLength;
2335 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2336 TRACE_(typelib)("header:\n");
2337 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2338 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2339 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2342 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2344 /* there is a small amount of information here until the next important
2346 * the segment directory . Try to calculate the amount of data */
2347 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2349 /* now read the segment directory */
2350 TRACE("read segment directory (at %ld)\n",lPSegDir);
2351 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2352 cx.pTblDir = &tlbSegDir;
2354 /* just check two entries */
2355 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2357 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2358 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2362 /* now fill our internal data */
2363 /* TLIBATTR fields */
2364 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2366 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2367 /* Windows seems to have zero here, is this correct? */
2368 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2369 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2371 pTypeLibImpl->LibAttr.lcid = 0;
2373 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2374 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2375 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2376 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2378 /* name, eventually add to a hash table */
2379 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2382 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2383 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2385 if( tlbHeader.varflags & HELPDLLFLAG)
2388 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2389 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2392 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2395 if(tlbHeader.CustomDataOffset >= 0)
2397 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2400 /* fill in typedescriptions */
2401 if(tlbSegDir.pTypdescTab.length > 0)
2403 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2405 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2406 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2409 /* FIXME: add several sanity checks here */
2410 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2411 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2413 /* FIXME: check safearray */
2415 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2417 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2419 else if(td[0] == VT_CARRAY)
2421 /* array descr table here */
2422 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2424 else if(td[0] == VT_USERDEFINED)
2426 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2428 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2431 /* second time around to fill the array subscript info */
2434 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2435 if(tlbSegDir.pArrayDescriptions.offset>0)
2437 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2438 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2441 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2443 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2445 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2447 for(j = 0; j<td[2]; j++)
2449 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2450 sizeof(INT), &cx, DO_NOT_SEEK);
2451 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2452 sizeof(INT), &cx, DO_NOT_SEEK);
2457 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2458 ERR("didn't find array description data\n");
2463 /* imported type libs */
2464 if(tlbSegDir.pImpFiles.offset>0)
2466 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2467 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2470 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2475 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2476 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2477 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2479 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2480 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2481 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2482 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2485 name = TLB_Alloc(size+1);
2486 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2487 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2488 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2489 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2492 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2493 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2495 ppImpLib = &(*ppImpLib)->next;
2500 if(tlbHeader.nrtypeinfos >= 0 )
2502 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2503 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2506 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2508 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2510 ppTI = &((*ppTI)->next);
2511 (pTypeLibImpl->TypeInfoCount)++;
2515 TRACE("(%p)\n", pTypeLibImpl);
2516 return (ITypeLib2*) pTypeLibImpl;
2520 static BSTR TLB_MultiByteToBSTR(char *ptr)
2526 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2527 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2528 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2529 ret = SysAllocString(nameW);
2530 HeapFree(GetProcessHeap(), 0, nameW);
2534 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2540 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2541 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2545 guid->Data4[0] = s >> 8;
2546 guid->Data4[1] = s & 0xff;
2549 for(i = 0; i < 6; i++) {
2550 memcpy(b, str + 24 + 2 * i, 2);
2551 guid->Data4[i + 2] = strtol(b, NULL, 16);
2556 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2563 bytelen = *(WORD*)ptr;
2564 if(bytelen == 0xffff) return 2;
2565 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2566 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2567 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2568 *pBstr = SysAllocStringLen(nameW, len);
2569 HeapFree(GetProcessHeap(), 0, nameW);
2573 static WORD SLTG_ReadStringA(char *ptr, char **str)
2578 bytelen = *(WORD*)ptr;
2579 if(bytelen == 0xffff) return 2;
2580 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2581 memcpy(*str, ptr + 2, bytelen);
2582 (*str)[bytelen] = '\0';
2586 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2588 char *ptr = pLibBlk;
2591 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2592 FIXME("libblk magic = %04x\n", w);
2597 if((w = *(WORD*)ptr) != 0xffff) {
2598 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2603 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2605 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2607 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2610 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2613 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2614 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2616 pTypeLibImpl->LibAttr.lcid = 0;
2619 ptr += 4; /* skip res12 */
2621 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2624 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2627 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2630 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2631 ptr += sizeof(GUID);
2633 return ptr - (char*)pLibBlk;
2636 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2641 if((*pType & 0xe00) == 0xe00) {
2643 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2645 pTD = pTD->u.lptdesc;
2647 switch(*pType & 0x3f) {
2650 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2652 pTD = pTD->u.lptdesc;
2655 case VT_USERDEFINED:
2656 pTD->vt = VT_USERDEFINED;
2657 pTD->u.hreftype = *(++pType) / 4;
2663 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2666 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2668 pTD->vt = VT_CARRAY;
2669 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2671 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2672 pTD->u.lpadesc->cDims = pSA->cDims;
2673 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2674 pSA->cDims * sizeof(SAFEARRAYBOUND));
2676 pTD = &pTD->u.lpadesc->tdescElem;
2682 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2686 pTD->vt = VT_SAFEARRAY;
2687 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2689 pTD = pTD->u.lptdesc;
2693 pTD->vt = *pType & 0x3f;
2702 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2704 /* Handle [in/out] first */
2705 if((*pType & 0xc000) == 0xc000)
2706 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2707 else if(*pType & 0x8000)
2708 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2709 else if(*pType & 0x4000)
2710 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2712 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2715 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2718 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2720 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2724 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2729 TLBRefType **ppRefType;
2731 if(pRef->magic != SLTG_REF_MAGIC) {
2732 FIXME("Ref magic = %x\n", pRef->magic);
2735 name = ( (char*)(&pRef->names) + pRef->number);
2737 ppRefType = &pTI->reflist;
2738 for(ref = 0; ref < pRef->number >> 3; ref++) {
2740 unsigned int lib_offs, type_num;
2742 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2743 sizeof(**ppRefType));
2745 name += SLTG_ReadStringA(name, &refname);
2746 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2747 FIXME("Can't sscanf ref\n");
2748 if(lib_offs != 0xffff) {
2749 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2752 if((*import)->offset == lib_offs)
2754 import = &(*import)->next;
2757 char fname[MAX_PATH+1];
2760 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2762 (*import)->offset = lib_offs;
2763 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2765 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2766 &(*import)->wVersionMajor,
2767 &(*import)->wVersionMinor,
2768 &(*import)->lcid, fname) != 4) {
2769 FIXME("can't sscanf ref %s\n",
2770 pNameTable + lib_offs + 40);
2772 len = strlen(fname);
2773 if(fname[len-1] != '#')
2774 FIXME("fname = %s\n", fname);
2775 fname[len-1] = '\0';
2776 (*import)->name = TLB_MultiByteToBSTR(fname);
2778 (*ppRefType)->pImpTLInfo = *import;
2779 } else { /* internal ref */
2780 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2782 (*ppRefType)->reference = ref;
2783 (*ppRefType)->index = type_num;
2785 HeapFree(GetProcessHeap(), 0, refname);
2786 ppRefType = &(*ppRefType)->next;
2788 if((BYTE)*name != SLTG_REF_MAGIC)
2789 FIXME("End of ref block magic = %x\n", *name);
2790 dump_TLBRefType(pTI->reflist);
2793 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2796 SLTG_ImplInfo *info;
2797 TLBImplType **ppImplType = &pTI->impltypelist;
2798 /* I don't really get this structure, usually it's 0x16 bytes
2799 long, but iuser.tlb contains some that are 0x18 bytes long.
2800 That's ok because we can use the next ptr to jump to the next
2801 one. But how do we know the length of the last one? The WORD
2802 at offs 0x8 might be the clue. For now I'm just assuming that
2803 the last one is the regular 0x16 bytes. */
2805 info = (SLTG_ImplInfo*)pBlk;
2807 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2808 sizeof(**ppImplType));
2809 (*ppImplType)->hRef = info->ref;
2810 (*ppImplType)->implflags = info->impltypeflags;
2811 pTI->TypeAttr.cImplTypes++;
2812 ppImplType = &(*ppImplType)->next;
2814 if(info->next == 0xffff)
2817 FIXME("Interface inheriting more than one interface\n");
2818 info = (SLTG_ImplInfo*)(pBlk + info->next);
2820 info++; /* see comment at top of function */
2824 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2826 TLBVarDesc **ppVarDesc = &pTI->varlist;
2827 BSTR bstrPrevName = NULL;
2828 SLTG_Variable *pItem;
2833 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2834 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2836 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2837 sizeof(**ppVarDesc));
2838 (*ppVarDesc)->vardesc.memid = pItem->memid;
2840 if (pItem->magic != SLTG_VAR_MAGIC &&
2841 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2842 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2846 if (pItem->name == 0xfffe)
2847 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2849 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2851 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2852 TRACE_(typelib)("memid = 0x%lx\n", pItem->memid);
2854 if (pItem->flags & 0x40) {
2855 TRACE_(typelib)("VAR_DISPATCH\n");
2856 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2858 else if (pItem->flags & 0x10) {
2859 TRACE_(typelib)("VAR_CONST\n");
2860 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2861 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2863 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2864 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2865 *(INT*)(pBlk + pItem->byte_offs);
2868 TRACE_(typelib)("VAR_PERINSTANCE\n");
2869 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2870 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2873 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2874 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2876 if (pItem->flags & 0x80)
2877 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2879 if(pItem->flags & 0x02)
2880 pType = &pItem->type;
2882 pType = (WORD*)(pBlk + pItem->type);
2884 if (pItem->flags & ~0xd2)
2885 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2887 SLTG_DoElem(pType, pBlk,
2888 &(*ppVarDesc)->vardesc.elemdescVar);
2890 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2892 bstrPrevName = (*ppVarDesc)->Name;
2893 ppVarDesc = &((*ppVarDesc)->next);
2895 pTI->TypeAttr.cVars = cVars;
2898 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2900 SLTG_Function *pFunc;
2902 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2904 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2905 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2910 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2911 sizeof(**ppFuncDesc));
2913 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2914 case SLTG_FUNCTION_MAGIC:
2915 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2917 case SLTG_DISPATCH_FUNCTION_MAGIC:
2918 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2920 case SLTG_STATIC_FUNCTION_MAGIC:
2921 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2924 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2925 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2929 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2931 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2932 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2933 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2934 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2935 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2936 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2938 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2939 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2941 if(pFunc->retnextopt & 0x80)
2942 pType = &pFunc->rettype;
2944 pType = (WORD*)(pBlk + pFunc->rettype);
2946 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2948 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2949 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2950 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2951 (*ppFuncDesc)->pParamDesc =
2952 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2953 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2955 pArg = (WORD*)(pBlk + pFunc->arg_off);
2957 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2958 char *paramName = pNameTable + *pArg;
2960 /* If arg type follows then paramName points to the 2nd
2961 letter of the name, else the next WORD is an offset to
2962 the arg type and paramName points to the first letter.
2963 So let's take one char off paramName and see if we're
2964 pointing at an alpha-numeric char. However if *pArg is
2965 0xffff or 0xfffe then the param has no name, the former
2966 meaning that the next WORD is the type, the latter
2967 meaning the the next WORD is an offset to the type. */
2972 else if(*pArg == 0xfffe) {
2976 else if(paramName[-1] && !isalnum(paramName[-1]))
2981 if(HaveOffs) { /* the next word is an offset to type */
2982 pType = (WORD*)(pBlk + *pArg);
2983 SLTG_DoElem(pType, pBlk,
2984 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2989 pArg = SLTG_DoElem(pArg, pBlk,
2990 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2993 /* Are we an optional param ? */
2994 if((*ppFuncDesc)->funcdesc.cParams - param <=
2995 (*ppFuncDesc)->funcdesc.cParamsOpt)
2996 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2999 (*ppFuncDesc)->pParamDesc[param].Name =
3000 TLB_MultiByteToBSTR(paramName);
3004 ppFuncDesc = &((*ppFuncDesc)->next);
3005 if(pFunc->next == 0xffff) break;
3007 pTI->TypeAttr.cFuncs = cFuncs;
3010 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3011 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3012 SLTG_TypeInfoTail *pTITail)
3014 char *pFirstItem, *pNextItem;
3016 if(pTIHeader->href_table != 0xffffffff) {
3017 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3021 pFirstItem = pNextItem = pBlk;
3023 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3024 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3029 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3030 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3031 SLTG_TypeInfoTail *pTITail)
3033 char *pFirstItem, *pNextItem;
3035 if(pTIHeader->href_table != 0xffffffff) {
3036 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3040 pFirstItem = pNextItem = pBlk;
3042 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3043 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3046 if (pTITail->funcs_off != 0xffff)
3047 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3049 if (TRACE_ON(typelib))
3050 dump_TLBFuncDesc(pTI->funclist);
3053 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3054 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3055 SLTG_TypeInfoTail *pTITail)
3057 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3060 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3061 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3062 SLTG_TypeInfoTail *pTITail)
3066 if (pTITail->simple_alias) {
3067 /* if simple alias, no more processing required */
3068 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3072 if(pTIHeader->href_table != 0xffffffff) {
3073 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3077 /* otherwise it is an offset to a type */
3078 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3080 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3083 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3084 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3085 SLTG_TypeInfoTail *pTITail)
3087 if (pTIHeader->href_table != 0xffffffff)
3088 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3091 if (pTITail->vars_off != 0xffff)
3092 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3094 if (pTITail->funcs_off != 0xffff)
3095 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3097 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3098 * of dispinterface functons including the IDispatch ones, so
3099 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3100 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3102 if (TRACE_ON(typelib))
3103 dump_TLBFuncDesc(pTI->funclist);
3106 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3107 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3108 SLTG_TypeInfoTail *pTITail)
3110 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3113 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3114 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3115 SLTG_TypeInfoTail *pTITail)
3117 if (pTIHeader->href_table != 0xffffffff)
3118 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3121 if (pTITail->vars_off != 0xffff)
3122 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3124 if (pTITail->funcs_off != 0xffff)
3125 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3128 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3129 managable copy of it into this */
3142 } SLTG_InternalOtherTypeInfo;
3144 /****************************************************************************
3145 * ITypeLib2_Constructor_SLTG
3147 * loading a SLTG typelib from an in-memory image
3149 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3151 ITypeLibImpl *pTypeLibImpl;
3152 SLTG_Header *pHeader;
3153 SLTG_BlkEntry *pBlkEntry;
3157 LPVOID pBlk, pFirstBlk;
3158 SLTG_LibBlk *pLibBlk;
3159 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3160 char *pAfterOTIBlks = NULL;
3161 char *pNameTable, *ptr;
3164 ITypeInfoImpl **ppTypeInfoImpl;
3166 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3169 pTypeLibImpl = TypeLibImpl_Constructor();
3170 if (!pTypeLibImpl) return NULL;
3174 TRACE_(typelib)("header:\n");
3175 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3176 pHeader->nrOfFileBlks );
3177 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3178 FIXME("Header type magic 0x%08lx not supported.\n",
3179 pHeader->SLTG_magic);
3183 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3184 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3186 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3187 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3189 /* Next we have a magic block */
3190 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3192 /* Let's see if we're still in sync */
3193 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3194 sizeof(SLTG_COMPOBJ_MAGIC))) {
3195 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3198 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3199 sizeof(SLTG_DIR_MAGIC))) {
3200 FIXME("dir magic = %s\n", pMagic->dir_magic);
3204 pIndex = (SLTG_Index*)(pMagic+1);
3206 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3208 pFirstBlk = (LPVOID)(pPad9 + 1);
3210 /* We'll set up a ptr to the main library block, which is the last one. */
3212 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3213 pBlkEntry[order].next != 0;
3214 order = pBlkEntry[order].next - 1, i++) {
3215 pBlk = (char*)pBlk + pBlkEntry[order].len;
3219 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3221 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3226 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3228 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3229 sizeof(*pOtherTypeInfoBlks) *
3230 pTypeLibImpl->TypeInfoCount);
3233 ptr = (char*)pLibBlk + len;
3235 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3239 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3241 w = *(WORD*)(ptr + 2);
3244 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3246 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3247 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3249 w = *(WORD*)(ptr + 4 + len);
3251 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3253 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3255 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3256 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3258 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3259 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3260 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3262 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3264 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3267 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3268 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3269 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3270 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3271 len += sizeof(SLTG_OtherTypeInfo);
3275 pAfterOTIBlks = ptr;
3277 /* Skip this WORD and get the next DWORD */
3278 len = *(DWORD*)(pAfterOTIBlks + 2);
3280 /* Now add this to pLibBLk look at what we're pointing at and
3281 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3282 dust and we should be pointing at the beginning of the name
3285 pNameTable = (char*)pLibBlk + len;
3287 switch(*(WORD*)pNameTable) {
3294 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3298 pNameTable += 0x216;
3302 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3304 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3307 /* Hopefully we now have enough ptrs set up to actually read in
3308 some TypeInfos. It's not clear which order to do them in, so
3309 I'll just follow the links along the BlkEntry chain and read
3310 them in in the order in which they're in the file */
3312 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3314 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3315 pBlkEntry[order].next != 0;
3316 order = pBlkEntry[order].next - 1, i++) {
3318 SLTG_TypeInfoHeader *pTIHeader;
3319 SLTG_TypeInfoTail *pTITail;
3320 SLTG_MemberHeader *pMemHeader;
3322 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3323 pOtherTypeInfoBlks[i].index_name)) {
3324 FIXME("Index strings don't match\n");
3329 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3330 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3333 TRACE("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
3334 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3336 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3337 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3338 (*ppTypeInfoImpl)->index = i;
3339 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3340 pOtherTypeInfoBlks[i].name_offs +
3342 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3343 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3345 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3346 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3347 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3348 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3349 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3351 if((pTIHeader->typeflags1 & 7) != 2)
3352 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3353 if(pTIHeader->typeflags3 != 2)
3354 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3356 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3357 debugstr_w((*ppTypeInfoImpl)->Name),
3358 typekind_desc[pTIHeader->typekind],
3359 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3360 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3362 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3364 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3366 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3367 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3368 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3370 switch(pTIHeader->typekind) {
3372 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3373 pTIHeader, pTITail);
3377 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3378 pTIHeader, pTITail);
3381 case TKIND_INTERFACE:
3382 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3383 pTIHeader, pTITail);
3387 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3388 pTIHeader, pTITail);
3392 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3393 pTIHeader, pTITail);
3396 case TKIND_DISPATCH:
3397 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3398 pTIHeader, pTITail);
3402 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3403 pTIHeader, pTITail);
3407 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3412 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3413 but we've already set those */
3414 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3429 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3430 pBlk = (char*)pBlk + pBlkEntry[order].len;
3433 if(i != pTypeLibImpl->TypeInfoCount) {
3434 FIXME("Somehow processed %d TypeInfos\n", i);
3438 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3439 return (ITypeLib2*)pTypeLibImpl;
3442 /* ITypeLib::QueryInterface
3444 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3449 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3451 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3454 if(IsEqualIID(riid, &IID_IUnknown) ||
3455 IsEqualIID(riid,&IID_ITypeLib)||
3456 IsEqualIID(riid,&IID_ITypeLib2))
3463 ITypeLib2_AddRef(iface);
3464 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3467 TRACE("-- Interface: E_NOINTERFACE\n");
3468 return E_NOINTERFACE;
3473 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3475 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3476 ULONG ref = InterlockedIncrement(&This->ref);
3478 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3483 /* ITypeLib::Release
3485 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3487 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3488 ULONG ref = InterlockedDecrement(&This->ref);
3490 TRACE("(%p)->(%lu)\n",This, ref);
3494 /* remove cache entry */
3497 TRACE("removing from cache list\n");
3498 EnterCriticalSection(&cache_section);
3499 if (This->next) This->next->prev = This->prev;
3500 if (This->prev) This->prev->next = This->next;
3501 else tlb_cache_first = This->next;
3502 LeaveCriticalSection(&cache_section);
3503 HeapFree(GetProcessHeap(), 0, This->path);
3505 /* FIXME destroy child objects */
3506 TRACE(" destroying ITypeLib(%p)\n",This);
3510 SysFreeString(This->Name);
3514 if (This->DocString)
3516 SysFreeString(This->DocString);
3517 This->DocString = NULL;
3522 SysFreeString(This->HelpFile);
3523 This->HelpFile = NULL;
3526 if (This->HelpStringDll)
3528 SysFreeString(This->HelpStringDll);
3529 This->HelpStringDll = NULL;
3532 if (This->pTypeInfo) /* can be NULL */
3533 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3534 HeapFree(GetProcessHeap(),0,This);
3541 /* ITypeLib::GetTypeInfoCount
3543 * Returns the number of type descriptions in the type library
3545 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3547 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3548 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3549 return This->TypeInfoCount;
3552 /* ITypeLib::GetTypeInfo
3554 * retrieves the specified type description in the library.
3556 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3559 ITypeInfo **ppTInfo)
3563 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3564 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3566 TRACE("(%p)->(index=%d)\n", This, index);
3568 if (!ppTInfo) return E_INVALIDARG;
3570 /* search element n in list */
3571 for(i=0; i < index; i++)
3573 pTypeInfo = pTypeInfo->next;
3576 TRACE("-- element not found\n");
3577 return TYPE_E_ELEMENTNOTFOUND;
3581 *ppTInfo = (ITypeInfo *) pTypeInfo;
3583 ITypeInfo_AddRef(*ppTInfo);
3584 TRACE("-- found (%p)\n",*ppTInfo);
3589 /* ITypeLibs::GetTypeInfoType
3591 * Retrieves the type of a type description.
3593 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3598 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3600 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3602 TRACE("(%p) index %d\n", This, index);
3604 if(!pTKind) return E_INVALIDARG;
3606 /* search element n in list */
3607 for(i=0; i < index; i++)
3611 TRACE("-- element not found\n");
3612 return TYPE_E_ELEMENTNOTFOUND;
3614 pTInfo = pTInfo->next;
3617 *pTKind = pTInfo->TypeAttr.typekind;
3618 TRACE("-- found Type (%d)\n", *pTKind);
3622 /* ITypeLib::GetTypeInfoOfGuid
3624 * Retrieves the type description that corresponds to the specified GUID.
3627 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3630 ITypeInfo **ppTInfo)
3632 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3633 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3635 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3639 WARN("-- element not found\n");
3640 return TYPE_E_ELEMENTNOTFOUND;
3643 /* search linked list for guid */
3644 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3646 pTypeInfo = pTypeInfo->next;
3650 /* end of list reached */
3651 WARN("-- element not found\n");
3652 return TYPE_E_ELEMENTNOTFOUND;
3656 TRACE("-- found (%p, %s)\n",
3658 debugstr_w(pTypeInfo->Name));
3660 *ppTInfo = (ITypeInfo*)pTypeInfo;
3661 ITypeInfo_AddRef(*ppTInfo);
3665 /* ITypeLib::GetLibAttr
3667 * Retrieves the structure that contains the library's attributes.
3670 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3672 LPTLIBATTR *ppTLibAttr)
3674 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3675 TRACE("(%p)\n",This);
3676 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3677 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3681 /* ITypeLib::GetTypeComp
3683 * Enables a client compiler to bind to a library's types, variables,
3684 * constants, and global functions.
3687 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3689 ITypeComp **ppTComp)
3691 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3693 TRACE("(%p)->(%p)\n",This,ppTComp);
3694 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3695 ITypeComp_AddRef(*ppTComp);
3700 /* ITypeLib::GetDocumentation
3702 * Retrieves the library's documentation string, the complete Help file name
3703 * and path, and the context identifier for the library Help topic in the Help
3706 * On a successful return all non-null BSTR pointers will have been set,
3709 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3713 BSTR *pBstrDocString,
3714 DWORD *pdwHelpContext,
3715 BSTR *pBstrHelpFile)
3717 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3719 HRESULT result = E_INVALIDARG;
3724 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3726 pBstrName, pBstrDocString,
3727 pdwHelpContext, pBstrHelpFile);
3731 /* documentation for the typelib */
3736 if(!(*pBstrName = SysAllocString(This->Name)))
3744 if (This->DocString)
3746 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3749 else if (This->Name)
3751 if(!(*pBstrDocString = SysAllocString(This->Name)))
3755 *pBstrDocString = NULL;
3759 *pdwHelpContext = This->dwHelpContext;
3765 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3769 *pBstrHelpFile = NULL;
3776 /* for a typeinfo */
3777 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3779 if(SUCCEEDED(result))
3781 result = ITypeInfo_GetDocumentation(pTInfo,
3785 pdwHelpContext, pBstrHelpFile);
3787 ITypeInfo_Release(pTInfo);
3792 if (pBstrDocString) SysFreeString (*pBstrDocString);
3794 if (pBstrName) SysFreeString (*pBstrName);
3796 return STG_E_INSUFFICIENTMEMORY;
3801 * Indicates whether a passed-in string contains the name of a type or member
3802 * described in the library.
3805 static HRESULT WINAPI ITypeLib2_fnIsName(
3811 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3812 ITypeInfoImpl *pTInfo;
3813 TLBFuncDesc *pFInfo;
3816 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3818 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3822 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3823 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3824 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3825 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3826 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3827 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3828 goto ITypeLib2_fnIsName_exit;
3830 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3831 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3836 ITypeLib2_fnIsName_exit:
3837 TRACE("(%p)slow! search for %s: %s found!\n", This,
3838 debugstr_w(szNameBuf), *pfName?"NOT":"");
3843 /* ITypeLib::FindName
3845 * Finds occurrences of a type description in a type library. This may be used
3846 * to quickly verify that a name exists in a type library.
3849 static HRESULT WINAPI ITypeLib2_fnFindName(
3853 ITypeInfo **ppTInfo,
3857 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3858 ITypeInfoImpl *pTInfo;
3859 TLBFuncDesc *pFInfo;
3862 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3864 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3865 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3866 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3867 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3868 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3869 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3870 goto ITypeLib2_fnFindName_exit;
3873 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3874 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3876 ITypeLib2_fnFindName_exit:
3877 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3878 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3881 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3882 This, *pcFound, debugstr_w(szNameBuf), j);
3889 /* ITypeLib::ReleaseTLibAttr
3891 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3894 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3896 TLIBATTR *pTLibAttr)
3898 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3899 TRACE("freeing (%p)\n",This);
3900 HeapFree(GetProcessHeap(),0,pTLibAttr);
3904 /* ITypeLib2::GetCustData
3906 * gets the custom data
3908 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3913 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3914 TLBCustData *pCData;
3916 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3918 if( IsEqualIID(guid, &pCData->guid)) break;
3921 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3925 VariantInit( pVarVal);
3926 VariantCopy( pVarVal, &pCData->data);
3929 return E_INVALIDARG; /* FIXME: correct? */
3932 /* ITypeLib2::GetLibStatistics
3934 * Returns statistics about a type library that are required for efficient
3935 * sizing of hash tables.
3938 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3940 ULONG *pcUniqueNames,
3941 ULONG *pcchUniqueNames)
3943 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3945 FIXME("(%p): stub!\n", This);
3947 if(pcUniqueNames) *pcUniqueNames=1;
3948 if(pcchUniqueNames) *pcchUniqueNames=1;
3952 /* ITypeLib2::GetDocumentation2
3954 * Retrieves the library's documentation string, the complete Help file name
3955 * and path, the localization context to use, and the context ID for the
3956 * library Help topic in the Help file.
3959 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3963 BSTR *pbstrHelpString,
3964 DWORD *pdwHelpStringContext,
3965 BSTR *pbstrHelpStringDll)
3967 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3971 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3973 /* the help string should be obtained from the helpstringdll,
3974 * using the _DLLGetDocumentation function, based on the supplied
3975 * lcid. Nice to do sometime...
3979 /* documentation for the typelib */
3981 *pbstrHelpString=SysAllocString(This->DocString);
3982 if(pdwHelpStringContext)
3983 *pdwHelpStringContext=This->dwHelpContext;
3984 if(pbstrHelpStringDll)
3985 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3991 /* for a typeinfo */
3992 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3994 if(SUCCEEDED(result))
3996 ITypeInfo2 * pTInfo2;
3997 result = ITypeInfo_QueryInterface(pTInfo,
3999 (LPVOID*) &pTInfo2);
4001 if(SUCCEEDED(result))
4003 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4007 pdwHelpStringContext,
4008 pbstrHelpStringDll);
4010 ITypeInfo2_Release(pTInfo2);
4013 ITypeInfo_Release(pTInfo);
4019 /* ITypeLib2::GetAllCustData
4021 * Gets all custom data items for the library.
4024 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4026 CUSTDATA *pCustData)
4028 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4029 TLBCustData *pCData;
4031 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4032 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4033 if(pCustData->prgCustData ){
4034 pCustData->cCustData=This->ctCustData;
4035 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4036 pCustData->prgCustData[i].guid=pCData->guid;
4037 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4040 ERR(" OUT OF MEMORY!\n");
4041 return E_OUTOFMEMORY;
4046 static const ITypeLib2Vtbl tlbvt = {
4047 ITypeLib2_fnQueryInterface,
4049 ITypeLib2_fnRelease,
4050 ITypeLib2_fnGetTypeInfoCount,
4051 ITypeLib2_fnGetTypeInfo,
4052 ITypeLib2_fnGetTypeInfoType,
4053 ITypeLib2_fnGetTypeInfoOfGuid,
4054 ITypeLib2_fnGetLibAttr,
4055 ITypeLib2_fnGetTypeComp,
4056 ITypeLib2_fnGetDocumentation,
4058 ITypeLib2_fnFindName,
4059 ITypeLib2_fnReleaseTLibAttr,
4061 ITypeLib2_fnGetCustData,
4062 ITypeLib2_fnGetLibStatistics,
4063 ITypeLib2_fnGetDocumentation2,
4064 ITypeLib2_fnGetAllCustData
4068 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4070 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4072 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4075 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4077 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4079 return ITypeLib2_AddRef((ITypeLib2 *)This);
4082 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4084 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4086 return ITypeLib2_Release((ITypeLib2 *)This);
4089 static HRESULT WINAPI ITypeLibComp_fnBind(
4094 ITypeInfo ** ppTInfo,
4095 DESCKIND * pDescKind,
4098 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4099 ITypeInfoImpl *pTypeInfo;
4101 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4103 *pDescKind = DESCKIND_NONE;
4104 pBindPtr->lptcomp = NULL;
4107 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4109 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4111 /* FIXME: check wFlags here? */
4112 /* FIXME: we should use a hash table to look this info up using lHash
4113 * instead of an O(n) search */
4114 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4115 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4117 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4119 *pDescKind = DESCKIND_TYPECOMP;
4120 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4121 ITypeComp_AddRef(pBindPtr->lptcomp);
4122 TRACE("module or enum: %s\n", debugstr_w(szName));
4127 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4128 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4130 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4133 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4134 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4136 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4141 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4142 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4144 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4146 ITypeInfo *subtypeinfo;
4148 DESCKIND subdesckind;
4150 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4151 &subtypeinfo, &subdesckind, &subbindptr);
4152 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4154 TYPEDESC tdesc_appobject =
4157 (TYPEDESC *)pTypeInfo->hreftype
4161 const VARDESC vardesc_appobject =
4164 NULL, /* lpstrSchema */
4179 VAR_STATIC /* varkind */
4182 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4184 /* cleanup things filled in by Bind call so we can put our
4185 * application object data in there instead */
4186 switch (subdesckind)
4188 case DESCKIND_FUNCDESC:
4189 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4191 case DESCKIND_VARDESC:
4192 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4197 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4199 if (pTypeInfo->hreftype == -1)
4200 FIXME("no hreftype for interface %p\n", pTypeInfo);
4202 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4206 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4207 *ppTInfo = (ITypeInfo *)pTypeInfo;
4208 ITypeInfo_AddRef(*ppTInfo);
4214 TRACE("name not found %s\n", debugstr_w(szName));
4218 static HRESULT WINAPI ITypeLibComp_fnBindType(
4222 ITypeInfo ** ppTInfo,
4223 ITypeComp ** ppTComp)
4225 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4229 static const ITypeCompVtbl tlbtcvt =
4232 ITypeLibComp_fnQueryInterface,
4233 ITypeLibComp_fnAddRef,
4234 ITypeLibComp_fnRelease,
4236 ITypeLibComp_fnBind,
4237 ITypeLibComp_fnBindType
4240 /*================== ITypeInfo(2) Methods ===================================*/
4241 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4243 ITypeInfoImpl * pTypeInfoImpl;
4245 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4248 pTypeInfoImpl->lpVtbl = &tinfvt;
4249 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4250 pTypeInfoImpl->ref=1;
4251 pTypeInfoImpl->hreftype = -1;
4252 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4253 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4255 TRACE("(%p)\n", pTypeInfoImpl);
4256 return (ITypeInfo2*) pTypeInfoImpl;
4259 /* ITypeInfo::QueryInterface
4261 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4266 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4268 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4271 if(IsEqualIID(riid, &IID_IUnknown) ||
4272 IsEqualIID(riid,&IID_ITypeInfo)||
4273 IsEqualIID(riid,&IID_ITypeInfo2))
4277 ITypeInfo_AddRef(iface);
4278 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4281 TRACE("-- Interface: E_NOINTERFACE\n");
4282 return E_NOINTERFACE;
4285 /* ITypeInfo::AddRef
4287 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4289 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4290 ULONG ref = InterlockedIncrement(&This->ref);
4292 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4294 TRACE("(%p)->ref is %lu\n",This, ref);
4298 /* ITypeInfo::Release
4300 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4302 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4303 ULONG ref = InterlockedDecrement(&This->ref);
4305 TRACE("(%p)->(%lu)\n",This, ref);
4308 /* We don't release ITypeLib when ref=0 because
4309 it means that function is called by ITypeLib2_Release */
4310 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4312 static int once = 0;
4316 FIXME("destroy child objects\n");
4319 TRACE("destroying ITypeInfo(%p)\n",This);
4322 SysFreeString(This->Name);
4326 if (This->DocString)
4328 SysFreeString(This->DocString);
4329 This->DocString = 0;
4334 SysFreeString(This->DllName);
4340 ITypeInfo_Release((ITypeInfo*)This->next);
4343 HeapFree(GetProcessHeap(),0,This);
4349 /* ITypeInfo::GetTypeAttr
4351 * Retrieves a TYPEATTR structure that contains the attributes of the type
4355 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4356 LPTYPEATTR *ppTypeAttr)
4358 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4361 TRACE("(%p)\n",This);
4363 size = sizeof(**ppTypeAttr);
4364 if (This->TypeAttr.typekind == TKIND_ALIAS)
4365 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4367 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4369 return E_OUTOFMEMORY;
4371 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4373 if (This->TypeAttr.typekind == TKIND_ALIAS)
4374 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4375 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4377 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4378 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4380 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4381 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4386 /* ITypeInfo::GetTypeComp
4388 * Retrieves the ITypeComp interface for the type description, which enables a
4389 * client compiler to bind to the type description's members.
4392 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4393 ITypeComp * *ppTComp)
4395 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4397 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4399 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4400 ITypeComp_AddRef(*ppTComp);
4404 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4406 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4407 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4408 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4412 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4414 memcpy(dest, src, sizeof(ELEMDESC));
4415 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4416 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4418 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4419 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4420 *buffer += sizeof(PARAMDESCEX);
4421 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4422 VariantInit(&pparamdescex_dest->varDefaultValue);
4423 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4424 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4427 dest->u.paramdesc.pparamdescex = NULL;
4431 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4433 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4434 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4437 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4441 SIZE_T size = sizeof(*src);
4445 size += sizeof(*src->lprgscode) * src->cScodes;
4446 size += TLB_SizeElemDesc(&src->elemdescFunc);
4447 for (i = 0; i < src->cParams; i++)
4449 size += sizeof(ELEMDESC);
4450 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4453 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4454 if (!dest) return E_OUTOFMEMORY;
4456 memcpy(dest, src, sizeof(FUNCDESC));
4457 buffer = (char *)(dest + 1);
4459 dest->lprgscode = (SCODE *)buffer;
4460 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4461 buffer += sizeof(*src->lprgscode) * src->cScodes;
4463 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4466 SysFreeString((BSTR)dest);
4470 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4471 buffer += sizeof(ELEMDESC) * src->cParams;
4472 for (i = 0; i < src->cParams; i++)
4474 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4480 /* undo the above actions */
4481 for (i = i - 1; i >= 0; i--)
4482 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4483 TLB_FreeElemDesc(&dest->elemdescFunc);
4484 SysFreeString((BSTR)dest);
4488 /* special treatment for dispinterfaces: this makes functions appear
4489 * to return their [retval] value when it is really returning an
4491 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4493 if (dest->cParams &&
4494 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4496 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4497 if (elemdesc->tdesc.vt != VT_PTR)
4499 ERR("elemdesc should have started with VT_PTR instead of:\n");
4501 dump_ELEMDESC(elemdesc);
4502 return E_UNEXPECTED;
4505 /* copy last parameter to the return value. we are using a flat
4506 * buffer so there is no danger of leaking memory in
4508 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4510 /* remove the last parameter */
4514 /* otherwise this function is made to appear to have no return
4516 dest->elemdescFunc.tdesc.vt = VT_VOID;
4524 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4526 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4527 const TLBFuncDesc *pFDesc;
4530 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4535 *ppFuncDesc = &pFDesc->funcdesc;
4539 return E_INVALIDARG;
4542 /* ITypeInfo::GetFuncDesc
4544 * Retrieves the FUNCDESC structure that contains information about a
4545 * specified function.
4548 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4549 LPFUNCDESC *ppFuncDesc)
4551 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4552 const FUNCDESC *internal_funcdesc;
4555 TRACE("(%p) index %d\n", This, index);
4557 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4561 return TLB_AllocAndInitFuncDesc(
4564 This->TypeAttr.typekind == TKIND_DISPATCH);
4567 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4571 SIZE_T size = sizeof(*src);
4574 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4575 if (src->varkind == VAR_CONST)
4576 size += sizeof(VARIANT);
4577 size += TLB_SizeElemDesc(&src->elemdescVar);
4579 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4580 if (!dest) return E_OUTOFMEMORY;
4583 buffer = (char *)(dest + 1);
4584 if (src->lpstrSchema)
4587 dest->lpstrSchema = (LPOLESTR)buffer;
4588 len = strlenW(src->lpstrSchema);
4589 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4590 buffer += (len + 1) * sizeof(WCHAR);
4593 if (src->varkind == VAR_CONST)
4597 dest->u.lpvarValue = (VARIANT *)buffer;
4598 *dest->u.lpvarValue = *src->u.lpvarValue;
4599 buffer += sizeof(VARIANT);
4600 VariantInit(dest->u.lpvarValue);
4601 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4604 SysFreeString((BSTR)dest_ptr);
4608 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4611 if (src->varkind == VAR_CONST)
4612 VariantClear(dest->u.lpvarValue);
4613 SysFreeString((BSTR)dest);
4620 /* ITypeInfo::GetVarDesc
4622 * Retrieves a VARDESC structure that describes the specified variable.
4625 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4626 LPVARDESC *ppVarDesc)
4628 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4630 const TLBVarDesc *pVDesc;
4632 TRACE("(%p) index %d\n", This, index);
4634 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4638 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4640 return E_INVALIDARG;
4643 /* ITypeInfo_GetNames
4645 * Retrieves the variable with the specified member ID (or the name of the
4646 * property or method and its parameters) that correspond to the specified
4649 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4650 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4652 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4653 const TLBFuncDesc *pFDesc;
4654 const TLBVarDesc *pVDesc;
4656 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4657 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4660 /* function found, now return function and parameter names */
4661 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4664 *rgBstrNames=SysAllocString(pFDesc->Name);
4666 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4672 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4675 *rgBstrNames=SysAllocString(pVDesc->Name);
4680 if(This->TypeAttr.cImplTypes &&
4681 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4682 /* recursive search */
4685 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4687 if(SUCCEEDED(result))
4689 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4690 ITypeInfo_Release(pTInfo);
4693 WARN("Could not search inherited interface!\n");
4697 WARN("no names found\n");
4700 return TYPE_E_ELEMENTNOTFOUND;
4707 /* ITypeInfo::GetRefTypeOfImplType
4709 * If a type description describes a COM class, it retrieves the type
4710 * description of the implemented interface types. For an interface,
4711 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4715 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4720 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4723 const TLBImplType *pImpl = This->impltypelist;
4725 TRACE("(%p) index %d\n", This, index);
4726 if (TRACE_ON(ole)) dump_TypeInfo(This);
4730 /* only valid on dual interfaces;
4731 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4733 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4735 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4736 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4742 hr = TYPE_E_ELEMENTNOTFOUND;
4747 /* get element n from linked list */
4748 for(i=0; pImpl && i<index; i++)
4750 pImpl = pImpl->next;
4754 *pRefType = pImpl->hRef;
4756 hr = TYPE_E_ELEMENTNOTFOUND;
4762 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4764 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4770 /* ITypeInfo::GetImplTypeFlags
4772 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4773 * or base interface in a type description.
4775 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4776 UINT index, INT *pImplTypeFlags)
4778 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4782 TRACE("(%p) index %d\n", This, index);
4783 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4784 i++, pImpl=pImpl->next)
4786 if(i==index && pImpl){
4787 *pImplTypeFlags=pImpl->implflags;
4791 return TYPE_E_ELEMENTNOTFOUND;
4795 * Maps between member names and member IDs, and parameter names and
4798 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4799 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4801 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4802 const TLBFuncDesc *pFDesc;
4803 const TLBVarDesc *pVDesc;
4807 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4810 /* init out parameters in case of failure */
4811 for (i = 0; i < cNames; i++)
4812 pMemId[i] = MEMBERID_NIL;
4814 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4816 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4817 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4818 for(i=1; i < cNames; i++){
4819 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4820 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4822 if( j<pFDesc->funcdesc.cParams)
4825 ret=DISP_E_UNKNOWNNAME;
4827 TRACE("-- 0x%08lx\n", ret);
4831 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4832 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4833 if(cNames) *pMemId=pVDesc->vardesc.memid;
4837 /* not found, see if it can be found in an inherited interface */
4838 if(This->TypeAttr.cImplTypes) {
4839 /* recursive search */
4841 ret=ITypeInfo_GetRefTypeInfo(iface,
4842 This->impltypelist->hRef, &pTInfo);
4844 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4845 ITypeInfo_Release(pTInfo);
4848 WARN("Could not search inherited interface!\n");
4850 WARN("no names found\n");
4851 return DISP_E_UNKNOWNNAME;
4854 /* ITypeInfo::Invoke
4856 * Invokes a method, or accesses a property of an object, that implements the
4857 * interface described by the type description.
4860 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4863 if (TRACE_ON(ole)) {
4865 TRACE("Calling %p(",func);
4866 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4878 res = func(args[0]);
4881 res = func(args[0],args[1]);
4884 res = func(args[0],args[1],args[2]);
4887 res = func(args[0],args[1],args[2],args[3]);
4890 res = func(args[0],args[1],args[2],args[3],args[4]);
4893 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4896 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4899 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4902 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4905 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4908 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4911 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]);
4914 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]);
4917 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]);
4920 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]);
4923 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]);
4926 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]);
4929 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]);
4932 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]);
4935 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]);
4938 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]);
4941 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]);
4944 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]);
4947 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4953 FIXME("unsupported calling convention %d\n",callconv);
4957 TRACE("returns %08lx\n",res);
4961 extern int _argsize(DWORD vt);
4963 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
4966 ITypeInfo *tinfo2 = NULL;
4967 TYPEATTR *tattr = NULL;
4969 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4972 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4974 tdesc->u.hreftype, hr);
4977 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4980 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4981 ITypeInfo_Release(tinfo2);
4985 switch (tattr->typekind)
4992 tdesc = &tattr->tdescAlias;
4993 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4996 case TKIND_INTERFACE:
4997 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5003 case TKIND_DISPATCH:
5008 FIXME("TKIND_RECORD unhandled.\n");
5013 FIXME("TKIND_UNION unhandled.\n");
5018 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5022 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5023 ITypeInfo_Release(tinfo2);
5027 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5031 /* enforce only one level of pointer indirection */
5032 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5034 tdesc = tdesc->u.lptdesc;
5036 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5037 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5038 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5039 if ((tdesc->vt == VT_USERDEFINED) ||
5040 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5042 VARTYPE vt_userdefined = 0;
5043 const TYPEDESC *tdesc_userdefined = tdesc;
5044 if (tdesc->vt == VT_PTR)
5046 vt_userdefined = VT_BYREF;
5047 tdesc_userdefined = tdesc->u.lptdesc;
5049 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5051 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5052 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5054 *vt |= vt_userdefined;
5066 case VT_USERDEFINED:
5067 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5074 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5075 hr = DISP_E_BADVARTYPE;
5079 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5088 /***********************************************************************
5089 * DispCallFunc (OLEAUT32.@)
5091 * Invokes a function of the specifed calling convention, passing the
5092 * specified arguments and returns the result.
5095 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5096 * oVft [I] The offset in the vtable. See notes.
5097 * cc [I] Calling convention of the function to call.
5098 * vtReturn [I] The return type of the function.
5099 * cActuals [I] Number of parameters.
5100 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5101 * prgpvarg [I] The arguments to pass.
5102 * pvargResult [O] The return value of the function. Can be NULL.
5106 * Failure: HRESULT code.
5109 * The HRESULT return value of this function is not affected by the return
5110 * value of the user supplied function, which is returned in pvargResult.
5112 * If pvInstance is NULL then a non-object function is to be called and oVft
5113 * is the address of the function to call.
5115 * The cc parameter can be one of the following values:
5128 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5129 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5131 int i, argsize, argspos;
5135 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5136 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5137 pvargResult, V_VT(pvargResult));
5141 argsize++; /* for This pointer */
5143 for (i=0;i<cActuals;i++)
5145 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5146 dump_Variant(prgpvarg[i]);
5147 argsize += _argsize(prgvt[i]);
5149 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5154 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5158 for (i=0;i<cActuals;i++)
5160 VARIANT *arg = prgpvarg[i];
5161 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5162 if (prgvt[i] == VT_VARIANT)
5163 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5165 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5166 argspos += _argsize(prgvt[i]);
5171 FARPROC *vtable = *(FARPROC**)pvInstance;
5172 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5175 /* if we aren't invoking an object then the function pointer is stored
5177 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5179 if (pvargResult && (vtReturn != VT_EMPTY))
5181 TRACE("Method returned 0x%08lx\n",hres);
5182 V_VT(pvargResult) = vtReturn;
5183 V_UI4(pvargResult) = hres;
5186 HeapFree(GetProcessHeap(),0,args);
5190 #define INVBUF_ELEMENT_SIZE \
5191 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5192 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5193 ((VARIANTARG *)(buffer))
5194 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5195 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5196 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5197 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5198 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5199 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5201 static HRESULT WINAPI ITypeInfo_fnInvoke(
5206 DISPPARAMS *pDispParams,
5207 VARIANT *pVarResult,
5208 EXCEPINFO *pExcepInfo,
5211 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5213 unsigned int var_index;
5216 const TLBFuncDesc *pFuncInfo;
5218 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5219 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5221 dump_DispParms(pDispParams);
5223 /* we do this instead of using GetFuncDesc since it will return a fake
5224 * FUNCDESC for dispinterfaces and we want the real function description */
5225 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5226 if ((memid == pFuncInfo->funcdesc.memid) &&
5227 (wFlags & pFuncInfo->funcdesc.invkind))
5231 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5235 TRACE("invoking:\n");
5236 dump_TLBFuncDescOne(pFuncInfo);
5239 switch (func_desc->funckind) {
5240 case FUNC_PUREVIRTUAL:
5241 case FUNC_VIRTUAL: {
5242 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5244 VARIANT retval; /* pointer for storing byref retvals in */
5245 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5246 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5247 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5250 for (i = 0; i < func_desc->cParams; i++)
5252 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5253 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5258 TRACE("changing args\n");
5259 for (i = 0; i < func_desc->cParams; i++)
5261 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5263 if (wParamFlags & PARAMFLAG_FRETVAL)
5265 /* note: this check is placed so that if the caller passes
5266 * in a VARIANTARG for the retval we just ignore it, like
5268 if (i == func_desc->cParams - 1)
5271 arg = prgpvarg[i] = &rgvarg[i];
5272 memset(arg, 0, sizeof(*arg));
5273 V_VT(arg) = rgvt[i];
5274 memset(&retval, 0, sizeof(retval));
5275 V_BYREF(arg) = &retval;
5279 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5280 hres = E_UNEXPECTED;
5284 else if (i < pDispParams->cArgs)
5286 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5287 dump_Variant(src_arg);
5289 if (rgvt[i] == VT_VARIANT)
5290 hres = VariantCopy(&rgvarg[i], src_arg);
5291 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5293 if (rgvt[i] == V_VT(src_arg))
5294 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5297 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5298 hres = VariantCopy(&missing_arg[i], src_arg);
5299 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5301 V_VT(&rgvarg[i]) = rgvt[i];
5303 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5305 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5306 V_VT(&missing_arg[i]) = V_VT(src_arg);
5307 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5308 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5309 V_VT(&rgvarg[i]) = rgvt[i];
5311 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5313 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5314 V_VT(&rgvarg[i]) = rgvt[i];
5318 /* FIXME: this doesn't work for VT_BYREF arguments if
5319 * they are not the same type as in the paramdesc */
5320 V_VT(&rgvarg[i]) = V_VT(src_arg);
5321 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5322 V_VT(&rgvarg[i]) = rgvt[i];
5327 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5328 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5329 debugstr_VT(src_arg), debugstr_VF(src_arg));
5332 prgpvarg[i] = &rgvarg[i];
5334 else if (wParamFlags & PARAMFLAG_FOPT)
5337 arg = prgpvarg[i] = &rgvarg[i];
5338 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5340 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5346 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5347 V_VT(arg) = VT_VARIANT | VT_BYREF;
5348 V_VARIANTREF(arg) = &missing_arg[i];
5349 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5350 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5355 hres = DISP_E_BADPARAMCOUNT;
5359 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5360 if (func_desc->cParamsOpt < 0)
5362 FIXME("Does not support safearray optional parameters\n");
5363 hres = DISP_E_BADPARAMCOUNT;
5364 goto func_fail; /* FIXME: we don't free changed types here */
5367 /* VT_VOID is a special case for return types, so it is not
5368 * handled in the general function */
5369 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5370 V_VT(&varresult) = VT_EMPTY;
5373 V_VT(&varresult) = 0;
5374 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5375 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5378 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5379 V_VT(&varresult), func_desc->cParams, rgvt,
5380 prgpvarg, &varresult);
5382 for (i = 0; i < func_desc->cParams; i++)
5384 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5385 if (wParamFlags & PARAMFLAG_FRETVAL)
5389 TRACE("[retval] value: ");
5390 dump_Variant(prgpvarg[i]);
5394 /* deref return value */
5395 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5397 /* free data stored in varresult. Note that
5398 * VariantClear doesn't do what we want because we are
5399 * working with byref types. */
5400 /* FIXME: clear safearrays, bstrs, records and
5401 * variants here too */
5402 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5403 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5405 if(*V_UNKNOWNREF(prgpvarg[i]))
5406 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5410 else if (i < pDispParams->cArgs)
5412 if (wParamFlags & PARAMFLAG_FOUT)
5414 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5416 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5417 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5421 ERR("failed to convert param %d to vt %d\n", i,
5422 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5426 VariantClear(&rgvarg[i]);
5428 else if (wParamFlags & PARAMFLAG_FOPT)
5430 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5431 VariantClear(&rgvarg[i]);
5435 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5437 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5438 hres = DISP_E_EXCEPTION;
5439 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5443 HeapFree(GetProcessHeap(), 0, buffer);
5446 case FUNC_DISPATCH: {
5449 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5450 if (SUCCEEDED(hres)) {
5451 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5452 hres = IDispatch_Invoke(
5453 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5454 pVarResult,pExcepInfo,pArgErr
5457 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5458 IDispatch_Release(disp);
5460 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5464 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5469 TRACE("-- 0x%08lx\n", hres);
5472 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5475 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5476 if(FAILED(hres)) return hres;
5478 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5479 dump_VARDESC(var_desc);
5480 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5484 /* not found, look for it in inherited interfaces */
5485 ITypeInfo2_GetTypeKind(iface, &type_kind);
5486 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5488 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5489 /* recursive search */
5491 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5492 if(SUCCEEDED(hres)){
5493 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5494 ITypeInfo_Release(pTInfo);
5497 WARN("Could not search inherited interface!\n");
5500 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5501 return DISP_E_MEMBERNOTFOUND;
5504 /* ITypeInfo::GetDocumentation
5506 * Retrieves the documentation string, the complete Help file name and path,
5507 * and the context ID for the Help topic for a specified type description.
5509 * (Can be tested by the Visual Basic Editor in Word for instance.)
5511 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5512 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5513 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5515 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5516 const TLBFuncDesc *pFDesc;
5517 const TLBVarDesc *pVDesc;
5518 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5519 " HelpContext(%p) HelpFile(%p)\n",
5520 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5521 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5523 *pBstrName=SysAllocString(This->Name);
5525 *pBstrDocString=SysAllocString(This->DocString);
5527 *pdwHelpContext=This->dwHelpContext;
5529 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5531 }else {/* for a member */
5532 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5533 if(pFDesc->funcdesc.memid==memid){
5535 *pBstrName = SysAllocString(pFDesc->Name);
5537 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5539 *pdwHelpContext=pFDesc->helpcontext;
5542 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5543 if(pVDesc->vardesc.memid==memid){
5545 *pBstrName = SysAllocString(pVDesc->Name);
5547 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5549 *pdwHelpContext=pVDesc->HelpContext;
5553 WARN("member %ld not found\n", memid);
5554 return TYPE_E_ELEMENTNOTFOUND;
5557 /* ITypeInfo::GetDllEntry
5559 * Retrieves a description or specification of an entry point for a function
5562 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5563 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5566 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5567 const TLBFuncDesc *pFDesc;
5569 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5571 if (pBstrDllName) *pBstrDllName = NULL;
5572 if (pBstrName) *pBstrName = NULL;
5573 if (pwOrdinal) *pwOrdinal = 0;
5575 if (This->TypeAttr.typekind != TKIND_MODULE)
5576 return TYPE_E_BADMODULEKIND;
5578 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5579 if(pFDesc->funcdesc.memid==memid){
5580 dump_TypeInfo(This);
5582 dump_TLBFuncDescOne(pFDesc);
5585 *pBstrDllName = SysAllocString(This->DllName);
5587 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5589 *pBstrName = SysAllocString(pFDesc->Entry);
5597 *pwOrdinal = (DWORD)pFDesc->Entry;
5600 return TYPE_E_ELEMENTNOTFOUND;
5603 /* ITypeInfo::GetRefTypeInfo
5605 * If a type description references other type descriptions, it retrieves
5606 * the referenced type descriptions.
5608 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5611 ITypeInfo **ppTInfo)
5613 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5614 HRESULT result = E_FAIL;
5616 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5618 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5619 ITypeInfo_AddRef(*ppTInfo);
5622 else if (hRefType == -1 &&
5623 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5624 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5626 /* when we meet a DUAL dispinterface, we must create the interface
5629 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5632 /* the interface version contains the same information as the dispinterface
5633 * copy the contents of the structs.
5635 *pTypeInfoImpl = *This;
5636 pTypeInfoImpl->ref = 1;
5638 /* change the type to interface */
5639 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5641 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5643 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5648 TLBRefType *pRefType;
5649 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5650 if(pRefType->reference == hRefType)
5654 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5655 if(pRefType && hRefType != -1) {
5656 ITypeLib *pTLib = NULL;
5658 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5660 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5662 if(pRefType->pImpTLInfo->pImpTypeLib) {
5663 TRACE("typeinfo in imported typelib that is already loaded\n");
5664 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5665 ITypeLib2_AddRef((ITypeLib*) pTLib);
5668 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5669 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5670 pRefType->pImpTLInfo->wVersionMajor,
5671 pRefType->pImpTLInfo->wVersionMinor,
5672 pRefType->pImpTLInfo->lcid,
5675 if(!SUCCEEDED(result)) {
5676 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5677 result=LoadTypeLib(libnam, &pTLib);
5678 SysFreeString(libnam);
5680 if(SUCCEEDED(result)) {
5681 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5682 ITypeLib2_AddRef(pTLib);
5686 if(SUCCEEDED(result)) {
5687 if(pRefType->index == TLB_REF_USE_GUID)
5688 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5692 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5696 ITypeLib2_Release(pTLib);
5700 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5701 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5705 /* ITypeInfo::AddressOfMember
5707 * Retrieves the addresses of static functions or variables, such as those
5710 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5711 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5713 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5719 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5721 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5725 module = LoadLibraryW(dll);
5728 ERR("couldn't load %s\n", debugstr_w(dll));
5730 if (entry) SysFreeString(entry);
5731 return STG_E_FILENOTFOUND;
5733 /* FIXME: store library somewhere where we can free it */
5738 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5739 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5740 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5742 *ppv = GetProcAddress(module, entryA);
5744 ERR("function not found %s\n", debugstr_a(entryA));
5746 HeapFree(GetProcessHeap(), 0, entryA);
5750 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5752 ERR("function not found %d\n", ordinal);
5756 if (entry) SysFreeString(entry);
5759 return TYPE_E_DLLFUNCTIONNOTFOUND;
5764 /* ITypeInfo::CreateInstance
5766 * Creates a new instance of a type that describes a component object class
5769 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5770 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5772 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5773 FIXME("(%p) stub!\n", This);
5777 /* ITypeInfo::GetMops
5779 * Retrieves marshalling information.
5781 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5784 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5785 FIXME("(%p) stub!\n", This);
5789 /* ITypeInfo::GetContainingTypeLib
5791 * Retrieves the containing type library and the index of the type description
5792 * within that type library.
5794 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5795 ITypeLib * *ppTLib, UINT *pIndex)
5797 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5799 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5801 *pIndex=This->index;
5802 TRACE("returning pIndex=%d\n", *pIndex);
5806 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5807 ITypeLib2_AddRef(*ppTLib);
5808 TRACE("returning ppTLib=%p\n", *ppTLib);
5814 /* ITypeInfo::ReleaseTypeAttr
5816 * Releases a TYPEATTR previously returned by GetTypeAttr.
5819 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5820 TYPEATTR* pTypeAttr)
5822 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5823 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5824 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5827 /* ITypeInfo::ReleaseFuncDesc
5829 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5831 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5833 FUNCDESC *pFuncDesc)
5835 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5838 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5840 for (i = 0; i < pFuncDesc->cParams; i++)
5841 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5842 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5844 SysFreeString((BSTR)pFuncDesc);
5847 /* ITypeInfo::ReleaseVarDesc
5849 * Releases a VARDESC previously returned by GetVarDesc.
5851 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5854 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5855 TRACE("(%p)->(%p)\n", This, pVarDesc);
5857 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5858 if (pVarDesc->varkind == VAR_CONST)
5859 VariantClear(pVarDesc->u.lpvarValue);
5860 SysFreeString((BSTR)pVarDesc);
5863 /* ITypeInfo2::GetTypeKind
5865 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5868 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5869 TYPEKIND *pTypeKind)
5871 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5872 *pTypeKind=This->TypeAttr.typekind;
5873 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5877 /* ITypeInfo2::GetTypeFlags
5879 * Returns the type flags without any allocations. This returns a DWORD type
5880 * flag, which expands the type flags without growing the TYPEATTR (type
5884 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5886 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5887 *pTypeFlags=This->TypeAttr.wTypeFlags;
5888 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5892 /* ITypeInfo2::GetFuncIndexOfMemId
5893 * Binds to a specific member based on a known DISPID, where the member name
5894 * is not known (for example, when binding to a default member).
5897 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5898 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5900 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5901 const TLBFuncDesc *pFuncInfo;
5905 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5906 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5912 result = TYPE_E_ELEMENTNOTFOUND;
5914 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5915 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5919 /* TypeInfo2::GetVarIndexOfMemId
5921 * Binds to a specific member based on a known DISPID, where the member name
5922 * is not known (for example, when binding to a default member).
5925 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5926 MEMBERID memid, UINT *pVarIndex)
5928 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5929 TLBVarDesc *pVarInfo;
5932 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5933 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5939 result = TYPE_E_ELEMENTNOTFOUND;
5941 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5942 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5946 /* ITypeInfo2::GetCustData
5948 * Gets the custom data
5950 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5955 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5956 TLBCustData *pCData;
5958 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5959 if( IsEqualIID(guid, &pCData->guid)) break;
5961 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5965 VariantInit( pVarVal);
5966 VariantCopy( pVarVal, &pCData->data);
5969 return E_INVALIDARG; /* FIXME: correct? */
5972 /* ITypeInfo2::GetFuncCustData
5974 * Gets the custom data
5976 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5982 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5983 TLBCustData *pCData=NULL;
5984 TLBFuncDesc * pFDesc;
5986 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5987 pFDesc=pFDesc->next);
5990 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5991 if( IsEqualIID(guid, &pCData->guid)) break;
5993 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5996 VariantInit( pVarVal);
5997 VariantCopy( pVarVal, &pCData->data);
6000 return E_INVALIDARG; /* FIXME: correct? */
6003 /* ITypeInfo2::GetParamCustData
6005 * Gets the custom data
6007 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6014 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6015 TLBCustData *pCData=NULL;
6016 TLBFuncDesc * pFDesc;
6019 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6021 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6022 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6023 pCData = pCData->next)
6024 if( IsEqualIID(guid, &pCData->guid)) break;
6026 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6030 VariantInit( pVarVal);
6031 VariantCopy( pVarVal, &pCData->data);
6034 return E_INVALIDARG; /* FIXME: correct? */
6037 /* ITypeInfo2::GetVarCustData
6039 * Gets the custom data
6041 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6047 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6048 TLBCustData *pCData=NULL;
6049 TLBVarDesc * pVDesc;
6052 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6056 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6058 if( IsEqualIID(guid, &pCData->guid)) break;
6062 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6066 VariantInit( pVarVal);
6067 VariantCopy( pVarVal, &pCData->data);
6070 return E_INVALIDARG; /* FIXME: correct? */
6073 /* ITypeInfo2::GetImplCustData
6075 * Gets the custom data
6077 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6083 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6084 TLBCustData *pCData=NULL;
6085 TLBImplType * pRDesc;
6088 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6092 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6094 if( IsEqualIID(guid, &pCData->guid)) break;
6098 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6102 VariantInit( pVarVal);
6103 VariantCopy( pVarVal, &pCData->data);
6106 return E_INVALIDARG; /* FIXME: correct? */
6109 /* ITypeInfo2::GetDocumentation2
6111 * Retrieves the documentation string, the complete Help file name and path,
6112 * the localization context to use, and the context ID for the library Help
6113 * topic in the Help file.
6116 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6120 BSTR *pbstrHelpString,
6121 DWORD *pdwHelpStringContext,
6122 BSTR *pbstrHelpStringDll)
6124 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6125 const TLBFuncDesc *pFDesc;
6126 const TLBVarDesc *pVDesc;
6127 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6128 "HelpStringContext(%p) HelpStringDll(%p)\n",
6129 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6130 pbstrHelpStringDll );
6131 /* the help string should be obtained from the helpstringdll,
6132 * using the _DLLGetDocumentation function, based on the supplied
6133 * lcid. Nice to do sometime...
6135 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6137 *pbstrHelpString=SysAllocString(This->Name);
6138 if(pdwHelpStringContext)
6139 *pdwHelpStringContext=This->dwHelpStringContext;
6140 if(pbstrHelpStringDll)
6141 *pbstrHelpStringDll=
6142 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6144 }else {/* for a member */
6145 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6146 if(pFDesc->funcdesc.memid==memid){
6148 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6149 if(pdwHelpStringContext)
6150 *pdwHelpStringContext=pFDesc->HelpStringContext;
6151 if(pbstrHelpStringDll)
6152 *pbstrHelpStringDll=
6153 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6156 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6157 if(pVDesc->vardesc.memid==memid){
6159 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6160 if(pdwHelpStringContext)
6161 *pdwHelpStringContext=pVDesc->HelpStringContext;
6162 if(pbstrHelpStringDll)
6163 *pbstrHelpStringDll=
6164 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6168 return TYPE_E_ELEMENTNOTFOUND;
6171 /* ITypeInfo2::GetAllCustData
6173 * Gets all custom data items for the Type info.
6176 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6178 CUSTDATA *pCustData)
6180 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6181 TLBCustData *pCData;
6184 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6186 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6187 if(pCustData->prgCustData ){
6188 pCustData->cCustData=This->ctCustData;
6189 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6190 pCustData->prgCustData[i].guid=pCData->guid;
6191 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6194 ERR(" OUT OF MEMORY!\n");
6195 return E_OUTOFMEMORY;
6200 /* ITypeInfo2::GetAllFuncCustData
6202 * Gets all custom data items for the specified Function
6205 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6208 CUSTDATA *pCustData)
6210 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6211 TLBCustData *pCData;
6212 TLBFuncDesc * pFDesc;
6214 TRACE("(%p) index %d\n", This, index);
6215 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6216 pFDesc=pFDesc->next)
6219 pCustData->prgCustData =
6220 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6221 if(pCustData->prgCustData ){
6222 pCustData->cCustData=pFDesc->ctCustData;
6223 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6224 pCData = pCData->next){
6225 pCustData->prgCustData[i].guid=pCData->guid;
6226 VariantCopy(& pCustData->prgCustData[i].varValue,
6230 ERR(" OUT OF MEMORY!\n");
6231 return E_OUTOFMEMORY;
6235 return TYPE_E_ELEMENTNOTFOUND;
6238 /* ITypeInfo2::GetAllParamCustData
6240 * Gets all custom data items for the Functions
6243 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6244 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6246 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6247 TLBCustData *pCData=NULL;
6248 TLBFuncDesc * pFDesc;
6250 TRACE("(%p) index %d\n", This, indexFunc);
6251 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6252 pFDesc=pFDesc->next)
6254 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6255 pCustData->prgCustData =
6256 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6257 sizeof(CUSTDATAITEM));
6258 if(pCustData->prgCustData ){
6259 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6260 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6261 pCData; i++, pCData = pCData->next){
6262 pCustData->prgCustData[i].guid=pCData->guid;
6263 VariantCopy(& pCustData->prgCustData[i].varValue,
6267 ERR(" OUT OF MEMORY!\n");
6268 return E_OUTOFMEMORY;
6272 return TYPE_E_ELEMENTNOTFOUND;
6275 /* ITypeInfo2::GetAllVarCustData
6277 * Gets all custom data items for the specified Variable
6280 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6281 UINT index, CUSTDATA *pCustData)
6283 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6284 TLBCustData *pCData;
6285 TLBVarDesc * pVDesc;
6287 TRACE("(%p) index %d\n", This, index);
6288 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6289 pVDesc=pVDesc->next)
6292 pCustData->prgCustData =
6293 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6294 if(pCustData->prgCustData ){
6295 pCustData->cCustData=pVDesc->ctCustData;
6296 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6297 pCData = pCData->next){
6298 pCustData->prgCustData[i].guid=pCData->guid;
6299 VariantCopy(& pCustData->prgCustData[i].varValue,
6303 ERR(" OUT OF MEMORY!\n");
6304 return E_OUTOFMEMORY;
6308 return TYPE_E_ELEMENTNOTFOUND;
6311 /* ITypeInfo2::GetAllImplCustData
6313 * Gets all custom data items for the specified implementation type
6316 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6319 CUSTDATA *pCustData)
6321 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6322 TLBCustData *pCData;
6323 TLBImplType * pRDesc;
6325 TRACE("(%p) index %d\n", This, index);
6326 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6327 pRDesc=pRDesc->next)
6330 pCustData->prgCustData =
6331 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6332 if(pCustData->prgCustData ){
6333 pCustData->cCustData=pRDesc->ctCustData;
6334 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6335 pCData = pCData->next){
6336 pCustData->prgCustData[i].guid=pCData->guid;
6337 VariantCopy(& pCustData->prgCustData[i].varValue,
6341 ERR(" OUT OF MEMORY!\n");
6342 return E_OUTOFMEMORY;
6346 return TYPE_E_ELEMENTNOTFOUND;
6349 static const ITypeInfo2Vtbl tinfvt =
6352 ITypeInfo_fnQueryInterface,
6354 ITypeInfo_fnRelease,
6356 ITypeInfo_fnGetTypeAttr,
6357 ITypeInfo_fnGetTypeComp,
6358 ITypeInfo_fnGetFuncDesc,
6359 ITypeInfo_fnGetVarDesc,
6360 ITypeInfo_fnGetNames,
6361 ITypeInfo_fnGetRefTypeOfImplType,
6362 ITypeInfo_fnGetImplTypeFlags,
6363 ITypeInfo_fnGetIDsOfNames,
6365 ITypeInfo_fnGetDocumentation,
6366 ITypeInfo_fnGetDllEntry,
6367 ITypeInfo_fnGetRefTypeInfo,
6368 ITypeInfo_fnAddressOfMember,
6369 ITypeInfo_fnCreateInstance,
6370 ITypeInfo_fnGetMops,
6371 ITypeInfo_fnGetContainingTypeLib,
6372 ITypeInfo_fnReleaseTypeAttr,
6373 ITypeInfo_fnReleaseFuncDesc,
6374 ITypeInfo_fnReleaseVarDesc,
6376 ITypeInfo2_fnGetTypeKind,
6377 ITypeInfo2_fnGetTypeFlags,
6378 ITypeInfo2_fnGetFuncIndexOfMemId,
6379 ITypeInfo2_fnGetVarIndexOfMemId,
6380 ITypeInfo2_fnGetCustData,
6381 ITypeInfo2_fnGetFuncCustData,
6382 ITypeInfo2_fnGetParamCustData,
6383 ITypeInfo2_fnGetVarCustData,
6384 ITypeInfo2_fnGetImplTypeCustData,
6385 ITypeInfo2_fnGetDocumentation2,
6386 ITypeInfo2_fnGetAllCustData,
6387 ITypeInfo2_fnGetAllFuncCustData,
6388 ITypeInfo2_fnGetAllParamCustData,
6389 ITypeInfo2_fnGetAllVarCustData,
6390 ITypeInfo2_fnGetAllImplTypeCustData,
6393 /******************************************************************************
6394 * CreateDispTypeInfo [OLEAUT32.31]
6396 * Build type information for an object so it can be called through an
6397 * IDispatch interface.
6400 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6401 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6404 * This call allows an objects methods to be accessed through IDispatch, by
6405 * building an ITypeInfo object that IDispatch can use to call through.
6407 HRESULT WINAPI CreateDispTypeInfo(
6408 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6409 LCID lcid, /* [I] Locale Id */
6410 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6412 ITypeInfoImpl *pTIClass, *pTIIface;
6413 ITypeLibImpl *pTypeLibImpl;
6415 TLBFuncDesc **ppFuncDesc;
6418 pTypeLibImpl = TypeLibImpl_Constructor();
6419 if (!pTypeLibImpl) return E_FAIL;
6421 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6422 pTIIface->pTypeLib = pTypeLibImpl;
6423 pTIIface->index = 0;
6424 pTIIface->Name = NULL;
6425 pTIIface->dwHelpContext = -1;
6426 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6427 pTIIface->TypeAttr.lcid = lcid;
6428 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6429 pTIIface->TypeAttr.wMajorVerNum = 0;
6430 pTIIface->TypeAttr.wMinorVerNum = 0;
6431 pTIIface->TypeAttr.cbAlignment = 2;
6432 pTIIface->TypeAttr.cbSizeInstance = -1;
6433 pTIIface->TypeAttr.cbSizeVft = -1;
6434 pTIIface->TypeAttr.cFuncs = 0;
6435 pTIIface->TypeAttr.cImplTypes = 0;
6436 pTIIface->TypeAttr.cVars = 0;
6437 pTIIface->TypeAttr.wTypeFlags = 0;
6439 ppFuncDesc = &pTIIface->funclist;
6440 for(func = 0; func < pidata->cMembers; func++) {
6441 METHODDATA *md = pidata->pmethdata + func;
6442 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6443 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6444 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6445 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6446 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6447 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6448 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6449 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6450 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6451 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6452 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6453 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6454 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6455 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6456 md->cArgs * sizeof(ELEMDESC));
6457 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6458 md->cArgs * sizeof(TLBParDesc));
6459 for(param = 0; param < md->cArgs; param++) {
6460 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6461 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6463 (*ppFuncDesc)->helpcontext = 0;
6464 (*ppFuncDesc)->HelpStringContext = 0;
6465 (*ppFuncDesc)->HelpString = NULL;
6466 (*ppFuncDesc)->Entry = NULL;
6467 (*ppFuncDesc)->ctCustData = 0;
6468 (*ppFuncDesc)->pCustData = NULL;
6469 (*ppFuncDesc)->next = NULL;
6470 ppFuncDesc = &(*ppFuncDesc)->next;
6473 dump_TypeInfo(pTIIface);
6475 pTypeLibImpl->pTypeInfo = pTIIface;
6476 pTypeLibImpl->TypeInfoCount++;
6478 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6479 pTIClass->pTypeLib = pTypeLibImpl;
6480 pTIClass->index = 1;
6481 pTIClass->Name = NULL;
6482 pTIClass->dwHelpContext = -1;
6483 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6484 pTIClass->TypeAttr.lcid = lcid;
6485 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6486 pTIClass->TypeAttr.wMajorVerNum = 0;
6487 pTIClass->TypeAttr.wMinorVerNum = 0;
6488 pTIClass->TypeAttr.cbAlignment = 2;
6489 pTIClass->TypeAttr.cbSizeInstance = -1;
6490 pTIClass->TypeAttr.cbSizeVft = -1;
6491 pTIClass->TypeAttr.cFuncs = 0;
6492 pTIClass->TypeAttr.cImplTypes = 1;
6493 pTIClass->TypeAttr.cVars = 0;
6494 pTIClass->TypeAttr.wTypeFlags = 0;
6496 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6497 pTIClass->impltypelist->hRef = 1;
6499 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6500 pTIClass->reflist->index = 0;
6501 pTIClass->reflist->reference = 1;
6502 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6504 dump_TypeInfo(pTIClass);
6506 pTIIface->next = pTIClass;
6507 pTypeLibImpl->TypeInfoCount++;
6509 *pptinfo = (ITypeInfo*)pTIClass;
6514 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6516 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6518 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6521 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6523 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6525 return ITypeInfo_AddRef((ITypeInfo *)This);
6528 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6530 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6532 return ITypeInfo_Release((ITypeInfo *)This);
6535 static HRESULT WINAPI ITypeComp_fnBind(
6540 ITypeInfo ** ppTInfo,
6541 DESCKIND * pDescKind,
6544 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6545 const TLBFuncDesc *pFDesc;
6546 const TLBVarDesc *pVDesc;
6547 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6549 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6551 *pDescKind = DESCKIND_NONE;
6552 pBindPtr->lpfuncdesc = NULL;
6555 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6556 if (!strcmpiW(pFDesc->Name, szName)) {
6557 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6560 /* name found, but wrong flags */
6561 hr = TYPE_E_TYPEMISMATCH;
6566 HRESULT hr = TLB_AllocAndInitFuncDesc(
6568 &pBindPtr->lpfuncdesc,
6569 This->TypeAttr.typekind == TKIND_DISPATCH);
6572 *pDescKind = DESCKIND_FUNCDESC;
6573 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6574 ITypeInfo_AddRef(*ppTInfo);
6577 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6578 if (!strcmpiW(pVDesc->Name, szName)) {
6579 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6582 *pDescKind = DESCKIND_VARDESC;
6583 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6584 ITypeInfo_AddRef(*ppTInfo);
6589 /* FIXME: search each inherited interface, not just the first */
6590 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6591 /* recursive search */
6595 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6598 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6599 ITypeInfo_Release(pTInfo);
6603 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6604 ITypeComp_Release(pTComp);
6607 WARN("Could not search inherited interface!\n");
6609 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6613 static HRESULT WINAPI ITypeComp_fnBindType(
6617 ITypeInfo ** ppTInfo,
6618 ITypeComp ** ppTComp)
6620 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6622 /* strange behaviour (does nothing) but like the
6625 if (!ppTInfo || !ppTComp)
6634 static const ITypeCompVtbl tcompvt =
6637 ITypeComp_fnQueryInterface,
6639 ITypeComp_fnRelease,
6642 ITypeComp_fnBindType