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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
86 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
88 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt);
89 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
91 /****************************************************************************
94 * Takes p_iVal (which is in little endian) and returns it
95 * in the host machine's byte order.
97 #ifdef WORDS_BIGENDIAN
98 static WORD FromLEWord(WORD p_iVal)
100 return (((p_iVal & 0x00FF) << 8) |
101 ((p_iVal & 0xFF00) >> 8));
105 static DWORD FromLEDWord(DWORD p_iVal)
107 return (((p_iVal & 0x000000FF) << 24) |
108 ((p_iVal & 0x0000FF00) << 8) |
109 ((p_iVal & 0x00FF0000) >> 8) |
110 ((p_iVal & 0xFF000000) >> 24));
113 #define FromLEWord(X) (X)
114 #define FromLEDWord(X) (X)
118 /****************************************************************************
121 * Fix byte order in any structure if necessary
123 #ifdef WORDS_BIGENDIAN
124 static void FromLEWords(void *p_Val, int p_iSize)
128 p_iSize /= sizeof(WORD);
131 *Val = FromLEWord(*Val);
138 static void FromLEDWords(void *p_Val, int p_iSize)
142 p_iSize /= sizeof(DWORD);
145 *Val = FromLEDWord(*Val);
151 #define FromLEWords(X,Y) /*nothing*/
152 #define FromLEDWords(X,Y) /*nothing*/
155 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
156 /* buffer must be at least 60 characters long */
157 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
159 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
160 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
162 memcpy( buffer, TypelibW, sizeof(TypelibW) );
163 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
164 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
168 /* get the path of an interface key, in the form "Interface\\<guid>" */
169 /* buffer must be at least 50 characters long */
170 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
172 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
174 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
175 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
179 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
180 /* buffer must be at least 16 characters long */
181 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
183 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
184 static const WCHAR win16W[] = {'w','i','n','1','6',0};
185 static const WCHAR win32W[] = {'w','i','n','3','2',0};
187 sprintfW( buffer, LcidFormatW, lcid );
190 case SYS_WIN16: strcatW( buffer, win16W ); break;
191 case SYS_WIN32: strcatW( buffer, win32W ); break;
193 TRACE("Typelib is for unsupported syskind %i\n", syskind);
199 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
202 /****************************************************************************
203 * QueryPathOfRegTypeLib [OLEAUT32.164]
205 * Gets the path to a registered type library.
208 * guid [I] referenced guid
209 * wMaj [I] major version
210 * wMin [I] minor version
212 * path [O] path of typelib
216 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
217 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
220 HRESULT WINAPI QueryPathOfRegTypeLib(
227 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
231 WCHAR Path[MAX_PATH];
234 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
236 get_typelib_key( guid, wMaj, wMin, buffer );
238 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
239 if (res == ERROR_FILE_NOT_FOUND)
241 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
242 return TYPE_E_LIBNOTREGISTERED;
244 else if (res != ERROR_SUCCESS)
246 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
247 return TYPE_E_REGISTRYACCESS;
252 LONG dwPathLen = sizeof(Path);
254 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
256 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
260 else if (myLCID == lcid)
262 /* try with sub-langid */
263 myLCID = SUBLANGID(lcid);
265 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
267 /* try with system langid */
277 *path = SysAllocString( Path );
282 TRACE_(typelib)("-- 0x%08lx\n", hr);
286 /******************************************************************************
287 * CreateTypeLib [OLEAUT32.160] creates a typelib
293 HRESULT WINAPI CreateTypeLib(
294 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
296 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
300 /******************************************************************************
301 * LoadTypeLib [OLEAUT32.161]
303 * Loads a type library
306 * szFile [I] Name of file to load from.
307 * pptLib [O] Pointer that receives ITypeLib object on success.
314 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
316 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
318 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
319 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
322 /******************************************************************************
323 * LoadTypeLibEx [OLEAUT32.183]
325 * Loads and optionally registers a type library
331 HRESULT WINAPI LoadTypeLibEx(
332 LPCOLESTR szFile, /* [in] Name of file to load from */
333 REGKIND regkind, /* [in] Specify kind of registration */
334 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
336 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
341 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
343 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
344 memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));
347 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
350 /* Look for a trailing '\\' followed by an index */
351 pIndexStr = strrchrW(szFile, '\\');
352 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
353 index = atoiW(pIndexStr);
354 memcpy(szFileCopy, szFile,
355 (pIndexStr - szFile - 1) * sizeof(WCHAR));
356 szFileCopy[pIndexStr - szFile - 1] = '\0';
357 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
359 return TYPE_E_CANTLOADLIBRARY;
360 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
361 return TYPE_E_CANTLOADLIBRARY;
365 TRACE("File %s index %d\n", debugstr_w(szPath), index);
367 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
372 case REGKIND_DEFAULT:
373 /* don't register typelibs supplied with full path. Experimentation confirms the following */
375 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
376 (szFile[0] && (szFile[1] == ':'))) break;
377 /* else fall-through */
379 case REGKIND_REGISTER:
380 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
382 IUnknown_Release(*pptLib);
390 TRACE(" returns %08lx\n",res);
394 /******************************************************************************
395 * LoadRegTypeLib [OLEAUT32.162]
397 * Loads a registered type library.
400 * rguid [I] GUID of the registered type library.
401 * wVerMajor [I] major version.
402 * wVerMinor [I] minor version.
403 * lcid [I] locale ID.
404 * ppTLib [O] pointer that receives an ITypeLib object on success.
408 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
411 HRESULT WINAPI LoadRegTypeLib(
419 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
423 res= LoadTypeLib(bstr, ppTLib);
427 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
433 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
434 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
435 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
436 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
437 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
438 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
440 /******************************************************************************
441 * RegisterTypeLib [OLEAUT32.163]
442 * Adds information about a type library to the System Registry
444 * Docs: ITypeLib FAR * ptlib
445 * Docs: OLECHAR FAR* szFullPath
446 * Docs: OLECHAR FAR* szHelpDir
452 HRESULT WINAPI RegisterTypeLib(
453 ITypeLib * ptlib, /* [in] Pointer to the library*/
454 OLECHAR * szFullPath, /* [in] full Path of the library*/
455 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
458 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
459 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
460 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
470 if (ptlib == NULL || szFullPath == NULL)
473 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
476 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
479 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
480 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
484 /* Set the human-readable name of the typelib */
485 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
487 if (RegSetValueExW(key, NULL, 0, REG_SZ,
488 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
496 /* Make up the name of the typelib path subkey */
497 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
499 /* Create the typelib path subkey */
500 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
501 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
503 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
504 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
512 /* Create the flags subkey */
513 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
514 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
516 /* FIXME: is %u correct? */
517 static const WCHAR formatW[] = {'%','u',0};
519 sprintfW(buf, formatW, attr->wLibFlags);
520 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
521 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
529 /* create the helpdir subkey */
530 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
531 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
533 BOOL freeHelpDir = FALSE;
536 /* if we created a new key, and helpDir was null, set the helpdir
537 to the directory which contains the typelib. However,
538 if we just opened an existing key, we leave the helpdir alone */
539 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
540 szHelpDir = SysAllocString(szFullPath);
541 pIndexStr = strrchrW(szHelpDir, '\\');
548 /* if we have an szHelpDir, set it! */
549 if (szHelpDir != NULL) {
550 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
551 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
557 if (freeHelpDir) SysFreeString(szHelpDir);
569 /* register OLE Automation-compatible interfaces for this typelib */
570 types = ITypeLib_GetTypeInfoCount(ptlib);
571 for (tidx=0; tidx<types; tidx++) {
572 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
573 LPOLESTR name = NULL;
574 ITypeInfo *tinfo = NULL;
576 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
579 case TKIND_INTERFACE:
580 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
581 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
585 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
586 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
590 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
595 TYPEATTR *tattr = NULL;
596 ITypeInfo_GetTypeAttr(tinfo, &tattr);
599 TRACE_(typelib)("guid=%s, flags=%04x (",
600 debugstr_guid(&tattr->guid),
603 if (TRACE_ON(typelib)) {
604 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
624 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
626 /* register interface<->typelib coupling */
627 get_interface_key( &tattr->guid, keyName );
628 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
629 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
632 RegSetValueExW(key, NULL, 0, REG_SZ,
633 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
635 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
636 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
637 RegSetValueExW(subKey, NULL, 0, REG_SZ,
638 (BYTE*)PSOA, sizeof PSOA);
642 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
643 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
644 RegSetValueExW(subKey, NULL, 0, REG_SZ,
645 (BYTE*)PSOA, sizeof PSOA);
649 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
650 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
653 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
654 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
656 StringFromGUID2(&attr->guid, buffer, 40);
657 RegSetValueExW(subKey, NULL, 0, REG_SZ,
658 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
659 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
660 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
661 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
669 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
672 ITypeInfo_Release(tinfo);
679 ITypeLib_ReleaseTLibAttr(ptlib, attr);
685 /******************************************************************************
686 * UnRegisterTypeLib [OLEAUT32.186]
687 * Removes information about a type library from the System Registry
694 HRESULT WINAPI UnRegisterTypeLib(
695 REFGUID libid, /* [in] Guid of the library */
696 WORD wVerMajor, /* [in] major version */
697 WORD wVerMinor, /* [in] minor version */
698 LCID lcid, /* [in] locale id */
701 BSTR tlibPath = NULL;
704 WCHAR subKeyName[50];
707 BOOL deleteOtherStuff;
710 TYPEATTR* typeAttr = NULL;
712 ITypeInfo* typeInfo = NULL;
713 ITypeLib* typeLib = NULL;
716 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
718 /* Create the path to the key */
719 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
721 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
723 TRACE("Unsupported syskind %i\n", syskind);
724 result = E_INVALIDARG;
728 /* get the path to the typelib on disk */
729 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
730 result = E_INVALIDARG;
734 /* Try and open the key to the type library. */
735 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
736 result = E_INVALIDARG;
740 /* Try and load the type library */
741 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
742 result = TYPE_E_INVALIDSTATE;
746 /* remove any types registered with this typelib */
747 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
748 for (i=0; i<numTypes; i++) {
749 /* get the kind of type */
750 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
754 /* skip non-interfaces, and get type info for the type */
755 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
758 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
761 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
765 /* the path to the type */
766 get_interface_key( &typeAttr->guid, subKeyName );
768 /* Delete its bits */
769 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
772 RegDeleteKeyW(subKey, ProxyStubClsidW);
773 RegDeleteKeyW(subKey, ProxyStubClsid32W);
774 RegDeleteKeyW(subKey, TypeLibW);
777 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
780 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
782 if (typeInfo) ITypeInfo_Release(typeInfo);
786 /* Now, delete the type library path subkey */
787 get_lcid_subkey( lcid, syskind, subKeyName );
788 RegDeleteKeyW(key, subKeyName);
789 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
790 RegDeleteKeyW(key, subKeyName);
792 /* check if there is anything besides the FLAGS/HELPDIR keys.
793 If there is, we don't delete them */
794 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
795 deleteOtherStuff = TRUE;
797 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
798 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
800 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
801 if (!strcmpW(subKeyName, FLAGSW)) continue;
802 if (!strcmpW(subKeyName, HELPDIRW)) continue;
803 deleteOtherStuff = FALSE;
807 /* only delete the other parts of the key if we're absolutely sure */
808 if (deleteOtherStuff) {
809 RegDeleteKeyW(key, FLAGSW);
810 RegDeleteKeyW(key, HELPDIRW);
814 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
815 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
816 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
820 if (tlibPath) SysFreeString(tlibPath);
821 if (typeLib) ITypeLib_Release(typeLib);
822 if (subKey) RegCloseKey(subKey);
823 if (key) RegCloseKey(key);
827 /*======================= ITypeLib implementation =======================*/
829 typedef struct tagTLBCustData
833 struct tagTLBCustData* next;
836 /* data structure for import typelibs */
837 typedef struct tagTLBImpLib
839 int offset; /* offset in the file (MSFT)
840 offset in nametable (SLTG)
841 just used to identify library while reading
843 GUID guid; /* libid */
844 BSTR name; /* name */
846 LCID lcid; /* lcid of imported typelib */
848 WORD wVersionMajor; /* major version number */
849 WORD wVersionMinor; /* minor version number */
851 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
852 NULL if not yet loaded */
853 struct tagTLBImpLib * next;
856 /* internal ITypeLib data */
857 typedef struct tagITypeLibImpl
859 const ITypeLib2Vtbl *lpVtbl;
860 const ITypeCompVtbl *lpVtblTypeComp;
862 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
864 /* strings can be stored in tlb as multibyte strings BUT they are *always*
865 * exported to the application as a UNICODE string.
871 unsigned long dwHelpContext;
872 int TypeInfoCount; /* nr of typeinfo's in librarry */
873 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
874 int ctCustData; /* number of items in cust data list */
875 TLBCustData * pCustData; /* linked list to cust data */
876 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
877 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
878 libary. Only used while read MSFT
881 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
882 struct tagITypeLibImpl *next, *prev;
887 static const ITypeLib2Vtbl tlbvt;
888 static const ITypeCompVtbl tlbtcvt;
890 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
892 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
895 /* ITypeLib methods */
896 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
897 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
899 /*======================= ITypeInfo implementation =======================*/
901 /* data for referenced types */
902 typedef struct tagTLBRefType
904 INT index; /* Type index for internal ref or for external ref
905 it the format is SLTG. -2 indicates to
908 GUID guid; /* guid of the referenced type */
909 /* if index == TLB_REF_USE_GUID */
911 HREFTYPE reference; /* The href of this ref */
912 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
913 TLB_REF_INTERNAL for internal refs
914 TLB_REF_NOT_FOUND for broken refs */
916 struct tagTLBRefType * next;
919 #define TLB_REF_USE_GUID -2
921 #define TLB_REF_INTERNAL (void*)-2
922 #define TLB_REF_NOT_FOUND (void*)-1
924 /* internal Parameter data */
925 typedef struct tagTLBParDesc
929 TLBCustData * pCustData; /* linked list to cust data */
932 /* internal Function data */
933 typedef struct tagTLBFuncDesc
935 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
936 BSTR Name; /* the name of this function */
937 TLBParDesc *pParamDesc; /* array with param names and custom data */
939 int HelpStringContext;
941 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
943 TLBCustData * pCustData; /* linked list to cust data; */
944 struct tagTLBFuncDesc * next;
947 /* internal Variable data */
948 typedef struct tagTLBVarDesc
950 VARDESC vardesc; /* lots of info on the variable and its attributes. */
951 BSTR Name; /* the name of this variable */
953 int HelpStringContext; /* FIXME: where? */
956 TLBCustData * pCustData;/* linked list to cust data; */
957 struct tagTLBVarDesc * next;
960 /* internal implemented interface data */
961 typedef struct tagTLBImplType
963 HREFTYPE hRef; /* hRef of interface */
964 int implflags; /* IMPLFLAG_*s */
966 TLBCustData * pCustData;/* linked list to custom data; */
967 struct tagTLBImplType *next;
970 /* internal TypeInfo data */
971 typedef struct tagITypeInfoImpl
973 const ITypeInfo2Vtbl *lpVtbl;
974 const ITypeCompVtbl *lpVtblTypeComp;
976 TYPEATTR TypeAttr ; /* _lots_ of type information. */
977 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
978 int index; /* index in this typelib; */
979 HREFTYPE hreftype; /* hreftype for app object binding */
980 /* type libs seem to store the doc strings in ascii
981 * so why should we do it in unicode?
986 unsigned long dwHelpContext;
987 unsigned long dwHelpStringContext;
990 TLBFuncDesc * funclist; /* linked list with function descriptions */
993 TLBVarDesc * varlist; /* linked list with variable descriptions */
995 /* Implemented Interfaces */
996 TLBImplType * impltypelist;
998 TLBRefType * reflist;
1000 TLBCustData * pCustData; /* linked list to cust data; */
1001 struct tagITypeInfoImpl * next;
1004 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1006 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1009 static const ITypeInfo2Vtbl tinfvt;
1010 static const ITypeCompVtbl tcompvt;
1012 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1014 typedef struct tagTLBContext
1016 unsigned int oStart; /* start of TLB in file */
1017 unsigned int pos; /* current pos */
1018 unsigned int length; /* total length */
1019 void *mapping; /* memory mapping */
1020 MSFT_SegDir * pTblDir;
1021 ITypeLibImpl* pLibInfo;
1025 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1030 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1031 if (pTD->vt & VT_RESERVED)
1032 szVarType += strlen(strcpy(szVarType, "reserved | "));
1033 if (pTD->vt & VT_BYREF)
1034 szVarType += strlen(strcpy(szVarType, "ref to "));
1035 if (pTD->vt & VT_ARRAY)
1036 szVarType += strlen(strcpy(szVarType, "array of "));
1037 if (pTD->vt & VT_VECTOR)
1038 szVarType += strlen(strcpy(szVarType, "vector of "));
1039 switch(pTD->vt & VT_TYPEMASK) {
1040 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1041 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1042 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1043 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1044 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1045 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1046 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1047 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1048 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1049 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1050 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1051 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1052 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1053 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1054 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1055 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1056 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1057 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1058 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1059 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1060 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1061 pTD->u.hreftype); break;
1062 case VT_PTR: sprintf(szVarType, "ptr to ");
1063 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1065 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1066 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1068 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1069 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1070 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1073 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1077 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1079 USHORT flags = edesc->u.paramdesc.wParamFlags;
1080 dump_TypeDesc(&edesc->tdesc,buf);
1081 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1082 MESSAGE("\t\tu.paramdesc.wParamFlags");
1083 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1084 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1085 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1086 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1087 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1088 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1089 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1090 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1091 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1093 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1095 MESSAGE("memid is %08lx\n",funcdesc->memid);
1096 for (i=0;i<funcdesc->cParams;i++) {
1097 MESSAGE("Param %d:\n",i);
1098 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1100 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1101 switch (funcdesc->funckind) {
1102 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1103 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1104 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1105 case FUNC_STATIC: MESSAGE("static");break;
1106 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1107 default: MESSAGE("unknown");break;
1109 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1110 switch (funcdesc->invkind) {
1111 case INVOKE_FUNC: MESSAGE("func");break;
1112 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1113 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1114 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1116 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1117 switch (funcdesc->callconv) {
1118 case CC_CDECL: MESSAGE("cdecl");break;
1119 case CC_PASCAL: MESSAGE("pascal");break;
1120 case CC_STDCALL: MESSAGE("stdcall");break;
1121 case CC_SYSCALL: MESSAGE("syscall");break;
1124 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1125 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1126 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1128 MESSAGE("\telemdescFunc (return value type):\n");
1129 dump_ELEMDESC(&funcdesc->elemdescFunc);
1132 static const char * typekind_desc[] =
1145 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1148 if (!TRACE_ON(typelib))
1150 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1151 for (i=0;i<pfd->funcdesc.cParams;i++)
1152 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1155 dump_FUNCDESC(&(pfd->funcdesc));
1157 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1158 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1160 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1164 dump_TLBFuncDescOne(pfd);
1168 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1172 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1177 static void dump_TLBImpLib(const TLBImpLib *import)
1179 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1180 debugstr_w(import->name));
1181 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1182 import->wVersionMinor, import->lcid, import->offset);
1185 static void dump_TLBRefType(const TLBRefType * prt)
1189 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1190 if(prt->index == -1)
1191 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1193 TRACE_(typelib)("type no: %d\n", prt->index);
1195 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1196 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1197 TRACE_(typelib)("in lib\n");
1198 dump_TLBImpLib(prt->pImpTLInfo);
1204 static void dump_TLBImplType(const TLBImplType * impl)
1208 "implementing/inheriting interface hRef = %lx implflags %x\n",
1209 impl->hRef, impl->implflags);
1214 void dump_Variant(const VARIANT * pvar)
1218 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1222 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1223 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1225 TRACE(",%p", V_BYREF(pvar));
1227 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1231 else switch (V_TYPE(pvar))
1233 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1234 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1235 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1236 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1238 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1240 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1241 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1242 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1243 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1244 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1245 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1246 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1247 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1248 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1249 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1250 V_CY(pvar).s.Lo); break;
1252 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1253 TRACE(",<invalid>");
1255 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1256 st.wHour, st.wMinute, st.wSecond);
1260 case VT_USERDEFINED:
1262 case VT_NULL: break;
1263 default: TRACE(",?"); break;
1269 static void dump_DispParms(const DISPPARAMS * pdp)
1273 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1275 while (index < pdp->cArgs)
1277 dump_Variant( &pdp->rgvarg[index] );
1282 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1284 TRACE("%p ref=%lu\n", pty, pty->ref);
1285 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1286 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1287 TRACE("fct:%u var:%u impl:%u\n",
1288 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1289 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1290 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1291 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1292 dump_TLBFuncDesc(pty->funclist);
1293 dump_TLBVarDesc(pty->varlist);
1294 dump_TLBImplType(pty->impltypelist);
1297 static void dump_VARDESC(const VARDESC *v)
1299 MESSAGE("memid %ld\n",v->memid);
1300 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1301 MESSAGE("oInst %ld\n",v->u.oInst);
1302 dump_ELEMDESC(&(v->elemdescVar));
1303 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1304 MESSAGE("varkind %d\n",v->varkind);
1307 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1309 /* VT_LPWSTR is largest type that */
1310 /* may appear in type description*/
1311 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1312 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1313 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1314 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1315 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1316 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1320 static void TLB_abort(void)
1324 static void * TLB_Alloc(unsigned size)
1327 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1329 ERR("cannot allocate memory\n");
1334 static void TLB_Free(void * ptr)
1336 HeapFree(GetProcessHeap(), 0, ptr);
1339 /* returns the size required for a deep copy of a typedesc into a
1341 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1345 if (alloc_initial_space)
1346 size += sizeof(TYPEDESC);
1352 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1355 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1356 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1362 /* deep copy a typedesc into a flat buffer */
1363 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1368 buffer = (char *)buffer + sizeof(TYPEDESC);
1377 dest->u.lptdesc = buffer;
1378 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1381 dest->u.lpadesc = buffer;
1382 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1383 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1384 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1390 /**********************************************************************
1392 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
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 if (where != DO_NOT_SEEK)
1402 where += pcx->oStart;
1403 if (where > pcx->length)
1406 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1411 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1412 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1417 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1422 ret = MSFT_Read(buffer, count, pcx, where);
1423 FromLEDWords(buffer, ret);
1428 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1433 ret = MSFT_Read(buffer, count, pcx, where);
1434 FromLEWords(buffer, ret);
1439 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1441 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1442 memset(pGuid,0, sizeof(GUID));
1445 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1446 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1447 pGuid->Data2 = FromLEWord(pGuid->Data2);
1448 pGuid->Data3 = FromLEWord(pGuid->Data3);
1449 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1452 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1454 MSFT_NameIntro niName;
1458 ERR_(typelib)("bad offset %d\n", offset);
1462 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1463 pcx->pTblDir->pNametab.offset+offset);
1465 return niName.hreftype;
1468 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1471 MSFT_NameIntro niName;
1473 WCHAR* pwstring = NULL;
1474 BSTR bstrName = NULL;
1478 ERR_(typelib)("bad offset %d\n", offset);
1481 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1482 pcx->pTblDir->pNametab.offset+offset);
1483 niName.namelen &= 0xFF; /* FIXME: correct ? */
1484 name=TLB_Alloc((niName.namelen & 0xff) +1);
1485 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1486 name[niName.namelen & 0xff]='\0';
1488 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1491 /* no invalid characters in string */
1494 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1496 /* don't check for invalid character since this has been done previously */
1497 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1499 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1500 lengthInChars = SysStringLen(bstrName);
1501 HeapFree(GetProcessHeap(), 0, pwstring);
1504 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1508 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1515 if(offset<0) return NULL;
1516 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1517 if(length <= 0) return 0;
1518 string=TLB_Alloc(length +1);
1519 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1520 string[length]='\0';
1522 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1523 string, -1, NULL, 0);
1525 /* no invalid characters in string */
1528 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1530 /* don't check for invalid character since this has been done previously */
1531 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1533 bstr = SysAllocStringLen(pwstring, lengthInChars);
1534 lengthInChars = SysStringLen(bstr);
1535 HeapFree(GetProcessHeap(), 0, pwstring);
1538 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1542 * read a value and fill a VARIANT structure
1544 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1548 TRACE_(typelib)("\n");
1550 if(offset <0) { /* data are packed in here */
1551 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1552 V_I4(pVar) = offset & 0x3ffffff;
1555 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1556 pcx->pTblDir->pCustData.offset + offset );
1557 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1558 switch (V_VT(pVar)){
1559 case VT_EMPTY: /* FIXME: is this right? */
1560 case VT_NULL: /* FIXME: is this right? */
1561 case VT_I2 : /* this should not happen */
1572 case VT_VOID : /* FIXME: is this right? */
1580 case VT_DECIMAL : /* FIXME: is this right? */
1583 /* pointer types with known behaviour */
1586 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1588 FIXME("BSTR length = %d?\n", size);
1590 ptr=TLB_Alloc(size);/* allocate temp buffer */
1591 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1592 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1593 /* FIXME: do we need a AtoW conversion here? */
1594 V_UNION(pVar, bstrVal[size])=L'\0';
1595 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1600 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1607 case VT_USERDEFINED :
1613 case VT_STREAMED_OBJECT :
1614 case VT_STORED_OBJECT :
1615 case VT_BLOB_OBJECT :
1620 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1624 if(size>0) /* (big|small) endian correct? */
1625 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1629 * create a linked list with custom data
1631 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1637 TRACE_(typelib)("\n");
1641 pNew=TLB_Alloc(sizeof(TLBCustData));
1642 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1643 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1644 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1645 /* add new custom data at head of the list */
1646 pNew->next=*ppCustData;
1648 offset = entry.next;
1653 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1657 pTd->vt=type & VT_TYPEMASK;
1659 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1661 if(pTd->vt == VT_USERDEFINED)
1662 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1664 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1668 MSFT_DoFuncs(TLBContext* pcx,
1673 TLBFuncDesc** pptfd)
1676 * member information is stored in a data structure at offset
1677 * indicated by the memoffset field of the typeinfo structure
1678 * There are several distinctive parts.
1679 * The first part starts with a field that holds the total length
1680 * of this (first) part excluding this field. Then follow the records,
1681 * for each member there is one record.
1683 * The first entry is always the length of the record (including this
1685 * The rest of the record depends on the type of the member. If there is
1686 * a field indicating the member type (function, variable, interface, etc)
1687 * I have not found it yet. At this time we depend on the information
1688 * in the type info and the usual order how things are stored.
1690 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1693 * Third is an equal sized array with file offsets to the name entry
1696 * The fourth and last (?) part is an array with offsets to the records
1697 * in the first part of this file segment.
1700 int infolen, nameoffset, reclength, nrattributes, i;
1701 int recoffset = offset + sizeof(INT);
1704 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1705 TLBFuncDesc *ptfd_prev = NULL;
1707 TRACE_(typelib)("\n");
1709 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1711 for ( i = 0; i < cFuncs ; i++ )
1713 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1715 /* name, eventually add to a hash table */
1716 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1717 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1719 /* nameoffset is sometimes -1 on the second half of a propget/propput
1720 * pair of functions */
1721 if ((nameoffset == -1) && (i > 0))
1722 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1724 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1726 /* read the function information record */
1727 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1731 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1733 /* do the attributes */
1734 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1737 if ( nrattributes > 0 )
1739 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1741 if ( nrattributes > 1 )
1743 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1744 pFuncRec->OptAttr[1]) ;
1746 if ( nrattributes > 2 )
1748 if ( pFuncRec->FKCCIC & 0x2000 )
1750 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1754 (*pptfd)->Entry = MSFT_ReadString(pcx,
1755 pFuncRec->OptAttr[2]);
1757 if( nrattributes > 5 )
1759 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1761 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1764 pFuncRec->OptAttr[6],
1765 &(*pptfd)->pCustData);
1772 /* fill the FuncDesc Structure */
1773 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1774 offset + infolen + ( i + 1) * sizeof(INT));
1776 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1777 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1778 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1779 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1780 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1781 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1782 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1786 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1789 /* do the parameters/arguments */
1790 if(pFuncRec->nrargs)
1793 MSFT_ParameterInfo paraminfo;
1795 (*pptfd)->funcdesc.lprgelemdescParam =
1796 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1798 (*pptfd)->pParamDesc =
1799 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1801 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1802 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1804 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1806 TYPEDESC *lpArgTypeDesc;
1807 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1814 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1817 if (paraminfo.oName == -1)
1818 /* this occurs for [propput] or [propget] methods, so
1819 * we should just set the name of the parameter to the
1820 * name of the method. */
1821 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1823 (*pptfd)->pParamDesc[j].Name =
1824 MSFT_ReadName( pcx, paraminfo.oName );
1825 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1827 lpArgTypeDesc = &elemdesc->tdesc;
1829 /* resolve referenced type if any */
1830 while ( lpArgTypeDesc != NULL )
1832 switch ( lpArgTypeDesc->vt )
1835 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1839 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1842 case VT_USERDEFINED:
1843 MSFT_DoRefType(pcx, pTI,
1844 lpArgTypeDesc->u.hreftype);
1846 lpArgTypeDesc = NULL;
1850 lpArgTypeDesc = NULL;
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;
1901 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1902 int cVars, int offset, TLBVarDesc ** pptvd)
1904 int infolen, nameoffset, reclength;
1906 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1910 TRACE_(typelib)("\n");
1912 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1913 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1914 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1915 recoffset += offset+sizeof(INT);
1916 for(i=0;i<cVars;i++){
1917 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1918 /* name, eventually add to a hash table */
1919 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1920 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1921 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1922 /* read the variable information record */
1923 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1925 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1927 if(reclength >(6*sizeof(INT)) )
1928 (*pptvd)->HelpContext=pVarRec->HelpContext;
1929 if(reclength >(7*sizeof(INT)) )
1930 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1931 if(reclength >(8*sizeof(INT)) )
1932 if(reclength >(9*sizeof(INT)) )
1933 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1934 /* fill the VarDesc Structure */
1935 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1936 offset + infolen + ( i + 1) * sizeof(INT));
1937 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1938 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1939 MSFT_GetTdesc(pcx, pVarRec->DataType,
1940 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1941 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1942 if(pVarRec->VarKind == VAR_CONST ){
1943 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1944 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1945 pVarRec->OffsValue, pcx);
1947 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1948 pptvd=&((*pptvd)->next);
1949 recoffset += reclength;
1952 /* fill in data for a hreftype (offset). When the referenced type is contained
1953 * in the typelib, it's just an (file) offset in the type info base dir.
1954 * If comes from import, it's an offset+1 in the ImpInfo table
1956 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1960 TLBRefType **ppRefType = &pTI->reflist;
1962 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1965 if((*ppRefType)->reference == offset)
1967 ppRefType = &(*ppRefType)->next;
1970 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1971 sizeof(**ppRefType));
1973 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1974 /* external typelib */
1975 MSFT_ImpInfo impinfo;
1976 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1978 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1980 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1981 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1982 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1983 if(pImpLib->offset==impinfo.oImpFile) break;
1984 pImpLib=pImpLib->next;
1987 (*ppRefType)->reference=offset;
1988 (*ppRefType)->pImpTLInfo = pImpLib;
1989 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1990 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1991 (*ppRefType)->index = TLB_REF_USE_GUID;
1993 (*ppRefType)->index = impinfo.oGuid;
1995 ERR("Cannot find a reference\n");
1996 (*ppRefType)->reference=-1;
1997 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2000 /* in this typelib */
2001 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2002 (*ppRefType)->reference=offset;
2003 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2007 /* process Implemented Interfaces of a com class */
2008 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2012 MSFT_RefRecord refrec;
2013 TLBImplType **ppImpl = &pTI->impltypelist;
2015 TRACE_(typelib)("\n");
2017 for(i=0;i<count;i++){
2018 if(offset<0) break; /* paranoia */
2019 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2020 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2021 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2022 (*ppImpl)->hRef = refrec.reftype;
2023 (*ppImpl)->implflags=refrec.flags;
2024 (*ppImpl)->ctCustData=
2025 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2026 offset=refrec.onext;
2027 ppImpl=&((*ppImpl)->next);
2031 * process a typeinfo record
2033 static ITypeInfoImpl * MSFT_DoTypeInfo(
2036 ITypeLibImpl * pLibInfo)
2038 MSFT_TypeInfoBase tiBase;
2039 ITypeInfoImpl *ptiRet;
2041 TRACE_(typelib)("count=%u\n", count);
2043 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2044 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2045 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2047 /* this is where we are coming from */
2048 ptiRet->pTypeLib = pLibInfo;
2049 ptiRet->index=count;
2050 /* fill in the typeattr fields */
2051 WARN("Assign constructor/destructor memid\n");
2053 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2054 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2055 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2056 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2057 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2058 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2059 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2060 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2061 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2062 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2063 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2064 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2065 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2066 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2067 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2068 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2069 MSFT_GetTdesc(pcx, tiBase.datatype1,
2070 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2073 /* IDLDESC idldescType; *//* never saw this one != zero */
2075 /* name, eventually add to a hash table */
2076 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2077 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2078 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2080 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2081 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2082 ptiRet->dwHelpContext=tiBase.helpcontext;
2084 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2085 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2087 /* note: InfoType's Help file and HelpStringDll come from the containing
2088 * library. Further HelpString and Docstring appear to be the same thing :(
2091 if(ptiRet->TypeAttr.cFuncs >0 )
2092 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2093 ptiRet->TypeAttr.cVars,
2094 tiBase.memoffset, & ptiRet->funclist);
2096 if(ptiRet->TypeAttr.cVars >0 )
2097 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2098 ptiRet->TypeAttr.cVars,
2099 tiBase.memoffset, & ptiRet->varlist);
2100 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2101 switch(ptiRet->TypeAttr.typekind)
2104 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2107 case TKIND_DISPATCH:
2108 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2110 if (tiBase.datatype1 != -1)
2112 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2113 ptiRet->impltypelist->hRef = tiBase.datatype1;
2116 { /* FIXME: This is a really bad hack to add IDispatch */
2117 const char* szStdOle = "stdole2.tlb\0";
2118 int nStdOleLen = strlen(szStdOle);
2119 TLBRefType **ppRef = &ptiRet->reflist;
2122 if((*ppRef)->reference == -1)
2124 ppRef = &(*ppRef)->next;
2127 *ppRef = TLB_Alloc(sizeof(**ppRef));
2128 (*ppRef)->guid = IID_IDispatch;
2129 (*ppRef)->reference = -1;
2130 (*ppRef)->index = TLB_REF_USE_GUID;
2131 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2132 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2133 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2136 MultiByteToWideChar(CP_ACP,
2140 (*ppRef)->pImpTLInfo->name,
2141 SysStringLen((*ppRef)->pImpTLInfo->name));
2143 (*ppRef)->pImpTLInfo->lcid = 0;
2144 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2145 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2150 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2151 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2152 ptiRet->impltypelist->hRef = tiBase.datatype1;
2157 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2159 TRACE_(typelib)("%s guid: %s kind:%s\n",
2160 debugstr_w(ptiRet->Name),
2161 debugstr_guid(&ptiRet->TypeAttr.guid),
2162 typekind_desc[ptiRet->TypeAttr.typekind]);
2167 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2168 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2169 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2172 static ITypeLibImpl *tlb_cache_first;
2173 static CRITICAL_SECTION cache_section;
2174 static CRITICAL_SECTION_DEBUG cache_section_debug =
2176 0, 0, &cache_section,
2177 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2178 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2180 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2183 /****************************************************************************
2186 * find the type of the typelib file and map the typelib resource into
2189 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2190 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2191 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2193 ITypeLibImpl *entry;
2194 int ret = TYPE_E_CANTLOADLIBRARY;
2195 DWORD dwSignature = 0;
2198 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2202 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2203 EnterCriticalSection(&cache_section);
2204 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2206 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2208 TRACE("cache hit\n");
2209 *ppTypeLib = (ITypeLib2*)entry;
2210 ITypeLib_AddRef(*ppTypeLib);
2211 LeaveCriticalSection(&cache_section);
2215 LeaveCriticalSection(&cache_section);
2217 /* check the signature of the file */
2218 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2219 if (INVALID_HANDLE_VALUE != hFile)
2221 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2224 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2227 /* retrieve file size */
2228 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2230 /* first try to load as *.tlb */
2231 dwSignature = FromLEDWord(*((DWORD*) pBase));
2232 if ( dwSignature == MSFT_SIGNATURE)
2234 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2236 else if ( dwSignature == SLTG_SIGNATURE)
2238 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2240 UnmapViewOfFile(pBase);
2242 CloseHandle(hMapping);
2248 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2251 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2252 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2254 /* find the typelibrary resource*/
2255 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2256 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2259 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2260 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2263 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2266 LPVOID pBase = LockResource(hGlobal);
2267 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2271 /* try to load as incore resource */
2272 dwSignature = FromLEDWord(*((DWORD*) pBase));
2273 if ( dwSignature == MSFT_SIGNATURE)
2275 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2277 else if ( dwSignature == SLTG_SIGNATURE)
2279 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2283 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2286 FreeResource( hGlobal );
2289 FreeLibrary(hinstDLL);
2294 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2296 TRACE("adding to cache\n");
2297 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2298 lstrcpyW(impl->path, pszFileName);
2299 /* We should really canonicalise the path here. */
2300 impl->index = index;
2302 /* FIXME: check if it has added already in the meantime */
2303 EnterCriticalSection(&cache_section);
2304 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2306 tlb_cache_first = impl;
2307 LeaveCriticalSection(&cache_section);
2310 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2315 /*================== ITypeLib(2) Methods ===================================*/
2317 /****************************************************************************
2318 * ITypeLib2_Constructor_MSFT
2320 * loading an MSFT typelib from an in-memory image
2322 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2326 MSFT_Header tlbHeader;
2327 MSFT_SegDir tlbSegDir;
2328 ITypeLibImpl * pTypeLibImpl;
2330 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2332 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2333 if (!pTypeLibImpl) return NULL;
2335 pTypeLibImpl->lpVtbl = &tlbvt;
2336 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2337 pTypeLibImpl->ref = 1;
2339 /* get pointer to beginning of typelib data */
2343 cx.pLibInfo = pTypeLibImpl;
2344 cx.length = dwTLBLength;
2347 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2349 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2350 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2351 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2354 /* there is a small amount of information here until the next important
2356 * the segment directory . Try to calculate the amount of data */
2357 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2359 /* now read the segment directory */
2360 TRACE("read segment directory (at %ld)\n",lPSegDir);
2361 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2362 cx.pTblDir = &tlbSegDir;
2364 /* just check two entries */
2365 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2367 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2368 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2372 /* now fill our internal data */
2373 /* TLIBATTR fields */
2374 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2376 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2377 /* Windows seems to have zero here, is this correct? */
2378 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2379 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2381 pTypeLibImpl->LibAttr.lcid = 0;
2383 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2384 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2385 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2386 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2388 /* name, eventually add to a hash table */
2389 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2392 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2393 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2395 if( tlbHeader.varflags & HELPDLLFLAG)
2398 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2399 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2402 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2405 if(tlbHeader.CustomDataOffset >= 0)
2407 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2410 /* fill in typedescriptions */
2411 if(tlbSegDir.pTypdescTab.length > 0)
2413 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2415 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2416 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2419 /* FIXME: add several sanity checks here */
2420 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2421 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2423 /* FIXME: check safearray */
2425 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2427 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2429 else if(td[0] == VT_CARRAY)
2431 /* array descr table here */
2432 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2434 else if(td[0] == VT_USERDEFINED)
2436 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2438 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2441 /* second time around to fill the array subscript info */
2444 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2445 if(tlbSegDir.pArrayDescriptions.offset>0)
2447 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2448 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2451 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2453 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2455 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2457 for(j = 0; j<td[2]; j++)
2459 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2460 sizeof(INT), &cx, DO_NOT_SEEK);
2461 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2462 sizeof(INT), &cx, DO_NOT_SEEK);
2467 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2468 ERR("didn't find array description data\n");
2473 /* imported type libs */
2474 if(tlbSegDir.pImpFiles.offset>0)
2476 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2477 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2480 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2485 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2486 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2487 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2489 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2490 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2491 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2492 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2495 name = TLB_Alloc(size+1);
2496 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2497 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2498 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2499 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2502 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2503 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2505 ppImpLib = &(*ppImpLib)->next;
2510 if(tlbHeader.nrtypeinfos >= 0 )
2512 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2513 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2516 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2518 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2520 ppTI = &((*ppTI)->next);
2521 (pTypeLibImpl->TypeInfoCount)++;
2525 TRACE("(%p)\n", pTypeLibImpl);
2526 return (ITypeLib2*) pTypeLibImpl;
2530 static BSTR TLB_MultiByteToBSTR(char *ptr)
2536 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2537 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2538 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2539 ret = SysAllocString(nameW);
2540 HeapFree(GetProcessHeap(), 0, nameW);
2544 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2550 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2551 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2555 guid->Data4[0] = s >> 8;
2556 guid->Data4[1] = s & 0xff;
2559 for(i = 0; i < 6; i++) {
2560 memcpy(b, str + 24 + 2 * i, 2);
2561 guid->Data4[i + 2] = strtol(b, NULL, 16);
2566 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2573 bytelen = *(WORD*)ptr;
2574 if(bytelen == 0xffff) return 2;
2575 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2576 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2577 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2578 *pBstr = SysAllocStringLen(nameW, len);
2579 HeapFree(GetProcessHeap(), 0, nameW);
2583 static WORD SLTG_ReadStringA(char *ptr, char **str)
2588 bytelen = *(WORD*)ptr;
2589 if(bytelen == 0xffff) return 2;
2590 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2591 memcpy(*str, ptr + 2, bytelen);
2592 (*str)[bytelen] = '\0';
2596 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2598 char *ptr = pLibBlk;
2601 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2602 FIXME("libblk magic = %04x\n", w);
2607 if((w = *(WORD*)ptr) != 0xffff) {
2608 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2613 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2615 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2617 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2620 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2623 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2624 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2626 pTypeLibImpl->LibAttr.lcid = 0;
2629 ptr += 4; /* skip res12 */
2631 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2634 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2637 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2640 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2641 ptr += sizeof(GUID);
2643 return ptr - (char*)pLibBlk;
2646 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2649 TYPEDESC *pTD = &pElem->tdesc;
2651 /* Handle [in/out] first */
2652 if((*pType & 0xc000) == 0xc000)
2653 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2654 else if(*pType & 0x8000)
2655 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2656 else if(*pType & 0x4000)
2657 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2659 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2662 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2665 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2668 if((*pType & 0xe00) == 0xe00) {
2670 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2672 pTD = pTD->u.lptdesc;
2674 switch(*pType & 0x7f) {
2677 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2679 pTD = pTD->u.lptdesc;
2682 case VT_USERDEFINED:
2683 pTD->vt = VT_USERDEFINED;
2684 pTD->u.hreftype = *(++pType) / 4;
2690 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2693 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2695 pTD->vt = VT_CARRAY;
2696 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2698 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2699 pTD->u.lpadesc->cDims = pSA->cDims;
2700 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2701 pSA->cDims * sizeof(SAFEARRAYBOUND));
2703 pTD = &pTD->u.lpadesc->tdescElem;
2709 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2713 pTD->vt = VT_SAFEARRAY;
2714 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2716 pTD = pTD->u.lptdesc;
2720 pTD->vt = *pType & 0x7f;
2730 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2735 TLBRefType **ppRefType;
2737 if(pRef->magic != SLTG_REF_MAGIC) {
2738 FIXME("Ref magic = %x\n", pRef->magic);
2741 name = ( (char*)(&pRef->names) + pRef->number);
2743 ppRefType = &pTI->reflist;
2744 for(ref = 0; ref < pRef->number >> 3; ref++) {
2746 unsigned int lib_offs, type_num;
2748 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2749 sizeof(**ppRefType));
2751 name += SLTG_ReadStringA(name, &refname);
2752 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2753 FIXME("Can't sscanf ref\n");
2754 if(lib_offs != 0xffff) {
2755 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2758 if((*import)->offset == lib_offs)
2760 import = &(*import)->next;
2763 char fname[MAX_PATH+1];
2766 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2768 (*import)->offset = lib_offs;
2769 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2771 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2772 &(*import)->wVersionMajor,
2773 &(*import)->wVersionMinor,
2774 &(*import)->lcid, fname) != 4) {
2775 FIXME("can't sscanf ref %s\n",
2776 pNameTable + lib_offs + 40);
2778 len = strlen(fname);
2779 if(fname[len-1] != '#')
2780 FIXME("fname = %s\n", fname);
2781 fname[len-1] = '\0';
2782 (*import)->name = TLB_MultiByteToBSTR(fname);
2784 (*ppRefType)->pImpTLInfo = *import;
2785 } else { /* internal ref */
2786 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2788 (*ppRefType)->reference = ref;
2789 (*ppRefType)->index = type_num;
2791 HeapFree(GetProcessHeap(), 0, refname);
2792 ppRefType = &(*ppRefType)->next;
2794 if((BYTE)*name != SLTG_REF_MAGIC)
2795 FIXME("End of ref block magic = %x\n", *name);
2796 dump_TLBRefType(pTI->reflist);
2799 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2802 SLTG_ImplInfo *info;
2803 TLBImplType **ppImplType = &pTI->impltypelist;
2804 /* I don't really get this structure, usually it's 0x16 bytes
2805 long, but iuser.tlb contains some that are 0x18 bytes long.
2806 That's ok because we can use the next ptr to jump to the next
2807 one. But how do we know the length of the last one? The WORD
2808 at offs 0x8 might be the clue. For now I'm just assuming that
2809 the last one is the regular 0x16 bytes. */
2811 info = (SLTG_ImplInfo*)pBlk;
2813 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2814 sizeof(**ppImplType));
2815 (*ppImplType)->hRef = info->ref;
2816 (*ppImplType)->implflags = info->impltypeflags;
2817 pTI->TypeAttr.cImplTypes++;
2818 ppImplType = &(*ppImplType)->next;
2820 if(info->next == 0xffff)
2823 FIXME("Interface inheriting more than one interface\n");
2824 info = (SLTG_ImplInfo*)(pBlk + info->next);
2826 info++; /* see comment at top of function */
2830 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2833 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2834 SLTG_MemberHeader *pMemHeader;
2835 char *pFirstItem, *pNextItem;
2837 if(pTIHeader->href_table != 0xffffffff) {
2838 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2843 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2845 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2847 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2848 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2851 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2855 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2858 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2859 SLTG_MemberHeader *pMemHeader;
2860 SLTG_Function *pFunc;
2861 char *pFirstItem, *pNextItem;
2862 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2865 if(pTIHeader->href_table != 0xffffffff) {
2866 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2870 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2872 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2874 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2875 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2878 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2879 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2884 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2885 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2886 FIXME("func magic = %02x\n", pFunc->magic);
2889 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2890 sizeof(**ppFuncDesc));
2891 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2893 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2894 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2895 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2896 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2897 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2898 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2900 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2901 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2903 if(pFunc->retnextopt & 0x80)
2904 pType = &pFunc->rettype;
2906 pType = (WORD*)(pFirstItem + pFunc->rettype);
2909 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2911 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2912 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2913 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2914 (*ppFuncDesc)->pParamDesc =
2915 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2916 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2918 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2920 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2921 char *paramName = pNameTable + *pArg;
2923 /* If arg type follows then paramName points to the 2nd
2924 letter of the name, else the next WORD is an offset to
2925 the arg type and paramName points to the first letter.
2926 So let's take one char off paramName and see if we're
2927 pointing at an alpha-numeric char. However if *pArg is
2928 0xffff or 0xfffe then the param has no name, the former
2929 meaning that the next WORD is the type, the latter
2930 meaning the the next WORD is an offset to the type. */
2935 else if(*pArg == 0xfffe) {
2939 else if(paramName[-1] && !isalnum(paramName[-1]))
2944 if(HaveOffs) { /* the next word is an offset to type */
2945 pType = (WORD*)(pFirstItem + *pArg);
2946 SLTG_DoType(pType, pFirstItem,
2947 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2952 pArg = SLTG_DoType(pArg, pFirstItem,
2953 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2956 /* Are we an optional param ? */
2957 if((*ppFuncDesc)->funcdesc.cParams - param <=
2958 (*ppFuncDesc)->funcdesc.cParamsOpt)
2959 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2962 (*ppFuncDesc)->pParamDesc[param].Name =
2963 TLB_MultiByteToBSTR(paramName);
2967 ppFuncDesc = &((*ppFuncDesc)->next);
2968 if(pFunc->next == 0xffff) break;
2970 pTI->TypeAttr.cFuncs = num;
2971 dump_TLBFuncDesc(pTI->funclist);
2972 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2975 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2978 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2979 SLTG_MemberHeader *pMemHeader;
2980 SLTG_RecordItem *pItem;
2982 TLBVarDesc **ppVarDesc = &pTI->varlist;
2987 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2989 pFirstItem = (char*)(pMemHeader + 1);
2990 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2991 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2992 if(pItem->magic != SLTG_RECORD_MAGIC) {
2993 FIXME("record magic = %02x\n", pItem->magic);
2996 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2997 sizeof(**ppVarDesc));
2998 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2999 (*ppVarDesc)->vardesc.memid = pItem->memid;
3000 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3001 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3003 if(pItem->typepos == 0x02)
3004 pType = &pItem->type;
3005 else if(pItem->typepos == 0x00)
3006 pType = (WORD*)(pFirstItem + pItem->type);
3008 FIXME("typepos = %02x\n", pItem->typepos);
3012 SLTG_DoType(pType, pFirstItem,
3013 &(*ppVarDesc)->vardesc.elemdescVar);
3015 /* FIXME("helpcontext, helpstring\n"); */
3017 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3019 ppVarDesc = &((*ppVarDesc)->next);
3020 if(pItem->next == 0xffff) break;
3022 pTI->TypeAttr.cVars = num;
3023 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3026 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3029 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3030 SLTG_MemberHeader *pMemHeader;
3031 SLTG_AliasItem *pItem;
3034 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3035 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3038 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3039 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3040 if (pItem->vt == 0xffff) {
3041 if (i<(pMemHeader->cbExtra/4-1))
3042 FIXME("Endmarker too early in process alias data!\n");
3046 FIXME("Chain extends over last entry?\n");
3049 if (pItem->vt == VT_USERDEFINED) {
3050 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3051 /* guessing here ... */
3052 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3053 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3056 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3057 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3061 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3064 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3067 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3068 SLTG_MemberHeader *pMemHeader;
3069 SLTG_AliasItem *pItem;
3071 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3072 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3073 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3074 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3075 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3078 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3081 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3082 SLTG_MemberHeader *pMemHeader;
3083 SLTG_EnumItem *pItem;
3085 TLBVarDesc **ppVarDesc = &pTI->varlist;
3088 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3090 pFirstItem = (char*)(pMemHeader + 1);
3091 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3092 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3093 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3094 FIXME("enumitem magic = %04x\n", pItem->magic);
3097 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3098 sizeof(**ppVarDesc));
3099 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3100 (*ppVarDesc)->vardesc.memid = pItem->memid;
3101 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3103 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3104 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3105 *(INT*)(pItem->value + pFirstItem);
3106 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3107 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3108 /* FIXME("helpcontext, helpstring\n"); */
3110 ppVarDesc = &((*ppVarDesc)->next);
3111 if(pItem->next == 0xffff) break;
3113 pTI->TypeAttr.cVars = num;
3114 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3117 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3118 managable copy of it into this */
3131 } SLTG_InternalOtherTypeInfo;
3133 /****************************************************************************
3134 * ITypeLib2_Constructor_SLTG
3136 * loading a SLTG typelib from an in-memory image
3138 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3140 ITypeLibImpl *pTypeLibImpl;
3141 SLTG_Header *pHeader;
3142 SLTG_BlkEntry *pBlkEntry;
3146 LPVOID pBlk, pFirstBlk;
3147 SLTG_LibBlk *pLibBlk;
3148 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3149 char *pAfterOTIBlks = NULL;
3150 char *pNameTable, *ptr;
3153 ITypeInfoImpl **ppTypeInfoImpl;
3155 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3157 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3158 if (!pTypeLibImpl) return NULL;
3160 pTypeLibImpl->lpVtbl = &tlbvt;
3161 pTypeLibImpl->ref = 1;
3165 TRACE_(typelib)("header:\n");
3166 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3167 pHeader->nrOfFileBlks );
3168 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3169 FIXME("Header type magic 0x%08lx not supported.\n",
3170 pHeader->SLTG_magic);
3174 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3175 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3177 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3178 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3180 /* Next we have a magic block */
3181 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3183 /* Let's see if we're still in sync */
3184 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3185 sizeof(SLTG_COMPOBJ_MAGIC))) {
3186 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3189 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3190 sizeof(SLTG_DIR_MAGIC))) {
3191 FIXME("dir magic = %s\n", pMagic->dir_magic);
3195 pIndex = (SLTG_Index*)(pMagic+1);
3197 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3199 pFirstBlk = (LPVOID)(pPad9 + 1);
3201 /* We'll set up a ptr to the main library block, which is the last one. */
3203 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3204 pBlkEntry[order].next != 0;
3205 order = pBlkEntry[order].next - 1, i++) {
3206 pBlk = (char*)pBlk + pBlkEntry[order].len;
3210 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3212 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3217 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3219 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3220 sizeof(*pOtherTypeInfoBlks) *
3221 pTypeLibImpl->TypeInfoCount);
3224 ptr = (char*)pLibBlk + len;
3226 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3230 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3232 w = *(WORD*)(ptr + 2);
3235 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3237 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3238 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3240 w = *(WORD*)(ptr + 4 + len);
3242 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3244 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3246 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3247 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3249 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3250 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3251 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3253 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3255 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3258 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3259 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3260 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3261 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3262 len += sizeof(SLTG_OtherTypeInfo);
3266 pAfterOTIBlks = ptr;
3268 /* Skip this WORD and get the next DWORD */
3269 len = *(DWORD*)(pAfterOTIBlks + 2);
3271 /* Now add this to pLibBLk look at what we're pointing at and
3272 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3273 dust and we should be pointing at the beginning of the name
3276 pNameTable = (char*)pLibBlk + len;
3278 switch(*(WORD*)pNameTable) {
3285 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3289 pNameTable += 0x216;
3293 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3295 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3298 /* Hopefully we now have enough ptrs set up to actually read in
3299 some TypeInfos. It's not clear which order to do them in, so
3300 I'll just follow the links along the BlkEntry chain and read
3301 them in in the order in which they're in the file */
3303 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3305 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3306 pBlkEntry[order].next != 0;
3307 order = pBlkEntry[order].next - 1, i++) {
3309 SLTG_TypeInfoHeader *pTIHeader;
3310 SLTG_TypeInfoTail *pTITail;
3312 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3313 pOtherTypeInfoBlks[i].index_name)) {
3314 FIXME("Index strings don't match\n");
3319 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3320 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3323 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3324 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3325 (*ppTypeInfoImpl)->index = i;
3326 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3327 pOtherTypeInfoBlks[i].name_offs +
3329 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3330 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3332 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3333 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3334 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3335 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3336 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3338 if((pTIHeader->typeflags1 & 7) != 2)
3339 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3340 if(pTIHeader->typeflags3 != 2)
3341 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3343 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3344 debugstr_w((*ppTypeInfoImpl)->Name),
3345 typekind_desc[pTIHeader->typekind],
3346 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3347 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3349 switch(pTIHeader->typekind) {
3351 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3355 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3358 case TKIND_INTERFACE:
3359 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3363 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3367 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3368 if (pTITail->tdescalias_vt)
3369 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3372 case TKIND_DISPATCH:
3373 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3377 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3383 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3384 but we've already set those */
3385 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3386 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3387 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3389 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3411 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3412 pBlk = (char*)pBlk + pBlkEntry[order].len;
3415 if(i != pTypeLibImpl->TypeInfoCount) {
3416 FIXME("Somehow processed %d TypeInfos\n", i);
3420 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3421 return (ITypeLib2*)pTypeLibImpl;
3424 /* ITypeLib::QueryInterface
3426 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3431 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3433 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3436 if(IsEqualIID(riid, &IID_IUnknown) ||
3437 IsEqualIID(riid,&IID_ITypeLib)||
3438 IsEqualIID(riid,&IID_ITypeLib2))
3445 ITypeLib2_AddRef(iface);
3446 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3449 TRACE("-- Interface: E_NOINTERFACE\n");
3450 return E_NOINTERFACE;
3455 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3457 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3458 ULONG ref = InterlockedIncrement(&This->ref);
3460 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3465 /* ITypeLib::Release
3467 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3469 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3470 ULONG ref = InterlockedDecrement(&This->ref);
3472 TRACE("(%p)->(%lu)\n",This, ref);
3476 /* remove cache entry */
3477 TRACE("removing from cache list\n");
3478 EnterCriticalSection(&cache_section);
3479 if (This->next) This->next->prev = This->prev;
3480 if (This->prev) This->prev->next = This->next;
3481 else tlb_cache_first = This->next;
3482 LeaveCriticalSection(&cache_section);
3484 /* FIXME destroy child objects */
3485 TRACE(" destroying ITypeLib(%p)\n",This);
3489 SysFreeString(This->Name);
3493 if (This->DocString)
3495 SysFreeString(This->DocString);
3496 This->DocString = NULL;
3501 SysFreeString(This->HelpFile);
3502 This->HelpFile = NULL;
3505 if (This->HelpStringDll)
3507 SysFreeString(This->HelpStringDll);
3508 This->HelpStringDll = NULL;
3511 if (This->pTypeInfo) /* can be NULL */
3512 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3513 HeapFree(GetProcessHeap(),0,This);
3520 /* ITypeLib::GetTypeInfoCount
3522 * Returns the number of type descriptions in the type library
3524 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3526 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3527 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3528 return This->TypeInfoCount;
3531 /* ITypeLib::GetTypeInfo
3533 * retrieves the specified type description in the library.
3535 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3538 ITypeInfo **ppTInfo)
3542 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3543 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3545 TRACE("(%p)->(index=%d)\n", This, index);
3547 if (!ppTInfo) return E_INVALIDARG;
3549 /* search element n in list */
3550 for(i=0; i < index; i++)
3552 pTypeInfo = pTypeInfo->next;
3555 TRACE("-- element not found\n");
3556 return TYPE_E_ELEMENTNOTFOUND;
3560 *ppTInfo = (ITypeInfo *) pTypeInfo;
3562 ITypeInfo_AddRef(*ppTInfo);
3563 TRACE("-- found (%p)\n",*ppTInfo);
3568 /* ITypeLibs::GetTypeInfoType
3570 * Retrieves the type of a type description.
3572 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3577 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3579 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3581 TRACE("(%p) index %d\n", This, index);
3583 if(!pTKind) return E_INVALIDARG;
3585 /* search element n in list */
3586 for(i=0; i < index; i++)
3590 TRACE("-- element not found\n");
3591 return TYPE_E_ELEMENTNOTFOUND;
3593 pTInfo = pTInfo->next;
3596 *pTKind = pTInfo->TypeAttr.typekind;
3597 TRACE("-- found Type (%d)\n", *pTKind);
3601 /* ITypeLib::GetTypeInfoOfGuid
3603 * Retrieves the type description that corresponds to the specified GUID.
3606 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3609 ITypeInfo **ppTInfo)
3611 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3612 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3614 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3616 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3618 /* search linked list for guid */
3619 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3621 pTypeInfo = pTypeInfo->next;
3625 /* end of list reached */
3626 TRACE("-- element not found\n");
3627 return TYPE_E_ELEMENTNOTFOUND;
3631 TRACE("-- found (%p, %s)\n",
3633 debugstr_w(pTypeInfo->Name));
3635 *ppTInfo = (ITypeInfo*)pTypeInfo;
3636 ITypeInfo_AddRef(*ppTInfo);
3640 /* ITypeLib::GetLibAttr
3642 * Retrieves the structure that contains the library's attributes.
3645 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3647 LPTLIBATTR *ppTLibAttr)
3649 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3650 TRACE("(%p)\n",This);
3651 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3652 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3656 /* ITypeLib::GetTypeComp
3658 * Enables a client compiler to bind to a library's types, variables,
3659 * constants, and global functions.
3662 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3664 ITypeComp **ppTComp)
3666 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3668 TRACE("(%p)->(%p)\n",This,ppTComp);
3669 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3670 ITypeComp_AddRef(*ppTComp);
3675 /* ITypeLib::GetDocumentation
3677 * Retrieves the library's documentation string, the complete Help file name
3678 * and path, and the context identifier for the library Help topic in the Help
3681 * On a successful return all non-null BSTR pointers will have been set,
3684 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3688 BSTR *pBstrDocString,
3689 DWORD *pdwHelpContext,
3690 BSTR *pBstrHelpFile)
3692 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3694 HRESULT result = E_INVALIDARG;
3699 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3701 pBstrName, pBstrDocString,
3702 pdwHelpContext, pBstrHelpFile);
3706 /* documentation for the typelib */
3711 if(!(*pBstrName = SysAllocString(This->Name)))
3719 if (This->DocString)
3721 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3724 else if (This->Name)
3726 if(!(*pBstrDocString = SysAllocString(This->Name)))
3730 *pBstrDocString = NULL;
3734 *pdwHelpContext = This->dwHelpContext;
3740 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3744 *pBstrHelpFile = NULL;
3751 /* for a typeinfo */
3752 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3754 if(SUCCEEDED(result))
3756 result = ITypeInfo_GetDocumentation(pTInfo,
3760 pdwHelpContext, pBstrHelpFile);
3762 ITypeInfo_Release(pTInfo);
3767 if (pBstrDocString) SysFreeString (*pBstrDocString);
3769 if (pBstrName) SysFreeString (*pBstrName);
3771 return STG_E_INSUFFICIENTMEMORY;
3776 * Indicates whether a passed-in string contains the name of a type or member
3777 * described in the library.
3780 static HRESULT WINAPI ITypeLib2_fnIsName(
3786 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3787 ITypeInfoImpl *pTInfo;
3788 TLBFuncDesc *pFInfo;
3791 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3793 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3797 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3798 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3799 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3800 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3801 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3802 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3803 goto ITypeLib2_fnIsName_exit;
3805 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3806 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3811 ITypeLib2_fnIsName_exit:
3812 TRACE("(%p)slow! search for %s: %s found!\n", This,
3813 debugstr_w(szNameBuf), *pfName?"NOT":"");
3818 /* ITypeLib::FindName
3820 * Finds occurrences of a type description in a type library. This may be used
3821 * to quickly verify that a name exists in a type library.
3824 static HRESULT WINAPI ITypeLib2_fnFindName(
3828 ITypeInfo **ppTInfo,
3832 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3833 ITypeInfoImpl *pTInfo;
3834 TLBFuncDesc *pFInfo;
3837 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3839 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3840 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3841 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3842 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3843 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3844 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3845 goto ITypeLib2_fnFindName_exit;
3848 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3849 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3851 ITypeLib2_fnFindName_exit:
3852 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3853 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3856 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3857 This, *pcFound, debugstr_w(szNameBuf), j);
3864 /* ITypeLib::ReleaseTLibAttr
3866 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3869 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3871 TLIBATTR *pTLibAttr)
3873 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3874 TRACE("freeing (%p)\n",This);
3875 HeapFree(GetProcessHeap(),0,pTLibAttr);
3879 /* ITypeLib2::GetCustData
3881 * gets the custom data
3883 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3888 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3889 TLBCustData *pCData;
3891 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3893 if( IsEqualIID(guid, &pCData->guid)) break;
3896 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3900 VariantInit( pVarVal);
3901 VariantCopy( pVarVal, &pCData->data);
3904 return E_INVALIDARG; /* FIXME: correct? */
3907 /* ITypeLib2::GetLibStatistics
3909 * Returns statistics about a type library that are required for efficient
3910 * sizing of hash tables.
3913 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3915 ULONG *pcUniqueNames,
3916 ULONG *pcchUniqueNames)
3918 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3920 FIXME("(%p): stub!\n", This);
3922 if(pcUniqueNames) *pcUniqueNames=1;
3923 if(pcchUniqueNames) *pcchUniqueNames=1;
3927 /* ITypeLib2::GetDocumentation2
3929 * Retrieves the library's documentation string, the complete Help file name
3930 * and path, the localization context to use, and the context ID for the
3931 * library Help topic in the Help file.
3934 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3938 BSTR *pbstrHelpString,
3939 DWORD *pdwHelpStringContext,
3940 BSTR *pbstrHelpStringDll)
3942 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3946 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3948 /* the help string should be obtained from the helpstringdll,
3949 * using the _DLLGetDocumentation function, based on the supplied
3950 * lcid. Nice to do sometime...
3954 /* documentation for the typelib */
3956 *pbstrHelpString=SysAllocString(This->DocString);
3957 if(pdwHelpStringContext)
3958 *pdwHelpStringContext=This->dwHelpContext;
3959 if(pbstrHelpStringDll)
3960 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3966 /* for a typeinfo */
3967 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3969 if(SUCCEEDED(result))
3971 ITypeInfo2 * pTInfo2;
3972 result = ITypeInfo_QueryInterface(pTInfo,
3974 (LPVOID*) &pTInfo2);
3976 if(SUCCEEDED(result))
3978 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3982 pdwHelpStringContext,
3983 pbstrHelpStringDll);
3985 ITypeInfo2_Release(pTInfo2);
3988 ITypeInfo_Release(pTInfo);
3994 /* ITypeLib2::GetAllCustData
3996 * Gets all custom data items for the library.
3999 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4001 CUSTDATA *pCustData)
4003 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4004 TLBCustData *pCData;
4006 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4007 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4008 if(pCustData->prgCustData ){
4009 pCustData->cCustData=This->ctCustData;
4010 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4011 pCustData->prgCustData[i].guid=pCData->guid;
4012 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4015 ERR(" OUT OF MEMORY!\n");
4016 return E_OUTOFMEMORY;
4021 static const ITypeLib2Vtbl tlbvt = {
4022 ITypeLib2_fnQueryInterface,
4024 ITypeLib2_fnRelease,
4025 ITypeLib2_fnGetTypeInfoCount,
4026 ITypeLib2_fnGetTypeInfo,
4027 ITypeLib2_fnGetTypeInfoType,
4028 ITypeLib2_fnGetTypeInfoOfGuid,
4029 ITypeLib2_fnGetLibAttr,
4030 ITypeLib2_fnGetTypeComp,
4031 ITypeLib2_fnGetDocumentation,
4033 ITypeLib2_fnFindName,
4034 ITypeLib2_fnReleaseTLibAttr,
4036 ITypeLib2_fnGetCustData,
4037 ITypeLib2_fnGetLibStatistics,
4038 ITypeLib2_fnGetDocumentation2,
4039 ITypeLib2_fnGetAllCustData
4043 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4045 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4047 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4050 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4052 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4054 return ITypeLib2_AddRef((ITypeLib2 *)This);
4057 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4059 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4061 return ITypeLib2_Release((ITypeLib2 *)This);
4064 static HRESULT WINAPI ITypeLibComp_fnBind(
4069 ITypeInfo ** ppTInfo,
4070 DESCKIND * pDescKind,
4073 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4074 ITypeInfoImpl *pTypeInfo;
4076 TRACE("(%s, 0x%lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4078 *pDescKind = DESCKIND_NONE;
4079 pBindPtr->lptcomp = NULL;
4082 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4084 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4086 /* FIXME: check wFlags here? */
4087 /* FIXME: we should use a hash table to look this info up using lHash
4088 * instead of an O(n) search */
4089 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4090 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4092 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4094 *pDescKind = DESCKIND_TYPECOMP;
4095 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4096 ITypeComp_AddRef(pBindPtr->lptcomp);
4097 TRACE("module or enum: %s\n", debugstr_w(szName));
4102 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4103 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4105 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4108 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4109 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4111 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4116 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4117 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4119 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4121 ITypeInfo *subtypeinfo;
4123 DESCKIND subdesckind;
4125 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4126 &subtypeinfo, &subdesckind, &subbindptr);
4127 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4129 TYPEDESC tdesc_appobject =
4132 (TYPEDESC *)pTypeInfo->hreftype
4136 const VARDESC vardesc_appobject =
4139 NULL, /* lpstrSchema */
4154 VAR_STATIC /* varkind */
4157 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4159 /* cleanup things filled in by Bind call so we can put our
4160 * application object data in there instead */
4161 switch (subdesckind)
4163 case DESCKIND_FUNCDESC:
4164 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4166 case DESCKIND_VARDESC:
4167 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4172 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4174 if (pTypeInfo->hreftype == -1)
4175 FIXME("no hreftype for interface %p\n", pTypeInfo);
4177 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4181 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4182 *ppTInfo = (ITypeInfo *)pTypeInfo;
4183 ITypeInfo_AddRef(*ppTInfo);
4189 TRACE("name not found %s\n", debugstr_w(szName));
4193 static HRESULT WINAPI ITypeLibComp_fnBindType(
4197 ITypeInfo ** ppTInfo,
4198 ITypeComp ** ppTComp)
4200 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4204 static const ITypeCompVtbl tlbtcvt =
4207 ITypeLibComp_fnQueryInterface,
4208 ITypeLibComp_fnAddRef,
4209 ITypeLibComp_fnRelease,
4211 ITypeLibComp_fnBind,
4212 ITypeLibComp_fnBindType
4215 /*================== ITypeInfo(2) Methods ===================================*/
4216 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4218 ITypeInfoImpl * pTypeInfoImpl;
4220 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4223 pTypeInfoImpl->lpVtbl = &tinfvt;
4224 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4225 pTypeInfoImpl->ref=1;
4226 pTypeInfoImpl->hreftype = -1;
4228 TRACE("(%p)\n", pTypeInfoImpl);
4229 return (ITypeInfo2*) pTypeInfoImpl;
4232 /* ITypeInfo::QueryInterface
4234 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4239 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4241 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4244 if(IsEqualIID(riid, &IID_IUnknown) ||
4245 IsEqualIID(riid,&IID_ITypeInfo)||
4246 IsEqualIID(riid,&IID_ITypeInfo2))
4250 ITypeInfo_AddRef(iface);
4251 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4254 TRACE("-- Interface: E_NOINTERFACE\n");
4255 return E_NOINTERFACE;
4258 /* ITypeInfo::AddRef
4260 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4262 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4263 ULONG ref = InterlockedIncrement(&This->ref);
4265 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4267 TRACE("(%p)->ref is %lu\n",This, ref);
4271 /* ITypeInfo::Release
4273 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4275 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4276 ULONG ref = InterlockedDecrement(&This->ref);
4278 TRACE("(%p)->(%lu)\n",This, ref);
4281 /* We don't release ITypeLib when ref=0 because
4282 it means that function is called by ITypeLib2_Release */
4283 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4285 FIXME("destroy child objects\n");
4287 TRACE("destroying ITypeInfo(%p)\n",This);
4290 SysFreeString(This->Name);
4294 if (This->DocString)
4296 SysFreeString(This->DocString);
4297 This->DocString = 0;
4302 SysFreeString(This->DllName);
4308 ITypeInfo_Release((ITypeInfo*)This->next);
4311 HeapFree(GetProcessHeap(),0,This);
4317 /* ITypeInfo::GetTypeAttr
4319 * Retrieves a TYPEATTR structure that contains the attributes of the type
4323 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4324 LPTYPEATTR *ppTypeAttr)
4326 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4329 TRACE("(%p)\n",This);
4331 size = sizeof(**ppTypeAttr);
4332 if (This->TypeAttr.typekind == TKIND_ALIAS)
4333 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
4335 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
4337 return E_OUTOFMEMORY;
4339 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4341 if (This->TypeAttr.typekind == TKIND_ALIAS)
4342 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
4343 &This->TypeAttr.tdescAlias, (void *)(*ppTypeAttr + 1));
4345 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4346 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4348 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4349 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4354 /* ITypeInfo::GetTypeComp
4356 * Retrieves the ITypeComp interface for the type description, which enables a
4357 * client compiler to bind to the type description's members.
4360 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4361 ITypeComp * *ppTComp)
4363 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4365 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4367 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4368 ITypeComp_AddRef(*ppTComp);
4372 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
4374 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
4375 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4376 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
4380 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
4382 memcpy(dest, src, sizeof(ELEMDESC));
4383 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
4384 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4386 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
4387 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
4388 *buffer += sizeof(PARAMDESCEX);
4389 memcpy(pparamdescex_dest, pparamdescex_src, sizeof(PARAMDESCEX));
4390 VariantInit(&pparamdescex_dest->varDefaultValue);
4391 return VariantCopy(&pparamdescex_dest->varDefaultValue,
4392 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
4395 dest->u.paramdesc.pparamdescex = NULL;
4399 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
4401 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4402 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4405 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
4409 SIZE_T size = sizeof(*src);
4413 size += sizeof(*src->lprgscode) * src->cScodes;
4414 size += TLB_SizeElemDesc(&src->elemdescFunc);
4415 for (i = 0; i < src->cParams; i++)
4417 size += sizeof(ELEMDESC);
4418 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
4421 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
4422 if (!dest) return E_OUTOFMEMORY;
4424 memcpy(dest, src, sizeof(FUNCDESC));
4425 buffer = (char *)(dest + 1);
4427 dest->lprgscode = (SCODE *)buffer;
4428 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
4429 buffer += sizeof(*src->lprgscode) * src->cScodes;
4431 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
4434 SysFreeString((BSTR)dest);
4438 dest->lprgelemdescParam = (ELEMDESC *)buffer;
4439 buffer += sizeof(ELEMDESC) * src->cParams;
4440 for (i = 0; i < src->cParams; i++)
4442 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
4448 /* undo the above actions */
4449 for (i = i - 1; i >= 0; i--)
4450 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
4451 TLB_FreeElemDesc(&dest->elemdescFunc);
4452 SysFreeString((BSTR)dest);
4456 /* special treatment for dispinterfaces: this makes functions appear
4457 * to return their [retval] value when it is really returning an
4459 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
4461 if (dest->cParams &&
4462 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
4464 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
4465 if (elemdesc->tdesc.vt != VT_PTR)
4467 ERR("elemdesc should have started with VT_PTR instead of:\n");
4469 dump_ELEMDESC(elemdesc);
4470 return E_UNEXPECTED;
4473 /* copy last parameter to the return value. we are using a flat
4474 * buffer so there is no danger of leaking memory in
4476 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
4478 /* remove the last parameter */
4482 /* otherwise this function is made to appear to have no return
4484 dest->elemdescFunc.tdesc.vt = VT_VOID;
4492 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
4494 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4495 const TLBFuncDesc *pFDesc;
4498 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4503 *ppFuncDesc = &pFDesc->funcdesc;
4507 return E_INVALIDARG;
4510 /* ITypeInfo::GetFuncDesc
4512 * Retrieves the FUNCDESC structure that contains information about a
4513 * specified function.
4516 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4517 LPFUNCDESC *ppFuncDesc)
4519 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4520 const FUNCDESC *internal_funcdesc;
4523 TRACE("(%p) index %d\n", This, index);
4525 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index, &internal_funcdesc);
4529 return TLB_AllocAndInitFuncDesc(
4532 This->TypeAttr.typekind == TKIND_DISPATCH);
4535 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
4539 SIZE_T size = sizeof(*src);
4542 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
4543 if (src->varkind == VAR_CONST)
4544 size += sizeof(VARIANT);
4545 size += TLB_SizeElemDesc(&src->elemdescVar);
4547 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
4548 if (!dest) return E_OUTOFMEMORY;
4551 buffer = (char *)(dest + 1);
4552 if (src->lpstrSchema)
4555 dest->lpstrSchema = (LPOLESTR)buffer;
4556 len = strlenW(src->lpstrSchema);
4557 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
4558 buffer += (len + 1) * sizeof(WCHAR);
4561 if (src->varkind == VAR_CONST)
4565 dest->u.lpvarValue = (VARIANT *)buffer;
4566 *dest->u.lpvarValue = *src->u.lpvarValue;
4567 buffer += sizeof(VARIANT);
4568 VariantInit(dest->u.lpvarValue);
4569 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
4572 SysFreeString((BSTR)dest_ptr);
4576 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
4579 if (src->varkind == VAR_CONST)
4580 VariantClear(dest->u.lpvarValue);
4581 SysFreeString((BSTR)dest);
4588 /* ITypeInfo::GetVarDesc
4590 * Retrieves a VARDESC structure that describes the specified variable.
4593 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4594 LPVARDESC *ppVarDesc)
4596 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4598 const TLBVarDesc *pVDesc;
4600 TRACE("(%p) index %d\n", This, index);
4602 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4606 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
4608 return E_INVALIDARG;
4611 /* ITypeInfo_GetNames
4613 * Retrieves the variable with the specified member ID (or the name of the
4614 * property or method and its parameters) that correspond to the specified
4617 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4618 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4620 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4621 TLBFuncDesc * pFDesc;
4622 TLBVarDesc * pVDesc;
4624 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4625 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4628 /* function found, now return function and parameter names */
4629 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4632 *rgBstrNames=SysAllocString(pFDesc->Name);
4634 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4640 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4643 *rgBstrNames=SysAllocString(pVDesc->Name);
4648 if(This->TypeAttr.cImplTypes &&
4649 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4650 /* recursive search */
4653 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4655 if(SUCCEEDED(result))
4657 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4658 ITypeInfo_Release(pTInfo);
4661 WARN("Could not search inherited interface!\n");
4665 WARN("no names found\n");
4668 return TYPE_E_ELEMENTNOTFOUND;
4675 /* ITypeInfo::GetRefTypeOfImplType
4677 * If a type description describes a COM class, it retrieves the type
4678 * description of the implemented interface types. For an interface,
4679 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4683 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4688 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4691 TLBImplType *pImpl = This->impltypelist;
4693 TRACE("(%p) index %d\n", This, index);
4694 if (TRACE_ON(ole)) dump_TypeInfo(This);
4698 /* only valid on dual interfaces;
4699 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4701 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4703 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4704 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4710 hr = TYPE_E_ELEMENTNOTFOUND;
4715 /* get element n from linked list */
4716 for(i=0; pImpl && i<index; i++)
4718 pImpl = pImpl->next;
4722 *pRefType = pImpl->hRef;
4724 hr = TYPE_E_ELEMENTNOTFOUND;
4730 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4732 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4738 /* ITypeInfo::GetImplTypeFlags
4740 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4741 * or base interface in a type description.
4743 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4744 UINT index, INT *pImplTypeFlags)
4746 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4750 TRACE("(%p) index %d\n", This, index);
4751 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4752 i++, pImpl=pImpl->next)
4754 if(i==index && pImpl){
4755 *pImplTypeFlags=pImpl->implflags;
4759 return TYPE_E_ELEMENTNOTFOUND;
4763 * Maps between member names and member IDs, and parameter names and
4766 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4767 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4769 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4770 TLBFuncDesc * pFDesc;
4771 TLBVarDesc * pVDesc;
4774 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4776 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4778 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4779 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4780 for(i=1; i < cNames; i++){
4781 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4782 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4784 if( j<pFDesc->funcdesc.cParams)
4787 ret=DISP_E_UNKNOWNNAME;
4792 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4793 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4794 if(cNames) *pMemId=pVDesc->vardesc.memid;
4798 /* not found, see if this is and interface with an inheritance */
4799 if(This->TypeAttr.cImplTypes &&
4800 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4801 /* recursive search */
4803 ret=ITypeInfo_GetRefTypeInfo(iface,
4804 This->impltypelist->hRef, &pTInfo);
4806 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4807 ITypeInfo_Release(pTInfo);
4810 WARN("Could not search inherited interface!\n");
4812 WARN("no names found\n");
4813 return DISP_E_UNKNOWNNAME;
4816 /* ITypeInfo::Invoke
4818 * Invokes a method, or accesses a property of an object, that implements the
4819 * interface described by the type description.
4822 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4825 if (TRACE_ON(ole)) {
4827 TRACE("Calling %p(",func);
4828 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4840 res = func(args[0]);
4843 res = func(args[0],args[1]);
4846 res = func(args[0],args[1],args[2]);
4849 res = func(args[0],args[1],args[2],args[3]);
4852 res = func(args[0],args[1],args[2],args[3],args[4]);
4855 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4858 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4861 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4864 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4867 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4870 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4873 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]);
4876 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]);
4879 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]);
4882 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4888 FIXME("unsupported calling convention %d\n",callconv);
4892 TRACE("returns %08lx\n",res);
4896 extern int _argsize(DWORD vt);
4898 /****************************************************************************
4899 * Helper functions for Dispcall / Invoke, which copies one variant
4900 * with target type onto the argument stack.
4903 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4904 DWORD *argpos, VARIANT *arg, VARTYPE vt
4906 UINT arglen = _argsize(vt)*sizeof(DWORD);
4909 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4910 memcpy(argpos,&arg,sizeof(void*));
4914 if (V_VT(arg) == vt) {
4915 memcpy(argpos, &V_I4(arg), arglen);
4919 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4920 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4924 if (vt == VT_VARIANT) {
4925 memcpy(argpos, arg, arglen);
4928 /* Deref BYREF vars if there is need */
4929 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4930 memcpy(argpos,(void*)V_I4(arg), arglen);
4933 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4934 /* in this context, if the type lib specifies IUnknown*, giving an
4935 IDispatch* is correct; so, don't invoke VariantChangeType */
4936 memcpy(argpos,&V_I4(arg), arglen);
4939 if ((vt == VT_PTR) && tdesc)
4940 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4942 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4943 ITypeInfo *tinfo2 = NULL;
4944 TYPEATTR *tattr = NULL;
4947 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4949 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4950 "while coercing from vt 0x%x. Copying 4 byte.\n",
4951 tdesc->u.hreftype,V_VT(arg));
4952 memcpy(argpos, &V_I4(arg), 4);
4955 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4958 ERR("GetTypeAttr failed\n");
4959 ITypeInfo_Release(tinfo2);
4962 switch (tattr->typekind) {
4964 switch ( V_VT( arg ) ) {
4966 *argpos = V_I2(arg);
4970 memcpy(argpos, &V_I4(arg), 4);
4973 case VT_BYREF|VT_I4:
4974 memcpy(argpos, V_I4REF(arg), 4);
4978 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4985 tdesc = &(tattr->tdescAlias);
4986 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4989 case TKIND_INTERFACE:
4990 if (V_VT(arg) == VT_DISPATCH) {
4992 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4993 memcpy(argpos, &V_DISPATCH(arg), 4);
4997 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4998 &IID_IDispatch,(LPVOID*)&disp);
4999 if (SUCCEEDED(hres)) {
5000 memcpy(argpos,&disp,4);
5001 IUnknown_Release(V_DISPATCH(arg));
5005 FIXME("Failed to query IDispatch interface from %s while "
5006 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
5010 if (V_VT(arg) == VT_UNKNOWN) {
5011 memcpy(argpos, &V_UNKNOWN(arg), 4);
5015 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
5016 V_VT(arg),debugstr_guid(&(tattr->guid)));
5020 case TKIND_DISPATCH:
5021 if (V_VT(arg) == VT_DISPATCH) {
5022 memcpy(argpos, &V_DISPATCH(arg), 4);
5027 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
5031 FIXME("TKIND_RECORD unhandled.\n");
5035 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5039 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5040 ITypeInfo_Release(tinfo2);
5045 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
5046 memcpy(argpos,&V_I4(&va), arglen);
5047 FIXME("Should not use VariantChangeType here."
5048 " (conversion from 0x%x -> 0x%x) %08lx\n",
5049 V_VT(arg), vt, *argpos
5053 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
5057 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
5060 ITypeInfo *tinfo2 = NULL;
5061 TYPEATTR *tattr = NULL;
5063 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5066 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
5068 tdesc->u.hreftype, hr);
5071 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5074 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
5075 ITypeInfo_Release(tinfo2);
5079 switch (tattr->typekind)
5086 tdesc = &tattr->tdescAlias;
5087 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5090 case TKIND_INTERFACE:
5091 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
5097 case TKIND_DISPATCH:
5102 FIXME("TKIND_RECORD unhandled.\n");
5107 FIXME("TKIND_RECORD unhandled.\n");
5112 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5116 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5117 ITypeInfo_Release(tinfo2);
5121 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
5125 /* enforce only one level of pointer indirection */
5126 if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
5128 tdesc = tdesc->u.lptdesc;
5130 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5131 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5132 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5133 if ((tdesc->vt == VT_USERDEFINED) ||
5134 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5136 VARTYPE vt_userdefined = 0;
5137 TYPEDESC *tdesc_userdefined = tdesc;
5138 if (tdesc->vt == VT_PTR)
5140 vt_userdefined = VT_BYREF;
5141 tdesc_userdefined = tdesc->u.lptdesc;
5143 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5145 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5146 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5148 *vt |= vt_userdefined;
5160 case VT_USERDEFINED:
5161 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5164 ERR("cannot convert VT_PTR into variant VT\n");
5174 /***********************************************************************
5175 * DispCallFunc (OLEAUT32.@)
5177 * Invokes a function of the specifed calling convention, passing the
5178 * specified arguments and returns the result.
5181 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5182 * oVft [I] The offset in the vtable. See notes.
5183 * cc [I] Calling convention of the function to call.
5184 * vtReturn [I] The return type of the function.
5185 * cActuals [I] Number of parameters.
5186 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5187 * prgpvarg [I] The arguments to pass.
5188 * pvargResult [O] The return value of the function. Can be NULL.
5192 * Failure: HRESULT code.
5195 * The HRESULT return value of this function is not affected by the return
5196 * value of the user supplied function, which is returned in pvargResult.
5198 * If pvInstance is NULL then a non-object function is to be called and oVft
5199 * is the address of the function to call.
5201 * The cc parameter can be one of the following values:
5212 * Native accepts arguments in the reverse order. I.e. the first item in the
5213 * prgpvarg array is the last argument in the C/C++ declaration of the
5214 * function to be called.
5218 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5219 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5221 int i, argsize, argspos;
5225 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5226 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5227 pvargResult, V_VT(pvargResult));
5231 argsize++; /* for This pointer */
5233 for (i=0;i<cActuals;i++)
5235 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
5236 dump_Variant(prgpvarg[i]);
5237 argsize += _argsize(prgvt[i]);
5239 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5244 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5248 for (i=0;i<cActuals;i++)
5250 VARIANT *arg = prgpvarg[i];
5251 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5252 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
5253 argspos += _argsize(prgvt[i]);
5258 FARPROC *vtable = *(FARPROC**)pvInstance;
5259 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5262 /* if we aren't invoking an object then the function pointer is stored
5264 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5266 if (pvargResult && (vtReturn != VT_EMPTY))
5268 TRACE("Method returned 0x%08lx\n",hres);
5269 V_VT(pvargResult) = vtReturn;
5270 V_UI4(pvargResult) = hres;
5273 HeapFree(GetProcessHeap(),0,args);
5277 static HRESULT WINAPI ITypeInfo_fnInvoke(
5282 DISPPARAMS *pDispParams,
5283 VARIANT *pVarResult,
5284 EXCEPINFO *pExcepInfo,
5287 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5289 unsigned int var_index;
5292 const TLBFuncDesc *pFuncInfo;
5294 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p)\n",
5295 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
5297 dump_DispParms(pDispParams);
5299 /* we do this instead of using GetFuncDesc since it will return a fake
5300 * FUNCDESC for dispinterfaces and we want the real function description */
5301 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
5302 if (memid == pFuncInfo->funcdesc.memid && (wFlags & pFuncInfo->funcdesc.invkind))
5306 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
5310 TRACE("invoking:\n");
5311 dump_TLBFuncDesc(pFuncInfo);
5314 switch (func_desc->funckind) {
5315 case FUNC_PUREVIRTUAL:
5316 case FUNC_VIRTUAL: {
5318 int numargs, numargs2, argspos, args2pos;
5319 DWORD *args , *args2;
5320 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
5321 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
5324 numargs = 1; /* sizeof(thisptr) */
5326 for (i = 0; i < func_desc->cParams; i++) {
5327 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
5329 numargs += _argsize(tdesc->vt);
5330 if (i>=pDispParams->cArgs) { /* arguments to return */
5331 if (tdesc->vt == VT_PTR) {
5332 numargs2 += _argsize(tdesc->u.lptdesc->vt);
5334 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
5335 numargs2 += _argsize(tdesc->vt);
5340 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
5341 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
5343 args[0] = (DWORD)pIUnk;
5344 argspos = 1; args2pos = 0;
5345 for (i = 0; i < func_desc->cParams; i++) {
5346 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
5347 TYPEDESC *tdesc = &(elemdesc->tdesc);
5348 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
5349 int arglen = _argsize(tdesc->vt);
5351 if (i<pDispParams->cArgs) {
5352 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
5354 if (paramFlags & PARAMFLAG_FOPT) {
5355 if(i < func_desc->cParams - func_desc->cParamsOpt)
5356 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5357 if(V_VT(arg) == VT_EMPTY
5358 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
5359 /* FIXME: Documentation says that we do this when parameter is left unspecified.
5360 How to determine it? */
5362 if(paramFlags & PARAMFLAG_FHASDEFAULT)
5363 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5364 V_VT(arg) = VT_ERROR;
5365 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5366 arglen = _argsize(VT_ERROR);
5369 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5370 if (FAILED(hres)) goto func_fail;
5372 } else if (paramFlags & PARAMFLAG_FOPT) {
5373 VARIANT *arg = &rgvarg[i];
5375 if (i < func_desc->cParams - func_desc->cParamsOpt)
5376 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5377 if (paramFlags & PARAMFLAG_FHASDEFAULT)
5378 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5380 V_VT(arg) = VT_ERROR;
5381 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5382 arglen = _argsize(VT_ERROR);
5383 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5384 if (FAILED(hres)) goto func_fail;
5387 if (tdesc->vt == VT_PTR)
5388 arglen = _argsize(tdesc->u.lptdesc->vt);
5390 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
5392 /* Supply pointers for the rest, so propertyget works*/
5393 args[argspos] = (DWORD)&args2[args2pos];
5395 /* If pointer to variant, pass reference it. */
5396 if ((tdesc->vt == VT_PTR) &&
5397 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
5400 args[argspos]= (DWORD)pVarResult;
5405 if (func_desc->cParamsOpt < 0)
5406 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
5408 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
5409 func_desc->callconv,
5415 for (i = 0; i < func_desc->cParams; i++) {
5416 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5417 if (wParamFlags & PARAMFLAG_FRETVAL) {
5418 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5419 TYPEDESC *tdesc = &elemdesc->tdesc;
5420 VARIANTARG varresult;
5421 V_VT(&varresult) = 0;
5422 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5425 /* FIXME: this is really messy - we should keep the
5426 * args in VARIANTARGs rather than a DWORD array */
5427 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5430 TRACE("varresult: ");
5431 dump_Variant(&varresult);
5433 hres = VariantCopyInd(pVarResult, &varresult);
5434 /* free data stored in varresult. Note that
5435 * VariantClear doesn't do what we want because we are
5436 * working with byref types. */
5437 /* FIXME: clear safearrays, bstrs, records and
5438 * variants here too */
5439 if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
5440 (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
5442 if(*V_UNKNOWNREF(&varresult))
5443 IUnknown_Release(*V_UNKNOWNREF(&varresult));
5450 if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
5451 WARN("invoked function failed with error 0x%08lx\n", res);
5452 hres = DISP_E_EXCEPTION;
5453 if (pExcepInfo) pExcepInfo->scode = res;
5456 HeapFree(GetProcessHeap(), 0, rgvarg);
5457 HeapFree(GetProcessHeap(),0,args2);
5458 HeapFree(GetProcessHeap(),0,args);
5461 case FUNC_DISPATCH: {
5464 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5465 if (SUCCEEDED(hres)) {
5466 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5467 hres = IDispatch_Invoke(
5468 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
5469 pVarResult,pExcepInfo,pArgErr
5472 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5473 IDispatch_Release(disp);
5475 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5479 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5484 TRACE("-- 0x%08lx\n", hres);
5487 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5490 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5491 if(FAILED(hres)) return hres;
5493 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5494 dump_VARDESC(var_desc);
5495 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5499 /* not found, look for it in inherited interfaces */
5500 ITypeInfo2_GetTypeKind(iface, &type_kind);
5501 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5503 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5504 /* recursive search */
5506 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5507 if(SUCCEEDED(hres)){
5508 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5509 ITypeInfo_Release(pTInfo);
5512 WARN("Could not search inherited interface!\n");
5515 ERR("did not find member id %ld, flags 0x%x!\n", memid, wFlags);
5516 return DISP_E_MEMBERNOTFOUND;
5519 /* ITypeInfo::GetDocumentation
5521 * Retrieves the documentation string, the complete Help file name and path,
5522 * and the context ID for the Help topic for a specified type description.
5524 * (Can be tested by the Visual Basic Editor in Word for instance.)
5526 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5527 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5528 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5530 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5531 TLBFuncDesc * pFDesc;
5532 TLBVarDesc * pVDesc;
5533 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5534 " HelpContext(%p) HelpFile(%p)\n",
5535 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5536 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5538 *pBstrName=SysAllocString(This->Name);
5540 *pBstrDocString=SysAllocString(This->DocString);
5542 *pdwHelpContext=This->dwHelpContext;
5544 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5546 }else {/* for a member */
5547 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5548 if(pFDesc->funcdesc.memid==memid){
5550 *pBstrName = SysAllocString(pFDesc->Name);
5552 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5554 *pdwHelpContext=pFDesc->helpcontext;
5557 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5558 if(pVDesc->vardesc.memid==memid){
5560 *pBstrName = SysAllocString(pVDesc->Name);
5562 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5564 *pdwHelpContext=pVDesc->HelpContext;
5568 WARN("member %ld not found\n", memid);
5569 return TYPE_E_ELEMENTNOTFOUND;
5572 /* ITypeInfo::GetDllEntry
5574 * Retrieves a description or specification of an entry point for a function
5577 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5578 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5581 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5582 TLBFuncDesc *pFDesc;
5584 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5586 if (pBstrDllName) *pBstrDllName = NULL;
5587 if (pBstrName) *pBstrName = NULL;
5588 if (pwOrdinal) *pwOrdinal = 0;
5590 if (This->TypeAttr.typekind != TKIND_MODULE)
5591 return TYPE_E_BADMODULEKIND;
5593 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5594 if(pFDesc->funcdesc.memid==memid){
5595 dump_TypeInfo(This);
5596 dump_TLBFuncDescOne(pFDesc);
5599 *pBstrDllName = SysAllocString(This->DllName);
5601 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5603 *pBstrName = SysAllocString(pFDesc->Entry);
5611 *pwOrdinal = (DWORD)pFDesc->Entry;
5614 return TYPE_E_ELEMENTNOTFOUND;
5617 /* ITypeInfo::GetRefTypeInfo
5619 * If a type description references other type descriptions, it retrieves
5620 * the referenced type descriptions.
5622 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5625 ITypeInfo **ppTInfo)
5627 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5628 HRESULT result = E_FAIL;
5630 if ((This->hreftype != -1) && (This->hreftype == hRefType))
5632 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5633 ITypeInfo_AddRef(*ppTInfo);
5636 else if (hRefType == -1 &&
5637 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5638 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5640 /* when we meet a DUAL dispinterface, we must create the interface
5643 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5646 /* the interface version contains the same information as the dispinterface
5647 * copy the contents of the structs.
5649 *pTypeInfoImpl = *This;
5650 pTypeInfoImpl->ref = 1;
5652 /* change the type to interface */
5653 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5655 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5657 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5662 TLBRefType *pRefType;
5663 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5664 if(pRefType->reference == hRefType)
5668 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5669 if(pRefType && hRefType != -1) {
5670 ITypeLib *pTLib = NULL;
5672 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5674 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5676 if(pRefType->pImpTLInfo->pImpTypeLib) {
5677 TRACE("typeinfo in imported typelib that is already loaded\n");
5678 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5679 ITypeLib2_AddRef((ITypeLib*) pTLib);
5682 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5683 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5684 pRefType->pImpTLInfo->wVersionMajor,
5685 pRefType->pImpTLInfo->wVersionMinor,
5686 pRefType->pImpTLInfo->lcid,
5689 if(!SUCCEEDED(result)) {
5690 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5691 result=LoadTypeLib(libnam, &pTLib);
5692 SysFreeString(libnam);
5694 if(SUCCEEDED(result)) {
5695 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5696 ITypeLib2_AddRef(pTLib);
5700 if(SUCCEEDED(result)) {
5701 if(pRefType->index == TLB_REF_USE_GUID)
5702 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5706 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5710 ITypeLib2_Release(pTLib);
5714 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5715 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5719 /* ITypeInfo::AddressOfMember
5721 * Retrieves the addresses of static functions or variables, such as those
5724 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5725 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5727 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5733 TRACE("(%p)->(0x%lx, 0x%x, %p)\n", This, memid, invKind, ppv);
5735 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
5739 module = LoadLibraryW(dll);
5742 ERR("couldn't load %s\n", debugstr_w(dll));
5744 if (entry) SysFreeString(entry);
5745 return STG_E_FILENOTFOUND;
5747 /* FIXME: store library somewhere where we can free it */
5752 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
5753 entryA = HeapAlloc(GetProcessHeap(), 0, len);
5754 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
5756 *ppv = GetProcAddress(module, entryA);
5758 ERR("function not found %s\n", debugstr_a(entryA));
5760 HeapFree(GetProcessHeap(), 0, entryA);
5764 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
5766 ERR("function not found %d\n", ordinal);
5770 if (entry) SysFreeString(entry);
5773 return TYPE_E_DLLFUNCTIONNOTFOUND;
5778 /* ITypeInfo::CreateInstance
5780 * Creates a new instance of a type that describes a component object class
5783 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5784 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5786 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5787 FIXME("(%p) stub!\n", This);
5791 /* ITypeInfo::GetMops
5793 * Retrieves marshalling information.
5795 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5798 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5799 FIXME("(%p) stub!\n", This);
5803 /* ITypeInfo::GetContainingTypeLib
5805 * Retrieves the containing type library and the index of the type description
5806 * within that type library.
5808 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5809 ITypeLib * *ppTLib, UINT *pIndex)
5811 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5813 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5815 *pIndex=This->index;
5816 TRACE("returning pIndex=%d\n", *pIndex);
5820 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5821 ITypeLib2_AddRef(*ppTLib);
5822 TRACE("returning ppTLib=%p\n", *ppTLib);
5828 /* ITypeInfo::ReleaseTypeAttr
5830 * Releases a TYPEATTR previously returned by GetTypeAttr.
5833 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5834 TYPEATTR* pTypeAttr)
5836 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5837 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5838 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5841 /* ITypeInfo::ReleaseFuncDesc
5843 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5845 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5847 FUNCDESC *pFuncDesc)
5849 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5852 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5854 for (i = 0; i < pFuncDesc->cParams; i++)
5855 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
5856 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
5858 SysFreeString((BSTR)pFuncDesc);
5861 /* ITypeInfo::ReleaseVarDesc
5863 * Releases a VARDESC previously returned by GetVarDesc.
5865 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5868 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5869 TRACE("(%p)->(%p)\n", This, pVarDesc);
5871 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
5872 if (pVarDesc->varkind == VAR_CONST)
5873 VariantClear(pVarDesc->u.lpvarValue);
5874 SysFreeString((BSTR)pVarDesc);
5877 /* ITypeInfo2::GetTypeKind
5879 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5882 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5883 TYPEKIND *pTypeKind)
5885 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5886 *pTypeKind=This->TypeAttr.typekind;
5887 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5891 /* ITypeInfo2::GetTypeFlags
5893 * Returns the type flags without any allocations. This returns a DWORD type
5894 * flag, which expands the type flags without growing the TYPEATTR (type
5898 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5900 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5901 *pTypeFlags=This->TypeAttr.wTypeFlags;
5902 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5906 /* ITypeInfo2::GetFuncIndexOfMemId
5907 * Binds to a specific member based on a known DISPID, where the member name
5908 * is not known (for example, when binding to a default member).
5911 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5912 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5914 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5915 TLBFuncDesc *pFuncInfo;
5919 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5920 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5926 result = TYPE_E_ELEMENTNOTFOUND;
5928 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5929 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5933 /* TypeInfo2::GetVarIndexOfMemId
5935 * Binds to a specific member based on a known DISPID, where the member name
5936 * is not known (for example, when binding to a default member).
5939 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5940 MEMBERID memid, UINT *pVarIndex)
5942 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5943 TLBVarDesc *pVarInfo;
5946 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5947 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5953 result = TYPE_E_ELEMENTNOTFOUND;
5955 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5956 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5960 /* ITypeInfo2::GetCustData
5962 * Gets the custom data
5964 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5969 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5970 TLBCustData *pCData;
5972 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5973 if( IsEqualIID(guid, &pCData->guid)) break;
5975 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5979 VariantInit( pVarVal);
5980 VariantCopy( pVarVal, &pCData->data);
5983 return E_INVALIDARG; /* FIXME: correct? */
5986 /* ITypeInfo2::GetFuncCustData
5988 * Gets the custom data
5990 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5996 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5997 TLBCustData *pCData=NULL;
5998 TLBFuncDesc * pFDesc;
6000 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6001 pFDesc=pFDesc->next);
6004 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
6005 if( IsEqualIID(guid, &pCData->guid)) break;
6007 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6010 VariantInit( pVarVal);
6011 VariantCopy( pVarVal, &pCData->data);
6014 return E_INVALIDARG; /* FIXME: correct? */
6017 /* ITypeInfo2::GetParamCustData
6019 * Gets the custom data
6021 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
6028 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6029 TLBCustData *pCData=NULL;
6030 TLBFuncDesc * pFDesc;
6033 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
6035 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
6036 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
6037 pCData = pCData->next)
6038 if( IsEqualIID(guid, &pCData->guid)) break;
6040 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6044 VariantInit( pVarVal);
6045 VariantCopy( pVarVal, &pCData->data);
6048 return E_INVALIDARG; /* FIXME: correct? */
6051 /* ITypeInfo2::GetVarCustData
6053 * Gets the custom data
6055 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
6061 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6062 TLBCustData *pCData=NULL;
6063 TLBVarDesc * pVDesc;
6066 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
6070 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
6072 if( IsEqualIID(guid, &pCData->guid)) break;
6076 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6080 VariantInit( pVarVal);
6081 VariantCopy( pVarVal, &pCData->data);
6084 return E_INVALIDARG; /* FIXME: correct? */
6087 /* ITypeInfo2::GetImplCustData
6089 * Gets the custom data
6091 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
6097 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6098 TLBCustData *pCData=NULL;
6099 TLBImplType * pRDesc;
6102 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
6106 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
6108 if( IsEqualIID(guid, &pCData->guid)) break;
6112 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
6116 VariantInit( pVarVal);
6117 VariantCopy( pVarVal, &pCData->data);
6120 return E_INVALIDARG; /* FIXME: correct? */
6123 /* ITypeInfo2::GetDocumentation2
6125 * Retrieves the documentation string, the complete Help file name and path,
6126 * the localization context to use, and the context ID for the library Help
6127 * topic in the Help file.
6130 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
6134 BSTR *pbstrHelpString,
6135 DWORD *pdwHelpStringContext,
6136 BSTR *pbstrHelpStringDll)
6138 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6139 TLBFuncDesc * pFDesc;
6140 TLBVarDesc * pVDesc;
6141 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
6142 "HelpStringContext(%p) HelpStringDll(%p)\n",
6143 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
6144 pbstrHelpStringDll );
6145 /* the help string should be obtained from the helpstringdll,
6146 * using the _DLLGetDocumentation function, based on the supplied
6147 * lcid. Nice to do sometime...
6149 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6151 *pbstrHelpString=SysAllocString(This->Name);
6152 if(pdwHelpStringContext)
6153 *pdwHelpStringContext=This->dwHelpStringContext;
6154 if(pbstrHelpStringDll)
6155 *pbstrHelpStringDll=
6156 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6158 }else {/* for a member */
6159 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6160 if(pFDesc->funcdesc.memid==memid){
6162 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
6163 if(pdwHelpStringContext)
6164 *pdwHelpStringContext=pFDesc->HelpStringContext;
6165 if(pbstrHelpStringDll)
6166 *pbstrHelpStringDll=
6167 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6170 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6171 if(pVDesc->vardesc.memid==memid){
6173 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
6174 if(pdwHelpStringContext)
6175 *pdwHelpStringContext=pVDesc->HelpStringContext;
6176 if(pbstrHelpStringDll)
6177 *pbstrHelpStringDll=
6178 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
6182 return TYPE_E_ELEMENTNOTFOUND;
6185 /* ITypeInfo2::GetAllCustData
6187 * Gets all custom data items for the Type info.
6190 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
6192 CUSTDATA *pCustData)
6194 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6195 TLBCustData *pCData;
6198 TRACE("(%p) returning %d items\n", This, This->ctCustData);
6200 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
6201 if(pCustData->prgCustData ){
6202 pCustData->cCustData=This->ctCustData;
6203 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
6204 pCustData->prgCustData[i].guid=pCData->guid;
6205 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
6208 ERR(" OUT OF MEMORY!\n");
6209 return E_OUTOFMEMORY;
6214 /* ITypeInfo2::GetAllFuncCustData
6216 * Gets all custom data items for the specified Function
6219 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
6222 CUSTDATA *pCustData)
6224 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6225 TLBCustData *pCData;
6226 TLBFuncDesc * pFDesc;
6228 TRACE("(%p) index %d\n", This, index);
6229 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
6230 pFDesc=pFDesc->next)
6233 pCustData->prgCustData =
6234 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
6235 if(pCustData->prgCustData ){
6236 pCustData->cCustData=pFDesc->ctCustData;
6237 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
6238 pCData = pCData->next){
6239 pCustData->prgCustData[i].guid=pCData->guid;
6240 VariantCopy(& pCustData->prgCustData[i].varValue,
6244 ERR(" OUT OF MEMORY!\n");
6245 return E_OUTOFMEMORY;
6249 return TYPE_E_ELEMENTNOTFOUND;
6252 /* ITypeInfo2::GetAllParamCustData
6254 * Gets all custom data items for the Functions
6257 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
6258 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
6260 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6261 TLBCustData *pCData=NULL;
6262 TLBFuncDesc * pFDesc;
6264 TRACE("(%p) index %d\n", This, indexFunc);
6265 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
6266 pFDesc=pFDesc->next)
6268 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
6269 pCustData->prgCustData =
6270 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
6271 sizeof(CUSTDATAITEM));
6272 if(pCustData->prgCustData ){
6273 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
6274 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
6275 pCData; i++, pCData = pCData->next){
6276 pCustData->prgCustData[i].guid=pCData->guid;
6277 VariantCopy(& pCustData->prgCustData[i].varValue,
6281 ERR(" OUT OF MEMORY!\n");
6282 return E_OUTOFMEMORY;
6286 return TYPE_E_ELEMENTNOTFOUND;
6289 /* ITypeInfo2::GetAllVarCustData
6291 * Gets all custom data items for the specified Variable
6294 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
6295 UINT index, CUSTDATA *pCustData)
6297 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6298 TLBCustData *pCData;
6299 TLBVarDesc * pVDesc;
6301 TRACE("(%p) index %d\n", This, index);
6302 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
6303 pVDesc=pVDesc->next)
6306 pCustData->prgCustData =
6307 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
6308 if(pCustData->prgCustData ){
6309 pCustData->cCustData=pVDesc->ctCustData;
6310 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
6311 pCData = pCData->next){
6312 pCustData->prgCustData[i].guid=pCData->guid;
6313 VariantCopy(& pCustData->prgCustData[i].varValue,
6317 ERR(" OUT OF MEMORY!\n");
6318 return E_OUTOFMEMORY;
6322 return TYPE_E_ELEMENTNOTFOUND;
6325 /* ITypeInfo2::GetAllImplCustData
6327 * Gets all custom data items for the specified implementation type
6330 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
6333 CUSTDATA *pCustData)
6335 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6336 TLBCustData *pCData;
6337 TLBImplType * pRDesc;
6339 TRACE("(%p) index %d\n", This, index);
6340 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
6341 pRDesc=pRDesc->next)
6344 pCustData->prgCustData =
6345 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
6346 if(pCustData->prgCustData ){
6347 pCustData->cCustData=pRDesc->ctCustData;
6348 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
6349 pCData = pCData->next){
6350 pCustData->prgCustData[i].guid=pCData->guid;
6351 VariantCopy(& pCustData->prgCustData[i].varValue,
6355 ERR(" OUT OF MEMORY!\n");
6356 return E_OUTOFMEMORY;
6360 return TYPE_E_ELEMENTNOTFOUND;
6363 static const ITypeInfo2Vtbl tinfvt =
6366 ITypeInfo_fnQueryInterface,
6368 ITypeInfo_fnRelease,
6370 ITypeInfo_fnGetTypeAttr,
6371 ITypeInfo_fnGetTypeComp,
6372 ITypeInfo_fnGetFuncDesc,
6373 ITypeInfo_fnGetVarDesc,
6374 ITypeInfo_fnGetNames,
6375 ITypeInfo_fnGetRefTypeOfImplType,
6376 ITypeInfo_fnGetImplTypeFlags,
6377 ITypeInfo_fnGetIDsOfNames,
6379 ITypeInfo_fnGetDocumentation,
6380 ITypeInfo_fnGetDllEntry,
6381 ITypeInfo_fnGetRefTypeInfo,
6382 ITypeInfo_fnAddressOfMember,
6383 ITypeInfo_fnCreateInstance,
6384 ITypeInfo_fnGetMops,
6385 ITypeInfo_fnGetContainingTypeLib,
6386 ITypeInfo_fnReleaseTypeAttr,
6387 ITypeInfo_fnReleaseFuncDesc,
6388 ITypeInfo_fnReleaseVarDesc,
6390 ITypeInfo2_fnGetTypeKind,
6391 ITypeInfo2_fnGetTypeFlags,
6392 ITypeInfo2_fnGetFuncIndexOfMemId,
6393 ITypeInfo2_fnGetVarIndexOfMemId,
6394 ITypeInfo2_fnGetCustData,
6395 ITypeInfo2_fnGetFuncCustData,
6396 ITypeInfo2_fnGetParamCustData,
6397 ITypeInfo2_fnGetVarCustData,
6398 ITypeInfo2_fnGetImplTypeCustData,
6399 ITypeInfo2_fnGetDocumentation2,
6400 ITypeInfo2_fnGetAllCustData,
6401 ITypeInfo2_fnGetAllFuncCustData,
6402 ITypeInfo2_fnGetAllParamCustData,
6403 ITypeInfo2_fnGetAllVarCustData,
6404 ITypeInfo2_fnGetAllImplTypeCustData,
6407 /******************************************************************************
6408 * CreateDispTypeInfo [OLEAUT32.31]
6410 * Build type information for an object so it can be called through an
6411 * IDispatch interface.
6414 * Success: S_OK. pptinfo contains the created ITypeInfo object.
6415 * Failure: E_INVALIDARG, if one or more arguments is invalid.
6418 * This call allows an objects methods to be accessed through IDispatch, by
6419 * building an ITypeInfo object that IDispatch can use to call through.
6421 HRESULT WINAPI CreateDispTypeInfo(
6422 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
6423 LCID lcid, /* [I] Locale Id */
6424 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
6426 ITypeInfoImpl *pTIImpl;
6428 TLBFuncDesc **ppFuncDesc;
6430 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
6431 pTIImpl->pTypeLib = NULL;
6433 pTIImpl->Name = NULL;
6434 pTIImpl->dwHelpContext = -1;
6435 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
6436 pTIImpl->TypeAttr.lcid = lcid;
6437 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
6438 pTIImpl->TypeAttr.wMajorVerNum = 0;
6439 pTIImpl->TypeAttr.wMinorVerNum = 0;
6440 pTIImpl->TypeAttr.cbAlignment = 2;
6441 pTIImpl->TypeAttr.cbSizeInstance = -1;
6442 pTIImpl->TypeAttr.cbSizeVft = -1;
6443 pTIImpl->TypeAttr.cFuncs = 0;
6444 pTIImpl->TypeAttr.cImplTypes = 1;
6445 pTIImpl->TypeAttr.cVars = 0;
6446 pTIImpl->TypeAttr.wTypeFlags = 0;
6448 ppFuncDesc = &pTIImpl->funclist;
6449 for(func = 0; func < pidata->cMembers; func++) {
6450 METHODDATA *md = pidata->pmethdata + func;
6451 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6452 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6453 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6454 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6455 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6456 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6457 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6458 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
6459 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
6460 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6461 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6462 md->cArgs * sizeof(ELEMDESC));
6463 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6464 md->cArgs * sizeof(TLBParDesc));
6465 for(param = 0; param < md->cArgs; param++) {
6466 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6467 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6469 ppFuncDesc = &(*ppFuncDesc)->next;
6471 *pptinfo = (ITypeInfo*)pTIImpl;
6476 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6478 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6480 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6483 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6485 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6487 return ITypeInfo_AddRef((ITypeInfo *)This);
6490 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6492 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6494 return ITypeInfo_Release((ITypeInfo *)This);
6497 static HRESULT WINAPI ITypeComp_fnBind(
6502 ITypeInfo ** ppTInfo,
6503 DESCKIND * pDescKind,
6506 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6507 TLBFuncDesc * pFDesc;
6508 TLBVarDesc * pVDesc;
6510 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6512 *pDescKind = DESCKIND_NONE;
6513 pBindPtr->lpfuncdesc = NULL;
6516 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6517 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
6518 if (!strcmpW(pFDesc->Name, szName)) {
6524 HRESULT hr = TLB_AllocAndInitFuncDesc(
6526 &pBindPtr->lpfuncdesc,
6527 This->TypeAttr.typekind == TKIND_DISPATCH);
6530 *pDescKind = DESCKIND_FUNCDESC;
6531 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6532 ITypeInfo_AddRef(*ppTInfo);
6535 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6536 if (!strcmpW(pVDesc->Name, szName)) {
6537 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
6540 *pDescKind = DESCKIND_VARDESC;
6541 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6542 ITypeInfo_AddRef(*ppTInfo);
6547 /* FIXME: search each inherited interface, not just the first */
6548 if (This->TypeAttr.cImplTypes) {
6549 /* recursive search */
6553 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6556 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6557 ITypeInfo_Release(pTInfo);
6561 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6562 ITypeComp_Release(pTComp);
6565 WARN("Could not search inherited interface!\n");
6567 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6568 return DISP_E_MEMBERNOTFOUND;
6571 static HRESULT WINAPI ITypeComp_fnBindType(
6575 ITypeInfo ** ppTInfo,
6576 ITypeComp ** ppTComp)
6578 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6580 /* strange behaviour (does nothing) but like the
6583 if (!ppTInfo || !ppTComp)
6592 static const ITypeCompVtbl tcompvt =
6595 ITypeComp_fnQueryInterface,
6597 ITypeComp_fnRelease,
6600 ITypeComp_fnBindType