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]);
5395 VariantInit(pVarResult);
5396 /* deref return value */
5397 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5400 /* free data stored in varresult. Note that
5401 * VariantClear doesn't do what we want because we are
5402 * working with byref types. */
5403 /* FIXME: clear safearrays, bstrs, records and
5404 * variants here too */
5405 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5406 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5408 if(*V_UNKNOWNREF(prgpvarg[i]))
5409 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5413 else if (i < pDispParams->cArgs)
5415 if (wParamFlags & PARAMFLAG_FOUT)
5417 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5419 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5420 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5424 ERR("failed to convert param %d to vt %d\n", i,
5425 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5429 VariantClear(&rgvarg[i]);
5431 else if (wParamFlags & PARAMFLAG_FOPT)
5433 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5434 VariantClear(&rgvarg[i]);
5438 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5440 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5441 hres = DISP_E_EXCEPTION;
5442 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5446 HeapFree(GetProcessHeap(), 0, buffer);
5449 case FUNC_DISPATCH: {
5452 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5453 if (SUCCEEDED(hres)) {
5454 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5455 hres = IDispatch_Invoke(
5456 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5457 pVarResult,pExcepInfo,pArgErr
5460 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5461 IDispatch_Release(disp);
5463 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5467 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5472 TRACE("-- 0x%08lx\n", hres);
5475 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5478 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5479 if(FAILED(hres)) return hres;
5481 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5482 dump_VARDESC(var_desc);
5483 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5487 /* not found, look for it in inherited interfaces */
5488 ITypeInfo2_GetTypeKind(iface, &type_kind);
5489 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5491 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5492 /* recursive search */
5494 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5495 if(SUCCEEDED(hres)){
5496 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5497 ITypeInfo_Release(pTInfo);
5500 WARN("Could not search inherited interface!\n");
5503 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5504 return DISP_E_MEMBERNOTFOUND;
5507 /* ITypeInfo::GetDocumentation
5509 * Retrieves the documentation string, the complete Help file name and path,
5510 * and the context ID for the Help topic for a specified type description.
5512 * (Can be tested by the Visual Basic Editor in Word for instance.)
5514 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5515 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5516 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5518 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5519 const TLBFuncDesc *pFDesc;
5520 const TLBVarDesc *pVDesc;
5521 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5522 " HelpContext(%p) HelpFile(%p)\n",
5523 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5524 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5526 *pBstrName=SysAllocString(This->Name);
5528 *pBstrDocString=SysAllocString(This->DocString);
5530 *pdwHelpContext=This->dwHelpContext;
5532 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5534 }else {/* for a member */
5535 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5536 if(pFDesc->funcdesc.memid==memid){
5538 *pBstrName = SysAllocString(pFDesc->Name);
5540 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5542 *pdwHelpContext=pFDesc->helpcontext;
5545 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5546 if(pVDesc->vardesc.memid==memid){
5548 *pBstrName = SysAllocString(pVDesc->Name);
5550 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5552 *pdwHelpContext=pVDesc->HelpContext;
5556 WARN("member %ld not found\n", memid);
5557 return TYPE_E_ELEMENTNOTFOUND;
5560 /* ITypeInfo::GetDllEntry
5562 * Retrieves a description or specification of an entry point for a function
5565 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5566 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5569 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5570 const TLBFuncDesc *pFDesc;
5572 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5574 if (pBstrDllName) *pBstrDllName = NULL;
5575 if (pBstrName) *pBstrName = NULL;
5576 if (pwOrdinal) *pwOrdinal = 0;
5578 if (This->TypeAttr.typekind != TKIND_MODULE)
5579 return TYPE_E_BADMODULEKIND;
5581 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5582 if(pFDesc->funcdesc.memid==memid){
5583 dump_TypeInfo(This);
5585 dump_TLBFuncDescOne(pFDesc);
5588 *pBstrDllName = SysAllocString(This->DllName);
5590 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5592 *pBstrName = SysAllocString(pFDesc->Entry);
5600 *pwOrdinal = (DWORD)pFDesc->Entry;
5603 return TYPE_E_ELEMENTNOTFOUND;
5606 /* ITypeInfo::GetRefTypeInfo
5608 * If a type description references other type descriptions, it retrieves
5609 * the referenced type descriptions.
5611 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5614 ITypeInfo **ppTInfo)
5616 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5617 HRESULT result = E_FAIL;
5619 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5621 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5622 ITypeInfo_AddRef(*ppTInfo);
5625 else if (hRefType == -1 &&
5626 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5627 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5629 /* when we meet a DUAL dispinterface, we must create the interface
5632 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5635 /* the interface version contains the same information as the dispinterface
5636 * copy the contents of the structs.
5638 *pTypeInfoImpl = *This;
5639 pTypeInfoImpl->ref = 1;
5641 /* change the type to interface */
5642 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5644 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5646 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5651 TLBRefType *pRefType;
5652 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5653 if(pRefType->reference == hRefType)
5657 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5658 if(pRefType && hRefType != -1) {
5659 ITypeLib *pTLib = NULL;
5661 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5663 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5665 if(pRefType->pImpTLInfo->pImpTypeLib) {
5666 TRACE("typeinfo in imported typelib that is already loaded\n");
5667 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5668 ITypeLib2_AddRef((ITypeLib*) pTLib);
5671 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5672 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5673 pRefType->pImpTLInfo->wVersionMajor,
5674 pRefType->pImpTLInfo->wVersionMinor,
5675 pRefType->pImpTLInfo->lcid,
5678 if(!SUCCEEDED(result)) {
5679 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5680 result=LoadTypeLib(libnam, &pTLib);
5681 SysFreeString(libnam);
5683 if(SUCCEEDED(result)) {
5684 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5685 ITypeLib2_AddRef(pTLib);
5689 if(SUCCEEDED(result)) {
5690 if(pRefType->index == TLB_REF_USE_GUID)
5691 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5695 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5699 ITypeLib2_Release(pTLib);
5703 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5704 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5708 /* ITypeInfo::AddressOfMember
5710 * Retrieves the addresses of static functions or variables, such as those
5713 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5714 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5716 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5722 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5724 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5728 module = LoadLibraryW(dll);
5731 ERR("couldn't load %s\n", debugstr_w(dll));
5733 if (entry) SysFreeString(entry);
5734 return STG_E_FILENOTFOUND;
5736 /* FIXME: store library somewhere where we can free it */
5741 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5742 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5743 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5745 *ppv = GetProcAddress(module, entryA);
5747 ERR("function not found %s\n", debugstr_a(entryA));
5749 HeapFree(GetProcessHeap(), 0, entryA);
5753 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5755 ERR("function not found %d\n", ordinal);
5759 if (entry) SysFreeString(entry);
5762 return TYPE_E_DLLFUNCTIONNOTFOUND;
5767 /* ITypeInfo::CreateInstance
5769 * Creates a new instance of a type that describes a component object class
5772 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5773 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5775 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5776 FIXME("(%p) stub!\n", This);
5780 /* ITypeInfo::GetMops
5782 * Retrieves marshalling information.
5784 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5787 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5788 FIXME("(%p) stub!\n", This);
5792 /* ITypeInfo::GetContainingTypeLib
5794 * Retrieves the containing type library and the index of the type description
5795 * within that type library.
5797 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5798 ITypeLib * *ppTLib, UINT *pIndex)
5800 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5802 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5804 *pIndex=This->index;
5805 TRACE("returning pIndex=%d\n", *pIndex);
5809 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5810 ITypeLib2_AddRef(*ppTLib);
5811 TRACE("returning ppTLib=%p\n", *ppTLib);
5817 /* ITypeInfo::ReleaseTypeAttr
5819 * Releases a TYPEATTR previously returned by GetTypeAttr.
5822 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5823 TYPEATTR* pTypeAttr)
5825 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5826 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5827 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5830 /* ITypeInfo::ReleaseFuncDesc
5832 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5834 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5836 FUNCDESC *pFuncDesc)
5838 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5841 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5843 for (i = 0; i < pFuncDesc->cParams; i++)
5844 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5845 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5847 SysFreeString((BSTR)pFuncDesc);
5850 /* ITypeInfo::ReleaseVarDesc
5852 * Releases a VARDESC previously returned by GetVarDesc.
5854 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5857 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5858 TRACE("(%p)->(%p)\n", This, pVarDesc);
5860 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5861 if (pVarDesc->varkind == VAR_CONST)
5862 VariantClear(pVarDesc->u.lpvarValue);
5863 SysFreeString((BSTR)pVarDesc);
5866 /* ITypeInfo2::GetTypeKind
5868 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5871 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5872 TYPEKIND *pTypeKind)
5874 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5875 *pTypeKind=This->TypeAttr.typekind;
5876 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5880 /* ITypeInfo2::GetTypeFlags
5882 * Returns the type flags without any allocations. This returns a DWORD type
5883 * flag, which expands the type flags without growing the TYPEATTR (type
5887 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5889 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5890 *pTypeFlags=This->TypeAttr.wTypeFlags;
5891 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5895 /* ITypeInfo2::GetFuncIndexOfMemId
5896 * Binds to a specific member based on a known DISPID, where the member name
5897 * is not known (for example, when binding to a default member).
5900 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5901 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5903 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5904 const TLBFuncDesc *pFuncInfo;
5908 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5909 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5915 result = TYPE_E_ELEMENTNOTFOUND;
5917 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5918 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5922 /* TypeInfo2::GetVarIndexOfMemId
5924 * Binds to a specific member based on a known DISPID, where the member name
5925 * is not known (for example, when binding to a default member).
5928 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5929 MEMBERID memid, UINT *pVarIndex)
5931 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5932 TLBVarDesc *pVarInfo;
5935 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5936 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5942 result = TYPE_E_ELEMENTNOTFOUND;
5944 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5945 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5949 /* ITypeInfo2::GetCustData
5951 * Gets the custom data
5953 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5958 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5959 TLBCustData *pCData;
5961 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5962 if( IsEqualIID(guid, &pCData->guid)) break;
5964 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5968 VariantInit( pVarVal);
5969 VariantCopy( pVarVal, &pCData->data);
5972 return E_INVALIDARG; /* FIXME: correct? */
5975 /* ITypeInfo2::GetFuncCustData
5977 * Gets the custom data
5979 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5985 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5986 TLBCustData *pCData=NULL;
5987 TLBFuncDesc * pFDesc;
5989 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5990 pFDesc=pFDesc->next);
5993 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5994 if( IsEqualIID(guid, &pCData->guid)) break;
5996 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5999 VariantInit( pVarVal);
6000 VariantCopy( pVarVal, &pCData->data);
6003 return E_INVALIDARG; /* FIXME: correct? */
6006 /* ITypeInfo2::GetParamCustData
6008 * Gets the custom data
6010 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6017 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6018 TLBCustData *pCData=NULL;
6019 TLBFuncDesc * pFDesc;
6022 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6024 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6025 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6026 pCData = pCData->next)
6027 if( IsEqualIID(guid, &pCData->guid)) break;
6029 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6033 VariantInit( pVarVal);
6034 VariantCopy( pVarVal, &pCData->data);
6037 return E_INVALIDARG; /* FIXME: correct? */
6040 /* ITypeInfo2::GetVarCustData
6042 * Gets the custom data
6044 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6050 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6051 TLBCustData *pCData=NULL;
6052 TLBVarDesc * pVDesc;
6055 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6059 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6061 if( IsEqualIID(guid, &pCData->guid)) break;
6065 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6069 VariantInit( pVarVal);
6070 VariantCopy( pVarVal, &pCData->data);
6073 return E_INVALIDARG; /* FIXME: correct? */
6076 /* ITypeInfo2::GetImplCustData
6078 * Gets the custom data
6080 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6086 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6087 TLBCustData *pCData=NULL;
6088 TLBImplType * pRDesc;
6091 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6095 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6097 if( IsEqualIID(guid, &pCData->guid)) break;
6101 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6105 VariantInit( pVarVal);
6106 VariantCopy( pVarVal, &pCData->data);
6109 return E_INVALIDARG; /* FIXME: correct? */
6112 /* ITypeInfo2::GetDocumentation2
6114 * Retrieves the documentation string, the complete Help file name and path,
6115 * the localization context to use, and the context ID for the library Help
6116 * topic in the Help file.
6119 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6123 BSTR *pbstrHelpString,
6124 DWORD *pdwHelpStringContext,
6125 BSTR *pbstrHelpStringDll)
6127 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6128 const TLBFuncDesc *pFDesc;
6129 const TLBVarDesc *pVDesc;
6130 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6131 "HelpStringContext(%p) HelpStringDll(%p)\n",
6132 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6133 pbstrHelpStringDll );
6134 /* the help string should be obtained from the helpstringdll,
6135 * using the _DLLGetDocumentation function, based on the supplied
6136 * lcid. Nice to do sometime...
6138 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6140 *pbstrHelpString=SysAllocString(This->Name);
6141 if(pdwHelpStringContext)
6142 *pdwHelpStringContext=This->dwHelpStringContext;
6143 if(pbstrHelpStringDll)
6144 *pbstrHelpStringDll=
6145 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6147 }else {/* for a member */
6148 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6149 if(pFDesc->funcdesc.memid==memid){
6151 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6152 if(pdwHelpStringContext)
6153 *pdwHelpStringContext=pFDesc->HelpStringContext;
6154 if(pbstrHelpStringDll)
6155 *pbstrHelpStringDll=
6156 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6159 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6160 if(pVDesc->vardesc.memid==memid){
6162 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6163 if(pdwHelpStringContext)
6164 *pdwHelpStringContext=pVDesc->HelpStringContext;
6165 if(pbstrHelpStringDll)
6166 *pbstrHelpStringDll=
6167 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6171 return TYPE_E_ELEMENTNOTFOUND;
6174 /* ITypeInfo2::GetAllCustData
6176 * Gets all custom data items for the Type info.
6179 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6181 CUSTDATA *pCustData)
6183 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6184 TLBCustData *pCData;
6187 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6189 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6190 if(pCustData->prgCustData ){
6191 pCustData->cCustData=This->ctCustData;
6192 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6193 pCustData->prgCustData[i].guid=pCData->guid;
6194 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6197 ERR(" OUT OF MEMORY!\n");
6198 return E_OUTOFMEMORY;
6203 /* ITypeInfo2::GetAllFuncCustData
6205 * Gets all custom data items for the specified Function
6208 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6211 CUSTDATA *pCustData)
6213 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6214 TLBCustData *pCData;
6215 TLBFuncDesc * pFDesc;
6217 TRACE("(%p) index %d\n", This, index);
6218 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6219 pFDesc=pFDesc->next)
6222 pCustData->prgCustData =
6223 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6224 if(pCustData->prgCustData ){
6225 pCustData->cCustData=pFDesc->ctCustData;
6226 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6227 pCData = pCData->next){
6228 pCustData->prgCustData[i].guid=pCData->guid;
6229 VariantCopy(& pCustData->prgCustData[i].varValue,
6233 ERR(" OUT OF MEMORY!\n");
6234 return E_OUTOFMEMORY;
6238 return TYPE_E_ELEMENTNOTFOUND;
6241 /* ITypeInfo2::GetAllParamCustData
6243 * Gets all custom data items for the Functions
6246 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6247 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6249 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6250 TLBCustData *pCData=NULL;
6251 TLBFuncDesc * pFDesc;
6253 TRACE("(%p) index %d\n", This, indexFunc);
6254 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6255 pFDesc=pFDesc->next)
6257 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6258 pCustData->prgCustData =
6259 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6260 sizeof(CUSTDATAITEM));
6261 if(pCustData->prgCustData ){
6262 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6263 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6264 pCData; i++, pCData = pCData->next){
6265 pCustData->prgCustData[i].guid=pCData->guid;
6266 VariantCopy(& pCustData->prgCustData[i].varValue,
6270 ERR(" OUT OF MEMORY!\n");
6271 return E_OUTOFMEMORY;
6275 return TYPE_E_ELEMENTNOTFOUND;
6278 /* ITypeInfo2::GetAllVarCustData
6280 * Gets all custom data items for the specified Variable
6283 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6284 UINT index, CUSTDATA *pCustData)
6286 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6287 TLBCustData *pCData;
6288 TLBVarDesc * pVDesc;
6290 TRACE("(%p) index %d\n", This, index);
6291 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6292 pVDesc=pVDesc->next)
6295 pCustData->prgCustData =
6296 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6297 if(pCustData->prgCustData ){
6298 pCustData->cCustData=pVDesc->ctCustData;
6299 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6300 pCData = pCData->next){
6301 pCustData->prgCustData[i].guid=pCData->guid;
6302 VariantCopy(& pCustData->prgCustData[i].varValue,
6306 ERR(" OUT OF MEMORY!\n");
6307 return E_OUTOFMEMORY;
6311 return TYPE_E_ELEMENTNOTFOUND;
6314 /* ITypeInfo2::GetAllImplCustData
6316 * Gets all custom data items for the specified implementation type
6319 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6322 CUSTDATA *pCustData)
6324 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6325 TLBCustData *pCData;
6326 TLBImplType * pRDesc;
6328 TRACE("(%p) index %d\n", This, index);
6329 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6330 pRDesc=pRDesc->next)
6333 pCustData->prgCustData =
6334 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6335 if(pCustData->prgCustData ){
6336 pCustData->cCustData=pRDesc->ctCustData;
6337 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6338 pCData = pCData->next){
6339 pCustData->prgCustData[i].guid=pCData->guid;
6340 VariantCopy(& pCustData->prgCustData[i].varValue,
6344 ERR(" OUT OF MEMORY!\n");
6345 return E_OUTOFMEMORY;
6349 return TYPE_E_ELEMENTNOTFOUND;
6352 static const ITypeInfo2Vtbl tinfvt =
6355 ITypeInfo_fnQueryInterface,
6357 ITypeInfo_fnRelease,
6359 ITypeInfo_fnGetTypeAttr,
6360 ITypeInfo_fnGetTypeComp,
6361 ITypeInfo_fnGetFuncDesc,
6362 ITypeInfo_fnGetVarDesc,
6363 ITypeInfo_fnGetNames,
6364 ITypeInfo_fnGetRefTypeOfImplType,
6365 ITypeInfo_fnGetImplTypeFlags,
6366 ITypeInfo_fnGetIDsOfNames,
6368 ITypeInfo_fnGetDocumentation,
6369 ITypeInfo_fnGetDllEntry,
6370 ITypeInfo_fnGetRefTypeInfo,
6371 ITypeInfo_fnAddressOfMember,
6372 ITypeInfo_fnCreateInstance,
6373 ITypeInfo_fnGetMops,
6374 ITypeInfo_fnGetContainingTypeLib,
6375 ITypeInfo_fnReleaseTypeAttr,
6376 ITypeInfo_fnReleaseFuncDesc,
6377 ITypeInfo_fnReleaseVarDesc,
6379 ITypeInfo2_fnGetTypeKind,
6380 ITypeInfo2_fnGetTypeFlags,
6381 ITypeInfo2_fnGetFuncIndexOfMemId,
6382 ITypeInfo2_fnGetVarIndexOfMemId,
6383 ITypeInfo2_fnGetCustData,
6384 ITypeInfo2_fnGetFuncCustData,
6385 ITypeInfo2_fnGetParamCustData,
6386 ITypeInfo2_fnGetVarCustData,
6387 ITypeInfo2_fnGetImplTypeCustData,
6388 ITypeInfo2_fnGetDocumentation2,
6389 ITypeInfo2_fnGetAllCustData,
6390 ITypeInfo2_fnGetAllFuncCustData,
6391 ITypeInfo2_fnGetAllParamCustData,
6392 ITypeInfo2_fnGetAllVarCustData,
6393 ITypeInfo2_fnGetAllImplTypeCustData,
6396 /******************************************************************************
6397 * CreateDispTypeInfo [OLEAUT32.31]
6399 * Build type information for an object so it can be called through an
6400 * IDispatch interface.
6403 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6404 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6407 * This call allows an objects methods to be accessed through IDispatch, by
6408 * building an ITypeInfo object that IDispatch can use to call through.
6410 HRESULT WINAPI CreateDispTypeInfo(
6411 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6412 LCID lcid, /* [I] Locale Id */
6413 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6415 ITypeInfoImpl *pTIClass, *pTIIface;
6416 ITypeLibImpl *pTypeLibImpl;
6418 TLBFuncDesc **ppFuncDesc;
6421 pTypeLibImpl = TypeLibImpl_Constructor();
6422 if (!pTypeLibImpl) return E_FAIL;
6424 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6425 pTIIface->pTypeLib = pTypeLibImpl;
6426 pTIIface->index = 0;
6427 pTIIface->Name = NULL;
6428 pTIIface->dwHelpContext = -1;
6429 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6430 pTIIface->TypeAttr.lcid = lcid;
6431 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6432 pTIIface->TypeAttr.wMajorVerNum = 0;
6433 pTIIface->TypeAttr.wMinorVerNum = 0;
6434 pTIIface->TypeAttr.cbAlignment = 2;
6435 pTIIface->TypeAttr.cbSizeInstance = -1;
6436 pTIIface->TypeAttr.cbSizeVft = -1;
6437 pTIIface->TypeAttr.cFuncs = 0;
6438 pTIIface->TypeAttr.cImplTypes = 0;
6439 pTIIface->TypeAttr.cVars = 0;
6440 pTIIface->TypeAttr.wTypeFlags = 0;
6442 ppFuncDesc = &pTIIface->funclist;
6443 for(func = 0; func < pidata->cMembers; func++) {
6444 METHODDATA *md = pidata->pmethdata + func;
6445 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6446 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6447 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6448 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6449 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6450 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6451 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6452 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6453 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6454 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6455 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6456 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6457 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6458 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6459 md->cArgs * sizeof(ELEMDESC));
6460 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6461 md->cArgs * sizeof(TLBParDesc));
6462 for(param = 0; param < md->cArgs; param++) {
6463 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6464 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6466 (*ppFuncDesc)->helpcontext = 0;
6467 (*ppFuncDesc)->HelpStringContext = 0;
6468 (*ppFuncDesc)->HelpString = NULL;
6469 (*ppFuncDesc)->Entry = NULL;
6470 (*ppFuncDesc)->ctCustData = 0;
6471 (*ppFuncDesc)->pCustData = NULL;
6472 (*ppFuncDesc)->next = NULL;
6473 ppFuncDesc = &(*ppFuncDesc)->next;
6476 dump_TypeInfo(pTIIface);
6478 pTypeLibImpl->pTypeInfo = pTIIface;
6479 pTypeLibImpl->TypeInfoCount++;
6481 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6482 pTIClass->pTypeLib = pTypeLibImpl;
6483 pTIClass->index = 1;
6484 pTIClass->Name = NULL;
6485 pTIClass->dwHelpContext = -1;
6486 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6487 pTIClass->TypeAttr.lcid = lcid;
6488 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6489 pTIClass->TypeAttr.wMajorVerNum = 0;
6490 pTIClass->TypeAttr.wMinorVerNum = 0;
6491 pTIClass->TypeAttr.cbAlignment = 2;
6492 pTIClass->TypeAttr.cbSizeInstance = -1;
6493 pTIClass->TypeAttr.cbSizeVft = -1;
6494 pTIClass->TypeAttr.cFuncs = 0;
6495 pTIClass->TypeAttr.cImplTypes = 1;
6496 pTIClass->TypeAttr.cVars = 0;
6497 pTIClass->TypeAttr.wTypeFlags = 0;
6499 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6500 pTIClass->impltypelist->hRef = 1;
6502 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6503 pTIClass->reflist->index = 0;
6504 pTIClass->reflist->reference = 1;
6505 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6507 dump_TypeInfo(pTIClass);
6509 pTIIface->next = pTIClass;
6510 pTypeLibImpl->TypeInfoCount++;
6512 *pptinfo = (ITypeInfo*)pTIClass;
6517 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6519 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6521 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6524 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6526 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6528 return ITypeInfo_AddRef((ITypeInfo *)This);
6531 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6533 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6535 return ITypeInfo_Release((ITypeInfo *)This);
6538 static HRESULT WINAPI ITypeComp_fnBind(
6543 ITypeInfo ** ppTInfo,
6544 DESCKIND * pDescKind,
6547 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6548 const TLBFuncDesc *pFDesc;
6549 const TLBVarDesc *pVDesc;
6550 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6552 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6554 *pDescKind = DESCKIND_NONE;
6555 pBindPtr->lpfuncdesc = NULL;
6558 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6559 if (!strcmpiW(pFDesc->Name, szName)) {
6560 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6563 /* name found, but wrong flags */
6564 hr = TYPE_E_TYPEMISMATCH;
6569 HRESULT hr = TLB_AllocAndInitFuncDesc(
6571 &pBindPtr->lpfuncdesc,
6572 This->TypeAttr.typekind == TKIND_DISPATCH);
6575 *pDescKind = DESCKIND_FUNCDESC;
6576 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6577 ITypeInfo_AddRef(*ppTInfo);
6580 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6581 if (!strcmpiW(pVDesc->Name, szName)) {
6582 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6585 *pDescKind = DESCKIND_VARDESC;
6586 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6587 ITypeInfo_AddRef(*ppTInfo);
6592 /* FIXME: search each inherited interface, not just the first */
6593 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6594 /* recursive search */
6598 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6601 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6602 ITypeInfo_Release(pTInfo);
6606 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6607 ITypeComp_Release(pTComp);
6610 WARN("Could not search inherited interface!\n");
6612 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6616 static HRESULT WINAPI ITypeComp_fnBindType(
6620 ITypeInfo ** ppTInfo,
6621 ITypeComp ** ppTComp)
6623 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6625 /* strange behaviour (does nothing) but like the
6628 if (!ppTInfo || !ppTComp)
6637 static const ITypeCompVtbl tcompvt =
6640 ITypeComp_fnQueryInterface,
6642 ITypeComp_fnRelease,
6645 ITypeComp_fnBindType