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 (const 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 (const BYTE *)PSOA, sizeof PSOA);
625 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
626 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
629 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
630 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
632 StringFromGUID2(&attr->guid, buffer, 40);
633 RegSetValueExW(subKey, NULL, 0, REG_SZ,
634 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
635 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
636 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
637 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
645 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
648 ITypeInfo_Release(tinfo);
655 ITypeLib_ReleaseTLibAttr(ptlib, attr);
661 /******************************************************************************
662 * UnRegisterTypeLib [OLEAUT32.186]
663 * Removes information about a type library from the System Registry
670 HRESULT WINAPI UnRegisterTypeLib(
671 REFGUID libid, /* [in] Guid of the library */
672 WORD wVerMajor, /* [in] major version */
673 WORD wVerMinor, /* [in] minor version */
674 LCID lcid, /* [in] locale id */
677 BSTR tlibPath = NULL;
680 WCHAR subKeyName[50];
683 BOOL deleteOtherStuff;
686 TYPEATTR* typeAttr = NULL;
688 ITypeInfo* typeInfo = NULL;
689 ITypeLib* typeLib = NULL;
692 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
694 /* Create the path to the key */
695 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
697 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
699 TRACE("Unsupported syskind %i\n", syskind);
700 result = E_INVALIDARG;
704 /* get the path to the typelib on disk */
705 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
706 result = E_INVALIDARG;
710 /* Try and open the key to the type library. */
711 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
712 result = E_INVALIDARG;
716 /* Try and load the type library */
717 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
718 result = TYPE_E_INVALIDSTATE;
722 /* remove any types registered with this typelib */
723 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
724 for (i=0; i<numTypes; i++) {
725 /* get the kind of type */
726 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
730 /* skip non-interfaces, and get type info for the type */
731 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
734 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
737 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
741 /* the path to the type */
742 get_interface_key( &typeAttr->guid, subKeyName );
744 /* Delete its bits */
745 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
748 RegDeleteKeyW(subKey, ProxyStubClsidW);
749 RegDeleteKeyW(subKey, ProxyStubClsid32W);
750 RegDeleteKeyW(subKey, TypeLibW);
753 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
756 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
758 if (typeInfo) ITypeInfo_Release(typeInfo);
762 /* Now, delete the type library path subkey */
763 get_lcid_subkey( lcid, syskind, subKeyName );
764 RegDeleteKeyW(key, subKeyName);
765 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
766 RegDeleteKeyW(key, subKeyName);
768 /* check if there is anything besides the FLAGS/HELPDIR keys.
769 If there is, we don't delete them */
770 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
771 deleteOtherStuff = TRUE;
773 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
774 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
776 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
777 if (!strcmpW(subKeyName, FLAGSW)) continue;
778 if (!strcmpW(subKeyName, HELPDIRW)) continue;
779 deleteOtherStuff = FALSE;
783 /* only delete the other parts of the key if we're absolutely sure */
784 if (deleteOtherStuff) {
785 RegDeleteKeyW(key, FLAGSW);
786 RegDeleteKeyW(key, HELPDIRW);
790 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
791 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
792 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
796 if (tlibPath) SysFreeString(tlibPath);
797 if (typeLib) ITypeLib_Release(typeLib);
798 if (subKey) RegCloseKey(subKey);
799 if (key) RegCloseKey(key);
803 /*======================= ITypeLib implementation =======================*/
805 typedef struct tagTLBCustData
809 struct tagTLBCustData* next;
812 /* data structure for import typelibs */
813 typedef struct tagTLBImpLib
815 int offset; /* offset in the file (MSFT)
816 offset in nametable (SLTG)
817 just used to identify library while reading
819 GUID guid; /* libid */
820 BSTR name; /* name */
822 LCID lcid; /* lcid of imported typelib */
824 WORD wVersionMajor; /* major version number */
825 WORD wVersionMinor; /* minor version number */
827 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
828 NULL if not yet loaded */
829 struct tagTLBImpLib * next;
832 /* internal ITypeLib data */
833 typedef struct tagITypeLibImpl
835 const ITypeLib2Vtbl *lpVtbl;
836 const ITypeCompVtbl *lpVtblTypeComp;
838 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
840 /* strings can be stored in tlb as multibyte strings BUT they are *always*
841 * exported to the application as a UNICODE string.
847 unsigned long dwHelpContext;
848 int TypeInfoCount; /* nr of typeinfo's in librarry */
849 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
850 int ctCustData; /* number of items in cust data list */
851 TLBCustData * pCustData; /* linked list to cust data */
852 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
853 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
854 libary. Only used while read MSFT
857 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
858 struct tagITypeLibImpl *next, *prev;
863 static const ITypeLib2Vtbl tlbvt;
864 static const ITypeCompVtbl tlbtcvt;
866 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
868 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
871 /* ITypeLib methods */
872 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
873 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
875 /*======================= ITypeInfo implementation =======================*/
877 /* data for referenced types */
878 typedef struct tagTLBRefType
880 INT index; /* Type index for internal ref or for external ref
881 it the format is SLTG. -2 indicates to
884 GUID guid; /* guid of the referenced type */
885 /* if index == TLB_REF_USE_GUID */
887 HREFTYPE reference; /* The href of this ref */
888 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
889 TLB_REF_INTERNAL for internal refs
890 TLB_REF_NOT_FOUND for broken refs */
892 struct tagTLBRefType * next;
895 #define TLB_REF_USE_GUID -2
897 #define TLB_REF_INTERNAL (void*)-2
898 #define TLB_REF_NOT_FOUND (void*)-1
900 /* internal Parameter data */
901 typedef struct tagTLBParDesc
905 TLBCustData * pCustData; /* linked list to cust data */
908 /* internal Function data */
909 typedef struct tagTLBFuncDesc
911 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
912 BSTR Name; /* the name of this function */
913 TLBParDesc *pParamDesc; /* array with param names and custom data */
915 int HelpStringContext;
917 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
919 TLBCustData * pCustData; /* linked list to cust data; */
920 struct tagTLBFuncDesc * next;
923 /* internal Variable data */
924 typedef struct tagTLBVarDesc
926 VARDESC vardesc; /* lots of info on the variable and its attributes. */
927 BSTR Name; /* the name of this variable */
929 int HelpStringContext; /* FIXME: where? */
932 TLBCustData * pCustData;/* linked list to cust data; */
933 struct tagTLBVarDesc * next;
936 /* internal implemented interface data */
937 typedef struct tagTLBImplType
939 HREFTYPE hRef; /* hRef of interface */
940 int implflags; /* IMPLFLAG_*s */
942 TLBCustData * pCustData;/* linked list to custom data; */
943 struct tagTLBImplType *next;
946 /* internal TypeInfo data */
947 typedef struct tagITypeInfoImpl
949 const ITypeInfo2Vtbl *lpVtbl;
950 const ITypeCompVtbl *lpVtblTypeComp;
952 TYPEATTR TypeAttr ; /* _lots_ of type information. */
953 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
954 int index; /* index in this typelib; */
955 HREFTYPE hreftype; /* hreftype for app object binding */
956 /* type libs seem to store the doc strings in ascii
957 * so why should we do it in unicode?
962 unsigned long dwHelpContext;
963 unsigned long dwHelpStringContext;
966 TLBFuncDesc * funclist; /* linked list with function descriptions */
969 TLBVarDesc * varlist; /* linked list with variable descriptions */
971 /* Implemented Interfaces */
972 TLBImplType * impltypelist;
974 TLBRefType * reflist;
976 TLBCustData * pCustData; /* linked list to cust data; */
977 struct tagITypeInfoImpl * next;
980 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
982 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
985 static const ITypeInfo2Vtbl tinfvt;
986 static const ITypeCompVtbl tcompvt;
988 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
990 typedef struct tagTLBContext
992 unsigned int oStart; /* start of TLB in file */
993 unsigned int pos; /* current pos */
994 unsigned int length; /* total length */
995 void *mapping; /* memory mapping */
996 MSFT_SegDir * pTblDir;
997 ITypeLibImpl* pLibInfo;
1001 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1006 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1007 if (pTD->vt & VT_RESERVED)
1008 szVarType += strlen(strcpy(szVarType, "reserved | "));
1009 if (pTD->vt & VT_BYREF)
1010 szVarType += strlen(strcpy(szVarType, "ref to "));
1011 if (pTD->vt & VT_ARRAY)
1012 szVarType += strlen(strcpy(szVarType, "array of "));
1013 if (pTD->vt & VT_VECTOR)
1014 szVarType += strlen(strcpy(szVarType, "vector of "));
1015 switch(pTD->vt & VT_TYPEMASK) {
1016 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1017 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1018 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1019 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1020 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1021 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1022 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1023 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1024 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1025 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1026 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1027 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1028 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1029 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1030 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1031 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1032 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1033 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1034 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1035 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1036 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1037 pTD->u.hreftype); break;
1038 case VT_PTR: sprintf(szVarType, "ptr to ");
1039 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1041 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1042 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1044 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1045 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1046 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1049 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1053 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1055 USHORT flags = edesc->u.paramdesc.wParamFlags;
1056 dump_TypeDesc(&edesc->tdesc,buf);
1057 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1058 MESSAGE("\t\tu.paramdesc.wParamFlags");
1059 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1060 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1061 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1062 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1063 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1064 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1065 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1066 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1067 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1069 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1071 MESSAGE("memid is %08lx\n",funcdesc->memid);
1072 for (i=0;i<funcdesc->cParams;i++) {
1073 MESSAGE("Param %d:\n",i);
1074 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1076 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1077 switch (funcdesc->funckind) {
1078 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1079 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1080 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1081 case FUNC_STATIC: MESSAGE("static");break;
1082 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1083 default: MESSAGE("unknown");break;
1085 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1086 switch (funcdesc->invkind) {
1087 case INVOKE_FUNC: MESSAGE("func");break;
1088 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1089 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1090 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1092 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1093 switch (funcdesc->callconv) {
1094 case CC_CDECL: MESSAGE("cdecl");break;
1095 case CC_PASCAL: MESSAGE("pascal");break;
1096 case CC_STDCALL: MESSAGE("stdcall");break;
1097 case CC_SYSCALL: MESSAGE("syscall");break;
1100 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1101 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1102 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1104 MESSAGE("\telemdescFunc (return value type):\n");
1105 dump_ELEMDESC(&funcdesc->elemdescFunc);
1108 static const char * typekind_desc[] =
1121 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1124 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1125 for (i=0;i<pfd->funcdesc.cParams;i++)
1126 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1129 dump_FUNCDESC(&(pfd->funcdesc));
1131 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1132 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1134 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1138 dump_TLBFuncDescOne(pfd);
1142 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1146 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1151 static void dump_TLBImpLib(const TLBImpLib *import)
1153 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1154 debugstr_w(import->name));
1155 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1156 import->wVersionMinor, import->lcid, import->offset);
1159 static void dump_TLBRefType(const TLBRefType * prt)
1163 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1164 if(prt->index == -1)
1165 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1167 TRACE_(typelib)("type no: %d\n", prt->index);
1169 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1170 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1171 TRACE_(typelib)("in lib\n");
1172 dump_TLBImpLib(prt->pImpTLInfo);
1178 static void dump_TLBImplType(const TLBImplType * impl)
1182 "implementing/inheriting interface hRef = %lx implflags %x\n",
1183 impl->hRef, impl->implflags);
1188 void dump_Variant(const VARIANT * pvar)
1192 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1196 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1197 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1199 TRACE(",%p", V_BYREF(pvar));
1201 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1203 TRACE(",%p", V_ARRAY(pvar));
1205 else switch (V_TYPE(pvar))
1207 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1208 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1209 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1210 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1212 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1214 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1215 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1216 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1217 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1218 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1219 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1220 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1221 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1222 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1223 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1224 V_CY(pvar).s.Lo); break;
1226 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1227 TRACE(",<invalid>");
1229 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1230 st.wHour, st.wMinute, st.wSecond);
1234 case VT_USERDEFINED:
1236 case VT_NULL: break;
1237 default: TRACE(",?"); break;
1243 static void dump_DispParms(const DISPPARAMS * pdp)
1247 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1249 if (pdp->cNamedArgs)
1250 TRACE("named args:\n");
1251 for (index = 0; index < pdp->cNamedArgs; index++)
1252 TRACE( "\t0x%lx\n", pdp->rgdispidNamedArgs[index] );
1256 for (index = 0; index < pdp->cArgs; index++)
1257 dump_Variant( &pdp->rgvarg[index] );
1260 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1262 TRACE("%p ref=%lu\n", pty, pty->ref);
1263 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1264 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1265 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1266 TRACE("fct:%u var:%u impl:%u\n",
1267 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1268 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1269 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1270 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1272 dump_TLBFuncDesc(pty->funclist);
1273 dump_TLBVarDesc(pty->varlist);
1274 dump_TLBImplType(pty->impltypelist);
1277 static void dump_VARDESC(const VARDESC *v)
1279 MESSAGE("memid %ld\n",v->memid);
1280 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1281 MESSAGE("oInst %ld\n",v->u.oInst);
1282 dump_ELEMDESC(&(v->elemdescVar));
1283 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1284 MESSAGE("varkind %d\n",v->varkind);
1287 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1289 /* VT_LPWSTR is largest type that */
1290 /* may appear in type description*/
1291 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1292 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1293 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1294 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1295 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1296 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1300 static void TLB_abort(void)
1304 static void * TLB_Alloc(unsigned size)
1307 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1309 ERR("cannot allocate memory\n");
1314 static void TLB_Free(void * ptr)
1316 HeapFree(GetProcessHeap(), 0, ptr);
1319 /* returns the size required for a deep copy of a typedesc into a
1321 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1325 if (alloc_initial_space)
1326 size += sizeof(TYPEDESC);
1332 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1335 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1336 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1342 /* deep copy a typedesc into a flat buffer */
1343 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1348 buffer = (char *)buffer + sizeof(TYPEDESC);
1357 dest->u.lptdesc = buffer;
1358 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1361 dest->u.lpadesc = buffer;
1362 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1363 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1364 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1370 /**********************************************************************
1372 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1374 static inline unsigned int MSFT_Tell(TLBContext *pcx)
1379 static inline void MSFT_Seek(TLBContext *pcx, long where)
1381 if (where != DO_NOT_SEEK)
1383 where += pcx->oStart;
1384 if (where > pcx->length)
1387 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1395 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1397 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1398 pcx->pos, count, pcx->oStart, pcx->length, where);
1400 MSFT_Seek(pcx, where);
1401 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1402 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1407 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1412 ret = MSFT_Read(buffer, count, pcx, where);
1413 FromLEDWords(buffer, ret);
1418 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1423 ret = MSFT_Read(buffer, count, pcx, where);
1424 FromLEWords(buffer, ret);
1429 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1431 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1432 memset(pGuid,0, sizeof(GUID));
1435 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1436 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1437 pGuid->Data2 = FromLEWord(pGuid->Data2);
1438 pGuid->Data3 = FromLEWord(pGuid->Data3);
1439 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1442 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1444 MSFT_NameIntro niName;
1448 ERR_(typelib)("bad offset %d\n", offset);
1452 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1453 pcx->pTblDir->pNametab.offset+offset);
1455 return niName.hreftype;
1458 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1461 MSFT_NameIntro niName;
1463 WCHAR* pwstring = NULL;
1464 BSTR bstrName = NULL;
1468 ERR_(typelib)("bad offset %d\n", offset);
1471 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1472 pcx->pTblDir->pNametab.offset+offset);
1473 niName.namelen &= 0xFF; /* FIXME: correct ? */
1474 name=TLB_Alloc((niName.namelen & 0xff) +1);
1475 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1476 name[niName.namelen & 0xff]='\0';
1478 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1481 /* no invalid characters in string */
1484 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1486 /* don't check for invalid character since this has been done previously */
1487 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1489 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1490 lengthInChars = SysStringLen(bstrName);
1491 HeapFree(GetProcessHeap(), 0, pwstring);
1494 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1498 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1505 if(offset<0) return NULL;
1506 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1507 if(length <= 0) return 0;
1508 string=TLB_Alloc(length +1);
1509 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1510 string[length]='\0';
1512 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1513 string, -1, NULL, 0);
1515 /* no invalid characters in string */
1518 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1520 /* don't check for invalid character since this has been done previously */
1521 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1523 bstr = SysAllocStringLen(pwstring, lengthInChars);
1524 lengthInChars = SysStringLen(bstr);
1525 HeapFree(GetProcessHeap(), 0, pwstring);
1528 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1532 * read a value and fill a VARIANT structure
1534 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1538 TRACE_(typelib)("\n");
1540 if(offset <0) { /* data are packed in here */
1541 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1542 V_I4(pVar) = offset & 0x3ffffff;
1545 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1546 pcx->pTblDir->pCustData.offset + offset );
1547 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1548 switch (V_VT(pVar)){
1549 case VT_EMPTY: /* FIXME: is this right? */
1550 case VT_NULL: /* FIXME: is this right? */
1551 case VT_I2 : /* this should not happen */
1562 case VT_VOID : /* FIXME: is this right? */
1570 case VT_DECIMAL : /* FIXME: is this right? */
1573 /* pointer types with known behaviour */
1576 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1579 DWORD origPos = MSFT_Tell(pcx), nullPos;
1582 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1584 nullPos = MSFT_Tell(pcx);
1585 size = nullPos - origPos;
1586 MSFT_Seek(pcx, origPos);
1588 ptr=TLB_Alloc(size);/* allocate temp buffer */
1589 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1590 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1591 /* FIXME: do we need a AtoW conversion here? */
1592 V_UNION(pVar, bstrVal[size])=L'\0';
1593 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1597 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1604 case VT_USERDEFINED :
1610 case VT_STREAMED_OBJECT :
1611 case VT_STORED_OBJECT :
1612 case VT_BLOB_OBJECT :
1617 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1621 if(size>0) /* (big|small) endian correct? */
1622 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1626 * create a linked list with custom data
1628 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1634 TRACE_(typelib)("\n");
1638 pNew=TLB_Alloc(sizeof(TLBCustData));
1639 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1640 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1641 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1642 /* add new custom data at head of the list */
1643 pNew->next=*ppCustData;
1645 offset = entry.next;
1650 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1654 pTd->vt=type & VT_TYPEMASK;
1656 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1658 if(pTd->vt == VT_USERDEFINED)
1659 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1661 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1664 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1666 /* resolve referenced type if any */
1669 switch (lpTypeDesc->vt)
1672 lpTypeDesc = lpTypeDesc->u.lptdesc;
1676 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1679 case VT_USERDEFINED:
1680 MSFT_DoRefType(pcx, pTI,
1681 lpTypeDesc->u.hreftype);
1693 MSFT_DoFuncs(TLBContext* pcx,
1698 TLBFuncDesc** pptfd)
1701 * member information is stored in a data structure at offset
1702 * indicated by the memoffset field of the typeinfo structure
1703 * There are several distinctive parts.
1704 * The first part starts with a field that holds the total length
1705 * of this (first) part excluding this field. Then follow the records,
1706 * for each member there is one record.
1708 * The first entry is always the length of the record (including this
1710 * The rest of the record depends on the type of the member. If there is
1711 * a field indicating the member type (function, variable, interface, etc)
1712 * I have not found it yet. At this time we depend on the information
1713 * in the type info and the usual order how things are stored.
1715 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1718 * Third is an equal sized array with file offsets to the name entry
1721 * The fourth and last (?) part is an array with offsets to the records
1722 * in the first part of this file segment.
1725 int infolen, nameoffset, reclength, nrattributes, i;
1726 int recoffset = offset + sizeof(INT);
1728 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1729 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1730 TLBFuncDesc *ptfd_prev = NULL;
1732 TRACE_(typelib)("\n");
1734 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1736 for ( i = 0; i < cFuncs ; i++ )
1738 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1740 /* name, eventually add to a hash table */
1741 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1742 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1744 /* nameoffset is sometimes -1 on the second half of a propget/propput
1745 * pair of functions */
1746 if ((nameoffset == -1) && (i > 0))
1747 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1749 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1751 /* read the function information record */
1752 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1754 reclength &= 0xffff;
1756 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1758 /* do the attributes */
1759 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1762 if ( nrattributes > 0 )
1764 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1766 if ( nrattributes > 1 )
1768 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1769 pFuncRec->OptAttr[1]) ;
1771 if ( nrattributes > 2 )
1773 if ( pFuncRec->FKCCIC & 0x2000 )
1775 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1779 (*pptfd)->Entry = MSFT_ReadString(pcx,
1780 pFuncRec->OptAttr[2]);
1782 if( nrattributes > 5 )
1784 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1786 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1789 pFuncRec->OptAttr[6],
1790 &(*pptfd)->pCustData);
1797 /* fill the FuncDesc Structure */
1798 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1799 offset + infolen + ( i + 1) * sizeof(INT));
1801 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1802 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1803 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1804 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1805 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1806 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1807 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1811 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1813 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1815 /* do the parameters/arguments */
1816 if(pFuncRec->nrargs)
1819 MSFT_ParameterInfo paraminfo;
1821 (*pptfd)->funcdesc.lprgelemdescParam =
1822 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1824 (*pptfd)->pParamDesc =
1825 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1827 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1828 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1830 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1832 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1839 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1842 if (paraminfo.oName == -1)
1843 /* this occurs for [propput] or [propget] methods, so
1844 * we should just set the name of the parameter to the
1845 * name of the method. */
1846 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1848 (*pptfd)->pParamDesc[j].Name =
1849 MSFT_ReadName( pcx, paraminfo.oName );
1850 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1852 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1855 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1856 (pFuncRec->FKCCIC & 0x1000) )
1858 INT* pInt = (INT *)((char *)pFuncRec +
1860 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1862 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
1864 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1865 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1867 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1871 elemdesc->u.paramdesc.pparamdescex = NULL;
1873 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1876 pFuncRec->OptAttr[7+j],
1877 &(*pptfd)->pParamDesc[j].pCustData);
1880 /* SEEK value = jump to offset,
1881 * from there jump to the end of record,
1882 * go back by (j-1) arguments
1884 MSFT_ReadLEDWords( ¶minfo ,
1885 sizeof(MSFT_ParameterInfo), pcx,
1886 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1887 * sizeof(MSFT_ParameterInfo)));
1891 /* scode is not used: archaic win16 stuff FIXME: right? */
1892 (*pptfd)->funcdesc.cScodes = 0 ;
1893 (*pptfd)->funcdesc.lprgscode = NULL ;
1896 pptfd = & ((*pptfd)->next);
1897 recoffset += reclength;
1899 HeapFree(GetProcessHeap(), 0, recbuf);
1902 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1903 int cVars, int offset, TLBVarDesc ** pptvd)
1905 int infolen, nameoffset, reclength;
1907 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1911 TRACE_(typelib)("\n");
1913 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1914 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1915 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1916 recoffset += offset+sizeof(INT);
1917 for(i=0;i<cVars;i++){
1918 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1919 /* name, eventually add to a hash table */
1920 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1921 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
1922 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1923 /* read the variable information record */
1924 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1926 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1928 if(reclength >(6*sizeof(INT)) )
1929 (*pptvd)->HelpContext=pVarRec->HelpContext;
1930 if(reclength >(7*sizeof(INT)) )
1931 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1932 if(reclength >(8*sizeof(INT)) )
1933 if(reclength >(9*sizeof(INT)) )
1934 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1935 /* fill the VarDesc Structure */
1936 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1937 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
1938 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1939 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1940 MSFT_GetTdesc(pcx, pVarRec->DataType,
1941 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1942 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1943 if(pVarRec->VarKind == VAR_CONST ){
1944 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1945 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1946 pVarRec->OffsValue, pcx);
1948 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1949 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
1950 pptvd=&((*pptvd)->next);
1951 recoffset += reclength;
1954 /* fill in data for a hreftype (offset). When the referenced type is contained
1955 * in the typelib, it's just an (file) offset in the type info base dir.
1956 * If comes from import, it's an offset+1 in the ImpInfo table
1958 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1962 TLBRefType **ppRefType = &pTI->reflist;
1964 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1967 if((*ppRefType)->reference == offset)
1969 ppRefType = &(*ppRefType)->next;
1972 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1973 sizeof(**ppRefType));
1975 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1976 /* external typelib */
1977 MSFT_ImpInfo impinfo;
1978 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1980 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1982 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1983 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1984 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1985 if(pImpLib->offset==impinfo.oImpFile) break;
1986 pImpLib=pImpLib->next;
1989 (*ppRefType)->reference=offset;
1990 (*ppRefType)->pImpTLInfo = pImpLib;
1991 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1992 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1993 TRACE("importing by guid %s\n", debugstr_guid(&(*ppRefType)->guid));
1994 (*ppRefType)->index = TLB_REF_USE_GUID;
1996 (*ppRefType)->index = impinfo.oGuid;
1998 ERR("Cannot find a reference\n");
1999 (*ppRefType)->reference=-1;
2000 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2003 /* in this typelib */
2004 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2005 (*ppRefType)->reference=offset;
2006 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2010 /* process Implemented Interfaces of a com class */
2011 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2015 MSFT_RefRecord refrec;
2016 TLBImplType **ppImpl = &pTI->impltypelist;
2018 TRACE_(typelib)("\n");
2020 for(i=0;i<count;i++){
2021 if(offset<0) break; /* paranoia */
2022 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2023 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2024 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2025 (*ppImpl)->hRef = refrec.reftype;
2026 (*ppImpl)->implflags=refrec.flags;
2027 (*ppImpl)->ctCustData=
2028 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2029 offset=refrec.onext;
2030 ppImpl=&((*ppImpl)->next);
2034 * process a typeinfo record
2036 static ITypeInfoImpl * MSFT_DoTypeInfo(
2040 ITypeLibImpl * pLibInfo)
2042 MSFT_TypeInfoBase tiBase;
2043 ITypeInfoImpl *ptiRet;
2045 TRACE_(typelib)("count=%u\n", count);
2047 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2048 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2049 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2051 /* this is where we are coming from */
2052 ptiRet->pTypeLib = pLibInfo;
2053 ptiRet->index=count;
2054 /* fill in the typeattr fields */
2056 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2057 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2058 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2059 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2060 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2061 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2062 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2063 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2064 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2065 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2066 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2067 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2068 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2069 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2070 MSFT_GetTdesc(pcx, tiBase.datatype1,
2071 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2074 /* IDLDESC idldescType; *//* never saw this one != zero */
2076 /* name, eventually add to a hash table */
2077 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2078 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2079 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2081 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2082 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2083 ptiRet->dwHelpContext=tiBase.helpcontext;
2085 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2086 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2088 /* note: InfoType's Help file and HelpStringDll come from the containing
2089 * library. Further HelpString and Docstring appear to be the same thing :(
2092 if(ptiRet->TypeAttr.cFuncs >0 )
2093 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2094 ptiRet->TypeAttr.cVars,
2095 tiBase.memoffset, & ptiRet->funclist);
2097 if(ptiRet->TypeAttr.cVars >0 )
2098 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2099 ptiRet->TypeAttr.cVars,
2100 tiBase.memoffset, & ptiRet->varlist);
2101 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2102 switch(ptiRet->TypeAttr.typekind)
2105 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2108 case TKIND_DISPATCH:
2109 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2111 if (tiBase.datatype1 != -1)
2113 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2114 ptiRet->impltypelist->hRef = tiBase.datatype1;
2118 MSFT_DoRefType(pcx, ptiRet, dispatch_href);
2119 ptiRet->impltypelist->hRef = dispatch_href;
2123 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2124 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2125 ptiRet->impltypelist->hRef = tiBase.datatype1;
2130 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2132 TRACE_(typelib)("%s guid: %s kind:%s\n",
2133 debugstr_w(ptiRet->Name),
2134 debugstr_guid(&ptiRet->TypeAttr.guid),
2135 typekind_desc[ptiRet->TypeAttr.typekind]);
2140 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2141 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2142 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2145 static ITypeLibImpl *tlb_cache_first;
2146 static CRITICAL_SECTION cache_section;
2147 static CRITICAL_SECTION_DEBUG cache_section_debug =
2149 0, 0, &cache_section,
2150 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2151 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2153 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2156 /****************************************************************************
2159 * find the type of the typelib file and map the typelib resource into
2162 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2163 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2164 static int TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2166 ITypeLibImpl *entry;
2167 int ret = TYPE_E_CANTLOADLIBRARY;
2173 lstrcpynW(pszPath, pszFileName, cchPath);
2175 /* first try loading as a dll and access the typelib as a resource */
2176 hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES |
2177 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2180 /* it may have been specified with resource index appended to the
2181 * path, so remove it and try again */
2182 const WCHAR *pIndexStr = strrchrW(pszFileName, '\\');
2183 if(pIndexStr && pIndexStr != pszFileName && *++pIndexStr != '\0')
2185 index = atoiW(pIndexStr);
2186 pszPath[pIndexStr - pszFileName - 1] = '\0';
2188 hinstDLL = LoadLibraryExW(pszPath, 0, DONT_RESOLVE_DLL_REFERENCES |
2189 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2193 /* get the path to the specified typelib file */
2196 /* otherwise, try loading as a regular file */
2197 if (!SearchPathW(NULL, pszFileName, NULL, cchPath, pszPath, NULL))
2198 return TYPE_E_CANTLOADLIBRARY;
2201 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2203 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2204 EnterCriticalSection(&cache_section);
2205 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2207 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2209 TRACE("cache hit\n");
2210 *ppTypeLib = (ITypeLib2*)entry;
2211 ITypeLib_AddRef(*ppTypeLib);
2212 LeaveCriticalSection(&cache_section);
2213 FreeLibrary(hinstDLL);
2217 LeaveCriticalSection(&cache_section);
2219 /* now actually load and parse the typelib */
2222 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2223 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2226 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2229 LPVOID pBase = LockResource(hGlobal);
2230 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2234 /* try to load as incore resource */
2235 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2236 if (dwSignature == MSFT_SIGNATURE)
2237 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2238 else if (dwSignature == SLTG_SIGNATURE)
2239 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2241 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2243 FreeResource( hGlobal );
2246 FreeLibrary(hinstDLL);
2250 HANDLE hFile = CreateFileW(pszPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2251 if (INVALID_HANDLE_VALUE != hFile)
2253 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2256 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2259 /* retrieve file size */
2260 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2261 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2263 if (dwSignature == MSFT_SIGNATURE)
2264 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2265 else if (dwSignature == SLTG_SIGNATURE)
2266 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2268 UnmapViewOfFile(pBase);
2270 CloseHandle(hMapping);
2277 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2279 TRACE("adding to cache\n");
2280 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2281 lstrcpyW(impl->path, pszPath);
2282 /* We should really canonicalise the path here. */
2283 impl->index = index;
2285 /* FIXME: check if it has added already in the meantime */
2286 EnterCriticalSection(&cache_section);
2287 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2289 tlb_cache_first = impl;
2290 LeaveCriticalSection(&cache_section);
2293 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2298 /*================== ITypeLib(2) Methods ===================================*/
2300 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2302 ITypeLibImpl* pTypeLibImpl;
2304 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2305 if (!pTypeLibImpl) return NULL;
2307 pTypeLibImpl->lpVtbl = &tlbvt;
2308 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2309 pTypeLibImpl->ref = 1;
2311 return pTypeLibImpl;
2314 /****************************************************************************
2315 * ITypeLib2_Constructor_MSFT
2317 * loading an MSFT typelib from an in-memory image
2319 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2323 MSFT_Header tlbHeader;
2324 MSFT_SegDir tlbSegDir;
2325 ITypeLibImpl * pTypeLibImpl;
2327 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2329 pTypeLibImpl = TypeLibImpl_Constructor();
2330 if (!pTypeLibImpl) return NULL;
2332 /* get pointer to beginning of typelib data */
2336 cx.pLibInfo = pTypeLibImpl;
2337 cx.length = dwTLBLength;
2340 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2341 TRACE_(typelib)("header:\n");
2342 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2343 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2344 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2347 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2349 /* there is a small amount of information here until the next important
2351 * the segment directory . Try to calculate the amount of data */
2352 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2354 /* now read the segment directory */
2355 TRACE("read segment directory (at %ld)\n",lPSegDir);
2356 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2357 cx.pTblDir = &tlbSegDir;
2359 /* just check two entries */
2360 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2362 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2363 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2367 /* now fill our internal data */
2368 /* TLIBATTR fields */
2369 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2371 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2372 /* Windows seems to have zero here, is this correct? */
2373 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2374 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2376 pTypeLibImpl->LibAttr.lcid = 0;
2378 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2379 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2380 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2381 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2383 /* name, eventually add to a hash table */
2384 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2387 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2388 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2390 if( tlbHeader.varflags & HELPDLLFLAG)
2393 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2394 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2397 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2400 if(tlbHeader.CustomDataOffset >= 0)
2402 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2405 /* fill in typedescriptions */
2406 if(tlbSegDir.pTypdescTab.length > 0)
2408 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2410 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2411 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2414 /* FIXME: add several sanity checks here */
2415 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2416 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2418 /* FIXME: check safearray */
2420 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2422 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2424 else if(td[0] == VT_CARRAY)
2426 /* array descr table here */
2427 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2429 else if(td[0] == VT_USERDEFINED)
2431 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2433 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2436 /* second time around to fill the array subscript info */
2439 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2440 if(tlbSegDir.pArrayDescriptions.offset>0)
2442 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2443 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2446 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2448 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2450 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2452 for(j = 0; j<td[2]; j++)
2454 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2455 sizeof(INT), &cx, DO_NOT_SEEK);
2456 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2457 sizeof(INT), &cx, DO_NOT_SEEK);
2462 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2463 ERR("didn't find array description data\n");
2468 /* imported type libs */
2469 if(tlbSegDir.pImpFiles.offset>0)
2471 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2472 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2475 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2480 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2481 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2482 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2484 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2485 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2486 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2487 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2490 name = TLB_Alloc(size+1);
2491 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2492 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2493 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2494 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2497 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2498 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2500 ppImpLib = &(*ppImpLib)->next;
2505 if(tlbHeader.nrtypeinfos >= 0 )
2507 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2508 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2511 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2513 *ppTI = MSFT_DoTypeInfo(&cx, i, tlbHeader.dispatchpos, pTypeLibImpl);
2515 ppTI = &((*ppTI)->next);
2516 (pTypeLibImpl->TypeInfoCount)++;
2520 TRACE("(%p)\n", pTypeLibImpl);
2521 return (ITypeLib2*) pTypeLibImpl;
2525 static BSTR TLB_MultiByteToBSTR(char *ptr)
2531 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2532 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2533 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2534 ret = SysAllocString(nameW);
2535 HeapFree(GetProcessHeap(), 0, nameW);
2539 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2545 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2546 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2550 guid->Data4[0] = s >> 8;
2551 guid->Data4[1] = s & 0xff;
2554 for(i = 0; i < 6; i++) {
2555 memcpy(b, str + 24 + 2 * i, 2);
2556 guid->Data4[i + 2] = strtol(b, NULL, 16);
2561 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2568 bytelen = *(WORD*)ptr;
2569 if(bytelen == 0xffff) return 2;
2570 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2571 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2572 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2573 *pBstr = SysAllocStringLen(nameW, len);
2574 HeapFree(GetProcessHeap(), 0, nameW);
2578 static WORD SLTG_ReadStringA(char *ptr, char **str)
2583 bytelen = *(WORD*)ptr;
2584 if(bytelen == 0xffff) return 2;
2585 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2586 memcpy(*str, ptr + 2, bytelen);
2587 (*str)[bytelen] = '\0';
2591 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2593 char *ptr = pLibBlk;
2596 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2597 FIXME("libblk magic = %04x\n", w);
2602 if((w = *(WORD*)ptr) != 0xffff) {
2603 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2608 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2610 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2612 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2615 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2618 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2619 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2621 pTypeLibImpl->LibAttr.lcid = 0;
2624 ptr += 4; /* skip res12 */
2626 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2629 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2632 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2635 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2636 ptr += sizeof(GUID);
2638 return ptr - (char*)pLibBlk;
2641 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD)
2646 if((*pType & 0xe00) == 0xe00) {
2648 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2650 pTD = pTD->u.lptdesc;
2652 switch(*pType & 0x3f) {
2655 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2657 pTD = pTD->u.lptdesc;
2660 case VT_USERDEFINED:
2661 pTD->vt = VT_USERDEFINED;
2662 pTD->u.hreftype = *(++pType) / 4;
2668 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2671 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2673 pTD->vt = VT_CARRAY;
2674 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2676 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2677 pTD->u.lpadesc->cDims = pSA->cDims;
2678 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2679 pSA->cDims * sizeof(SAFEARRAYBOUND));
2681 pTD = &pTD->u.lpadesc->tdescElem;
2687 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2691 pTD->vt = VT_SAFEARRAY;
2692 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2694 pTD = pTD->u.lptdesc;
2698 pTD->vt = *pType & 0x3f;
2707 static WORD *SLTG_DoElem(WORD *pType, char *pBlk, ELEMDESC *pElem)
2709 /* Handle [in/out] first */
2710 if((*pType & 0xc000) == 0xc000)
2711 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2712 else if(*pType & 0x8000)
2713 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2714 else if(*pType & 0x4000)
2715 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2717 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2720 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2723 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2725 return SLTG_DoType(pType, pBlk, &pElem->tdesc);
2729 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2734 TLBRefType **ppRefType;
2736 if(pRef->magic != SLTG_REF_MAGIC) {
2737 FIXME("Ref magic = %x\n", pRef->magic);
2740 name = ( (char*)(&pRef->names) + pRef->number);
2742 ppRefType = &pTI->reflist;
2743 for(ref = 0; ref < pRef->number >> 3; ref++) {
2745 unsigned int lib_offs, type_num;
2747 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2748 sizeof(**ppRefType));
2750 name += SLTG_ReadStringA(name, &refname);
2751 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2752 FIXME("Can't sscanf ref\n");
2753 if(lib_offs != 0xffff) {
2754 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2757 if((*import)->offset == lib_offs)
2759 import = &(*import)->next;
2762 char fname[MAX_PATH+1];
2765 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2767 (*import)->offset = lib_offs;
2768 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2770 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2771 &(*import)->wVersionMajor,
2772 &(*import)->wVersionMinor,
2773 &(*import)->lcid, fname) != 4) {
2774 FIXME("can't sscanf ref %s\n",
2775 pNameTable + lib_offs + 40);
2777 len = strlen(fname);
2778 if(fname[len-1] != '#')
2779 FIXME("fname = %s\n", fname);
2780 fname[len-1] = '\0';
2781 (*import)->name = TLB_MultiByteToBSTR(fname);
2783 (*ppRefType)->pImpTLInfo = *import;
2784 } else { /* internal ref */
2785 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2787 (*ppRefType)->reference = ref;
2788 (*ppRefType)->index = type_num;
2790 HeapFree(GetProcessHeap(), 0, refname);
2791 ppRefType = &(*ppRefType)->next;
2793 if((BYTE)*name != SLTG_REF_MAGIC)
2794 FIXME("End of ref block magic = %x\n", *name);
2795 dump_TLBRefType(pTI->reflist);
2798 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2801 SLTG_ImplInfo *info;
2802 TLBImplType **ppImplType = &pTI->impltypelist;
2803 /* I don't really get this structure, usually it's 0x16 bytes
2804 long, but iuser.tlb contains some that are 0x18 bytes long.
2805 That's ok because we can use the next ptr to jump to the next
2806 one. But how do we know the length of the last one? The WORD
2807 at offs 0x8 might be the clue. For now I'm just assuming that
2808 the last one is the regular 0x16 bytes. */
2810 info = (SLTG_ImplInfo*)pBlk;
2812 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2813 sizeof(**ppImplType));
2814 (*ppImplType)->hRef = info->ref;
2815 (*ppImplType)->implflags = info->impltypeflags;
2816 pTI->TypeAttr.cImplTypes++;
2817 ppImplType = &(*ppImplType)->next;
2819 if(info->next == 0xffff)
2822 FIXME("Interface inheriting more than one interface\n");
2823 info = (SLTG_ImplInfo*)(pBlk + info->next);
2825 info++; /* see comment at top of function */
2829 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars, char *pNameTable)
2831 TLBVarDesc **ppVarDesc = &pTI->varlist;
2832 BSTR bstrPrevName = NULL;
2833 SLTG_Variable *pItem;
2838 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
2839 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
2841 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2842 sizeof(**ppVarDesc));
2843 (*ppVarDesc)->vardesc.memid = pItem->memid;
2845 if (pItem->magic != SLTG_VAR_MAGIC &&
2846 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
2847 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
2851 if (pItem->name == 0xfffe)
2852 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
2854 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2856 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
2857 TRACE_(typelib)("memid = 0x%lx\n", pItem->memid);
2859 if (pItem->flags & 0x40) {
2860 TRACE_(typelib)("VAR_DISPATCH\n");
2861 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
2863 else if (pItem->flags & 0x10) {
2864 TRACE_(typelib)("VAR_CONST\n");
2865 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
2866 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
2868 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
2869 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
2870 *(INT*)(pBlk + pItem->byte_offs);
2873 TRACE_(typelib)("VAR_PERINSTANCE\n");
2874 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2875 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2878 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
2879 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
2881 if (pItem->flags & 0x80)
2882 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
2884 if(pItem->flags & 0x02)
2885 pType = &pItem->type;
2887 pType = (WORD*)(pBlk + pItem->type);
2889 if (pItem->flags & ~0xd2)
2890 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xd2);
2892 SLTG_DoElem(pType, pBlk,
2893 &(*ppVarDesc)->vardesc.elemdescVar);
2895 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2897 bstrPrevName = (*ppVarDesc)->Name;
2898 ppVarDesc = &((*ppVarDesc)->next);
2900 pTI->TypeAttr.cVars = cVars;
2903 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cFuncs, char *pNameTable)
2905 SLTG_Function *pFunc;
2907 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2909 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
2910 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
2915 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2916 sizeof(**ppFuncDesc));
2918 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
2919 case SLTG_FUNCTION_MAGIC:
2920 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
2922 case SLTG_DISPATCH_FUNCTION_MAGIC:
2923 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
2925 case SLTG_STATIC_FUNCTION_MAGIC:
2926 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
2929 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
2930 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
2934 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2936 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2937 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2938 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2939 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2940 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2941 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2943 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
2944 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2946 if(pFunc->retnextopt & 0x80)
2947 pType = &pFunc->rettype;
2949 pType = (WORD*)(pBlk + pFunc->rettype);
2951 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2953 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2954 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2955 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2956 (*ppFuncDesc)->pParamDesc =
2957 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2958 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2960 pArg = (WORD*)(pBlk + pFunc->arg_off);
2962 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2963 char *paramName = pNameTable + *pArg;
2965 /* If arg type follows then paramName points to the 2nd
2966 letter of the name, else the next WORD is an offset to
2967 the arg type and paramName points to the first letter.
2968 So let's take one char off paramName and see if we're
2969 pointing at an alpha-numeric char. However if *pArg is
2970 0xffff or 0xfffe then the param has no name, the former
2971 meaning that the next WORD is the type, the latter
2972 meaning the the next WORD is an offset to the type. */
2977 else if(*pArg == 0xfffe) {
2981 else if(paramName[-1] && !isalnum(paramName[-1]))
2986 if(HaveOffs) { /* the next word is an offset to type */
2987 pType = (WORD*)(pBlk + *pArg);
2988 SLTG_DoElem(pType, pBlk,
2989 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2994 pArg = SLTG_DoElem(pArg, pBlk,
2995 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2998 /* Are we an optional param ? */
2999 if((*ppFuncDesc)->funcdesc.cParams - param <=
3000 (*ppFuncDesc)->funcdesc.cParamsOpt)
3001 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3004 (*ppFuncDesc)->pParamDesc[param].Name =
3005 TLB_MultiByteToBSTR(paramName);
3009 ppFuncDesc = &((*ppFuncDesc)->next);
3010 if(pFunc->next == 0xffff) break;
3012 pTI->TypeAttr.cFuncs = cFuncs;
3015 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3016 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3017 SLTG_TypeInfoTail *pTITail)
3019 char *pFirstItem, *pNextItem;
3021 if(pTIHeader->href_table != 0xffffffff) {
3022 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3026 pFirstItem = pNextItem = pBlk;
3028 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3029 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
3034 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3035 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3036 SLTG_TypeInfoTail *pTITail)
3038 char *pFirstItem, *pNextItem;
3040 if(pTIHeader->href_table != 0xffffffff) {
3041 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3045 pFirstItem = pNextItem = pBlk;
3047 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3048 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
3051 if (pTITail->funcs_off != 0xffff)
3052 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3054 if (TRACE_ON(typelib))
3055 dump_TLBFuncDesc(pTI->funclist);
3058 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3059 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3060 SLTG_TypeInfoTail *pTITail)
3062 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3065 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3066 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3067 SLTG_TypeInfoTail *pTITail)
3071 if (pTITail->simple_alias) {
3072 /* if simple alias, no more processing required */
3073 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3077 if(pTIHeader->href_table != 0xffffffff) {
3078 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3082 /* otherwise it is an offset to a type */
3083 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3085 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias);
3088 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3089 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3090 SLTG_TypeInfoTail *pTITail)
3092 if (pTIHeader->href_table != 0xffffffff)
3093 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3096 if (pTITail->vars_off != 0xffff)
3097 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3099 if (pTITail->funcs_off != 0xffff)
3100 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3102 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3103 * of dispinterface functons including the IDispatch ones, so
3104 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3105 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3107 if (TRACE_ON(typelib))
3108 dump_TLBFuncDesc(pTI->funclist);
3111 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3112 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3113 SLTG_TypeInfoTail *pTITail)
3115 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3118 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3119 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3120 SLTG_TypeInfoTail *pTITail)
3122 if (pTIHeader->href_table != 0xffffffff)
3123 SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI,
3126 if (pTITail->vars_off != 0xffff)
3127 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable);
3129 if (pTITail->funcs_off != 0xffff)
3130 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable);
3133 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3134 managable copy of it into this */
3147 } SLTG_InternalOtherTypeInfo;
3149 /****************************************************************************
3150 * ITypeLib2_Constructor_SLTG
3152 * loading a SLTG typelib from an in-memory image
3154 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3156 ITypeLibImpl *pTypeLibImpl;
3157 SLTG_Header *pHeader;
3158 SLTG_BlkEntry *pBlkEntry;
3162 LPVOID pBlk, pFirstBlk;
3163 SLTG_LibBlk *pLibBlk;
3164 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3165 char *pAfterOTIBlks = NULL;
3166 char *pNameTable, *ptr;
3169 ITypeInfoImpl **ppTypeInfoImpl;
3171 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3174 pTypeLibImpl = TypeLibImpl_Constructor();
3175 if (!pTypeLibImpl) return NULL;
3179 TRACE_(typelib)("header:\n");
3180 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3181 pHeader->nrOfFileBlks );
3182 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3183 FIXME("Header type magic 0x%08lx not supported.\n",
3184 pHeader->SLTG_magic);
3188 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3189 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3191 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3192 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3194 /* Next we have a magic block */
3195 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3197 /* Let's see if we're still in sync */
3198 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3199 sizeof(SLTG_COMPOBJ_MAGIC))) {
3200 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3203 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3204 sizeof(SLTG_DIR_MAGIC))) {
3205 FIXME("dir magic = %s\n", pMagic->dir_magic);
3209 pIndex = (SLTG_Index*)(pMagic+1);
3211 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3213 pFirstBlk = (LPVOID)(pPad9 + 1);
3215 /* We'll set up a ptr to the main library block, which is the last one. */
3217 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3218 pBlkEntry[order].next != 0;
3219 order = pBlkEntry[order].next - 1, i++) {
3220 pBlk = (char*)pBlk + pBlkEntry[order].len;
3224 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3226 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3231 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3233 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3234 sizeof(*pOtherTypeInfoBlks) *
3235 pTypeLibImpl->TypeInfoCount);
3238 ptr = (char*)pLibBlk + len;
3240 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3244 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3246 w = *(WORD*)(ptr + 2);
3249 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3251 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3252 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3254 w = *(WORD*)(ptr + 4 + len);
3256 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3258 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3260 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3261 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3263 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3264 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3265 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3267 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3269 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3272 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3273 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3274 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3275 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3276 len += sizeof(SLTG_OtherTypeInfo);
3280 pAfterOTIBlks = ptr;
3282 /* Skip this WORD and get the next DWORD */
3283 len = *(DWORD*)(pAfterOTIBlks + 2);
3285 /* Now add this to pLibBLk look at what we're pointing at and
3286 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3287 dust and we should be pointing at the beginning of the name
3290 pNameTable = (char*)pLibBlk + len;
3292 switch(*(WORD*)pNameTable) {
3299 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3303 pNameTable += 0x216;
3307 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3309 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3312 /* Hopefully we now have enough ptrs set up to actually read in
3313 some TypeInfos. It's not clear which order to do them in, so
3314 I'll just follow the links along the BlkEntry chain and read
3315 them in in the order in which they're in the file */
3317 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3319 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3320 pBlkEntry[order].next != 0;
3321 order = pBlkEntry[order].next - 1, i++) {
3323 SLTG_TypeInfoHeader *pTIHeader;
3324 SLTG_TypeInfoTail *pTITail;
3325 SLTG_MemberHeader *pMemHeader;
3327 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3328 pOtherTypeInfoBlks[i].index_name)) {
3329 FIXME("Index strings don't match\n");
3334 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3335 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3338 TRACE("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
3339 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3341 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3342 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3343 (*ppTypeInfoImpl)->index = i;
3344 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3345 pOtherTypeInfoBlks[i].name_offs +
3347 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3348 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3350 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3351 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3352 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3353 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3354 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3356 if((pTIHeader->typeflags1 & 7) != 2)
3357 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3358 if(pTIHeader->typeflags3 != 2)
3359 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3361 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3362 debugstr_w((*ppTypeInfoImpl)->Name),
3363 typekind_desc[pTIHeader->typekind],
3364 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3365 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3367 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3369 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3371 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3372 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3373 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3375 switch(pTIHeader->typekind) {
3377 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3378 pTIHeader, pTITail);
3382 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3383 pTIHeader, pTITail);
3386 case TKIND_INTERFACE:
3387 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3388 pTIHeader, pTITail);
3392 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3393 pTIHeader, pTITail);
3397 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3398 pTIHeader, pTITail);
3401 case TKIND_DISPATCH:
3402 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3403 pTIHeader, pTITail);
3407 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3408 pTIHeader, pTITail);
3412 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3417 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3418 but we've already set those */
3419 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3434 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3435 pBlk = (char*)pBlk + pBlkEntry[order].len;
3438 if(i != pTypeLibImpl->TypeInfoCount) {
3439 FIXME("Somehow processed %d TypeInfos\n", i);
3443 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3444 return (ITypeLib2*)pTypeLibImpl;
3447 /* ITypeLib::QueryInterface
3449 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3454 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3456 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3459 if(IsEqualIID(riid, &IID_IUnknown) ||
3460 IsEqualIID(riid,&IID_ITypeLib)||
3461 IsEqualIID(riid,&IID_ITypeLib2))
3468 ITypeLib2_AddRef(iface);
3469 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3472 TRACE("-- Interface: E_NOINTERFACE\n");
3473 return E_NOINTERFACE;
3478 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3480 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3481 ULONG ref = InterlockedIncrement(&This->ref);
3483 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3488 /* ITypeLib::Release
3490 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3492 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3493 ULONG ref = InterlockedDecrement(&This->ref);
3495 TRACE("(%p)->(%lu)\n",This, ref);
3499 /* remove cache entry */
3502 TRACE("removing from cache list\n");
3503 EnterCriticalSection(&cache_section);
3504 if (This->next) This->next->prev = This->prev;
3505 if (This->prev) This->prev->next = This->next;
3506 else tlb_cache_first = This->next;
3507 LeaveCriticalSection(&cache_section);
3508 HeapFree(GetProcessHeap(), 0, This->path);
3510 /* FIXME destroy child objects */
3511 TRACE(" destroying ITypeLib(%p)\n",This);
3515 SysFreeString(This->Name);
3519 if (This->DocString)
3521 SysFreeString(This->DocString);
3522 This->DocString = NULL;
3527 SysFreeString(This->HelpFile);
3528 This->HelpFile = NULL;
3531 if (This->HelpStringDll)
3533 SysFreeString(This->HelpStringDll);
3534 This->HelpStringDll = NULL;
3537 if (This->pTypeInfo) /* can be NULL */
3538 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3539 HeapFree(GetProcessHeap(),0,This);
3546 /* ITypeLib::GetTypeInfoCount
3548 * Returns the number of type descriptions in the type library
3550 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3552 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3553 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3554 return This->TypeInfoCount;
3557 /* ITypeLib::GetTypeInfo
3559 * retrieves the specified type description in the library.
3561 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3564 ITypeInfo **ppTInfo)
3568 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3569 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3571 TRACE("(%p)->(index=%d)\n", This, index);
3573 if (!ppTInfo) return E_INVALIDARG;
3575 /* search element n in list */
3576 for(i=0; i < index; i++)
3578 pTypeInfo = pTypeInfo->next;
3581 TRACE("-- element not found\n");
3582 return TYPE_E_ELEMENTNOTFOUND;
3586 *ppTInfo = (ITypeInfo *) pTypeInfo;
3588 ITypeInfo_AddRef(*ppTInfo);
3589 TRACE("-- found (%p)\n",*ppTInfo);
3594 /* ITypeLibs::GetTypeInfoType
3596 * Retrieves the type of a type description.
3598 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3603 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3605 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3607 if ((ITypeLib2_fnGetTypeInfoCount(iface) < index + 1) || (index < 0))
3608 return TYPE_E_ELEMENTNOTFOUND;
3610 TRACE("(%p) index %d\n", This, index);
3612 if(!pTKind) return E_INVALIDARG;
3614 /* search element n in list */
3615 for(i=0; i < index; i++)
3619 TRACE("-- element not found\n");
3620 return TYPE_E_ELEMENTNOTFOUND;
3622 pTInfo = pTInfo->next;
3625 *pTKind = pTInfo->TypeAttr.typekind;
3626 TRACE("-- found Type (%d)\n", *pTKind);
3630 /* ITypeLib::GetTypeInfoOfGuid
3632 * Retrieves the type description that corresponds to the specified GUID.
3635 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3638 ITypeInfo **ppTInfo)
3640 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3641 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3643 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3647 WARN("-- element not found\n");
3648 return TYPE_E_ELEMENTNOTFOUND;
3651 /* search linked list for guid */
3652 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3654 pTypeInfo = pTypeInfo->next;
3658 /* end of list reached */
3659 WARN("-- element not found\n");
3660 return TYPE_E_ELEMENTNOTFOUND;
3664 TRACE("-- found (%p, %s)\n",
3666 debugstr_w(pTypeInfo->Name));
3668 *ppTInfo = (ITypeInfo*)pTypeInfo;
3669 ITypeInfo_AddRef(*ppTInfo);
3673 /* ITypeLib::GetLibAttr
3675 * Retrieves the structure that contains the library's attributes.
3678 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3680 LPTLIBATTR *ppTLibAttr)
3682 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3683 TRACE("(%p)\n",This);
3684 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3685 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3689 /* ITypeLib::GetTypeComp
3691 * Enables a client compiler to bind to a library's types, variables,
3692 * constants, and global functions.
3695 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3697 ITypeComp **ppTComp)
3699 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3701 TRACE("(%p)->(%p)\n",This,ppTComp);
3702 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3703 ITypeComp_AddRef(*ppTComp);
3708 /* ITypeLib::GetDocumentation
3710 * Retrieves the library's documentation string, the complete Help file name
3711 * and path, and the context identifier for the library Help topic in the Help
3714 * On a successful return all non-null BSTR pointers will have been set,
3717 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3721 BSTR *pBstrDocString,
3722 DWORD *pdwHelpContext,
3723 BSTR *pBstrHelpFile)
3725 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3727 HRESULT result = E_INVALIDARG;
3732 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3734 pBstrName, pBstrDocString,
3735 pdwHelpContext, pBstrHelpFile);
3739 /* documentation for the typelib */
3744 if(!(*pBstrName = SysAllocString(This->Name)))
3752 if (This->DocString)
3754 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3757 else if (This->Name)
3759 if(!(*pBstrDocString = SysAllocString(This->Name)))
3763 *pBstrDocString = NULL;
3767 *pdwHelpContext = This->dwHelpContext;
3773 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3777 *pBstrHelpFile = NULL;
3784 /* for a typeinfo */
3785 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3787 if(SUCCEEDED(result))
3789 result = ITypeInfo_GetDocumentation(pTInfo,
3793 pdwHelpContext, pBstrHelpFile);
3795 ITypeInfo_Release(pTInfo);
3800 if (pBstrDocString) SysFreeString (*pBstrDocString);
3802 if (pBstrName) SysFreeString (*pBstrName);
3804 return STG_E_INSUFFICIENTMEMORY;
3809 * Indicates whether a passed-in string contains the name of a type or member
3810 * described in the library.
3813 static HRESULT WINAPI ITypeLib2_fnIsName(
3819 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3820 ITypeInfoImpl *pTInfo;
3821 TLBFuncDesc *pFInfo;
3824 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3826 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3830 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3831 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3832 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3833 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3834 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3835 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3836 goto ITypeLib2_fnIsName_exit;
3838 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3839 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3844 ITypeLib2_fnIsName_exit:
3845 TRACE("(%p)slow! search for %s: %s found!\n", This,
3846 debugstr_w(szNameBuf), *pfName?"NOT":"");
3851 /* ITypeLib::FindName
3853 * Finds occurrences of a type description in a type library. This may be used
3854 * to quickly verify that a name exists in a type library.
3857 static HRESULT WINAPI ITypeLib2_fnFindName(
3861 ITypeInfo **ppTInfo,
3865 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3866 ITypeInfoImpl *pTInfo;
3867 TLBFuncDesc *pFInfo;
3870 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3872 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3873 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3874 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3875 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3876 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3877 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3878 goto ITypeLib2_fnFindName_exit;
3881 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3882 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3884 ITypeLib2_fnFindName_exit:
3885 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3886 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3889 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3890 This, *pcFound, debugstr_w(szNameBuf), j);
3897 /* ITypeLib::ReleaseTLibAttr
3899 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3902 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3904 TLIBATTR *pTLibAttr)
3906 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3907 TRACE("freeing (%p)\n",This);
3908 HeapFree(GetProcessHeap(),0,pTLibAttr);
3912 /* ITypeLib2::GetCustData
3914 * gets the custom data
3916 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3921 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3922 TLBCustData *pCData;
3924 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3926 if( IsEqualIID(guid, &pCData->guid)) break;
3929 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3933 VariantInit( pVarVal);
3934 VariantCopy( pVarVal, &pCData->data);
3937 return E_INVALIDARG; /* FIXME: correct? */
3940 /* ITypeLib2::GetLibStatistics
3942 * Returns statistics about a type library that are required for efficient
3943 * sizing of hash tables.
3946 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3948 ULONG *pcUniqueNames,
3949 ULONG *pcchUniqueNames)
3951 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3953 FIXME("(%p): stub!\n", This);
3955 if(pcUniqueNames) *pcUniqueNames=1;
3956 if(pcchUniqueNames) *pcchUniqueNames=1;
3960 /* ITypeLib2::GetDocumentation2
3962 * Retrieves the library's documentation string, the complete Help file name
3963 * and path, the localization context to use, and the context ID for the
3964 * library Help topic in the Help file.
3967 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3971 BSTR *pbstrHelpString,
3972 DWORD *pdwHelpStringContext,
3973 BSTR *pbstrHelpStringDll)
3975 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3979 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3981 /* the help string should be obtained from the helpstringdll,
3982 * using the _DLLGetDocumentation function, based on the supplied
3983 * lcid. Nice to do sometime...
3987 /* documentation for the typelib */
3989 *pbstrHelpString=SysAllocString(This->DocString);
3990 if(pdwHelpStringContext)
3991 *pdwHelpStringContext=This->dwHelpContext;
3992 if(pbstrHelpStringDll)
3993 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3999 /* for a typeinfo */
4000 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4002 if(SUCCEEDED(result))
4004 ITypeInfo2 * pTInfo2;
4005 result = ITypeInfo_QueryInterface(pTInfo,
4007 (LPVOID*) &pTInfo2);
4009 if(SUCCEEDED(result))
4011 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4015 pdwHelpStringContext,
4016 pbstrHelpStringDll);
4018 ITypeInfo2_Release(pTInfo2);
4021 ITypeInfo_Release(pTInfo);
4027 /* ITypeLib2::GetAllCustData
4029 * Gets all custom data items for the library.
4032 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4034 CUSTDATA *pCustData)
4036 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4037 TLBCustData *pCData;
4039 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4040 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4041 if(pCustData->prgCustData ){
4042 pCustData->cCustData=This->ctCustData;
4043 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4044 pCustData->prgCustData[i].guid=pCData->guid;
4045 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4048 ERR(" OUT OF MEMORY!\n");
4049 return E_OUTOFMEMORY;
4054 static const ITypeLib2Vtbl tlbvt = {
4055 ITypeLib2_fnQueryInterface,
4057 ITypeLib2_fnRelease,
4058 ITypeLib2_fnGetTypeInfoCount,
4059 ITypeLib2_fnGetTypeInfo,
4060 ITypeLib2_fnGetTypeInfoType,
4061 ITypeLib2_fnGetTypeInfoOfGuid,
4062 ITypeLib2_fnGetLibAttr,
4063 ITypeLib2_fnGetTypeComp,
4064 ITypeLib2_fnGetDocumentation,
4066 ITypeLib2_fnFindName,
4067 ITypeLib2_fnReleaseTLibAttr,
4069 ITypeLib2_fnGetCustData,
4070 ITypeLib2_fnGetLibStatistics,
4071 ITypeLib2_fnGetDocumentation2,
4072 ITypeLib2_fnGetAllCustData
4076 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4078 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4080 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4083 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4085 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4087 return ITypeLib2_AddRef((ITypeLib2 *)This);
4090 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4092 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4094 return ITypeLib2_Release((ITypeLib2 *)This);
4097 static HRESULT WINAPI ITypeLibComp_fnBind(
4102 ITypeInfo ** ppTInfo,
4103 DESCKIND * pDescKind,
4106 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4107 ITypeInfoImpl *pTypeInfo;
4109 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4111 *pDescKind = DESCKIND_NONE;
4112 pBindPtr->lptcomp = NULL;
4115 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4117 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4119 /* FIXME: check wFlags here? */
4120 /* FIXME: we should use a hash table to look this info up using lHash
4121 * instead of an O(n) search */
4122 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4123 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4125 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4127 *pDescKind = DESCKIND_TYPECOMP;
4128 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4129 ITypeComp_AddRef(pBindPtr->lptcomp);
4130 TRACE("module or enum: %s\n", debugstr_w(szName));
4135 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4136 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4138 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4141 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4142 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4144 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4149 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4150 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4152 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4154 ITypeInfo *subtypeinfo;
4156 DESCKIND subdesckind;
4158 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4159 &subtypeinfo, &subdesckind, &subbindptr);
4160 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4162 TYPEDESC tdesc_appobject =
4165 (TYPEDESC *)pTypeInfo->hreftype
4169 const VARDESC vardesc_appobject =
4172 NULL, /* lpstrSchema */
4187 VAR_STATIC /* varkind */
4190 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4192 /* cleanup things filled in by Bind call so we can put our
4193 * application object data in there instead */
4194 switch (subdesckind)
4196 case DESCKIND_FUNCDESC:
4197 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4199 case DESCKIND_VARDESC:
4200 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4205 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4207 if (pTypeInfo->hreftype == -1)
4208 FIXME("no hreftype for interface %p\n", pTypeInfo);
4210 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4214 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4215 *ppTInfo = (ITypeInfo *)pTypeInfo;
4216 ITypeInfo_AddRef(*ppTInfo);
4222 TRACE("name not found %s\n", debugstr_w(szName));
4226 static HRESULT WINAPI ITypeLibComp_fnBindType(
4230 ITypeInfo ** ppTInfo,
4231 ITypeComp ** ppTComp)
4233 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4237 static const ITypeCompVtbl tlbtcvt =
4240 ITypeLibComp_fnQueryInterface,
4241 ITypeLibComp_fnAddRef,
4242 ITypeLibComp_fnRelease,
4244 ITypeLibComp_fnBind,
4245 ITypeLibComp_fnBindType
4248 /*================== ITypeInfo(2) Methods ===================================*/
4249 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4251 ITypeInfoImpl * pTypeInfoImpl;
4253 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4256 pTypeInfoImpl->lpVtbl = &tinfvt;
4257 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4258 pTypeInfoImpl->ref=1;
4259 pTypeInfoImpl->hreftype = -1;
4260 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4261 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4263 TRACE("(%p)\n", pTypeInfoImpl);
4264 return (ITypeInfo2*) pTypeInfoImpl;
4267 /* ITypeInfo::QueryInterface
4269 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4274 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4276 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4279 if(IsEqualIID(riid, &IID_IUnknown) ||
4280 IsEqualIID(riid,&IID_ITypeInfo)||
4281 IsEqualIID(riid,&IID_ITypeInfo2))
4285 ITypeInfo_AddRef(iface);
4286 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4289 TRACE("-- Interface: E_NOINTERFACE\n");
4290 return E_NOINTERFACE;
4293 /* ITypeInfo::AddRef
4295 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4297 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4298 ULONG ref = InterlockedIncrement(&This->ref);
4300 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4302 TRACE("(%p)->ref is %lu\n",This, ref);
4306 /* ITypeInfo::Release
4308 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4310 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4311 ULONG ref = InterlockedDecrement(&This->ref);
4313 TRACE("(%p)->(%lu)\n",This, ref);
4316 /* We don't release ITypeLib when ref=0 because
4317 it means that function is called by ITypeLib2_Release */
4318 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4320 static int once = 0;
4324 FIXME("destroy child objects\n");
4327 TRACE("destroying ITypeInfo(%p)\n",This);
4330 SysFreeString(This->Name);
4334 if (This->DocString)
4336 SysFreeString(This->DocString);
4337 This->DocString = 0;
4342 SysFreeString(This->DllName);
4348 ITypeInfo_Release((ITypeInfo*)This->next);
4351 HeapFree(GetProcessHeap(),0,This);
4357 /* ITypeInfo::GetTypeAttr
4359 * Retrieves a TYPEATTR structure that contains the attributes of the type
4363 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4364 LPTYPEATTR *ppTypeAttr)
4366 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4369 TRACE("(%p)\n",This);
4371 size = sizeof(**ppTypeAttr);
4372 if (This->TypeAttr.typekind == TKIND_ALIAS)
4373 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4375 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4377 return E_OUTOFMEMORY;
4379 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4381 if (This->TypeAttr.typekind == TKIND_ALIAS)
4382 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4383 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4385 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4386 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4388 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4389 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4394 /* ITypeInfo::GetTypeComp
4396 * Retrieves the ITypeComp interface for the type description, which enables a
4397 * client compiler to bind to the type description's members.
4400 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4401 ITypeComp * *ppTComp)
4403 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4405 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4407 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4408 ITypeComp_AddRef(*ppTComp);
4412 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4414 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4415 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4416 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4420 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4422 memcpy(dest, src, sizeof(ELEMDESC));
4423 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4424 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4426 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4427 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4428 *buffer += sizeof(PARAMDESCEX);
4429 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4430 VariantInit(&pparamdescex_dest->varDefaultValue);
4431 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4432 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4435 dest->u.paramdesc.pparamdescex = NULL;
4439 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4441 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4442 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4445 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4449 SIZE_T size = sizeof(*src);
4453 size += sizeof(*src->lprgscode) * src->cScodes;
4454 size += TLB_SizeElemDesc(&src->elemdescFunc);
4455 for (i = 0; i < src->cParams; i++)
4457 size += sizeof(ELEMDESC);
4458 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4461 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4462 if (!dest) return E_OUTOFMEMORY;
4464 memcpy(dest, src, sizeof(FUNCDESC));
4465 buffer = (char *)(dest + 1);
4467 dest->lprgscode = (SCODE *)buffer;
4468 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4469 buffer += sizeof(*src->lprgscode) * src->cScodes;
4471 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4474 SysFreeString((BSTR)dest);
4478 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4479 buffer += sizeof(ELEMDESC) * src->cParams;
4480 for (i = 0; i < src->cParams; i++)
4482 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4488 /* undo the above actions */
4489 for (i = i - 1; i >= 0; i--)
4490 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4491 TLB_FreeElemDesc(&dest->elemdescFunc);
4492 SysFreeString((BSTR)dest);
4496 /* special treatment for dispinterfaces: this makes functions appear
4497 * to return their [retval] value when it is really returning an
4499 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4501 if (dest->cParams &&
4502 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4504 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4505 if (elemdesc->tdesc.vt != VT_PTR)
4507 ERR("elemdesc should have started with VT_PTR instead of:\n");
4509 dump_ELEMDESC(elemdesc);
4510 return E_UNEXPECTED;
4513 /* copy last parameter to the return value. we are using a flat
4514 * buffer so there is no danger of leaking memory in
4516 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4518 /* remove the last parameter */
4522 /* otherwise this function is made to appear to have no return
4524 dest->elemdescFunc.tdesc.vt = VT_VOID;
4532 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4534 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4535 const TLBFuncDesc *pFDesc;
4538 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4543 *ppFuncDesc = &pFDesc->funcdesc;
4547 return E_INVALIDARG;
4550 /* internal function to make the inherited interfaces' methods appear
4551 * part of the interface */
4552 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
4553 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs)
4555 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4558 UINT implemented_funcs = 0;
4563 for (i = 0; i < This->TypeAttr.cImplTypes; i++)
4566 ITypeInfo *pSubTypeInfo;
4569 hr = ITypeInfo_GetRefTypeOfImplType(iface, i, &href);
4572 hr = ITypeInfo_GetRefTypeInfo(iface, href, &pSubTypeInfo);
4576 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
4580 implemented_funcs += sub_funcs;
4581 ITypeInfo_Release(pSubTypeInfo);
4587 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
4589 if (index < implemented_funcs)
4590 return E_INVALIDARG;
4591 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
4595 /* ITypeInfo::GetFuncDesc
4597 * Retrieves the FUNCDESC structure that contains information about a
4598 * specified function.
4601 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4602 LPFUNCDESC *ppFuncDesc)
4604 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4605 const FUNCDESC *internal_funcdesc;
4608 TRACE("(%p) index %d\n", This, index);
4610 if ((This->TypeAttr.typekind == TKIND_DISPATCH) &&
4611 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
4612 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
4613 &internal_funcdesc, NULL);
4615 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
4616 &internal_funcdesc);
4619 WARN("description for function %d not found\n", index);
4623 return TLB_AllocAndInitFuncDesc(
4626 This->TypeAttr.typekind == TKIND_DISPATCH);
4629 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4633 SIZE_T size = sizeof(*src);
4636 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4637 if (src->varkind == VAR_CONST)
4638 size += sizeof(VARIANT);
4639 size += TLB_SizeElemDesc(&src->elemdescVar);
4641 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4642 if (!dest) return E_OUTOFMEMORY;
4645 buffer = (char *)(dest + 1);
4646 if (src->lpstrSchema)
4649 dest->lpstrSchema = (LPOLESTR)buffer;
4650 len = strlenW(src->lpstrSchema);
4651 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4652 buffer += (len + 1) * sizeof(WCHAR);
4655 if (src->varkind == VAR_CONST)
4659 dest->u.lpvarValue = (VARIANT *)buffer;
4660 *dest->u.lpvarValue = *src->u.lpvarValue;
4661 buffer += sizeof(VARIANT);
4662 VariantInit(dest->u.lpvarValue);
4663 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4666 SysFreeString((BSTR)dest_ptr);
4670 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4673 if (src->varkind == VAR_CONST)
4674 VariantClear(dest->u.lpvarValue);
4675 SysFreeString((BSTR)dest);
4682 /* ITypeInfo::GetVarDesc
4684 * Retrieves a VARDESC structure that describes the specified variable.
4687 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4688 LPVARDESC *ppVarDesc)
4690 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4692 const TLBVarDesc *pVDesc;
4694 TRACE("(%p) index %d\n", This, index);
4696 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4700 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4702 return E_INVALIDARG;
4705 /* ITypeInfo_GetNames
4707 * Retrieves the variable with the specified member ID (or the name of the
4708 * property or method and its parameters) that correspond to the specified
4711 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4712 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4714 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4715 const TLBFuncDesc *pFDesc;
4716 const TLBVarDesc *pVDesc;
4718 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4719 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4722 /* function found, now return function and parameter names */
4723 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4726 *rgBstrNames=SysAllocString(pFDesc->Name);
4728 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4734 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4737 *rgBstrNames=SysAllocString(pVDesc->Name);
4742 if(This->TypeAttr.cImplTypes &&
4743 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4744 /* recursive search */
4747 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4749 if(SUCCEEDED(result))
4751 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4752 ITypeInfo_Release(pTInfo);
4755 WARN("Could not search inherited interface!\n");
4759 WARN("no names found\n");
4762 return TYPE_E_ELEMENTNOTFOUND;
4769 /* ITypeInfo::GetRefTypeOfImplType
4771 * If a type description describes a COM class, it retrieves the type
4772 * description of the implemented interface types. For an interface,
4773 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4777 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4782 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4785 const TLBImplType *pImpl = This->impltypelist;
4787 TRACE("(%p) index %d\n", This, index);
4788 if (TRACE_ON(ole)) dump_TypeInfo(This);
4792 /* only valid on dual interfaces;
4793 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4795 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4797 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4798 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4804 hr = TYPE_E_ELEMENTNOTFOUND;
4809 /* get element n from linked list */
4810 for(i=0; pImpl && i<index; i++)
4812 pImpl = pImpl->next;
4816 *pRefType = pImpl->hRef;
4818 hr = TYPE_E_ELEMENTNOTFOUND;
4824 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4826 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4832 /* ITypeInfo::GetImplTypeFlags
4834 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4835 * or base interface in a type description.
4837 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4838 UINT index, INT *pImplTypeFlags)
4840 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4844 TRACE("(%p) index %d\n", This, index);
4845 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4846 i++, pImpl=pImpl->next)
4848 if(i==index && pImpl){
4849 *pImplTypeFlags=pImpl->implflags;
4853 return TYPE_E_ELEMENTNOTFOUND;
4857 * Maps between member names and member IDs, and parameter names and
4860 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4861 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4863 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4864 const TLBFuncDesc *pFDesc;
4865 const TLBVarDesc *pVDesc;
4869 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4872 /* init out parameters in case of failure */
4873 for (i = 0; i < cNames; i++)
4874 pMemId[i] = MEMBERID_NIL;
4876 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4878 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4879 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4880 for(i=1; i < cNames; i++){
4881 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4882 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4884 if( j<pFDesc->funcdesc.cParams)
4887 ret=DISP_E_UNKNOWNNAME;
4889 TRACE("-- 0x%08lx\n", ret);
4893 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4894 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4895 if(cNames) *pMemId=pVDesc->vardesc.memid;
4899 /* not found, see if it can be found in an inherited interface */
4900 if(This->TypeAttr.cImplTypes) {
4901 /* recursive search */
4903 ret=ITypeInfo_GetRefTypeInfo(iface,
4904 This->impltypelist->hRef, &pTInfo);
4906 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4907 ITypeInfo_Release(pTInfo);
4910 WARN("Could not search inherited interface!\n");
4912 WARN("no names found\n");
4913 return DISP_E_UNKNOWNNAME;
4916 /* ITypeInfo::Invoke
4918 * Invokes a method, or accesses a property of an object, that implements the
4919 * interface described by the type description.
4922 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4925 if (TRACE_ON(ole)) {
4927 TRACE("Calling %p(",func);
4928 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4940 res = func(args[0]);
4943 res = func(args[0],args[1]);
4946 res = func(args[0],args[1],args[2]);
4949 res = func(args[0],args[1],args[2],args[3]);
4952 res = func(args[0],args[1],args[2],args[3],args[4]);
4955 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4958 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4961 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4964 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4967 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4970 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4973 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]);
4976 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]);
4979 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]);
4982 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]);
4985 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]);
4988 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]);
4991 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]);
4994 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]);
4997 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]);
5000 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]);
5003 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]);
5006 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]);
5009 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
5015 FIXME("unsupported calling convention %d\n",callconv);
5019 TRACE("returns %08lx\n",res);
5023 extern int _argsize(DWORD vt);
5025 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5028 ITypeInfo *tinfo2 = NULL;
5029 TYPEATTR *tattr = NULL;
5031 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5034 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
5036 tdesc->u.hreftype, hr);
5039 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5042 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
5043 ITypeInfo_Release(tinfo2);
5047 switch (tattr->typekind)
5054 tdesc = &tattr->tdescAlias;
5055 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5058 case TKIND_INTERFACE:
5059 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5065 case TKIND_DISPATCH:
5074 FIXME("TKIND_RECORD unhandled.\n");
5079 FIXME("TKIND_UNION unhandled.\n");
5084 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5088 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5089 ITypeInfo_Release(tinfo2);
5093 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5097 /* enforce only one level of pointer indirection */
5098 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5100 tdesc = tdesc->u.lptdesc;
5102 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5103 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5104 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5105 if ((tdesc->vt == VT_USERDEFINED) ||
5106 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5108 VARTYPE vt_userdefined = 0;
5109 const TYPEDESC *tdesc_userdefined = tdesc;
5110 if (tdesc->vt == VT_PTR)
5112 vt_userdefined = VT_BYREF;
5113 tdesc_userdefined = tdesc->u.lptdesc;
5115 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5117 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5118 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5120 *vt |= vt_userdefined;
5132 case VT_USERDEFINED:
5133 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5140 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5141 hr = DISP_E_BADVARTYPE;
5145 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5154 /***********************************************************************
5155 * DispCallFunc (OLEAUT32.@)
5157 * Invokes a function of the specifed calling convention, passing the
5158 * specified arguments and returns the result.
5161 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5162 * oVft [I] The offset in the vtable. See notes.
5163 * cc [I] Calling convention of the function to call.
5164 * vtReturn [I] The return type of the function.
5165 * cActuals [I] Number of parameters.
5166 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5167 * prgpvarg [I] The arguments to pass.
5168 * pvargResult [O] The return value of the function. Can be NULL.
5172 * Failure: HRESULT code.
5175 * The HRESULT return value of this function is not affected by the return
5176 * value of the user supplied function, which is returned in pvargResult.
5178 * If pvInstance is NULL then a non-object function is to be called and oVft
5179 * is the address of the function to call.
5181 * The cc parameter can be one of the following values:
5194 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5195 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5197 int i, argsize, argspos;
5201 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5202 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5203 pvargResult, V_VT(pvargResult));
5207 argsize++; /* for This pointer */
5209 for (i=0;i<cActuals;i++)
5211 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5212 dump_Variant(prgpvarg[i]);
5213 argsize += _argsize(prgvt[i]);
5215 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5220 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5224 for (i=0;i<cActuals;i++)
5226 VARIANT *arg = prgpvarg[i];
5227 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5228 if (prgvt[i] == VT_VARIANT)
5229 memcpy(&args[argspos], arg, _argsize(prgvt[i]) * sizeof(DWORD));
5231 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5232 argspos += _argsize(prgvt[i]);
5237 FARPROC *vtable = *(FARPROC**)pvInstance;
5238 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5241 /* if we aren't invoking an object then the function pointer is stored
5243 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5245 if (pvargResult && (vtReturn != VT_EMPTY))
5247 TRACE("Method returned 0x%08lx\n",hres);
5248 V_VT(pvargResult) = vtReturn;
5249 V_UI4(pvargResult) = hres;
5252 HeapFree(GetProcessHeap(),0,args);
5256 #define INVBUF_ELEMENT_SIZE \
5257 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5258 #define INVBUF_GET_ARG_ARRAY(buffer, params) \
5259 ((VARIANTARG *)(buffer))
5260 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5261 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
5262 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
5263 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
5264 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
5265 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
5267 static HRESULT WINAPI ITypeInfo_fnInvoke(
5272 DISPPARAMS *pDispParams,
5273 VARIANT *pVarResult,
5274 EXCEPINFO *pExcepInfo,
5277 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5279 unsigned int var_index;
5282 const TLBFuncDesc *pFuncInfo;
5284 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5285 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5290 ERR("NULL pDispParams not allowed\n");
5291 return E_INVALIDARG;
5294 dump_DispParms(pDispParams);
5296 if (pDispParams->cNamedArgs > pDispParams->cArgs)
5298 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
5299 pDispParams->cNamedArgs, pDispParams->cArgs);
5300 return E_INVALIDARG;
5303 /* we do this instead of using GetFuncDesc since it will return a fake
5304 * FUNCDESC for dispinterfaces and we want the real function description */
5305 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5306 if ((memid == pFuncInfo->funcdesc.memid) &&
5307 (wFlags & pFuncInfo->funcdesc.invkind))
5311 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5315 TRACE("invoking:\n");
5316 dump_TLBFuncDescOne(pFuncInfo);
5319 switch (func_desc->funckind) {
5320 case FUNC_PUREVIRTUAL:
5321 case FUNC_VIRTUAL: {
5322 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
5324 VARIANT retval; /* pointer for storing byref retvals in */
5325 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
5326 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
5327 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
5330 for (i = 0; i < func_desc->cParams; i++)
5332 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5333 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
5338 TRACE("changing args\n");
5339 for (i = 0; i < func_desc->cParams; i++)
5341 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5343 if (wParamFlags & PARAMFLAG_FRETVAL)
5345 /* note: this check is placed so that if the caller passes
5346 * in a VARIANTARG for the retval we just ignore it, like
5348 if (i == func_desc->cParams - 1)
5351 arg = prgpvarg[i] = &rgvarg[i];
5352 memset(arg, 0, sizeof(*arg));
5353 V_VT(arg) = rgvt[i];
5354 memset(&retval, 0, sizeof(retval));
5355 V_BYREF(arg) = &retval;
5359 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
5360 hres = E_UNEXPECTED;
5364 else if (i < pDispParams->cArgs)
5366 VARIANTARG *src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5367 dump_Variant(src_arg);
5369 if (rgvt[i] == VT_VARIANT)
5370 hres = VariantCopy(&rgvarg[i], src_arg);
5371 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
5373 if (rgvt[i] == V_VT(src_arg))
5374 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
5377 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5378 hres = VariantCopy(&missing_arg[i], src_arg);
5379 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
5381 V_VT(&rgvarg[i]) = rgvt[i];
5383 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
5385 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5386 V_VT(&missing_arg[i]) = V_VT(src_arg);
5387 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
5388 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
5389 V_VT(&rgvarg[i]) = rgvt[i];
5391 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
5393 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
5394 V_VT(&rgvarg[i]) = rgvt[i];
5398 /* FIXME: this doesn't work for VT_BYREF arguments if
5399 * they are not the same type as in the paramdesc */
5400 V_VT(&rgvarg[i]) = V_VT(src_arg);
5401 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
5402 V_VT(&rgvarg[i]) = rgvt[i];
5407 ERR("failed to convert param %d to %s%s from %s%s\n", i,
5408 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
5409 debugstr_VT(src_arg), debugstr_VF(src_arg));
5412 prgpvarg[i] = &rgvarg[i];
5414 else if (wParamFlags & PARAMFLAG_FOPT)
5417 arg = prgpvarg[i] = &rgvarg[i];
5418 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5420 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
5426 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
5427 V_VT(arg) = VT_VARIANT | VT_BYREF;
5428 V_VARIANTREF(arg) = &missing_arg[i];
5429 V_VT(V_VARIANTREF(arg)) = VT_ERROR;
5430 V_ERROR(V_VARIANTREF(arg)) = DISP_E_PARAMNOTFOUND;
5435 hres = DISP_E_BADPARAMCOUNT;
5439 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5440 if (func_desc->cParamsOpt < 0)
5442 FIXME("Does not support safearray optional parameters\n");
5443 hres = DISP_E_BADPARAMCOUNT;
5444 goto func_fail; /* FIXME: we don't free changed types here */
5447 /* VT_VOID is a special case for return types, so it is not
5448 * handled in the general function */
5449 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
5450 V_VT(&varresult) = VT_EMPTY;
5453 V_VT(&varresult) = 0;
5454 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
5455 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
5458 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
5459 V_VT(&varresult), func_desc->cParams, rgvt,
5460 prgpvarg, &varresult);
5462 for (i = 0; i < func_desc->cParams; i++)
5464 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5465 if (wParamFlags & PARAMFLAG_FRETVAL)
5469 TRACE("[retval] value: ");
5470 dump_Variant(prgpvarg[i]);
5475 VariantInit(pVarResult);
5476 /* deref return value */
5477 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
5480 /* free data stored in varresult. Note that
5481 * VariantClear doesn't do what we want because we are
5482 * working with byref types. */
5483 /* FIXME: clear safearrays, bstrs, records and
5484 * variants here too */
5485 if ((V_VT(prgpvarg[i]) == (VT_UNKNOWN | VT_BYREF)) ||
5486 (V_VT(prgpvarg[i]) == (VT_DISPATCH | VT_BYREF)))
5488 if(*V_UNKNOWNREF(prgpvarg[i]))
5489 IUnknown_Release(*V_UNKNOWNREF(prgpvarg[i]));
5493 else if (i < pDispParams->cArgs)
5495 if (wParamFlags & PARAMFLAG_FOUT)
5497 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - i];
5499 if ((rgvt[i] == VT_BYREF) && (V_VT(arg) != VT_BYREF))
5500 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
5504 ERR("failed to convert param %d to vt %d\n", i,
5505 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - i]));
5509 VariantClear(&rgvarg[i]);
5511 else if (wParamFlags & PARAMFLAG_FOPT)
5513 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
5514 VariantClear(&rgvarg[i]);
5518 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
5520 WARN("invoked function failed with error 0x%08lx\n", V_ERROR(&varresult));
5521 hres = DISP_E_EXCEPTION;
5522 if (pExcepInfo) pExcepInfo->scode = V_ERROR(&varresult);
5526 HeapFree(GetProcessHeap(), 0, buffer);
5529 case FUNC_DISPATCH: {
5532 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5533 if (SUCCEEDED(hres)) {
5534 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5535 hres = IDispatch_Invoke(
5536 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5537 pVarResult,pExcepInfo,pArgErr
5540 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5541 IDispatch_Release(disp);
5543 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5547 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5552 TRACE("-- 0x%08lx\n", hres);
5555 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5558 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5559 if(FAILED(hres)) return hres;
5561 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5562 dump_VARDESC(var_desc);
5563 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5567 /* not found, look for it in inherited interfaces */
5568 ITypeInfo2_GetTypeKind(iface, &type_kind);
5569 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5571 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5572 /* recursive search */
5574 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5575 if(SUCCEEDED(hres)){
5576 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5577 ITypeInfo_Release(pTInfo);
5580 WARN("Could not search inherited interface!\n");
5583 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5584 return DISP_E_MEMBERNOTFOUND;
5587 /* ITypeInfo::GetDocumentation
5589 * Retrieves the documentation string, the complete Help file name and path,
5590 * and the context ID for the Help topic for a specified type description.
5592 * (Can be tested by the Visual Basic Editor in Word for instance.)
5594 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5595 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5596 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5598 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5599 const TLBFuncDesc *pFDesc;
5600 const TLBVarDesc *pVDesc;
5601 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5602 " HelpContext(%p) HelpFile(%p)\n",
5603 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5604 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5606 *pBstrName=SysAllocString(This->Name);
5608 *pBstrDocString=SysAllocString(This->DocString);
5610 *pdwHelpContext=This->dwHelpContext;
5612 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5614 }else {/* for a member */
5615 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5616 if(pFDesc->funcdesc.memid==memid){
5618 *pBstrName = SysAllocString(pFDesc->Name);
5620 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5622 *pdwHelpContext=pFDesc->helpcontext;
5625 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5626 if(pVDesc->vardesc.memid==memid){
5628 *pBstrName = SysAllocString(pVDesc->Name);
5630 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5632 *pdwHelpContext=pVDesc->HelpContext;
5637 if(This->TypeAttr.cImplTypes &&
5638 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5639 /* recursive search */
5642 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5644 if(SUCCEEDED(result)) {
5645 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
5646 pBstrDocString, pdwHelpContext, pBstrHelpFile);
5647 ITypeInfo_Release(pTInfo);
5650 WARN("Could not search inherited interface!\n");
5653 WARN("member %ld not found\n", memid);
5654 return TYPE_E_ELEMENTNOTFOUND;
5657 /* ITypeInfo::GetDllEntry
5659 * Retrieves a description or specification of an entry point for a function
5662 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5663 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5666 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5667 const TLBFuncDesc *pFDesc;
5669 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5671 if (pBstrDllName) *pBstrDllName = NULL;
5672 if (pBstrName) *pBstrName = NULL;
5673 if (pwOrdinal) *pwOrdinal = 0;
5675 if (This->TypeAttr.typekind != TKIND_MODULE)
5676 return TYPE_E_BADMODULEKIND;
5678 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5679 if(pFDesc->funcdesc.memid==memid){
5680 dump_TypeInfo(This);
5682 dump_TLBFuncDescOne(pFDesc);
5685 *pBstrDllName = SysAllocString(This->DllName);
5687 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5689 *pBstrName = SysAllocString(pFDesc->Entry);
5697 *pwOrdinal = (DWORD)pFDesc->Entry;
5700 return TYPE_E_ELEMENTNOTFOUND;
5703 /* ITypeInfo::GetRefTypeInfo
5705 * If a type description references other type descriptions, it retrieves
5706 * the referenced type descriptions.
5708 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5711 ITypeInfo **ppTInfo)
5713 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5714 HRESULT result = E_FAIL;
5716 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5718 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5719 ITypeInfo_AddRef(*ppTInfo);
5722 else if (hRefType == -1 &&
5723 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5724 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5726 /* when we meet a DUAL dispinterface, we must create the interface
5729 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5732 /* the interface version contains the same information as the dispinterface
5733 * copy the contents of the structs.
5735 *pTypeInfoImpl = *This;
5736 pTypeInfoImpl->ref = 1;
5738 /* change the type to interface */
5739 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5741 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5743 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5748 TLBRefType *pRefType;
5749 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5750 if(pRefType->reference == hRefType)
5754 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5755 if(pRefType && hRefType != -1) {
5756 ITypeLib *pTLib = NULL;
5758 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5760 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5762 if(pRefType->pImpTLInfo->pImpTypeLib) {
5763 TRACE("typeinfo in imported typelib that is already loaded\n");
5764 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5765 ITypeLib2_AddRef((ITypeLib*) pTLib);
5768 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5769 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5770 pRefType->pImpTLInfo->wVersionMajor,
5771 pRefType->pImpTLInfo->wVersionMinor,
5772 pRefType->pImpTLInfo->lcid,
5775 if(!SUCCEEDED(result)) {
5776 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5777 result=LoadTypeLib(libnam, &pTLib);
5778 SysFreeString(libnam);
5780 if(SUCCEEDED(result)) {
5781 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5782 ITypeLib2_AddRef(pTLib);
5786 if(SUCCEEDED(result)) {
5787 if(pRefType->index == TLB_REF_USE_GUID)
5788 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5792 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5796 ITypeLib2_Release(pTLib);
5800 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5801 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5805 /* ITypeInfo::AddressOfMember
5807 * Retrieves the addresses of static functions or variables, such as those
5810 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5811 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5813 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5819 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5821 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5825 module = LoadLibraryW(dll);
5828 ERR("couldn't load %s\n", debugstr_w(dll));
5830 if (entry) SysFreeString(entry);
5831 return STG_E_FILENOTFOUND;
5833 /* FIXME: store library somewhere where we can free it */
5838 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5839 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5840 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5842 *ppv = GetProcAddress(module, entryA);
5844 ERR("function not found %s\n", debugstr_a(entryA));
5846 HeapFree(GetProcessHeap(), 0, entryA);
5850 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5852 ERR("function not found %d\n", ordinal);
5856 if (entry) SysFreeString(entry);
5859 return TYPE_E_DLLFUNCTIONNOTFOUND;
5864 /* ITypeInfo::CreateInstance
5866 * Creates a new instance of a type that describes a component object class
5869 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5870 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
5872 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5876 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
5882 WARN("Not able to aggregate\n");
5883 return CLASS_E_NOAGGREGATION;
5886 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
5887 if(FAILED(hr)) return hr;
5889 if(pTA->typekind != TKIND_COCLASS)
5891 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
5897 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
5900 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
5901 TRACE("GetActiveObject rets %08lx\n", hr);
5904 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
5905 IUnknown_Release(pUnk);
5910 hr = CoCreateInstance(&pTA->guid, NULL,
5911 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
5915 ITypeInfo_ReleaseTypeAttr(iface, pTA);
5919 /* ITypeInfo::GetMops
5921 * Retrieves marshalling information.
5923 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5926 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5927 FIXME("(%p) stub!\n", This);
5931 /* ITypeInfo::GetContainingTypeLib
5933 * Retrieves the containing type library and the index of the type description
5934 * within that type library.
5936 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5937 ITypeLib * *ppTLib, UINT *pIndex)
5939 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5941 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5943 *pIndex=This->index;
5944 TRACE("returning pIndex=%d\n", *pIndex);
5948 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5949 ITypeLib2_AddRef(*ppTLib);
5950 TRACE("returning ppTLib=%p\n", *ppTLib);
5956 /* ITypeInfo::ReleaseTypeAttr
5958 * Releases a TYPEATTR previously returned by GetTypeAttr.
5961 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5962 TYPEATTR* pTypeAttr)
5964 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5965 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5966 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5969 /* ITypeInfo::ReleaseFuncDesc
5971 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5973 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5975 FUNCDESC *pFuncDesc)
5977 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5980 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5982 for (i = 0; i < pFuncDesc->cParams; i++)
5983 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5984 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5986 SysFreeString((BSTR)pFuncDesc);
5989 /* ITypeInfo::ReleaseVarDesc
5991 * Releases a VARDESC previously returned by GetVarDesc.
5993 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5996 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5997 TRACE("(%p)->(%p)\n", This, pVarDesc);
5999 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6000 if (pVarDesc->varkind == VAR_CONST)
6001 VariantClear(pVarDesc->u.lpvarValue);
6002 SysFreeString((BSTR)pVarDesc);
6005 /* ITypeInfo2::GetTypeKind
6007 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6010 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6011 TYPEKIND *pTypeKind)
6013 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6014 *pTypeKind=This->TypeAttr.typekind;
6015 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6019 /* ITypeInfo2::GetTypeFlags
6021 * Returns the type flags without any allocations. This returns a DWORD type
6022 * flag, which expands the type flags without growing the TYPEATTR (type
6026 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6028 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6029 *pTypeFlags=This->TypeAttr.wTypeFlags;
6030 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
6034 /* ITypeInfo2::GetFuncIndexOfMemId
6035 * Binds to a specific member based on a known DISPID, where the member name
6036 * is not known (for example, when binding to a default member).
6039 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
6040 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
6042 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6043 const TLBFuncDesc *pFuncInfo;
6047 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
6048 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
6054 result = TYPE_E_ELEMENTNOTFOUND;
6056 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
6057 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6061 /* TypeInfo2::GetVarIndexOfMemId
6063 * Binds to a specific member based on a known DISPID, where the member name
6064 * is not known (for example, when binding to a default member).
6067 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
6068 MEMBERID memid, UINT *pVarIndex)
6070 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6071 TLBVarDesc *pVarInfo;
6074 for(i=0, pVarInfo=This->varlist; pVarInfo &&
6075 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
6081 result = TYPE_E_ELEMENTNOTFOUND;
6083 TRACE("(%p) memid 0x%08lx -> %s\n", This,
6084 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
6088 /* ITypeInfo2::GetCustData
6090 * Gets the custom data
6092 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
6097 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6098 TLBCustData *pCData;
6100 for(pCData=This->pCustData; pCData; pCData = pCData->next)
6101 if( IsEqualIID(guid, &pCData->guid)) break;
6103 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6107 VariantInit( pVarVal);
6108 VariantCopy( pVarVal, &pCData->data);
6111 return E_INVALIDARG; /* FIXME: correct? */
6114 /* ITypeInfo2::GetFuncCustData
6116 * Gets the custom data
6118 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
6124 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6125 TLBCustData *pCData=NULL;
6126 TLBFuncDesc * pFDesc;
6128 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6129 pFDesc=pFDesc->next);
6132 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6133 if( IsEqualIID(guid, &pCData->guid)) break;
6135 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6138 VariantInit( pVarVal);
6139 VariantCopy( pVarVal, &pCData->data);
6142 return E_INVALIDARG; /* FIXME: correct? */
6145 /* ITypeInfo2::GetParamCustData
6147 * Gets the custom data
6149 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6156 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6157 TLBCustData *pCData=NULL;
6158 TLBFuncDesc * pFDesc;
6161 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6163 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6164 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6165 pCData = pCData->next)
6166 if( IsEqualIID(guid, &pCData->guid)) break;
6168 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6172 VariantInit( pVarVal);
6173 VariantCopy( pVarVal, &pCData->data);
6176 return E_INVALIDARG; /* FIXME: correct? */
6179 /* ITypeInfo2::GetVarCustData
6181 * Gets the custom data
6183 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6189 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6190 TLBCustData *pCData=NULL;
6191 TLBVarDesc * pVDesc;
6194 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6198 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6200 if( IsEqualIID(guid, &pCData->guid)) break;
6204 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6208 VariantInit( pVarVal);
6209 VariantCopy( pVarVal, &pCData->data);
6212 return E_INVALIDARG; /* FIXME: correct? */
6215 /* ITypeInfo2::GetImplCustData
6217 * Gets the custom data
6219 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6225 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6226 TLBCustData *pCData=NULL;
6227 TLBImplType * pRDesc;
6230 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6234 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6236 if( IsEqualIID(guid, &pCData->guid)) break;
6240 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6244 VariantInit( pVarVal);
6245 VariantCopy( pVarVal, &pCData->data);
6248 return E_INVALIDARG; /* FIXME: correct? */
6251 /* ITypeInfo2::GetDocumentation2
6253 * Retrieves the documentation string, the complete Help file name and path,
6254 * the localization context to use, and the context ID for the library Help
6255 * topic in the Help file.
6258 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6262 BSTR *pbstrHelpString,
6263 DWORD *pdwHelpStringContext,
6264 BSTR *pbstrHelpStringDll)
6266 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6267 const TLBFuncDesc *pFDesc;
6268 const TLBVarDesc *pVDesc;
6269 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6270 "HelpStringContext(%p) HelpStringDll(%p)\n",
6271 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6272 pbstrHelpStringDll );
6273 /* the help string should be obtained from the helpstringdll,
6274 * using the _DLLGetDocumentation function, based on the supplied
6275 * lcid. Nice to do sometime...
6277 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6279 *pbstrHelpString=SysAllocString(This->Name);
6280 if(pdwHelpStringContext)
6281 *pdwHelpStringContext=This->dwHelpStringContext;
6282 if(pbstrHelpStringDll)
6283 *pbstrHelpStringDll=
6284 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6286 }else {/* for a member */
6287 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6288 if(pFDesc->funcdesc.memid==memid){
6290 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6291 if(pdwHelpStringContext)
6292 *pdwHelpStringContext=pFDesc->HelpStringContext;
6293 if(pbstrHelpStringDll)
6294 *pbstrHelpStringDll=
6295 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6298 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6299 if(pVDesc->vardesc.memid==memid){
6301 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6302 if(pdwHelpStringContext)
6303 *pdwHelpStringContext=pVDesc->HelpStringContext;
6304 if(pbstrHelpStringDll)
6305 *pbstrHelpStringDll=
6306 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6310 return TYPE_E_ELEMENTNOTFOUND;
6313 /* ITypeInfo2::GetAllCustData
6315 * Gets all custom data items for the Type info.
6318 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6320 CUSTDATA *pCustData)
6322 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6323 TLBCustData *pCData;
6326 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6328 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6329 if(pCustData->prgCustData ){
6330 pCustData->cCustData=This->ctCustData;
6331 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6332 pCustData->prgCustData[i].guid=pCData->guid;
6333 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6336 ERR(" OUT OF MEMORY!\n");
6337 return E_OUTOFMEMORY;
6342 /* ITypeInfo2::GetAllFuncCustData
6344 * Gets all custom data items for the specified Function
6347 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6350 CUSTDATA *pCustData)
6352 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6353 TLBCustData *pCData;
6354 TLBFuncDesc * pFDesc;
6356 TRACE("(%p) index %d\n", This, index);
6357 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6358 pFDesc=pFDesc->next)
6361 pCustData->prgCustData =
6362 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6363 if(pCustData->prgCustData ){
6364 pCustData->cCustData=pFDesc->ctCustData;
6365 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6366 pCData = pCData->next){
6367 pCustData->prgCustData[i].guid=pCData->guid;
6368 VariantCopy(& pCustData->prgCustData[i].varValue,
6372 ERR(" OUT OF MEMORY!\n");
6373 return E_OUTOFMEMORY;
6377 return TYPE_E_ELEMENTNOTFOUND;
6380 /* ITypeInfo2::GetAllParamCustData
6382 * Gets all custom data items for the Functions
6385 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6386 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6388 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6389 TLBCustData *pCData=NULL;
6390 TLBFuncDesc * pFDesc;
6392 TRACE("(%p) index %d\n", This, indexFunc);
6393 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6394 pFDesc=pFDesc->next)
6396 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6397 pCustData->prgCustData =
6398 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6399 sizeof(CUSTDATAITEM));
6400 if(pCustData->prgCustData ){
6401 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6402 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6403 pCData; i++, pCData = pCData->next){
6404 pCustData->prgCustData[i].guid=pCData->guid;
6405 VariantCopy(& pCustData->prgCustData[i].varValue,
6409 ERR(" OUT OF MEMORY!\n");
6410 return E_OUTOFMEMORY;
6414 return TYPE_E_ELEMENTNOTFOUND;
6417 /* ITypeInfo2::GetAllVarCustData
6419 * Gets all custom data items for the specified Variable
6422 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6423 UINT index, CUSTDATA *pCustData)
6425 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6426 TLBCustData *pCData;
6427 TLBVarDesc * pVDesc;
6429 TRACE("(%p) index %d\n", This, index);
6430 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6431 pVDesc=pVDesc->next)
6434 pCustData->prgCustData =
6435 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6436 if(pCustData->prgCustData ){
6437 pCustData->cCustData=pVDesc->ctCustData;
6438 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6439 pCData = pCData->next){
6440 pCustData->prgCustData[i].guid=pCData->guid;
6441 VariantCopy(& pCustData->prgCustData[i].varValue,
6445 ERR(" OUT OF MEMORY!\n");
6446 return E_OUTOFMEMORY;
6450 return TYPE_E_ELEMENTNOTFOUND;
6453 /* ITypeInfo2::GetAllImplCustData
6455 * Gets all custom data items for the specified implementation type
6458 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6461 CUSTDATA *pCustData)
6463 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6464 TLBCustData *pCData;
6465 TLBImplType * pRDesc;
6467 TRACE("(%p) index %d\n", This, index);
6468 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6469 pRDesc=pRDesc->next)
6472 pCustData->prgCustData =
6473 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6474 if(pCustData->prgCustData ){
6475 pCustData->cCustData=pRDesc->ctCustData;
6476 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6477 pCData = pCData->next){
6478 pCustData->prgCustData[i].guid=pCData->guid;
6479 VariantCopy(& pCustData->prgCustData[i].varValue,
6483 ERR(" OUT OF MEMORY!\n");
6484 return E_OUTOFMEMORY;
6488 return TYPE_E_ELEMENTNOTFOUND;
6491 static const ITypeInfo2Vtbl tinfvt =
6494 ITypeInfo_fnQueryInterface,
6496 ITypeInfo_fnRelease,
6498 ITypeInfo_fnGetTypeAttr,
6499 ITypeInfo_fnGetTypeComp,
6500 ITypeInfo_fnGetFuncDesc,
6501 ITypeInfo_fnGetVarDesc,
6502 ITypeInfo_fnGetNames,
6503 ITypeInfo_fnGetRefTypeOfImplType,
6504 ITypeInfo_fnGetImplTypeFlags,
6505 ITypeInfo_fnGetIDsOfNames,
6507 ITypeInfo_fnGetDocumentation,
6508 ITypeInfo_fnGetDllEntry,
6509 ITypeInfo_fnGetRefTypeInfo,
6510 ITypeInfo_fnAddressOfMember,
6511 ITypeInfo_fnCreateInstance,
6512 ITypeInfo_fnGetMops,
6513 ITypeInfo_fnGetContainingTypeLib,
6514 ITypeInfo_fnReleaseTypeAttr,
6515 ITypeInfo_fnReleaseFuncDesc,
6516 ITypeInfo_fnReleaseVarDesc,
6518 ITypeInfo2_fnGetTypeKind,
6519 ITypeInfo2_fnGetTypeFlags,
6520 ITypeInfo2_fnGetFuncIndexOfMemId,
6521 ITypeInfo2_fnGetVarIndexOfMemId,
6522 ITypeInfo2_fnGetCustData,
6523 ITypeInfo2_fnGetFuncCustData,
6524 ITypeInfo2_fnGetParamCustData,
6525 ITypeInfo2_fnGetVarCustData,
6526 ITypeInfo2_fnGetImplTypeCustData,
6527 ITypeInfo2_fnGetDocumentation2,
6528 ITypeInfo2_fnGetAllCustData,
6529 ITypeInfo2_fnGetAllFuncCustData,
6530 ITypeInfo2_fnGetAllParamCustData,
6531 ITypeInfo2_fnGetAllVarCustData,
6532 ITypeInfo2_fnGetAllImplTypeCustData,
6535 /******************************************************************************
6536 * CreateDispTypeInfo [OLEAUT32.31]
6538 * Build type information for an object so it can be called through an
6539 * IDispatch interface.
6542 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6543 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6546 * This call allows an objects methods to be accessed through IDispatch, by
6547 * building an ITypeInfo object that IDispatch can use to call through.
6549 HRESULT WINAPI CreateDispTypeInfo(
6550 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6551 LCID lcid, /* [I] Locale Id */
6552 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6554 ITypeInfoImpl *pTIClass, *pTIIface;
6555 ITypeLibImpl *pTypeLibImpl;
6557 TLBFuncDesc **ppFuncDesc;
6560 pTypeLibImpl = TypeLibImpl_Constructor();
6561 if (!pTypeLibImpl) return E_FAIL;
6563 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
6564 pTIIface->pTypeLib = pTypeLibImpl;
6565 pTIIface->index = 0;
6566 pTIIface->Name = NULL;
6567 pTIIface->dwHelpContext = -1;
6568 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
6569 pTIIface->TypeAttr.lcid = lcid;
6570 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
6571 pTIIface->TypeAttr.wMajorVerNum = 0;
6572 pTIIface->TypeAttr.wMinorVerNum = 0;
6573 pTIIface->TypeAttr.cbAlignment = 2;
6574 pTIIface->TypeAttr.cbSizeInstance = -1;
6575 pTIIface->TypeAttr.cbSizeVft = -1;
6576 pTIIface->TypeAttr.cFuncs = 0;
6577 pTIIface->TypeAttr.cImplTypes = 0;
6578 pTIIface->TypeAttr.cVars = 0;
6579 pTIIface->TypeAttr.wTypeFlags = 0;
6581 ppFuncDesc = &pTIIface->funclist;
6582 for(func = 0; func < pidata->cMembers; func++) {
6583 METHODDATA *md = pidata->pmethdata + func;
6584 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6585 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6586 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6587 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
6588 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6589 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6590 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6591 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6592 (*ppFuncDesc)->funcdesc.oVft = md->iMeth << 2;
6593 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
6594 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6595 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
6596 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
6597 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6598 md->cArgs * sizeof(ELEMDESC));
6599 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6600 md->cArgs * sizeof(TLBParDesc));
6601 for(param = 0; param < md->cArgs; param++) {
6602 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6603 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6605 (*ppFuncDesc)->helpcontext = 0;
6606 (*ppFuncDesc)->HelpStringContext = 0;
6607 (*ppFuncDesc)->HelpString = NULL;
6608 (*ppFuncDesc)->Entry = NULL;
6609 (*ppFuncDesc)->ctCustData = 0;
6610 (*ppFuncDesc)->pCustData = NULL;
6611 (*ppFuncDesc)->next = NULL;
6612 ppFuncDesc = &(*ppFuncDesc)->next;
6615 dump_TypeInfo(pTIIface);
6617 pTypeLibImpl->pTypeInfo = pTIIface;
6618 pTypeLibImpl->TypeInfoCount++;
6620 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
6621 pTIClass->pTypeLib = pTypeLibImpl;
6622 pTIClass->index = 1;
6623 pTIClass->Name = NULL;
6624 pTIClass->dwHelpContext = -1;
6625 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
6626 pTIClass->TypeAttr.lcid = lcid;
6627 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
6628 pTIClass->TypeAttr.wMajorVerNum = 0;
6629 pTIClass->TypeAttr.wMinorVerNum = 0;
6630 pTIClass->TypeAttr.cbAlignment = 2;
6631 pTIClass->TypeAttr.cbSizeInstance = -1;
6632 pTIClass->TypeAttr.cbSizeVft = -1;
6633 pTIClass->TypeAttr.cFuncs = 0;
6634 pTIClass->TypeAttr.cImplTypes = 1;
6635 pTIClass->TypeAttr.cVars = 0;
6636 pTIClass->TypeAttr.wTypeFlags = 0;
6638 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
6639 pTIClass->impltypelist->hRef = 1;
6641 pTIClass->reflist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->reflist));
6642 pTIClass->reflist->index = 0;
6643 pTIClass->reflist->reference = 1;
6644 pTIClass->reflist->pImpTLInfo = TLB_REF_INTERNAL;
6646 dump_TypeInfo(pTIClass);
6648 pTIIface->next = pTIClass;
6649 pTypeLibImpl->TypeInfoCount++;
6651 *pptinfo = (ITypeInfo*)pTIClass;
6656 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6658 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6660 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6663 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6665 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6667 return ITypeInfo_AddRef((ITypeInfo *)This);
6670 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6672 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6674 return ITypeInfo_Release((ITypeInfo *)This);
6677 static HRESULT WINAPI ITypeComp_fnBind(
6682 ITypeInfo ** ppTInfo,
6683 DESCKIND * pDescKind,
6686 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6687 const TLBFuncDesc *pFDesc;
6688 const TLBVarDesc *pVDesc;
6689 HRESULT hr = DISP_E_MEMBERNOTFOUND;
6691 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6693 *pDescKind = DESCKIND_NONE;
6694 pBindPtr->lpfuncdesc = NULL;
6697 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6698 if (!strcmpiW(pFDesc->Name, szName)) {
6699 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6702 /* name found, but wrong flags */
6703 hr = TYPE_E_TYPEMISMATCH;
6708 HRESULT hr = TLB_AllocAndInitFuncDesc(
6710 &pBindPtr->lpfuncdesc,
6711 This->TypeAttr.typekind == TKIND_DISPATCH);
6714 *pDescKind = DESCKIND_FUNCDESC;
6715 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6716 ITypeInfo_AddRef(*ppTInfo);
6719 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6720 if (!strcmpiW(pVDesc->Name, szName)) {
6721 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6724 *pDescKind = DESCKIND_VARDESC;
6725 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6726 ITypeInfo_AddRef(*ppTInfo);
6731 /* FIXME: search each inherited interface, not just the first */
6732 if (hr == DISP_E_MEMBERNOTFOUND && This->TypeAttr.cImplTypes) {
6733 /* recursive search */
6737 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6740 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6741 ITypeInfo_Release(pTInfo);
6745 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6746 ITypeComp_Release(pTComp);
6749 WARN("Could not search inherited interface!\n");
6751 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6755 static HRESULT WINAPI ITypeComp_fnBindType(
6759 ITypeInfo ** ppTInfo,
6760 ITypeComp ** ppTComp)
6762 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6764 /* strange behaviour (does nothing) but like the
6767 if (!ppTInfo || !ppTComp)
6776 static const ITypeCompVtbl tcompvt =
6779 ITypeComp_fnQueryInterface,
6781 ITypeComp_fnRelease,
6784 ITypeComp_fnBindType