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);
90 /****************************************************************************
93 * Takes p_iVal (which is in little endian) and returns it
94 * in the host machine's byte order.
96 #ifdef WORDS_BIGENDIAN
97 static WORD FromLEWord(WORD p_iVal)
99 return (((p_iVal & 0x00FF) << 8) |
100 ((p_iVal & 0xFF00) >> 8));
104 static DWORD FromLEDWord(DWORD p_iVal)
106 return (((p_iVal & 0x000000FF) << 24) |
107 ((p_iVal & 0x0000FF00) << 8) |
108 ((p_iVal & 0x00FF0000) >> 8) |
109 ((p_iVal & 0xFF000000) >> 24));
112 #define FromLEWord(X) (X)
113 #define FromLEDWord(X) (X)
117 /****************************************************************************
120 * Fix byte order in any structure if necessary
122 #ifdef WORDS_BIGENDIAN
123 static void FromLEWords(void *p_Val, int p_iSize)
127 p_iSize /= sizeof(WORD);
130 *Val = FromLEWord(*Val);
137 static void FromLEDWords(void *p_Val, int p_iSize)
141 p_iSize /= sizeof(DWORD);
144 *Val = FromLEDWord(*Val);
150 #define FromLEWords(X,Y) /*nothing*/
151 #define FromLEDWords(X,Y) /*nothing*/
154 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
155 /* buffer must be at least 60 characters long */
156 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
158 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
159 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
161 memcpy( buffer, TypelibW, sizeof(TypelibW) );
162 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
163 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
167 /* get the path of an interface key, in the form "Interface\\<guid>" */
168 /* buffer must be at least 50 characters long */
169 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
171 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
173 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
174 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
178 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
179 /* buffer must be at least 16 characters long */
180 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
182 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
183 static const WCHAR win16W[] = {'w','i','n','1','6',0};
184 static const WCHAR win32W[] = {'w','i','n','3','2',0};
186 sprintfW( buffer, LcidFormatW, lcid );
189 case SYS_WIN16: strcatW( buffer, win16W ); break;
190 case SYS_WIN32: strcatW( buffer, win32W ); break;
192 TRACE("Typelib is for unsupported syskind %i\n", syskind);
198 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
201 /****************************************************************************
202 * QueryPathOfRegTypeLib [OLEAUT32.164]
204 * Gets the path to a registered type library.
207 * guid [I] referenced guid
208 * wMaj [I] major version
209 * wMin [I] minor version
211 * path [O] path of typelib
215 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
216 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
219 HRESULT WINAPI QueryPathOfRegTypeLib(
226 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
230 WCHAR Path[MAX_PATH];
233 TRACE_(typelib)("(%s, %x.%x, 0x%lx, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
235 get_typelib_key( guid, wMaj, wMin, buffer );
237 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
238 if (res == ERROR_FILE_NOT_FOUND)
240 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
241 return TYPE_E_LIBNOTREGISTERED;
243 else if (res != ERROR_SUCCESS)
245 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
246 return TYPE_E_REGISTRYACCESS;
251 LONG dwPathLen = sizeof(Path);
253 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
255 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
259 else if (myLCID == lcid)
261 /* try with sub-langid */
262 myLCID = SUBLANGID(lcid);
264 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
266 /* try with system langid */
276 *path = SysAllocString( Path );
281 TRACE_(typelib)("-- 0x%08lx\n", hr);
285 /******************************************************************************
286 * CreateTypeLib [OLEAUT32.160] creates a typelib
292 HRESULT WINAPI CreateTypeLib(
293 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
295 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
299 /******************************************************************************
300 * LoadTypeLib [OLEAUT32.161]
302 * Loads a type library
305 * szFile [I] Name of file to load from.
306 * pptLib [O] Pointer that receives ITypeLib object on success.
313 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
315 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
317 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
318 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
321 /******************************************************************************
322 * LoadTypeLibEx [OLEAUT32.183]
324 * Loads and optionally registers a type library
330 HRESULT WINAPI LoadTypeLibEx(
331 LPCOLESTR szFile, /* [in] Name of file to load from */
332 REGKIND regkind, /* [in] Specify kind of registration */
333 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
335 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
340 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
342 /* by default try and load using LoadLibrary (for builtin stdole32.tlb) */
343 memcpy(szPath, szFile, (strlenW(szFile)+1)*sizeof(WCHAR));
346 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
349 /* Look for a trailing '\\' followed by an index */
350 pIndexStr = strrchrW(szFile, '\\');
351 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
352 index = atoiW(pIndexStr);
353 memcpy(szFileCopy, szFile,
354 (pIndexStr - szFile - 1) * sizeof(WCHAR));
355 szFileCopy[pIndexStr - szFile - 1] = '\0';
356 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
358 return TYPE_E_CANTLOADLIBRARY;
359 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
360 return TYPE_E_CANTLOADLIBRARY;
364 TRACE("File %s index %d\n", debugstr_w(szPath), index);
366 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
371 case REGKIND_DEFAULT:
372 /* don't register typelibs supplied with full path. Experimentation confirms the following */
374 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
375 (szFile[0] && (szFile[1] == ':'))) break;
376 /* else fall-through */
378 case REGKIND_REGISTER:
379 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
381 IUnknown_Release(*pptLib);
389 TRACE(" returns %08lx\n",res);
393 /******************************************************************************
394 * LoadRegTypeLib [OLEAUT32.162]
396 * Loads a registered type library.
399 * rguid [I] GUID of the registered type library.
400 * wVerMajor [I] major version.
401 * wVerMinor [I] minor version.
402 * lcid [I] locale ID.
403 * ppTLib [O] pointer that receives an ITypeLib object on success.
407 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
410 HRESULT WINAPI LoadRegTypeLib(
418 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
422 res= LoadTypeLib(bstr, ppTLib);
426 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
432 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
433 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
434 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
435 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
436 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
437 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
439 /******************************************************************************
440 * RegisterTypeLib [OLEAUT32.163]
441 * Adds information about a type library to the System Registry
443 * Docs: ITypeLib FAR * ptlib
444 * Docs: OLECHAR FAR* szFullPath
445 * Docs: OLECHAR FAR* szHelpDir
451 HRESULT WINAPI RegisterTypeLib(
452 ITypeLib * ptlib, /* [in] Pointer to the library*/
453 OLECHAR * szFullPath, /* [in] full Path of the library*/
454 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
457 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
458 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
459 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
469 if (ptlib == NULL || szFullPath == NULL)
472 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
475 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
478 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
479 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
483 /* Set the human-readable name of the typelib */
484 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
486 if (RegSetValueExW(key, NULL, 0, REG_SZ,
487 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
495 /* Make up the name of the typelib path subkey */
496 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
498 /* Create the typelib path subkey */
499 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
500 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
502 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
503 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
511 /* Create the flags subkey */
512 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
513 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
515 /* FIXME: is %u correct? */
516 static const WCHAR formatW[] = {'%','u',0};
518 sprintfW(buf, formatW, attr->wLibFlags);
519 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
520 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
528 /* create the helpdir subkey */
529 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
530 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
532 BOOL freeHelpDir = FALSE;
535 /* if we created a new key, and helpDir was null, set the helpdir
536 to the directory which contains the typelib. However,
537 if we just opened an existing key, we leave the helpdir alone */
538 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
539 szHelpDir = SysAllocString(szFullPath);
540 pIndexStr = strrchrW(szHelpDir, '\\');
547 /* if we have an szHelpDir, set it! */
548 if (szHelpDir != NULL) {
549 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
550 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
556 if (freeHelpDir) SysFreeString(szHelpDir);
568 /* register OLE Automation-compatible interfaces for this typelib */
569 types = ITypeLib_GetTypeInfoCount(ptlib);
570 for (tidx=0; tidx<types; tidx++) {
571 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
572 LPOLESTR name = NULL;
573 ITypeInfo *tinfo = NULL;
575 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
578 case TKIND_INTERFACE:
579 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
580 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
584 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
585 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
589 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
594 TYPEATTR *tattr = NULL;
595 ITypeInfo_GetTypeAttr(tinfo, &tattr);
598 TRACE_(typelib)("guid=%s, flags=%04x (",
599 debugstr_guid(&tattr->guid),
602 if (TRACE_ON(typelib)) {
603 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
623 if (tattr->wTypeFlags & (TYPEFLAG_FOLEAUTOMATION|TYPEFLAG_FDUAL))
625 /* register interface<->typelib coupling */
626 get_interface_key( &tattr->guid, keyName );
627 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
628 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
631 RegSetValueExW(key, NULL, 0, REG_SZ,
632 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
634 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
635 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
636 RegSetValueExW(subKey, NULL, 0, REG_SZ,
637 (BYTE*)PSOA, sizeof PSOA);
641 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
642 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
643 RegSetValueExW(subKey, NULL, 0, REG_SZ,
644 (BYTE*)PSOA, sizeof PSOA);
648 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
649 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
652 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
653 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
655 StringFromGUID2(&attr->guid, buffer, 40);
656 RegSetValueExW(subKey, NULL, 0, REG_SZ,
657 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
658 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
659 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
660 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
668 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
671 ITypeInfo_Release(tinfo);
678 ITypeLib_ReleaseTLibAttr(ptlib, attr);
684 /******************************************************************************
685 * UnRegisterTypeLib [OLEAUT32.186]
686 * Removes information about a type library from the System Registry
693 HRESULT WINAPI UnRegisterTypeLib(
694 REFGUID libid, /* [in] Guid of the library */
695 WORD wVerMajor, /* [in] major version */
696 WORD wVerMinor, /* [in] minor version */
697 LCID lcid, /* [in] locale id */
700 BSTR tlibPath = NULL;
703 WCHAR subKeyName[50];
706 BOOL deleteOtherStuff;
709 TYPEATTR* typeAttr = NULL;
711 ITypeInfo* typeInfo = NULL;
712 ITypeLib* typeLib = NULL;
715 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
717 /* Create the path to the key */
718 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
720 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
722 TRACE("Unsupported syskind %i\n", syskind);
723 result = E_INVALIDARG;
727 /* get the path to the typelib on disk */
728 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
729 result = E_INVALIDARG;
733 /* Try and open the key to the type library. */
734 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
735 result = E_INVALIDARG;
739 /* Try and load the type library */
740 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
741 result = TYPE_E_INVALIDSTATE;
745 /* remove any types registered with this typelib */
746 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
747 for (i=0; i<numTypes; i++) {
748 /* get the kind of type */
749 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
753 /* skip non-interfaces, and get type info for the type */
754 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
757 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
760 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
764 /* the path to the type */
765 get_interface_key( &typeAttr->guid, subKeyName );
767 /* Delete its bits */
768 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
771 RegDeleteKeyW(subKey, ProxyStubClsidW);
772 RegDeleteKeyW(subKey, ProxyStubClsid32W);
773 RegDeleteKeyW(subKey, TypeLibW);
776 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
779 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
781 if (typeInfo) ITypeInfo_Release(typeInfo);
785 /* Now, delete the type library path subkey */
786 get_lcid_subkey( lcid, syskind, subKeyName );
787 RegDeleteKeyW(key, subKeyName);
788 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
789 RegDeleteKeyW(key, subKeyName);
791 /* check if there is anything besides the FLAGS/HELPDIR keys.
792 If there is, we don't delete them */
793 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
794 deleteOtherStuff = TRUE;
796 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
797 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
799 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
800 if (!strcmpW(subKeyName, FLAGSW)) continue;
801 if (!strcmpW(subKeyName, HELPDIRW)) continue;
802 deleteOtherStuff = FALSE;
806 /* only delete the other parts of the key if we're absolutely sure */
807 if (deleteOtherStuff) {
808 RegDeleteKeyW(key, FLAGSW);
809 RegDeleteKeyW(key, HELPDIRW);
813 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
814 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
815 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
819 if (tlibPath) SysFreeString(tlibPath);
820 if (typeLib) ITypeLib_Release(typeLib);
821 if (subKey) RegCloseKey(subKey);
822 if (key) RegCloseKey(key);
826 /*======================= ITypeLib implementation =======================*/
828 typedef struct tagTLBCustData
832 struct tagTLBCustData* next;
835 /* data structure for import typelibs */
836 typedef struct tagTLBImpLib
838 int offset; /* offset in the file (MSFT)
839 offset in nametable (SLTG)
840 just used to identify library while reading
842 GUID guid; /* libid */
843 BSTR name; /* name */
845 LCID lcid; /* lcid of imported typelib */
847 WORD wVersionMajor; /* major version number */
848 WORD wVersionMinor; /* minor version number */
850 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
851 NULL if not yet loaded */
852 struct tagTLBImpLib * next;
855 /* internal ITypeLib data */
856 typedef struct tagITypeLibImpl
858 const ITypeLib2Vtbl *lpVtbl;
859 const ITypeCompVtbl *lpVtblTypeComp;
861 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
863 /* strings can be stored in tlb as multibyte strings BUT they are *always*
864 * exported to the application as a UNICODE string.
870 unsigned long dwHelpContext;
871 int TypeInfoCount; /* nr of typeinfo's in librarry */
872 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
873 int ctCustData; /* number of items in cust data list */
874 TLBCustData * pCustData; /* linked list to cust data */
875 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
876 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
877 libary. Only used while read MSFT
880 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
881 struct tagITypeLibImpl *next, *prev;
886 static const ITypeLib2Vtbl tlbvt;
887 static const ITypeCompVtbl tlbtcvt;
889 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
891 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
894 /* ITypeLib methods */
895 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
896 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
898 /*======================= ITypeInfo implementation =======================*/
900 /* data for referenced types */
901 typedef struct tagTLBRefType
903 INT index; /* Type index for internal ref or for external ref
904 it the format is SLTG. -2 indicates to
907 GUID guid; /* guid of the referenced type */
908 /* if index == TLB_REF_USE_GUID */
910 HREFTYPE reference; /* The href of this ref */
911 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
912 TLB_REF_INTERNAL for internal refs
913 TLB_REF_NOT_FOUND for broken refs */
915 struct tagTLBRefType * next;
918 #define TLB_REF_USE_GUID -2
920 #define TLB_REF_INTERNAL (void*)-2
921 #define TLB_REF_NOT_FOUND (void*)-1
923 /* internal Parameter data */
924 typedef struct tagTLBParDesc
928 TLBCustData * pCustData; /* linked list to cust data */
931 /* internal Function data */
932 typedef struct tagTLBFuncDesc
934 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
935 BSTR Name; /* the name of this function */
936 TLBParDesc *pParamDesc; /* array with param names and custom data */
938 int HelpStringContext;
940 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
942 TLBCustData * pCustData; /* linked list to cust data; */
943 struct tagTLBFuncDesc * next;
946 /* internal Variable data */
947 typedef struct tagTLBVarDesc
949 VARDESC vardesc; /* lots of info on the variable and its attributes. */
950 BSTR Name; /* the name of this variable */
952 int HelpStringContext; /* FIXME: where? */
955 TLBCustData * pCustData;/* linked list to cust data; */
956 struct tagTLBVarDesc * next;
959 /* internal implemented interface data */
960 typedef struct tagTLBImplType
962 HREFTYPE hRef; /* hRef of interface */
963 int implflags; /* IMPLFLAG_*s */
965 TLBCustData * pCustData;/* linked list to custom data; */
966 struct tagTLBImplType *next;
969 /* internal TypeInfo data */
970 typedef struct tagITypeInfoImpl
972 const ITypeInfo2Vtbl *lpVtbl;
973 const ITypeCompVtbl *lpVtblTypeComp;
975 TYPEATTR TypeAttr ; /* _lots_ of type information. */
976 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
977 int index; /* index in this typelib; */
978 /* type libs seem to store the doc strings in ascii
979 * so why should we do it in unicode?
984 unsigned long dwHelpContext;
985 unsigned long dwHelpStringContext;
988 TLBFuncDesc * funclist; /* linked list with function descriptions */
991 TLBVarDesc * varlist; /* linked list with variable descriptions */
993 /* Implemented Interfaces */
994 TLBImplType * impltypelist;
996 TLBRefType * reflist;
998 TLBCustData * pCustData; /* linked list to cust data; */
999 struct tagITypeInfoImpl * next;
1002 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1004 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1007 static const ITypeInfo2Vtbl tinfvt;
1008 static const ITypeCompVtbl tcompvt;
1010 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
1012 typedef struct tagTLBContext
1014 unsigned int oStart; /* start of TLB in file */
1015 unsigned int pos; /* current pos */
1016 unsigned int length; /* total length */
1017 void *mapping; /* memory mapping */
1018 MSFT_SegDir * pTblDir;
1019 ITypeLibImpl* pLibInfo;
1023 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1028 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1029 if (pTD->vt & VT_RESERVED)
1030 szVarType += strlen(strcpy(szVarType, "reserved | "));
1031 if (pTD->vt & VT_BYREF)
1032 szVarType += strlen(strcpy(szVarType, "ref to "));
1033 if (pTD->vt & VT_ARRAY)
1034 szVarType += strlen(strcpy(szVarType, "array of "));
1035 if (pTD->vt & VT_VECTOR)
1036 szVarType += strlen(strcpy(szVarType, "vector of "));
1037 switch(pTD->vt & VT_TYPEMASK) {
1038 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1039 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1040 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1041 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1042 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1043 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1044 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1045 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1046 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1047 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1048 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1049 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1050 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1051 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1052 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1053 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1054 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1055 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1056 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1057 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1058 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1059 pTD->u.hreftype); break;
1060 case VT_PTR: sprintf(szVarType, "ptr to ");
1061 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1063 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1064 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1066 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1067 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1068 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1071 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1075 static void dump_ELEMDESC(ELEMDESC *edesc) {
1077 USHORT flags = edesc->u.paramdesc.wParamFlags;
1078 dump_TypeDesc(&edesc->tdesc,buf);
1079 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1080 MESSAGE("\t\tu.paramdesc.wParamFlags");
1081 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1082 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1083 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1084 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1085 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1086 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1087 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1088 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1089 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1091 static void dump_FUNCDESC(FUNCDESC *funcdesc) {
1093 MESSAGE("memid is %08lx\n",funcdesc->memid);
1094 for (i=0;i<funcdesc->cParams;i++) {
1095 MESSAGE("Param %d:\n",i);
1096 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1098 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1099 switch (funcdesc->funckind) {
1100 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1101 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1102 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1103 case FUNC_STATIC: MESSAGE("static");break;
1104 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1105 default: MESSAGE("unknown");break;
1107 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1108 switch (funcdesc->invkind) {
1109 case INVOKE_FUNC: MESSAGE("func");break;
1110 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1111 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1112 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1114 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1115 switch (funcdesc->callconv) {
1116 case CC_CDECL: MESSAGE("cdecl");break;
1117 case CC_PASCAL: MESSAGE("pascal");break;
1118 case CC_STDCALL: MESSAGE("stdcall");break;
1119 case CC_SYSCALL: MESSAGE("syscall");break;
1122 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1123 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1124 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1126 MESSAGE("\telemdescFunc (return value type):\n");
1127 dump_ELEMDESC(&funcdesc->elemdescFunc);
1130 static const char * typekind_desc[] =
1143 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1146 if (!TRACE_ON(typelib))
1148 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1149 for (i=0;i<pfd->funcdesc.cParams;i++)
1150 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1153 dump_FUNCDESC(&(pfd->funcdesc));
1155 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1156 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1158 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1162 dump_TLBFuncDescOne(pfd);
1166 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1170 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1175 static void dump_TLBImpLib(TLBImpLib *import)
1177 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1178 debugstr_w(import->name));
1179 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1180 import->wVersionMinor, import->lcid, import->offset);
1183 static void dump_TLBRefType(TLBRefType * prt)
1187 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1188 if(prt->index == -1)
1189 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1191 TRACE_(typelib)("type no: %d\n", prt->index);
1193 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1194 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1195 TRACE_(typelib)("in lib\n");
1196 dump_TLBImpLib(prt->pImpTLInfo);
1202 static void dump_TLBImplType(TLBImplType * impl)
1206 "implementing/inheriting interface hRef = %lx implflags %x\n",
1207 impl->hRef, impl->implflags);
1212 void dump_Variant(VARIANT * pvar)
1216 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1220 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1221 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1223 TRACE(",%p", V_BYREF(pvar));
1225 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1229 else switch (V_TYPE(pvar))
1231 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1232 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1233 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1234 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1236 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1238 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1239 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1240 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1241 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1242 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1243 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1244 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1245 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1246 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1247 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1248 V_CY(pvar).s.Lo); break;
1250 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1251 TRACE(",<invalid>");
1253 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1254 st.wHour, st.wMinute, st.wSecond);
1258 case VT_USERDEFINED:
1260 case VT_NULL: break;
1261 default: TRACE(",?"); break;
1267 static void dump_DispParms(DISPPARAMS * pdp)
1271 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1273 while (index < pdp->cArgs)
1275 dump_Variant( &pdp->rgvarg[index] );
1280 static void dump_TypeInfo(ITypeInfoImpl * pty)
1282 TRACE("%p ref=%lu\n", pty, pty->ref);
1283 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1284 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1285 TRACE("fct:%u var:%u impl:%u\n",
1286 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1287 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1288 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1289 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1290 dump_TLBFuncDesc(pty->funclist);
1291 dump_TLBVarDesc(pty->varlist);
1292 dump_TLBImplType(pty->impltypelist);
1295 static void dump_VARDESC(VARDESC *v)
1297 MESSAGE("memid %ld\n",v->memid);
1298 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1299 MESSAGE("oInst %ld\n",v->u.oInst);
1300 dump_ELEMDESC(&(v->elemdescVar));
1301 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1302 MESSAGE("varkind %d\n",v->varkind);
1305 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1307 /* VT_LPWSTR is largest type that */
1308 /* may appear in type description*/
1309 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1310 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1311 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1312 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1313 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1314 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1318 static void TLB_abort(void)
1322 static void * TLB_Alloc(unsigned size)
1325 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1327 ERR("cannot allocate memory\n");
1332 static void TLB_Free(void * ptr)
1334 HeapFree(GetProcessHeap(), 0, ptr);
1337 /* deep copy a typedesc */
1338 static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in)
1343 out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC));
1344 copy_typedesc(out->u.lptdesc, in->u.lptdesc);
1346 case VT_USERDEFINED:
1347 out->u.hreftype = in->u.hreftype;
1350 out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) +
1351 (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND));
1352 copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem);
1353 out->u.lpadesc->cDims = in->u.lpadesc->cDims;
1354 memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND));
1361 /* free()s any allocated memory pointed to by the tdesc. NB does not
1362 free the tdesc itself - this is because the tdesc is typically part
1363 of a larger structure */
1364 static void free_deep_typedesc(TYPEDESC *tdesc)
1368 free_deep_typedesc(tdesc->u.lptdesc);
1369 HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);
1370 tdesc->u.lptdesc = NULL;
1373 free_deep_typedesc(&tdesc->u.lpadesc->tdescElem);
1374 HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);
1375 tdesc->u.lpadesc = NULL;
1382 /**********************************************************************
1384 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1387 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1389 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1390 pcx->pos, count, pcx->oStart, pcx->length, where);
1392 if (where != DO_NOT_SEEK)
1394 where += pcx->oStart;
1395 if (where > pcx->length)
1398 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1403 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1404 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1409 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1414 ret = MSFT_Read(buffer, count, pcx, where);
1415 FromLEDWords(buffer, ret);
1420 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1425 ret = MSFT_Read(buffer, count, pcx, where);
1426 FromLEWords(buffer, ret);
1431 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1433 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1434 memset(pGuid,0, sizeof(GUID));
1437 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1438 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1439 pGuid->Data2 = FromLEWord(pGuid->Data2);
1440 pGuid->Data3 = FromLEWord(pGuid->Data3);
1441 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1444 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1447 MSFT_NameIntro niName;
1449 WCHAR* pwstring = NULL;
1450 BSTR bstrName = NULL;
1454 ERR_(typelib)("bad offset %d\n", offset);
1457 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1458 pcx->pTblDir->pNametab.offset+offset);
1459 niName.namelen &= 0xFF; /* FIXME: correct ? */
1460 name=TLB_Alloc((niName.namelen & 0xff) +1);
1461 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1462 name[niName.namelen & 0xff]='\0';
1464 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1467 /* no invalid characters in string */
1470 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1472 /* don't check for invalid character since this has been done previously */
1473 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1475 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1476 lengthInChars = SysStringLen(bstrName);
1477 HeapFree(GetProcessHeap(), 0, pwstring);
1480 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1484 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1491 if(offset<0) return NULL;
1492 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1493 if(length <= 0) return 0;
1494 string=TLB_Alloc(length +1);
1495 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1496 string[length]='\0';
1498 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1499 string, -1, NULL, 0);
1501 /* no invalid characters in string */
1504 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1506 /* don't check for invalid character since this has been done previously */
1507 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1509 bstr = SysAllocStringLen(pwstring, lengthInChars);
1510 lengthInChars = SysStringLen(bstr);
1511 HeapFree(GetProcessHeap(), 0, pwstring);
1514 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1518 * read a value and fill a VARIANT structure
1520 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1524 TRACE_(typelib)("\n");
1526 if(offset <0) { /* data are packed in here */
1527 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1528 V_I2(pVar) = offset & 0x3ffffff;
1531 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1532 pcx->pTblDir->pCustData.offset + offset );
1533 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1534 switch (V_VT(pVar)){
1535 case VT_EMPTY: /* FIXME: is this right? */
1536 case VT_NULL: /* FIXME: is this right? */
1537 case VT_I2 : /* this should not happen */
1548 case VT_VOID : /* FIXME: is this right? */
1556 case VT_DECIMAL : /* FIXME: is this right? */
1559 /* pointer types with known behaviour */
1562 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1564 FIXME("BSTR length = %d?\n", size);
1566 ptr=TLB_Alloc(size);/* allocate temp buffer */
1567 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1568 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1569 /* FIXME: do we need a AtoW conversion here? */
1570 V_UNION(pVar, bstrVal[size])=L'\0';
1571 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1576 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1583 case VT_USERDEFINED :
1589 case VT_STREAMED_OBJECT :
1590 case VT_STORED_OBJECT :
1591 case VT_BLOB_OBJECT :
1596 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1600 if(size>0) /* (big|small) endian correct? */
1601 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1605 * create a linked list with custom data
1607 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1613 TRACE_(typelib)("\n");
1617 pNew=TLB_Alloc(sizeof(TLBCustData));
1618 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1619 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1620 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1621 /* add new custom data at head of the list */
1622 pNew->next=*ppCustData;
1624 offset = entry.next;
1629 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1633 pTd->vt=type & VT_TYPEMASK;
1635 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1637 if(pTd->vt == VT_USERDEFINED)
1638 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1640 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1644 MSFT_DoFuncs(TLBContext* pcx,
1649 TLBFuncDesc** pptfd)
1652 * member information is stored in a data structure at offset
1653 * indicated by the memoffset field of the typeinfo structure
1654 * There are several distinctive parts.
1655 * The first part starts with a field that holds the total length
1656 * of this (first) part excluding this field. Then follow the records,
1657 * for each member there is one record.
1659 * The first entry is always the length of the record (including this
1661 * The rest of the record depends on the type of the member. If there is
1662 * a field indicating the member type (function, variable, interface, etc)
1663 * I have not found it yet. At this time we depend on the information
1664 * in the type info and the usual order how things are stored.
1666 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1669 * Third is an equal sized array with file offsets to the name entry
1672 * The fourth and last (?) part is an array with offsets to the records
1673 * in the first part of this file segment.
1676 int infolen, nameoffset, reclength, nrattributes, i;
1677 int recoffset = offset + sizeof(INT);
1680 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1682 TRACE_(typelib)("\n");
1684 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1686 for ( i = 0; i < cFuncs ; i++ )
1688 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1690 /* name, eventually add to a hash table */
1691 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1692 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1694 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1696 /* read the function information record */
1697 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1701 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1703 /* do the attributes */
1704 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1707 if ( nrattributes > 0 )
1709 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1711 if ( nrattributes > 1 )
1713 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1714 pFuncRec->OptAttr[1]) ;
1716 if ( nrattributes > 2 )
1718 if ( pFuncRec->FKCCIC & 0x2000 )
1720 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1724 (*pptfd)->Entry = MSFT_ReadString(pcx,
1725 pFuncRec->OptAttr[2]);
1727 if( nrattributes > 5 )
1729 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1731 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1734 pFuncRec->OptAttr[6],
1735 &(*pptfd)->pCustData);
1742 /* fill the FuncDesc Structure */
1743 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1744 offset + infolen + ( i + 1) * sizeof(INT));
1746 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1747 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1748 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1749 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1750 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1751 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1752 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1756 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1759 /* do the parameters/arguments */
1760 if(pFuncRec->nrargs)
1763 MSFT_ParameterInfo paraminfo;
1765 (*pptfd)->funcdesc.lprgelemdescParam =
1766 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1768 (*pptfd)->pParamDesc =
1769 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1771 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1772 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1774 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1776 TYPEDESC* lpArgTypeDesc = 0;
1780 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1783 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1786 if (paraminfo.oName == -1)
1787 /* this occurs for [propput] or [propget] methods, so
1788 * we should just set the name of the parameter to the
1789 * name of the method. */
1790 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1792 (*pptfd)->pParamDesc[j].Name =
1793 MSFT_ReadName( pcx, paraminfo.oName );
1794 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1796 /* SEEK value = jump to offset,
1797 * from there jump to the end of record,
1798 * go back by (j-1) arguments
1800 MSFT_ReadLEDWords( ¶minfo ,
1801 sizeof(MSFT_ParameterInfo), pcx,
1802 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1803 * sizeof(MSFT_ParameterInfo)));
1805 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1807 while ( lpArgTypeDesc != NULL )
1809 switch ( lpArgTypeDesc->vt )
1812 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1816 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1819 case VT_USERDEFINED:
1820 MSFT_DoRefType(pcx, pTI,
1821 lpArgTypeDesc->u.hreftype);
1823 lpArgTypeDesc = NULL;
1827 lpArgTypeDesc = NULL;
1833 /* parameter is the return value! */
1834 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1836 TYPEDESC* lpArgTypeDesc;
1838 (*pptfd)->funcdesc.elemdescFunc =
1839 (*pptfd)->funcdesc.lprgelemdescParam[j];
1841 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1843 while ( lpArgTypeDesc != NULL )
1845 switch ( lpArgTypeDesc->vt )
1848 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1852 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1856 case VT_USERDEFINED:
1859 lpArgTypeDesc->u.hreftype);
1861 lpArgTypeDesc = NULL;
1865 lpArgTypeDesc = NULL;
1870 /* second time around */
1871 for(j=0;j<pFuncRec->nrargs;j++)
1874 if ( (PARAMFLAG_FHASDEFAULT &
1875 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1876 ((pFuncRec->FKCCIC) & 0x1000) )
1878 INT* pInt = (INT *)((char *)pFuncRec +
1880 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1882 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1884 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1885 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1887 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1891 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1894 pFuncRec->OptAttr[7+j],
1895 &(*pptfd)->pParamDesc[j].pCustData);
1900 /* scode is not used: archaic win16 stuff FIXME: right? */
1901 (*pptfd)->funcdesc.cScodes = 0 ;
1902 (*pptfd)->funcdesc.lprgscode = NULL ;
1904 pptfd = & ((*pptfd)->next);
1905 recoffset += reclength;
1909 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1910 int cVars, int offset, TLBVarDesc ** pptvd)
1912 int infolen, nameoffset, reclength;
1914 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1918 TRACE_(typelib)("\n");
1920 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1921 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1922 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1923 recoffset += offset+sizeof(INT);
1924 for(i=0;i<cVars;i++){
1925 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1926 /* name, eventually add to a hash table */
1927 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1928 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1929 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1930 /* read the variable information record */
1931 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1933 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1935 if(reclength >(6*sizeof(INT)) )
1936 (*pptvd)->HelpContext=pVarRec->HelpContext;
1937 if(reclength >(7*sizeof(INT)) )
1938 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1939 if(reclength >(8*sizeof(INT)) )
1940 if(reclength >(9*sizeof(INT)) )
1941 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1942 /* fill the VarDesc Structure */
1943 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1944 offset + infolen + ( i + 1) * sizeof(INT));
1945 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1946 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1947 MSFT_GetTdesc(pcx, pVarRec->DataType,
1948 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1949 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1950 if(pVarRec->VarKind == VAR_CONST ){
1951 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1952 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1953 pVarRec->OffsValue, pcx);
1955 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1956 pptvd=&((*pptvd)->next);
1957 recoffset += reclength;
1960 /* fill in data for a hreftype (offset). When the referenced type is contained
1961 * in the typelib, it's just an (file) offset in the type info base dir.
1962 * If comes from import, it's an offset+1 in the ImpInfo table
1964 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1968 TLBRefType **ppRefType = &pTI->reflist;
1970 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1973 if((*ppRefType)->reference == offset)
1975 ppRefType = &(*ppRefType)->next;
1978 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1979 sizeof(**ppRefType));
1981 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1982 /* external typelib */
1983 MSFT_ImpInfo impinfo;
1984 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1986 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1988 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1989 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1990 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1991 if(pImpLib->offset==impinfo.oImpFile) break;
1992 pImpLib=pImpLib->next;
1995 (*ppRefType)->reference=offset;
1996 (*ppRefType)->pImpTLInfo = pImpLib;
1997 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
1998 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1999 (*ppRefType)->index = TLB_REF_USE_GUID;
2001 (*ppRefType)->index = impinfo.oGuid;
2003 ERR("Cannot find a reference\n");
2004 (*ppRefType)->reference=-1;
2005 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
2008 /* in this typelib */
2009 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
2010 (*ppRefType)->reference=offset;
2011 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
2015 /* process Implemented Interfaces of a com class */
2016 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2020 MSFT_RefRecord refrec;
2021 TLBImplType **ppImpl = &pTI->impltypelist;
2023 TRACE_(typelib)("\n");
2025 for(i=0;i<count;i++){
2026 if(offset<0) break; /* paranoia */
2027 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2028 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2029 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2030 (*ppImpl)->hRef = refrec.reftype;
2031 (*ppImpl)->implflags=refrec.flags;
2032 (*ppImpl)->ctCustData=
2033 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2034 offset=refrec.onext;
2035 ppImpl=&((*ppImpl)->next);
2039 * process a typeinfo record
2041 static ITypeInfoImpl * MSFT_DoTypeInfo(
2044 ITypeLibImpl * pLibInfo)
2046 MSFT_TypeInfoBase tiBase;
2047 ITypeInfoImpl *ptiRet;
2049 TRACE_(typelib)("count=%u\n", count);
2051 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2052 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2053 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2055 /* this is where we are coming from */
2056 ptiRet->pTypeLib = pLibInfo;
2057 ptiRet->index=count;
2058 /* fill in the typeattr fields */
2059 WARN("Assign constructor/destructor memid\n");
2061 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2062 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2063 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2064 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2065 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2066 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2067 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2068 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2069 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2070 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2071 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2072 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2073 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2074 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2075 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2076 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2077 MSFT_GetTdesc(pcx, tiBase.datatype1,
2078 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2081 /* IDLDESC idldescType; *//* never saw this one != zero */
2083 /* name, eventually add to a hash table */
2084 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2085 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2087 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2088 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2089 ptiRet->dwHelpContext=tiBase.helpcontext;
2091 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2092 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2094 /* note: InfoType's Help file and HelpStringDll come from the containing
2095 * library. Further HelpString and Docstring appear to be the same thing :(
2098 if(ptiRet->TypeAttr.cFuncs >0 )
2099 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2100 ptiRet->TypeAttr.cVars,
2101 tiBase.memoffset, & ptiRet->funclist);
2103 if(ptiRet->TypeAttr.cVars >0 )
2104 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2105 ptiRet->TypeAttr.cVars,
2106 tiBase.memoffset, & ptiRet->varlist);
2107 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2108 switch(ptiRet->TypeAttr.typekind)
2111 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2114 case TKIND_DISPATCH:
2115 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2117 if (tiBase.datatype1 != -1)
2119 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2120 ptiRet->impltypelist->hRef = tiBase.datatype1;
2123 { /* FIXME: This is a really bad hack to add IDispatch */
2124 const char* szStdOle = "stdole2.tlb\0";
2125 int nStdOleLen = strlen(szStdOle);
2126 TLBRefType **ppRef = &ptiRet->reflist;
2129 if((*ppRef)->reference == -1)
2131 ppRef = &(*ppRef)->next;
2134 *ppRef = TLB_Alloc(sizeof(**ppRef));
2135 (*ppRef)->guid = IID_IDispatch;
2136 (*ppRef)->reference = -1;
2137 (*ppRef)->index = TLB_REF_USE_GUID;
2138 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2139 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2140 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2143 MultiByteToWideChar(CP_ACP,
2147 (*ppRef)->pImpTLInfo->name,
2148 SysStringLen((*ppRef)->pImpTLInfo->name));
2150 (*ppRef)->pImpTLInfo->lcid = 0;
2151 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2152 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2157 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2158 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2159 ptiRet->impltypelist->hRef = tiBase.datatype1;
2164 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2166 TRACE_(typelib)("%s guid: %s kind:%s\n",
2167 debugstr_w(ptiRet->Name),
2168 debugstr_guid(&ptiRet->TypeAttr.guid),
2169 typekind_desc[ptiRet->TypeAttr.typekind]);
2174 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2175 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2176 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2179 static ITypeLibImpl *tlb_cache_first;
2180 static CRITICAL_SECTION cache_section;
2181 static CRITICAL_SECTION_DEBUG cache_section_debug =
2183 0, 0, &cache_section,
2184 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2185 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2187 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2190 /****************************************************************************
2193 * find the type of the typelib file and map the typelib resource into
2196 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2197 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2198 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2200 ITypeLibImpl *entry;
2201 int ret = TYPE_E_CANTLOADLIBRARY;
2202 DWORD dwSignature = 0;
2205 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2209 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2210 EnterCriticalSection(&cache_section);
2211 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2213 if (!strcmpiW(entry->path, pszFileName) && entry->index == index)
2215 TRACE("cache hit\n");
2216 *ppTypeLib = (ITypeLib2*)entry;
2217 ITypeLib_AddRef(*ppTypeLib);
2218 LeaveCriticalSection(&cache_section);
2222 LeaveCriticalSection(&cache_section);
2224 /* check the signature of the file */
2225 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2226 if (INVALID_HANDLE_VALUE != hFile)
2228 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2231 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2234 /* retrieve file size */
2235 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2237 /* first try to load as *.tlb */
2238 dwSignature = FromLEDWord(*((DWORD*) pBase));
2239 if ( dwSignature == MSFT_SIGNATURE)
2241 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2243 else if ( dwSignature == SLTG_SIGNATURE)
2245 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2247 UnmapViewOfFile(pBase);
2249 CloseHandle(hMapping);
2255 TRACE("not found, trying to load %s as library\n", debugstr_w(pszFileName));
2258 /* if the file is a DLL or not found, try loading it with LoadLibrary */
2259 if (((WORD)dwSignature == IMAGE_DOS_SIGNATURE) || (dwSignature == 0))
2261 /* find the typelibrary resource*/
2262 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2263 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2266 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2267 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2270 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2273 LPVOID pBase = LockResource(hGlobal);
2274 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2278 /* try to load as incore resource */
2279 dwSignature = FromLEDWord(*((DWORD*) pBase));
2280 if ( dwSignature == MSFT_SIGNATURE)
2282 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2284 else if ( dwSignature == SLTG_SIGNATURE)
2286 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2290 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2293 FreeResource( hGlobal );
2296 FreeLibrary(hinstDLL);
2301 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2303 TRACE("adding to cache\n");
2304 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2305 lstrcpyW(impl->path, pszFileName);
2306 /* We should really canonicalise the path here. */
2307 impl->index = index;
2309 /* FIXME: check if it has added already in the meantime */
2310 EnterCriticalSection(&cache_section);
2311 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2313 tlb_cache_first = impl;
2314 LeaveCriticalSection(&cache_section);
2317 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2322 /*================== ITypeLib(2) Methods ===================================*/
2324 /****************************************************************************
2325 * ITypeLib2_Constructor_MSFT
2327 * loading an MSFT typelib from an in-memory image
2329 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2333 MSFT_Header tlbHeader;
2334 MSFT_SegDir tlbSegDir;
2335 ITypeLibImpl * pTypeLibImpl;
2337 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2339 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2340 if (!pTypeLibImpl) return NULL;
2342 pTypeLibImpl->lpVtbl = &tlbvt;
2343 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2344 pTypeLibImpl->ref = 1;
2346 /* get pointer to beginning of typelib data */
2350 cx.pLibInfo = pTypeLibImpl;
2351 cx.length = dwTLBLength;
2354 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2356 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2357 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2358 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2361 /* there is a small amount of information here until the next important
2363 * the segment directory . Try to calculate the amount of data */
2364 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2366 /* now read the segment directory */
2367 TRACE("read segment directory (at %ld)\n",lPSegDir);
2368 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2369 cx.pTblDir = &tlbSegDir;
2371 /* just check two entries */
2372 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2374 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2375 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2379 /* now fill our internal data */
2380 /* TLIBATTR fields */
2381 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2383 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2384 /* Windows seems to have zero here, is this correct? */
2385 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2386 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2388 pTypeLibImpl->LibAttr.lcid = 0;
2390 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2391 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2392 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2393 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2395 /* name, eventually add to a hash table */
2396 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2399 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2400 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2402 if( tlbHeader.varflags & HELPDLLFLAG)
2405 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2406 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2409 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2412 if(tlbHeader.CustomDataOffset >= 0)
2414 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2417 /* fill in typedescriptions */
2418 if(tlbSegDir.pTypdescTab.length > 0)
2420 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2422 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2423 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2426 /* FIXME: add several sanity checks here */
2427 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2428 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2430 /* FIXME: check safearray */
2432 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2434 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2436 else if(td[0] == VT_CARRAY)
2438 /* array descr table here */
2439 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2441 else if(td[0] == VT_USERDEFINED)
2443 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2445 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2448 /* second time around to fill the array subscript info */
2451 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2452 if(tlbSegDir.pArrayDescriptions.offset>0)
2454 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2455 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2458 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2460 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2462 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2464 for(j = 0; j<td[2]; j++)
2466 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2467 sizeof(INT), &cx, DO_NOT_SEEK);
2468 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2469 sizeof(INT), &cx, DO_NOT_SEEK);
2474 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2475 ERR("didn't find array description data\n");
2480 /* imported type libs */
2481 if(tlbSegDir.pImpFiles.offset>0)
2483 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2484 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2487 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2492 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2493 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2494 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2496 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2497 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2498 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2499 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2502 name = TLB_Alloc(size+1);
2503 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2504 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2505 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2506 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2509 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2510 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2512 ppImpLib = &(*ppImpLib)->next;
2517 if(tlbHeader.nrtypeinfos >= 0 )
2519 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2520 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2523 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2525 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2527 ppTI = &((*ppTI)->next);
2528 (pTypeLibImpl->TypeInfoCount)++;
2532 TRACE("(%p)\n", pTypeLibImpl);
2533 return (ITypeLib2*) pTypeLibImpl;
2537 static BSTR TLB_MultiByteToBSTR(char *ptr)
2543 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2544 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2545 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2546 ret = SysAllocString(nameW);
2547 HeapFree(GetProcessHeap(), 0, nameW);
2551 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2557 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2558 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2562 guid->Data4[0] = s >> 8;
2563 guid->Data4[1] = s & 0xff;
2566 for(i = 0; i < 6; i++) {
2567 memcpy(b, str + 24 + 2 * i, 2);
2568 guid->Data4[i + 2] = strtol(b, NULL, 16);
2573 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2580 bytelen = *(WORD*)ptr;
2581 if(bytelen == 0xffff) return 2;
2582 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2583 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2584 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2585 *pBstr = SysAllocStringLen(nameW, len);
2586 HeapFree(GetProcessHeap(), 0, nameW);
2590 static WORD SLTG_ReadStringA(char *ptr, char **str)
2595 bytelen = *(WORD*)ptr;
2596 if(bytelen == 0xffff) return 2;
2597 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2598 memcpy(*str, ptr + 2, bytelen);
2599 (*str)[bytelen] = '\0';
2603 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2605 char *ptr = pLibBlk;
2608 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2609 FIXME("libblk magic = %04x\n", w);
2614 if((w = *(WORD*)ptr) != 0xffff) {
2615 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2620 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2622 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2624 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2627 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2630 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2631 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2633 pTypeLibImpl->LibAttr.lcid = 0;
2636 ptr += 4; /* skip res12 */
2638 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2641 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2644 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2647 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2648 ptr += sizeof(GUID);
2650 return ptr - (char*)pLibBlk;
2653 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2656 TYPEDESC *pTD = &pElem->tdesc;
2658 /* Handle [in/out] first */
2659 if((*pType & 0xc000) == 0xc000)
2660 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2661 else if(*pType & 0x8000)
2662 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2663 else if(*pType & 0x4000)
2664 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2666 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2669 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2672 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2675 if((*pType & 0xe00) == 0xe00) {
2677 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2679 pTD = pTD->u.lptdesc;
2681 switch(*pType & 0x7f) {
2684 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2686 pTD = pTD->u.lptdesc;
2689 case VT_USERDEFINED:
2690 pTD->vt = VT_USERDEFINED;
2691 pTD->u.hreftype = *(++pType) / 4;
2697 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2700 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2702 pTD->vt = VT_CARRAY;
2703 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2705 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2706 pTD->u.lpadesc->cDims = pSA->cDims;
2707 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2708 pSA->cDims * sizeof(SAFEARRAYBOUND));
2710 pTD = &pTD->u.lpadesc->tdescElem;
2716 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2720 pTD->vt = VT_SAFEARRAY;
2721 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2723 pTD = pTD->u.lptdesc;
2727 pTD->vt = *pType & 0x7f;
2737 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2742 TLBRefType **ppRefType;
2744 if(pRef->magic != SLTG_REF_MAGIC) {
2745 FIXME("Ref magic = %x\n", pRef->magic);
2748 name = ( (char*)(&pRef->names) + pRef->number);
2750 ppRefType = &pTI->reflist;
2751 for(ref = 0; ref < pRef->number >> 3; ref++) {
2753 unsigned int lib_offs, type_num;
2755 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2756 sizeof(**ppRefType));
2758 name += SLTG_ReadStringA(name, &refname);
2759 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2760 FIXME("Can't sscanf ref\n");
2761 if(lib_offs != 0xffff) {
2762 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2765 if((*import)->offset == lib_offs)
2767 import = &(*import)->next;
2770 char fname[MAX_PATH+1];
2773 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2775 (*import)->offset = lib_offs;
2776 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2778 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2779 &(*import)->wVersionMajor,
2780 &(*import)->wVersionMinor,
2781 &(*import)->lcid, fname) != 4) {
2782 FIXME("can't sscanf ref %s\n",
2783 pNameTable + lib_offs + 40);
2785 len = strlen(fname);
2786 if(fname[len-1] != '#')
2787 FIXME("fname = %s\n", fname);
2788 fname[len-1] = '\0';
2789 (*import)->name = TLB_MultiByteToBSTR(fname);
2791 (*ppRefType)->pImpTLInfo = *import;
2792 } else { /* internal ref */
2793 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2795 (*ppRefType)->reference = ref;
2796 (*ppRefType)->index = type_num;
2798 HeapFree(GetProcessHeap(), 0, refname);
2799 ppRefType = &(*ppRefType)->next;
2801 if((BYTE)*name != SLTG_REF_MAGIC)
2802 FIXME("End of ref block magic = %x\n", *name);
2803 dump_TLBRefType(pTI->reflist);
2806 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2809 SLTG_ImplInfo *info;
2810 TLBImplType **ppImplType = &pTI->impltypelist;
2811 /* I don't really get this structure, usually it's 0x16 bytes
2812 long, but iuser.tlb contains some that are 0x18 bytes long.
2813 That's ok because we can use the next ptr to jump to the next
2814 one. But how do we know the length of the last one? The WORD
2815 at offs 0x8 might be the clue. For now I'm just assuming that
2816 the last one is the regular 0x16 bytes. */
2818 info = (SLTG_ImplInfo*)pBlk;
2820 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2821 sizeof(**ppImplType));
2822 (*ppImplType)->hRef = info->ref;
2823 (*ppImplType)->implflags = info->impltypeflags;
2824 pTI->TypeAttr.cImplTypes++;
2825 ppImplType = &(*ppImplType)->next;
2827 if(info->next == 0xffff)
2830 FIXME("Interface inheriting more than one interface\n");
2831 info = (SLTG_ImplInfo*)(pBlk + info->next);
2833 info++; /* see comment at top of function */
2837 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2840 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2841 SLTG_MemberHeader *pMemHeader;
2842 char *pFirstItem, *pNextItem;
2844 if(pTIHeader->href_table != 0xffffffff) {
2845 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2850 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2852 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2854 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2855 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2858 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2862 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2865 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2866 SLTG_MemberHeader *pMemHeader;
2867 SLTG_Function *pFunc;
2868 char *pFirstItem, *pNextItem;
2869 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2872 if(pTIHeader->href_table != 0xffffffff) {
2873 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2877 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2879 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2881 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2882 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2885 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2886 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2891 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2892 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2893 FIXME("func magic = %02x\n", pFunc->magic);
2896 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2897 sizeof(**ppFuncDesc));
2898 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2900 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2901 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2902 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2903 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2904 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2905 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2907 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2908 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2910 if(pFunc->retnextopt & 0x80)
2911 pType = &pFunc->rettype;
2913 pType = (WORD*)(pFirstItem + pFunc->rettype);
2916 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2918 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2919 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2920 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2921 (*ppFuncDesc)->pParamDesc =
2922 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2923 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2925 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2927 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2928 char *paramName = pNameTable + *pArg;
2930 /* If arg type follows then paramName points to the 2nd
2931 letter of the name, else the next WORD is an offset to
2932 the arg type and paramName points to the first letter.
2933 So let's take one char off paramName and see if we're
2934 pointing at an alpha-numeric char. However if *pArg is
2935 0xffff or 0xfffe then the param has no name, the former
2936 meaning that the next WORD is the type, the latter
2937 meaning the the next WORD is an offset to the type. */
2942 else if(*pArg == 0xfffe) {
2946 else if(paramName[-1] && !isalnum(paramName[-1]))
2951 if(HaveOffs) { /* the next word is an offset to type */
2952 pType = (WORD*)(pFirstItem + *pArg);
2953 SLTG_DoType(pType, pFirstItem,
2954 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2959 pArg = SLTG_DoType(pArg, pFirstItem,
2960 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2963 /* Are we an optional param ? */
2964 if((*ppFuncDesc)->funcdesc.cParams - param <=
2965 (*ppFuncDesc)->funcdesc.cParamsOpt)
2966 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2969 (*ppFuncDesc)->pParamDesc[param].Name =
2970 TLB_MultiByteToBSTR(paramName);
2974 ppFuncDesc = &((*ppFuncDesc)->next);
2975 if(pFunc->next == 0xffff) break;
2977 pTI->TypeAttr.cFuncs = num;
2978 dump_TLBFuncDesc(pTI->funclist);
2979 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2982 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2985 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2986 SLTG_MemberHeader *pMemHeader;
2987 SLTG_RecordItem *pItem;
2989 TLBVarDesc **ppVarDesc = &pTI->varlist;
2994 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2996 pFirstItem = (char*)(pMemHeader + 1);
2997 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2998 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2999 if(pItem->magic != SLTG_RECORD_MAGIC) {
3000 FIXME("record magic = %02x\n", pItem->magic);
3003 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3004 sizeof(**ppVarDesc));
3005 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3006 (*ppVarDesc)->vardesc.memid = pItem->memid;
3007 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3008 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3010 if(pItem->typepos == 0x02)
3011 pType = &pItem->type;
3012 else if(pItem->typepos == 0x00)
3013 pType = (WORD*)(pFirstItem + pItem->type);
3015 FIXME("typepos = %02x\n", pItem->typepos);
3019 SLTG_DoType(pType, pFirstItem,
3020 &(*ppVarDesc)->vardesc.elemdescVar);
3022 /* FIXME("helpcontext, helpstring\n"); */
3024 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3026 ppVarDesc = &((*ppVarDesc)->next);
3027 if(pItem->next == 0xffff) break;
3029 pTI->TypeAttr.cVars = num;
3030 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3033 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3036 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3037 SLTG_MemberHeader *pMemHeader;
3038 SLTG_AliasItem *pItem;
3041 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3042 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3045 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3046 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3047 if (pItem->vt == 0xffff) {
3048 if (i<(pMemHeader->cbExtra/4-1))
3049 FIXME("Endmarker too early in process alias data!\n");
3053 FIXME("Chain extends over last entry?\n");
3056 if (pItem->vt == VT_USERDEFINED) {
3057 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3058 /* guessing here ... */
3059 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3060 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3063 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3064 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3068 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3071 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3074 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3075 SLTG_MemberHeader *pMemHeader;
3076 SLTG_AliasItem *pItem;
3078 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3079 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3080 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3081 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3082 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3085 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3088 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3089 SLTG_MemberHeader *pMemHeader;
3090 SLTG_EnumItem *pItem;
3092 TLBVarDesc **ppVarDesc = &pTI->varlist;
3095 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3097 pFirstItem = (char*)(pMemHeader + 1);
3098 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3099 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3100 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3101 FIXME("enumitem magic = %04x\n", pItem->magic);
3104 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3105 sizeof(**ppVarDesc));
3106 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3107 (*ppVarDesc)->vardesc.memid = pItem->memid;
3108 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3110 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3111 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3112 *(INT*)(pItem->value + pFirstItem);
3113 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3114 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3115 /* FIXME("helpcontext, helpstring\n"); */
3117 ppVarDesc = &((*ppVarDesc)->next);
3118 if(pItem->next == 0xffff) break;
3120 pTI->TypeAttr.cVars = num;
3121 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3124 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3125 managable copy of it into this */
3138 } SLTG_InternalOtherTypeInfo;
3140 /****************************************************************************
3141 * ITypeLib2_Constructor_SLTG
3143 * loading a SLTG typelib from an in-memory image
3145 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3147 ITypeLibImpl *pTypeLibImpl;
3148 SLTG_Header *pHeader;
3149 SLTG_BlkEntry *pBlkEntry;
3153 LPVOID pBlk, pFirstBlk;
3154 SLTG_LibBlk *pLibBlk;
3155 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3156 char *pAfterOTIBlks = NULL;
3157 char *pNameTable, *ptr;
3160 ITypeInfoImpl **ppTypeInfoImpl;
3162 TRACE_(typelib)("%p, TLB length = %ld\n", pLib, dwTLBLength);
3164 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3165 if (!pTypeLibImpl) return NULL;
3167 pTypeLibImpl->lpVtbl = &tlbvt;
3168 pTypeLibImpl->ref = 1;
3172 TRACE_(typelib)("header:\n");
3173 TRACE_(typelib)("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3174 pHeader->nrOfFileBlks );
3175 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3176 FIXME("Header type magic 0x%08lx not supported.\n",
3177 pHeader->SLTG_magic);
3181 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3182 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3184 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3185 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3187 /* Next we have a magic block */
3188 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3190 /* Let's see if we're still in sync */
3191 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3192 sizeof(SLTG_COMPOBJ_MAGIC))) {
3193 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3196 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3197 sizeof(SLTG_DIR_MAGIC))) {
3198 FIXME("dir magic = %s\n", pMagic->dir_magic);
3202 pIndex = (SLTG_Index*)(pMagic+1);
3204 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3206 pFirstBlk = (LPVOID)(pPad9 + 1);
3208 /* We'll set up a ptr to the main library block, which is the last one. */
3210 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3211 pBlkEntry[order].next != 0;
3212 order = pBlkEntry[order].next - 1, i++) {
3213 pBlk = (char*)pBlk + pBlkEntry[order].len;
3217 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3219 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3224 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3226 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3227 sizeof(*pOtherTypeInfoBlks) *
3228 pTypeLibImpl->TypeInfoCount);
3231 ptr = (char*)pLibBlk + len;
3233 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3237 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3239 w = *(WORD*)(ptr + 2);
3242 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3244 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3245 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3247 w = *(WORD*)(ptr + 4 + len);
3249 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3251 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3253 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3254 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3256 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3257 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3258 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3260 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3262 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3265 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3266 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3267 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3268 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3269 len += sizeof(SLTG_OtherTypeInfo);
3273 pAfterOTIBlks = ptr;
3275 /* Skip this WORD and get the next DWORD */
3276 len = *(DWORD*)(pAfterOTIBlks + 2);
3278 /* Now add this to pLibBLk look at what we're pointing at and
3279 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3280 dust and we should be pointing at the beginning of the name
3283 pNameTable = (char*)pLibBlk + len;
3285 switch(*(WORD*)pNameTable) {
3292 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3296 pNameTable += 0x216;
3300 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3302 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3305 /* Hopefully we now have enough ptrs set up to actually read in
3306 some TypeInfos. It's not clear which order to do them in, so
3307 I'll just follow the links along the BlkEntry chain and read
3308 them in in the order in which they're in the file */
3310 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3312 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3313 pBlkEntry[order].next != 0;
3314 order = pBlkEntry[order].next - 1, i++) {
3316 SLTG_TypeInfoHeader *pTIHeader;
3317 SLTG_TypeInfoTail *pTITail;
3319 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3320 pOtherTypeInfoBlks[i].index_name)) {
3321 FIXME("Index strings don't match\n");
3326 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3327 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3330 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3331 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3332 (*ppTypeInfoImpl)->index = i;
3333 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3334 pOtherTypeInfoBlks[i].name_offs +
3336 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3337 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3339 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3340 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3341 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3342 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3343 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3345 if((pTIHeader->typeflags1 & 7) != 2)
3346 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3347 if(pTIHeader->typeflags3 != 2)
3348 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3350 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3351 debugstr_w((*ppTypeInfoImpl)->Name),
3352 typekind_desc[pTIHeader->typekind],
3353 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3354 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3356 switch(pTIHeader->typekind) {
3358 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3362 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3365 case TKIND_INTERFACE:
3366 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3370 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3374 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3375 if (pTITail->tdescalias_vt)
3376 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3379 case TKIND_DISPATCH:
3380 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3384 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3390 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3391 but we've already set those */
3392 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3393 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3394 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3396 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
3418 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3419 pBlk = (char*)pBlk + pBlkEntry[order].len;
3422 if(i != pTypeLibImpl->TypeInfoCount) {
3423 FIXME("Somehow processed %d TypeInfos\n", i);
3427 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3428 return (ITypeLib2*)pTypeLibImpl;
3431 /* ITypeLib::QueryInterface
3433 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3438 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3440 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3443 if(IsEqualIID(riid, &IID_IUnknown) ||
3444 IsEqualIID(riid,&IID_ITypeLib)||
3445 IsEqualIID(riid,&IID_ITypeLib2))
3452 ITypeLib2_AddRef(iface);
3453 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3456 TRACE("-- Interface: E_NOINTERFACE\n");
3457 return E_NOINTERFACE;
3462 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3464 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3465 ULONG ref = InterlockedIncrement(&This->ref);
3467 TRACE("(%p)->ref was %lu\n",This, ref - 1);
3472 /* ITypeLib::Release
3474 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3476 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3477 ULONG ref = InterlockedDecrement(&This->ref);
3479 TRACE("(%p)->(%lu)\n",This, ref);
3483 /* remove cache entry */
3484 TRACE("removing from cache list\n");
3485 EnterCriticalSection(&cache_section);
3486 if (This->next) This->next->prev = This->prev;
3487 if (This->prev) This->prev->next = This->next;
3488 else tlb_cache_first = This->next;
3489 LeaveCriticalSection(&cache_section);
3491 /* FIXME destroy child objects */
3492 TRACE(" destroying ITypeLib(%p)\n",This);
3496 SysFreeString(This->Name);
3500 if (This->DocString)
3502 SysFreeString(This->DocString);
3503 This->DocString = NULL;
3508 SysFreeString(This->HelpFile);
3509 This->HelpFile = NULL;
3512 if (This->HelpStringDll)
3514 SysFreeString(This->HelpStringDll);
3515 This->HelpStringDll = NULL;
3518 if (This->pTypeInfo) /* can be NULL */
3519 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3520 HeapFree(GetProcessHeap(),0,This);
3527 /* ITypeLib::GetTypeInfoCount
3529 * Returns the number of type descriptions in the type library
3531 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3533 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3534 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3535 return This->TypeInfoCount;
3538 /* ITypeLib::GetTypeInfo
3540 * retrieves the specified type description in the library.
3542 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3545 ITypeInfo **ppTInfo)
3549 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3550 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3552 TRACE("(%p)->(index=%d) \n", This, index);
3554 if (!ppTInfo) return E_INVALIDARG;
3556 /* search element n in list */
3557 for(i=0; i < index; i++)
3559 pTypeInfo = pTypeInfo->next;
3562 TRACE("-- element not found\n");
3563 return TYPE_E_ELEMENTNOTFOUND;
3567 *ppTInfo = (ITypeInfo *) pTypeInfo;
3569 ITypeInfo_AddRef(*ppTInfo);
3570 TRACE("-- found (%p)\n",*ppTInfo);
3575 /* ITypeLibs::GetTypeInfoType
3577 * Retrieves the type of a type description.
3579 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3584 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3586 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3588 TRACE("(%p) index %d \n",This, index);
3590 if(!pTKind) return E_INVALIDARG;
3592 /* search element n in list */
3593 for(i=0; i < index; i++)
3597 TRACE("-- element not found\n");
3598 return TYPE_E_ELEMENTNOTFOUND;
3600 pTInfo = pTInfo->next;
3603 *pTKind = pTInfo->TypeAttr.typekind;
3604 TRACE("-- found Type (%d)\n", *pTKind);
3608 /* ITypeLib::GetTypeInfoOfGuid
3610 * Retrieves the type description that corresponds to the specified GUID.
3613 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3616 ITypeInfo **ppTInfo)
3618 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3619 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3621 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3623 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3625 /* search linked list for guid */
3626 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3628 pTypeInfo = pTypeInfo->next;
3632 /* end of list reached */
3633 TRACE("-- element not found\n");
3634 return TYPE_E_ELEMENTNOTFOUND;
3638 TRACE("-- found (%p, %s)\n",
3640 debugstr_w(pTypeInfo->Name));
3642 *ppTInfo = (ITypeInfo*)pTypeInfo;
3643 ITypeInfo_AddRef(*ppTInfo);
3647 /* ITypeLib::GetLibAttr
3649 * Retrieves the structure that contains the library's attributes.
3652 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3654 LPTLIBATTR *ppTLibAttr)
3656 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3657 TRACE("(%p)\n",This);
3658 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3659 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3663 /* ITypeLib::GetTypeComp
3665 * Enables a client compiler to bind to a library's types, variables,
3666 * constants, and global functions.
3669 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3671 ITypeComp **ppTComp)
3673 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3675 TRACE("(%p)->(%p)\n",This,ppTComp);
3676 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3677 ITypeComp_AddRef(*ppTComp);
3682 /* ITypeLib::GetDocumentation
3684 * Retrieves the library's documentation string, the complete Help file name
3685 * and path, and the context identifier for the library Help topic in the Help
3688 * On a successful return all non-null BSTR pointers will have been set,
3691 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3695 BSTR *pBstrDocString,
3696 DWORD *pdwHelpContext,
3697 BSTR *pBstrHelpFile)
3699 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3701 HRESULT result = E_INVALIDARG;
3706 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3708 pBstrName, pBstrDocString,
3709 pdwHelpContext, pBstrHelpFile);
3713 /* documentation for the typelib */
3718 if(!(*pBstrName = SysAllocString(This->Name)))
3726 if (This->DocString)
3728 if(!(*pBstrDocString = SysAllocString(This->DocString)))
3731 else if (This->Name)
3733 if(!(*pBstrDocString = SysAllocString(This->Name)))
3737 *pBstrDocString = NULL;
3741 *pdwHelpContext = This->dwHelpContext;
3747 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
3751 *pBstrHelpFile = NULL;
3758 /* for a typeinfo */
3759 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3761 if(SUCCEEDED(result))
3763 result = ITypeInfo_GetDocumentation(pTInfo,
3767 pdwHelpContext, pBstrHelpFile);
3769 ITypeInfo_Release(pTInfo);
3774 if (pBstrDocString) SysFreeString (*pBstrDocString);
3776 if (pBstrName) SysFreeString (*pBstrName);
3778 return STG_E_INSUFFICIENTMEMORY;
3783 * Indicates whether a passed-in string contains the name of a type or member
3784 * described in the library.
3787 static HRESULT WINAPI ITypeLib2_fnIsName(
3793 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3794 ITypeInfoImpl *pTInfo;
3795 TLBFuncDesc *pFInfo;
3798 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3800 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3804 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3805 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3806 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3807 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3808 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3809 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3810 goto ITypeLib2_fnIsName_exit;
3812 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3813 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3818 ITypeLib2_fnIsName_exit:
3819 TRACE("(%p)slow! search for %s: %s found!\n", This,
3820 debugstr_w(szNameBuf), *pfName?"NOT":"");
3825 /* ITypeLib::FindName
3827 * Finds occurrences of a type description in a type library. This may be used
3828 * to quickly verify that a name exists in a type library.
3831 static HRESULT WINAPI ITypeLib2_fnFindName(
3835 ITypeInfo **ppTInfo,
3839 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3840 ITypeInfoImpl *pTInfo;
3841 TLBFuncDesc *pFInfo;
3844 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
3846 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3847 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3848 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3849 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3850 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
3851 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3852 goto ITypeLib2_fnFindName_exit;
3855 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3856 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3858 ITypeLib2_fnFindName_exit:
3859 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3860 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3863 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3864 This, *pcFound, debugstr_w(szNameBuf), j);
3871 /* ITypeLib::ReleaseTLibAttr
3873 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3876 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3878 TLIBATTR *pTLibAttr)
3880 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3881 TRACE("freeing (%p)\n",This);
3882 HeapFree(GetProcessHeap(),0,pTLibAttr);
3886 /* ITypeLib2::GetCustData
3888 * gets the custom data
3890 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3895 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3896 TLBCustData *pCData;
3898 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3900 if( IsEqualIID(guid, &pCData->guid)) break;
3903 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3907 VariantInit( pVarVal);
3908 VariantCopy( pVarVal, &pCData->data);
3911 return E_INVALIDARG; /* FIXME: correct? */
3914 /* ITypeLib2::GetLibStatistics
3916 * Returns statistics about a type library that are required for efficient
3917 * sizing of hash tables.
3920 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3922 ULONG *pcUniqueNames,
3923 ULONG *pcchUniqueNames)
3925 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3927 FIXME("(%p): stub!\n", This);
3929 if(pcUniqueNames) *pcUniqueNames=1;
3930 if(pcchUniqueNames) *pcchUniqueNames=1;
3934 /* ITypeLib2::GetDocumentation2
3936 * Retrieves the library's documentation string, the complete Help file name
3937 * and path, the localization context to use, and the context ID for the
3938 * library Help topic in the Help file.
3941 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3945 BSTR *pbstrHelpString,
3946 DWORD *pdwHelpStringContext,
3947 BSTR *pbstrHelpStringDll)
3949 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3953 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3955 /* the help string should be obtained from the helpstringdll,
3956 * using the _DLLGetDocumentation function, based on the supplied
3957 * lcid. Nice to do sometime...
3961 /* documentation for the typelib */
3963 *pbstrHelpString=SysAllocString(This->DocString);
3964 if(pdwHelpStringContext)
3965 *pdwHelpStringContext=This->dwHelpContext;
3966 if(pbstrHelpStringDll)
3967 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3973 /* for a typeinfo */
3974 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3976 if(SUCCEEDED(result))
3978 ITypeInfo2 * pTInfo2;
3979 result = ITypeInfo_QueryInterface(pTInfo,
3981 (LPVOID*) &pTInfo2);
3983 if(SUCCEEDED(result))
3985 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3989 pdwHelpStringContext,
3990 pbstrHelpStringDll);
3992 ITypeInfo2_Release(pTInfo2);
3995 ITypeInfo_Release(pTInfo);
4001 /* ITypeLib2::GetAllCustData
4003 * Gets all custom data items for the library.
4006 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4008 CUSTDATA *pCustData)
4010 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4011 TLBCustData *pCData;
4013 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4014 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4015 if(pCustData->prgCustData ){
4016 pCustData->cCustData=This->ctCustData;
4017 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4018 pCustData->prgCustData[i].guid=pCData->guid;
4019 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4022 ERR(" OUT OF MEMORY! \n");
4023 return E_OUTOFMEMORY;
4028 static const ITypeLib2Vtbl tlbvt = {
4029 ITypeLib2_fnQueryInterface,
4031 ITypeLib2_fnRelease,
4032 ITypeLib2_fnGetTypeInfoCount,
4033 ITypeLib2_fnGetTypeInfo,
4034 ITypeLib2_fnGetTypeInfoType,
4035 ITypeLib2_fnGetTypeInfoOfGuid,
4036 ITypeLib2_fnGetLibAttr,
4037 ITypeLib2_fnGetTypeComp,
4038 ITypeLib2_fnGetDocumentation,
4040 ITypeLib2_fnFindName,
4041 ITypeLib2_fnReleaseTLibAttr,
4043 ITypeLib2_fnGetCustData,
4044 ITypeLib2_fnGetLibStatistics,
4045 ITypeLib2_fnGetDocumentation2,
4046 ITypeLib2_fnGetAllCustData
4050 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4052 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4054 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4057 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4059 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4061 return ITypeLib2_AddRef((ITypeLib2 *)This);
4064 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4066 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4068 return ITypeLib2_Release((ITypeLib2 *)This);
4071 static HRESULT WINAPI ITypeLibComp_fnBind(
4076 ITypeInfo ** ppTInfo,
4077 DESCKIND * pDescKind,
4080 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4084 static HRESULT WINAPI ITypeLibComp_fnBindType(
4088 ITypeInfo ** ppTInfo,
4089 ITypeComp ** ppTComp)
4091 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4095 static const ITypeCompVtbl tlbtcvt =
4098 ITypeLibComp_fnQueryInterface,
4099 ITypeLibComp_fnAddRef,
4100 ITypeLibComp_fnRelease,
4102 ITypeLibComp_fnBind,
4103 ITypeLibComp_fnBindType
4106 /*================== ITypeInfo(2) Methods ===================================*/
4107 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4109 ITypeInfoImpl * pTypeInfoImpl;
4111 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4114 pTypeInfoImpl->lpVtbl = &tinfvt;
4115 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4116 pTypeInfoImpl->ref=1;
4118 TRACE("(%p)\n", pTypeInfoImpl);
4119 return (ITypeInfo2*) pTypeInfoImpl;
4122 /* ITypeInfo::QueryInterface
4124 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4129 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4131 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4134 if(IsEqualIID(riid, &IID_IUnknown) ||
4135 IsEqualIID(riid,&IID_ITypeInfo)||
4136 IsEqualIID(riid,&IID_ITypeInfo2))
4140 ITypeInfo_AddRef(iface);
4141 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4144 TRACE("-- Interface: E_NOINTERFACE\n");
4145 return E_NOINTERFACE;
4148 /* ITypeInfo::AddRef
4150 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4152 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4153 ULONG ref = InterlockedIncrement(&This->ref);
4155 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4157 TRACE("(%p)->ref is %lu\n",This, ref);
4161 /* ITypeInfo::Release
4163 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4165 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4166 ULONG ref = InterlockedDecrement(&This->ref);
4168 TRACE("(%p)->(%lu)\n",This, ref);
4171 /* We don't release ITypeLib when ref=0 because
4172 it means that function is called by ITypeLib2_Release */
4173 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4175 FIXME("destroy child objects\n");
4177 TRACE("destroying ITypeInfo(%p)\n",This);
4180 SysFreeString(This->Name);
4184 if (This->DocString)
4186 SysFreeString(This->DocString);
4187 This->DocString = 0;
4192 SysFreeString(This->DllName);
4198 ITypeInfo_Release((ITypeInfo*)This->next);
4201 HeapFree(GetProcessHeap(),0,This);
4207 /* ITypeInfo::GetTypeAttr
4209 * Retrieves a TYPEATTR structure that contains the attributes of the type
4213 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4214 LPTYPEATTR *ppTypeAttr)
4216 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4217 TRACE("(%p)\n",This);
4218 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr));
4219 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4221 if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */
4222 copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias);
4224 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
4225 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4227 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4228 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4233 /* ITypeInfo::GetTypeComp
4235 * Retrieves the ITypeComp interface for the type description, which enables a
4236 * client compiler to bind to the type description's members.
4239 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4240 ITypeComp * *ppTComp)
4242 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4244 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4246 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4247 ITypeComp_AddRef(*ppTComp);
4251 /* ITypeInfo::GetFuncDesc
4253 * Retrieves the FUNCDESC structure that contains information about a
4254 * specified function.
4257 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4258 LPFUNCDESC *ppFuncDesc)
4260 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4262 TLBFuncDesc * pFDesc;
4263 TRACE("(%p) index %d\n", This, index);
4264 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4267 /* FIXME: must do a copy here */
4268 *ppFuncDesc=&pFDesc->funcdesc;
4271 return E_INVALIDARG;
4274 /* ITypeInfo::GetVarDesc
4276 * Retrieves a VARDESC structure that describes the specified variable.
4279 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4280 LPVARDESC *ppVarDesc)
4282 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4284 TLBVarDesc * pVDesc;
4285 TRACE("(%p) index %d\n", This, index);
4286 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4289 /* FIXME: must do a copy here */
4290 *ppVarDesc=&pVDesc->vardesc;
4293 return E_INVALIDARG;
4296 /* ITypeInfo_GetNames
4298 * Retrieves the variable with the specified member ID (or the name of the
4299 * property or method and its parameters) that correspond to the specified
4302 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4303 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4305 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4306 TLBFuncDesc * pFDesc;
4307 TLBVarDesc * pVDesc;
4309 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4310 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4313 /* function found, now return function and parameter names */
4314 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4317 *rgBstrNames=SysAllocString(pFDesc->Name);
4319 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4325 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4328 *rgBstrNames=SysAllocString(pVDesc->Name);
4333 if(This->TypeAttr.cImplTypes &&
4334 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4335 /* recursive search */
4338 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4340 if(SUCCEEDED(result))
4342 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4343 ITypeInfo_Release(pTInfo);
4346 WARN("Could not search inherited interface!\n");
4350 WARN("no names found\n");
4353 return TYPE_E_ELEMENTNOTFOUND;
4360 /* ITypeInfo::GetRefTypeOfImplType
4362 * If a type description describes a COM class, it retrieves the type
4363 * description of the implemented interface types. For an interface,
4364 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4368 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4373 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4376 TLBImplType *pImpl = This->impltypelist;
4378 TRACE("(%p) index %d\n", This, index);
4379 if (TRACE_ON(ole)) dump_TypeInfo(This);
4383 /* only valid on dual interfaces;
4384 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4386 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4388 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4389 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4395 hr = TYPE_E_ELEMENTNOTFOUND;
4400 /* get element n from linked list */
4401 for(i=0; pImpl && i<index; i++)
4403 pImpl = pImpl->next;
4407 *pRefType = pImpl->hRef;
4409 hr = TYPE_E_ELEMENTNOTFOUND;
4415 TRACE("SUCCESS -- hRef = 0x%08lx\n", *pRefType );
4417 TRACE("FAILURE -- hresult = 0x%08lx\n", hr);
4423 /* ITypeInfo::GetImplTypeFlags
4425 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4426 * or base interface in a type description.
4428 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4429 UINT index, INT *pImplTypeFlags)
4431 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4435 TRACE("(%p) index %d\n", This, index);
4436 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4437 i++, pImpl=pImpl->next)
4439 if(i==index && pImpl){
4440 *pImplTypeFlags=pImpl->implflags;
4444 return TYPE_E_ELEMENTNOTFOUND;
4448 * Maps between member names and member IDs, and parameter names and
4451 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4452 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4454 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4455 TLBFuncDesc * pFDesc;
4456 TLBVarDesc * pVDesc;
4459 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4461 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4463 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4464 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4465 for(i=1; i < cNames; i++){
4466 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4467 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4469 if( j<pFDesc->funcdesc.cParams)
4472 ret=DISP_E_UNKNOWNNAME;
4477 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4478 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4479 if(cNames) *pMemId=pVDesc->vardesc.memid;
4483 /* not found, see if this is and interface with an inheritance */
4484 if(This->TypeAttr.cImplTypes &&
4485 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4486 /* recursive search */
4488 ret=ITypeInfo_GetRefTypeInfo(iface,
4489 This->impltypelist->hRef, &pTInfo);
4491 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4492 ITypeInfo_Release(pTInfo);
4495 WARN("Could not search inherited interface!\n");
4497 WARN("no names found\n");
4498 return DISP_E_UNKNOWNNAME;
4501 /* ITypeInfo::Invoke
4503 * Invokes a method, or accesses a property of an object, that implements the
4504 * interface described by the type description.
4507 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4510 if (TRACE_ON(ole)) {
4512 TRACE("Calling %p(",func);
4513 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4525 res = func(args[0]);
4528 res = func(args[0],args[1]);
4531 res = func(args[0],args[1],args[2]);
4534 res = func(args[0],args[1],args[2],args[3]);
4537 res = func(args[0],args[1],args[2],args[3],args[4]);
4540 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4543 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4546 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4549 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4552 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4555 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4558 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]);
4561 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]);
4564 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]);
4567 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4573 FIXME("unsupported calling convention %d\n",callconv);
4577 TRACE("returns %08lx\n",res);
4581 extern int _argsize(DWORD vt);
4583 /****************************************************************************
4584 * Helper functions for Dispcall / Invoke, which copies one variant
4585 * with target type onto the argument stack.
4588 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4589 DWORD *argpos, VARIANT *arg, VARTYPE vt
4591 UINT arglen = _argsize(vt)*sizeof(DWORD);
4594 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4595 memcpy(argpos,&arg,sizeof(void*));
4599 if (V_VT(arg) == vt) {
4600 memcpy(argpos, &V_I4(arg), arglen);
4604 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4605 memcpy(argpos, &V_ARRAY(arg), sizeof(SAFEARRAY*));
4609 if (vt == VT_VARIANT) {
4610 memcpy(argpos, arg, arglen);
4613 /* Deref BYREF vars if there is need */
4614 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4615 memcpy(argpos,(void*)V_I4(arg), arglen);
4618 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4619 /* in this context, if the type lib specifies IUnknown*, giving an
4620 IDispatch* is correct; so, don't invoke VariantChangeType */
4621 memcpy(argpos,&V_I4(arg), arglen);
4624 if ((vt == VT_PTR) && tdesc)
4625 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4627 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4628 ITypeInfo *tinfo2 = NULL;
4629 TYPEATTR *tattr = NULL;
4632 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4634 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4635 "while coercing from vt 0x%x. Copying 4 byte.\n",
4636 tdesc->u.hreftype,V_VT(arg));
4637 memcpy(argpos, &V_I4(arg), 4);
4640 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4643 ERR("GetTypeAttr failed\n");
4644 ITypeInfo_Release(tinfo2);
4647 switch (tattr->typekind) {
4649 switch ( V_VT( arg ) ) {
4651 *argpos = V_I2(arg);
4655 memcpy(argpos, &V_I4(arg), 4);
4658 case VT_BYREF|VT_I4:
4659 memcpy(argpos, V_I4REF(arg), 4);
4663 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4670 tdesc = &(tattr->tdescAlias);
4671 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4674 case TKIND_INTERFACE:
4675 if (V_VT(arg) == VT_DISPATCH) {
4677 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4678 memcpy(argpos, &V_DISPATCH(arg), 4);
4682 hres=IUnknown_QueryInterface(V_DISPATCH(arg),
4683 &IID_IDispatch,(LPVOID*)&disp);
4684 if (SUCCEEDED(hres)) {
4685 memcpy(argpos,&disp,4);
4686 IUnknown_Release(V_DISPATCH(arg));
4690 FIXME("Failed to query IDispatch interface from %s while "
4691 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4695 if (V_VT(arg) == VT_UNKNOWN) {
4696 memcpy(argpos, &V_UNKNOWN(arg), 4);
4700 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4701 V_VT(arg),debugstr_guid(&(tattr->guid)));
4705 case TKIND_DISPATCH:
4706 if (V_VT(arg) == VT_DISPATCH) {
4707 memcpy(argpos, &V_DISPATCH(arg), 4);
4712 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4716 FIXME("TKIND_RECORD unhandled.\n");
4720 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4724 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4725 ITypeInfo_Release(tinfo2);
4730 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4731 memcpy(argpos,&V_I4(&va), arglen);
4732 FIXME("Should not use VariantChangeType here."
4733 " (conversion from 0x%x -> 0x%x) %08lx\n",
4734 V_VT(arg), vt, *argpos
4738 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4742 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4745 ITypeInfo *tinfo2 = NULL;
4746 TYPEATTR *tattr = NULL;
4748 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
4751 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4753 tdesc->u.hreftype, hr);
4756 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
4759 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08lx\n", hr);
4760 ITypeInfo_Release(tinfo2);
4764 switch (tattr->typekind)
4771 tdesc = &tattr->tdescAlias;
4772 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
4775 case TKIND_INTERFACE:
4776 if (IsEqualIID(&IID_IDispatch, &tattr->guid))
4782 case TKIND_DISPATCH:
4787 FIXME("TKIND_RECORD unhandled.\n");
4792 FIXME("TKIND_RECORD unhandled.\n");
4797 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4801 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4802 ITypeInfo_Release(tinfo2);
4806 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, TYPEDESC *tdesc, VARTYPE *vt)
4810 /* enforce only one level of pointer indirection */
4811 if (!(*vt & VT_BYREF) && (tdesc->vt == VT_PTR))
4813 tdesc = tdesc->u.lptdesc;
4815 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
4816 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
4817 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
4818 if ((tdesc->vt == VT_USERDEFINED) ||
4819 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
4821 VARTYPE vt_userdefined = 0;
4822 TYPEDESC *tdesc_userdefined = tdesc;
4823 if (tdesc->vt == VT_PTR)
4825 vt_userdefined = VT_BYREF;
4826 tdesc_userdefined = tdesc->u.lptdesc;
4828 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
4830 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
4831 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
4833 *vt |= vt_userdefined;
4845 case VT_USERDEFINED:
4846 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
4849 ERR("cannot convert VT_PTR into variant VT\n");
4859 /***********************************************************************
4860 * DispCallFunc (OLEAUT32.@)
4864 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4865 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4867 int i, argsize, argspos;
4871 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4872 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4874 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4875 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4877 for (i=0;i<cActuals;i++) {
4878 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4879 dump_Variant(prgpvarg[i]);
4880 argsize += _argsize(prgvt[i]);
4882 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4883 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4885 for (i=0;i<cActuals;i++) {
4886 VARIANT *arg = prgpvarg[i];
4887 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4888 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4889 argspos += _argsize(prgvt[i]);
4892 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4894 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4899 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4900 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4901 FIXME("Method returned %lx\n",hres);
4903 HeapFree(GetProcessHeap(),0,args);
4907 static HRESULT WINAPI ITypeInfo_fnInvoke(
4912 DISPPARAMS *pDispParams,
4913 VARIANT *pVarResult,
4914 EXCEPINFO *pExcepInfo,
4917 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4919 unsigned int func_index, var_index;
4923 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4924 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4926 dump_DispParms(pDispParams);
4928 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4929 if (SUCCEEDED(hres)) {
4930 FUNCDESC *func_desc;
4932 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4933 if(FAILED(hres)) return hres;
4936 TRACE("invoking:\n");
4937 dump_FUNCDESC(func_desc);
4940 switch (func_desc->funckind) {
4941 case FUNC_PUREVIRTUAL:
4942 case FUNC_VIRTUAL: {
4944 int numargs, numargs2, argspos, args2pos;
4945 DWORD *args , *args2;
4946 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4947 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4950 numargs = 1; /* sizeof(thisptr) */
4952 for (i = 0; i < func_desc->cParams; i++) {
4953 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4955 numargs += _argsize(tdesc->vt);
4956 if (i>=pDispParams->cArgs) { /* arguments to return */
4957 if (tdesc->vt == VT_PTR) {
4958 numargs2 += _argsize(tdesc->u.lptdesc->vt);
4960 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
4961 numargs2 += _argsize(tdesc->vt);
4966 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4967 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
4969 args[0] = (DWORD)pIUnk;
4970 argspos = 1; args2pos = 0;
4971 for (i = 0; i < func_desc->cParams; i++) {
4972 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
4973 TYPEDESC *tdesc = &(elemdesc->tdesc);
4974 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
4975 int arglen = _argsize(tdesc->vt);
4977 if (i<pDispParams->cArgs) {
4978 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4980 if (paramFlags & PARAMFLAG_FOPT) {
4981 if(i < func_desc->cParams - func_desc->cParamsOpt)
4982 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4983 if(V_VT(arg) == VT_EMPTY
4984 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
4985 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4986 How to determine it? */
4988 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4989 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4990 V_VT(arg) = VT_ERROR;
4991 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4992 arglen = _argsize(VT_ERROR);
4995 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4996 if (FAILED(hres)) goto func_fail;
4998 } else if (paramFlags & PARAMFLAG_FOPT) {
4999 VARIANT *arg = &rgvarg[i];
5001 if (i < func_desc->cParams - func_desc->cParamsOpt)
5002 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5003 if (paramFlags & PARAMFLAG_FHASDEFAULT)
5004 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5006 V_VT(arg) = VT_ERROR;
5007 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5008 arglen = _argsize(VT_ERROR);
5009 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5010 if (FAILED(hres)) goto func_fail;
5013 if (tdesc->vt == VT_PTR)
5014 arglen = _argsize(tdesc->u.lptdesc->vt);
5016 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
5018 /* Supply pointers for the rest, so propertyget works*/
5019 args[argspos] = (DWORD)&args2[args2pos];
5021 /* If pointer to variant, pass reference it. */
5022 if ((tdesc->vt == VT_PTR) &&
5023 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
5026 args[argspos]= (DWORD)pVarResult;
5031 if (func_desc->cParamsOpt < 0)
5032 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
5034 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
5035 func_desc->callconv,
5041 for (i = 0; i < func_desc->cParams; i++) {
5042 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5043 if (wParamFlags & PARAMFLAG_FRETVAL) {
5044 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5045 TYPEDESC *tdesc = &elemdesc->tdesc;
5046 VARIANTARG varresult;
5047 V_VT(&varresult) = 0;
5048 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5051 /* FIXME: this is really messy - we should keep the
5052 * args in VARIANTARGs rather than a DWORD array */
5053 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5056 TRACE("varresult: ");
5057 dump_Variant(&varresult);
5059 hres = VariantCopyInd(pVarResult, &varresult);
5060 /* free data stored in varresult. Note that
5061 * VariantClear doesn't do what we want because we are
5062 * working with byref types. */
5063 /* FIXME: clear safearrays, bstrs, records and
5064 * variants here too */
5065 if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
5066 (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
5068 if(*V_UNKNOWNREF(&varresult))
5069 IUnknown_Release(*V_UNKNOWNREF(&varresult));
5076 if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
5077 WARN("invoked function failed with error 0x%08lx\n", res);
5078 hres = DISP_E_EXCEPTION;
5079 if (pExcepInfo) pExcepInfo->scode = res;
5082 HeapFree(GetProcessHeap(), 0, rgvarg);
5083 HeapFree(GetProcessHeap(),0,args2);
5084 HeapFree(GetProcessHeap(),0,args);
5087 case FUNC_DISPATCH: {
5090 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5091 if (SUCCEEDED(hres)) {
5092 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5093 hres = IDispatch_Invoke(
5094 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
5095 pVarResult,pExcepInfo,pArgErr
5098 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5099 IDispatch_Release(disp);
5101 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5105 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5110 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
5111 TRACE("-- 0x%08lx\n", hres);
5114 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5117 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5118 if(FAILED(hres)) return hres;
5120 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5121 dump_VARDESC(var_desc);
5122 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5126 /* not found, look for it in inherited interfaces */
5127 ITypeInfo2_GetTypeKind(iface, &type_kind);
5128 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5130 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5131 /* recursive search */
5133 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5134 if(SUCCEEDED(hres)){
5135 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5136 ITypeInfo_Release(pTInfo);
5139 WARN("Could not search inherited interface!\n");
5142 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
5143 return DISP_E_MEMBERNOTFOUND;
5146 /* ITypeInfo::GetDocumentation
5148 * Retrieves the documentation string, the complete Help file name and path,
5149 * and the context ID for the Help topic for a specified type description.
5151 * (Can be tested by the Visual Basic Editor in Word for instance.)
5153 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5154 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5155 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5157 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5158 TLBFuncDesc * pFDesc;
5159 TLBVarDesc * pVDesc;
5160 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5161 " HelpContext(%p) HelpFile(%p)\n",
5162 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5163 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5165 *pBstrName=SysAllocString(This->Name);
5167 *pBstrDocString=SysAllocString(This->DocString);
5169 *pdwHelpContext=This->dwHelpContext;
5171 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5173 }else {/* for a member */
5174 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5175 if(pFDesc->funcdesc.memid==memid){
5177 *pBstrName = SysAllocString(pFDesc->Name);
5179 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5181 *pdwHelpContext=pFDesc->helpcontext;
5184 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5185 if(pVDesc->vardesc.memid==memid){
5187 *pBstrName = SysAllocString(pVDesc->Name);
5189 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5191 *pdwHelpContext=pVDesc->HelpContext;
5195 WARN("member %ld not found\n", memid);
5196 return TYPE_E_ELEMENTNOTFOUND;
5199 /* ITypeInfo::GetDllEntry
5201 * Retrieves a description or specification of an entry point for a function
5204 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5205 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5208 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5209 TLBFuncDesc *pFDesc;
5211 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5213 if (pBstrDllName) *pBstrDllName = NULL;
5214 if (pBstrName) *pBstrName = NULL;
5215 if (pwOrdinal) *pwOrdinal = 0;
5217 if (This->TypeAttr.typekind != TKIND_MODULE)
5218 return TYPE_E_BADMODULEKIND;
5220 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5221 if(pFDesc->funcdesc.memid==memid){
5222 dump_TypeInfo(This);
5223 dump_TLBFuncDescOne(pFDesc);
5226 *pBstrDllName = SysAllocString(This->DllName);
5228 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5230 *pBstrName = SysAllocString(pFDesc->Entry);
5238 *pwOrdinal = (DWORD)pFDesc->Entry;
5241 return TYPE_E_ELEMENTNOTFOUND;
5244 /* ITypeInfo::GetRefTypeInfo
5246 * If a type description references other type descriptions, it retrieves
5247 * the referenced type descriptions.
5249 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5252 ITypeInfo **ppTInfo)
5254 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5255 HRESULT result = E_FAIL;
5257 if (hRefType == -1 &&
5258 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5259 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5261 /* when we meet a DUAL dispinterface, we must create the interface
5264 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5267 /* the interface version contains the same information as the dispinterface
5268 * copy the contents of the structs.
5270 *pTypeInfoImpl = *This;
5271 pTypeInfoImpl->ref = 1;
5273 /* change the type to interface */
5274 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5276 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5278 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5283 TLBRefType *pRefType;
5284 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5285 if(pRefType->reference == hRefType)
5289 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5290 if(pRefType && hRefType != -1) {
5291 ITypeLib *pTLib = NULL;
5293 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5295 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5297 if(pRefType->pImpTLInfo->pImpTypeLib) {
5298 TRACE("typeinfo in imported typelib that is already loaded\n");
5299 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5300 ITypeLib2_AddRef((ITypeLib*) pTLib);
5303 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5304 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5305 pRefType->pImpTLInfo->wVersionMajor,
5306 pRefType->pImpTLInfo->wVersionMinor,
5307 pRefType->pImpTLInfo->lcid,
5310 if(!SUCCEEDED(result)) {
5311 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5312 result=LoadTypeLib(libnam, &pTLib);
5313 SysFreeString(libnam);
5315 if(SUCCEEDED(result)) {
5316 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5317 ITypeLib2_AddRef(pTLib);
5321 if(SUCCEEDED(result)) {
5322 if(pRefType->index == TLB_REF_USE_GUID)
5323 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5327 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5331 ITypeLib2_Release(pTLib);
5335 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5336 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5340 /* ITypeInfo::AddressOfMember
5342 * Retrieves the addresses of static functions or variables, such as those
5345 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5346 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5348 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5349 FIXME("(%p) stub!\n", This);
5353 /* ITypeInfo::CreateInstance
5355 * Creates a new instance of a type that describes a component object class
5358 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5359 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5361 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5362 FIXME("(%p) stub!\n", This);
5366 /* ITypeInfo::GetMops
5368 * Retrieves marshalling information.
5370 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5373 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5374 FIXME("(%p) stub!\n", This);
5378 /* ITypeInfo::GetContainingTypeLib
5380 * Retrieves the containing type library and the index of the type description
5381 * within that type library.
5383 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5384 ITypeLib * *ppTLib, UINT *pIndex)
5386 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5388 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5390 *pIndex=This->index;
5391 TRACE("returning pIndex=%d\n", *pIndex);
5395 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5396 ITypeLib2_AddRef(*ppTLib);
5397 TRACE("returning ppTLib=%p\n", *ppTLib);
5403 /* ITypeInfo::ReleaseTypeAttr
5405 * Releases a TYPEATTR previously returned by GetTypeAttr.
5408 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5409 TYPEATTR* pTypeAttr)
5411 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5412 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5413 if(This->TypeAttr.typekind == TKIND_ALIAS)
5414 free_deep_typedesc(&pTypeAttr->tdescAlias);
5415 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5418 /* ITypeInfo::ReleaseFuncDesc
5420 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5422 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5424 FUNCDESC *pFuncDesc)
5426 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5427 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5430 /* ITypeInfo::ReleaseVarDesc
5432 * Releases a VARDESC previously returned by GetVarDesc.
5434 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5437 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5438 TRACE("(%p)->(%p)\n", This, pVarDesc);
5441 /* ITypeInfo2::GetTypeKind
5443 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5446 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5447 TYPEKIND *pTypeKind)
5449 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5450 *pTypeKind=This->TypeAttr.typekind;
5451 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5455 /* ITypeInfo2::GetTypeFlags
5457 * Returns the type flags without any allocations. This returns a DWORD type
5458 * flag, which expands the type flags without growing the TYPEATTR (type
5462 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5464 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5465 *pTypeFlags=This->TypeAttr.wTypeFlags;
5466 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5470 /* ITypeInfo2::GetFuncIndexOfMemId
5471 * Binds to a specific member based on a known DISPID, where the member name
5472 * is not known (for example, when binding to a default member).
5475 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5476 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5478 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5479 TLBFuncDesc *pFuncInfo;
5483 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5484 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5490 result = TYPE_E_ELEMENTNOTFOUND;
5492 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5493 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5497 /* TypeInfo2::GetVarIndexOfMemId
5499 * Binds to a specific member based on a known DISPID, where the member name
5500 * is not known (for example, when binding to a default member).
5503 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5504 MEMBERID memid, UINT *pVarIndex)
5506 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5507 TLBVarDesc *pVarInfo;
5510 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5511 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5517 result = TYPE_E_ELEMENTNOTFOUND;
5519 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5520 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5524 /* ITypeInfo2::GetCustData
5526 * Gets the custom data
5528 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5533 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5534 TLBCustData *pCData;
5536 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5537 if( IsEqualIID(guid, &pCData->guid)) break;
5539 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5543 VariantInit( pVarVal);
5544 VariantCopy( pVarVal, &pCData->data);
5547 return E_INVALIDARG; /* FIXME: correct? */
5550 /* ITypeInfo2::GetFuncCustData
5552 * Gets the custom data
5554 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5560 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5561 TLBCustData *pCData=NULL;
5562 TLBFuncDesc * pFDesc;
5564 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5565 pFDesc=pFDesc->next);
5568 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5569 if( IsEqualIID(guid, &pCData->guid)) break;
5571 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5574 VariantInit( pVarVal);
5575 VariantCopy( pVarVal, &pCData->data);
5578 return E_INVALIDARG; /* FIXME: correct? */
5581 /* ITypeInfo2::GetParamCustData
5583 * Gets the custom data
5585 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5592 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5593 TLBCustData *pCData=NULL;
5594 TLBFuncDesc * pFDesc;
5597 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5599 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5600 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5601 pCData = pCData->next)
5602 if( IsEqualIID(guid, &pCData->guid)) break;
5604 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5608 VariantInit( pVarVal);
5609 VariantCopy( pVarVal, &pCData->data);
5612 return E_INVALIDARG; /* FIXME: correct? */
5615 /* ITypeInfo2::GetVarCustData
5617 * Gets the custom data
5619 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5625 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5626 TLBCustData *pCData=NULL;
5627 TLBVarDesc * pVDesc;
5630 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5634 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5636 if( IsEqualIID(guid, &pCData->guid)) break;
5640 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5644 VariantInit( pVarVal);
5645 VariantCopy( pVarVal, &pCData->data);
5648 return E_INVALIDARG; /* FIXME: correct? */
5651 /* ITypeInfo2::GetImplCustData
5653 * Gets the custom data
5655 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5661 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5662 TLBCustData *pCData=NULL;
5663 TLBImplType * pRDesc;
5666 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5670 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5672 if( IsEqualIID(guid, &pCData->guid)) break;
5676 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5680 VariantInit( pVarVal);
5681 VariantCopy( pVarVal, &pCData->data);
5684 return E_INVALIDARG; /* FIXME: correct? */
5687 /* ITypeInfo2::GetDocumentation2
5689 * Retrieves the documentation string, the complete Help file name and path,
5690 * the localization context to use, and the context ID for the library Help
5691 * topic in the Help file.
5694 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5698 BSTR *pbstrHelpString,
5699 DWORD *pdwHelpStringContext,
5700 BSTR *pbstrHelpStringDll)
5702 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5703 TLBFuncDesc * pFDesc;
5704 TLBVarDesc * pVDesc;
5705 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5706 "HelpStringContext(%p) HelpStringDll(%p)\n",
5707 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5708 pbstrHelpStringDll );
5709 /* the help string should be obtained from the helpstringdll,
5710 * using the _DLLGetDocumentation function, based on the supplied
5711 * lcid. Nice to do sometime...
5713 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5715 *pbstrHelpString=SysAllocString(This->Name);
5716 if(pdwHelpStringContext)
5717 *pdwHelpStringContext=This->dwHelpStringContext;
5718 if(pbstrHelpStringDll)
5719 *pbstrHelpStringDll=
5720 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5722 }else {/* for a member */
5723 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5724 if(pFDesc->funcdesc.memid==memid){
5726 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5727 if(pdwHelpStringContext)
5728 *pdwHelpStringContext=pFDesc->HelpStringContext;
5729 if(pbstrHelpStringDll)
5730 *pbstrHelpStringDll=
5731 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5734 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5735 if(pVDesc->vardesc.memid==memid){
5737 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5738 if(pdwHelpStringContext)
5739 *pdwHelpStringContext=pVDesc->HelpStringContext;
5740 if(pbstrHelpStringDll)
5741 *pbstrHelpStringDll=
5742 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5746 return TYPE_E_ELEMENTNOTFOUND;
5749 /* ITypeInfo2::GetAllCustData
5751 * Gets all custom data items for the Type info.
5754 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5756 CUSTDATA *pCustData)
5758 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5759 TLBCustData *pCData;
5762 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5764 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5765 if(pCustData->prgCustData ){
5766 pCustData->cCustData=This->ctCustData;
5767 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5768 pCustData->prgCustData[i].guid=pCData->guid;
5769 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5772 ERR(" OUT OF MEMORY! \n");
5773 return E_OUTOFMEMORY;
5778 /* ITypeInfo2::GetAllFuncCustData
5780 * Gets all custom data items for the specified Function
5783 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5786 CUSTDATA *pCustData)
5788 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5789 TLBCustData *pCData;
5790 TLBFuncDesc * pFDesc;
5792 TRACE("(%p) index %d\n", This, index);
5793 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5794 pFDesc=pFDesc->next)
5797 pCustData->prgCustData =
5798 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5799 if(pCustData->prgCustData ){
5800 pCustData->cCustData=pFDesc->ctCustData;
5801 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5802 pCData = pCData->next){
5803 pCustData->prgCustData[i].guid=pCData->guid;
5804 VariantCopy(& pCustData->prgCustData[i].varValue,
5808 ERR(" OUT OF MEMORY! \n");
5809 return E_OUTOFMEMORY;
5813 return TYPE_E_ELEMENTNOTFOUND;
5816 /* ITypeInfo2::GetAllParamCustData
5818 * Gets all custom data items for the Functions
5821 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5822 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5824 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5825 TLBCustData *pCData=NULL;
5826 TLBFuncDesc * pFDesc;
5828 TRACE("(%p) index %d\n", This, indexFunc);
5829 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5830 pFDesc=pFDesc->next)
5832 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5833 pCustData->prgCustData =
5834 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5835 sizeof(CUSTDATAITEM));
5836 if(pCustData->prgCustData ){
5837 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5838 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5839 pCData; i++, pCData = pCData->next){
5840 pCustData->prgCustData[i].guid=pCData->guid;
5841 VariantCopy(& pCustData->prgCustData[i].varValue,
5845 ERR(" OUT OF MEMORY! \n");
5846 return E_OUTOFMEMORY;
5850 return TYPE_E_ELEMENTNOTFOUND;
5853 /* ITypeInfo2::GetAllVarCustData
5855 * Gets all custom data items for the specified Variable
5858 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5859 UINT index, CUSTDATA *pCustData)
5861 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5862 TLBCustData *pCData;
5863 TLBVarDesc * pVDesc;
5865 TRACE("(%p) index %d\n", This, index);
5866 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5867 pVDesc=pVDesc->next)
5870 pCustData->prgCustData =
5871 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5872 if(pCustData->prgCustData ){
5873 pCustData->cCustData=pVDesc->ctCustData;
5874 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5875 pCData = pCData->next){
5876 pCustData->prgCustData[i].guid=pCData->guid;
5877 VariantCopy(& pCustData->prgCustData[i].varValue,
5881 ERR(" OUT OF MEMORY! \n");
5882 return E_OUTOFMEMORY;
5886 return TYPE_E_ELEMENTNOTFOUND;
5889 /* ITypeInfo2::GetAllImplCustData
5891 * Gets all custom data items for the specified implementation type
5894 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5897 CUSTDATA *pCustData)
5899 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5900 TLBCustData *pCData;
5901 TLBImplType * pRDesc;
5903 TRACE("(%p) index %d\n", This, index);
5904 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5905 pRDesc=pRDesc->next)
5908 pCustData->prgCustData =
5909 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5910 if(pCustData->prgCustData ){
5911 pCustData->cCustData=pRDesc->ctCustData;
5912 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5913 pCData = pCData->next){
5914 pCustData->prgCustData[i].guid=pCData->guid;
5915 VariantCopy(& pCustData->prgCustData[i].varValue,
5919 ERR(" OUT OF MEMORY! \n");
5920 return E_OUTOFMEMORY;
5924 return TYPE_E_ELEMENTNOTFOUND;
5927 static const ITypeInfo2Vtbl tinfvt =
5930 ITypeInfo_fnQueryInterface,
5932 ITypeInfo_fnRelease,
5934 ITypeInfo_fnGetTypeAttr,
5935 ITypeInfo_fnGetTypeComp,
5936 ITypeInfo_fnGetFuncDesc,
5937 ITypeInfo_fnGetVarDesc,
5938 ITypeInfo_fnGetNames,
5939 ITypeInfo_fnGetRefTypeOfImplType,
5940 ITypeInfo_fnGetImplTypeFlags,
5941 ITypeInfo_fnGetIDsOfNames,
5943 ITypeInfo_fnGetDocumentation,
5944 ITypeInfo_fnGetDllEntry,
5945 ITypeInfo_fnGetRefTypeInfo,
5946 ITypeInfo_fnAddressOfMember,
5947 ITypeInfo_fnCreateInstance,
5948 ITypeInfo_fnGetMops,
5949 ITypeInfo_fnGetContainingTypeLib,
5950 ITypeInfo_fnReleaseTypeAttr,
5951 ITypeInfo_fnReleaseFuncDesc,
5952 ITypeInfo_fnReleaseVarDesc,
5954 ITypeInfo2_fnGetTypeKind,
5955 ITypeInfo2_fnGetTypeFlags,
5956 ITypeInfo2_fnGetFuncIndexOfMemId,
5957 ITypeInfo2_fnGetVarIndexOfMemId,
5958 ITypeInfo2_fnGetCustData,
5959 ITypeInfo2_fnGetFuncCustData,
5960 ITypeInfo2_fnGetParamCustData,
5961 ITypeInfo2_fnGetVarCustData,
5962 ITypeInfo2_fnGetImplTypeCustData,
5963 ITypeInfo2_fnGetDocumentation2,
5964 ITypeInfo2_fnGetAllCustData,
5965 ITypeInfo2_fnGetAllFuncCustData,
5966 ITypeInfo2_fnGetAllParamCustData,
5967 ITypeInfo2_fnGetAllVarCustData,
5968 ITypeInfo2_fnGetAllImplTypeCustData,
5971 /******************************************************************************
5972 * CreateDispTypeInfo [OLEAUT32.31]
5974 * Build type information for an object so it can be called through an
5975 * IDispatch interface.
5978 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5979 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5982 * This call allows an objects methods to be accessed through IDispatch, by
5983 * building an ITypeInfo object that IDispatch can use to call through.
5985 HRESULT WINAPI CreateDispTypeInfo(
5986 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5987 LCID lcid, /* [I] Locale Id */
5988 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5990 ITypeInfoImpl *pTIImpl;
5992 TLBFuncDesc **ppFuncDesc;
5994 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5995 pTIImpl->pTypeLib = NULL;
5997 pTIImpl->Name = NULL;
5998 pTIImpl->dwHelpContext = -1;
5999 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
6000 pTIImpl->TypeAttr.lcid = lcid;
6001 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
6002 pTIImpl->TypeAttr.wMajorVerNum = 0;
6003 pTIImpl->TypeAttr.wMinorVerNum = 0;
6004 pTIImpl->TypeAttr.cbAlignment = 2;
6005 pTIImpl->TypeAttr.cbSizeInstance = -1;
6006 pTIImpl->TypeAttr.cbSizeVft = -1;
6007 pTIImpl->TypeAttr.cFuncs = 0;
6008 pTIImpl->TypeAttr.cImplTypes = 1;
6009 pTIImpl->TypeAttr.cVars = 0;
6010 pTIImpl->TypeAttr.wTypeFlags = 0;
6012 ppFuncDesc = &pTIImpl->funclist;
6013 for(func = 0; func < pidata->cMembers; func++) {
6014 METHODDATA *md = pidata->pmethdata + func;
6015 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6016 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6017 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6018 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6019 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6020 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6021 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6022 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
6023 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
6024 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6025 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6026 md->cArgs * sizeof(ELEMDESC));
6027 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6028 md->cArgs * sizeof(TLBParDesc));
6029 for(param = 0; param < md->cArgs; param++) {
6030 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6031 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6033 ppFuncDesc = &(*ppFuncDesc)->next;
6035 *pptinfo = (ITypeInfo*)pTIImpl;
6040 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6042 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6044 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6047 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6049 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6051 return ITypeInfo_AddRef((ITypeInfo *)This);
6054 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6056 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6058 return ITypeInfo_Release((ITypeInfo *)This);
6061 static HRESULT WINAPI ITypeComp_fnBind(
6066 ITypeInfo ** ppTInfo,
6067 DESCKIND * pDescKind,
6070 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6071 TLBFuncDesc * pFDesc;
6072 TLBVarDesc * pVDesc;
6074 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6076 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6077 if (pFDesc->funcdesc.invkind & wFlags)
6078 if (!strcmpW(pFDesc->Name, szName)) {
6084 *pDescKind = DESCKIND_FUNCDESC;
6085 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
6086 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6089 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
6091 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6092 if (!strcmpW(pVDesc->Name, szName)) {
6093 *pDescKind = DESCKIND_VARDESC;
6094 pBindPtr->lpvardesc = &pVDesc->vardesc;
6095 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6101 /* not found, look for it in inherited interfaces */
6102 if (This->TypeAttr.cImplTypes &&
6103 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
6104 /* recursive search */
6108 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6111 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6112 ITypeInfo_Release(pTInfo);
6116 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6117 ITypeComp_Release(pTComp);
6120 WARN("Could not search inherited interface!\n");
6122 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6123 *pDescKind = DESCKIND_NONE;
6124 pBindPtr->lpfuncdesc = NULL;
6126 return DISP_E_MEMBERNOTFOUND;
6129 static HRESULT WINAPI ITypeComp_fnBindType(
6133 ITypeInfo ** ppTInfo,
6134 ITypeComp ** ppTComp)
6136 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6138 /* strange behaviour (does nothing) but like the
6141 if (!ppTInfo || !ppTComp)
6150 static const ITypeCompVtbl tcompvt =
6153 ITypeComp_fnQueryInterface,
6155 ITypeComp_fnRelease,
6158 ITypeComp_fnBindType