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,
4873 pvargResult, V_VT(pvargResult));
4875 /* DispCallFunc is only used to invoke methods belonging to an
4876 * IDispatch-derived COM interface. So we need to add a first parameter
4877 * to the list of arguments, to supply the interface pointer */
4879 for (i=0;i<cActuals;i++)
4881 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4882 dump_Variant(prgpvarg[i]);
4883 argsize += _argsize(prgvt[i]);
4885 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4886 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4888 for (i=0;i<cActuals;i++)
4890 VARIANT *arg = prgpvarg[i];
4891 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4892 memcpy(&args[argspos], &V_NONE(arg), _argsize(prgvt[i]) * sizeof(DWORD));
4893 argspos += _argsize(prgvt[i]);
4896 hres = _invoke((*(FARPROC**)pvInstance)[oVft/sizeof(void *)],cc,argsize,args);
4897 if (pvargResult && (vtReturn != VT_EMPTY))
4899 TRACE("Method returned 0x%08lx\n",hres);
4900 V_VT(pvargResult) = vtReturn;
4901 V_UI4(pvargResult) = hres;
4904 HeapFree(GetProcessHeap(),0,args);
4908 static HRESULT WINAPI ITypeInfo_fnInvoke(
4913 DISPPARAMS *pDispParams,
4914 VARIANT *pVarResult,
4915 EXCEPINFO *pExcepInfo,
4918 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4920 unsigned int func_index, var_index;
4924 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4925 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4927 dump_DispParms(pDispParams);
4929 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4930 if (SUCCEEDED(hres)) {
4931 FUNCDESC *func_desc;
4933 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4934 if(FAILED(hres)) return hres;
4937 TRACE("invoking:\n");
4938 dump_FUNCDESC(func_desc);
4941 switch (func_desc->funckind) {
4942 case FUNC_PUREVIRTUAL:
4943 case FUNC_VIRTUAL: {
4945 int numargs, numargs2, argspos, args2pos;
4946 DWORD *args , *args2;
4947 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4948 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4951 numargs = 1; /* sizeof(thisptr) */
4953 for (i = 0; i < func_desc->cParams; i++) {
4954 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4956 numargs += _argsize(tdesc->vt);
4957 if (i>=pDispParams->cArgs) { /* arguments to return */
4958 if (tdesc->vt == VT_PTR) {
4959 numargs2 += _argsize(tdesc->u.lptdesc->vt);
4961 FIXME("The variant type here should have been VT_PTR, not vt %d\n", tdesc->vt);
4962 numargs2 += _argsize(tdesc->vt);
4967 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4968 args2 = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(DWORD)*numargs2);
4970 args[0] = (DWORD)pIUnk;
4971 argspos = 1; args2pos = 0;
4972 for (i = 0; i < func_desc->cParams; i++) {
4973 ELEMDESC *elemdesc = &(func_desc->lprgelemdescParam[i]);
4974 TYPEDESC *tdesc = &(elemdesc->tdesc);
4975 USHORT paramFlags = elemdesc->u.paramdesc.wParamFlags;
4976 int arglen = _argsize(tdesc->vt);
4978 if (i<pDispParams->cArgs) {
4979 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4981 if (paramFlags & PARAMFLAG_FOPT) {
4982 if(i < func_desc->cParams - func_desc->cParamsOpt)
4983 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4984 if(V_VT(arg) == VT_EMPTY
4985 || ((V_ISBYREF(arg)) && !V_BYREF(arg))) {
4986 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4987 How to determine it? */
4989 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4990 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4991 V_VT(arg) = VT_ERROR;
4992 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4993 arglen = _argsize(VT_ERROR);
4996 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4997 if (FAILED(hres)) goto func_fail;
4999 } else if (paramFlags & PARAMFLAG_FOPT) {
5000 VARIANT *arg = &rgvarg[i];
5002 if (i < func_desc->cParams - func_desc->cParamsOpt)
5003 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
5004 if (paramFlags & PARAMFLAG_FHASDEFAULT)
5005 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
5007 V_VT(arg) = VT_ERROR;
5008 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
5009 arglen = _argsize(VT_ERROR);
5010 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
5011 if (FAILED(hres)) goto func_fail;
5014 if (tdesc->vt == VT_PTR)
5015 arglen = _argsize(tdesc->u.lptdesc->vt);
5017 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
5019 /* Supply pointers for the rest, so propertyget works*/
5020 args[argspos] = (DWORD)&args2[args2pos];
5022 /* If pointer to variant, pass reference it. */
5023 if ((tdesc->vt == VT_PTR) &&
5024 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
5027 args[argspos]= (DWORD)pVarResult;
5032 if (func_desc->cParamsOpt < 0)
5033 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
5035 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
5036 func_desc->callconv,
5042 for (i = 0; i < func_desc->cParams; i++) {
5043 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
5044 if (wParamFlags & PARAMFLAG_FRETVAL) {
5045 ELEMDESC *elemdesc = &func_desc->lprgelemdescParam[i];
5046 TYPEDESC *tdesc = &elemdesc->tdesc;
5047 VARIANTARG varresult;
5048 V_VT(&varresult) = 0;
5049 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &V_VT(&varresult));
5052 /* FIXME: this is really messy - we should keep the
5053 * args in VARIANTARGs rather than a DWORD array */
5054 memcpy(&V_UI4(&varresult), &args[i+1], sizeof(DWORD));
5057 TRACE("varresult: ");
5058 dump_Variant(&varresult);
5060 hres = VariantCopyInd(pVarResult, &varresult);
5061 /* free data stored in varresult. Note that
5062 * VariantClear doesn't do what we want because we are
5063 * working with byref types. */
5064 /* FIXME: clear safearrays, bstrs, records and
5065 * variants here too */
5066 if ((V_VT(&varresult) == (VT_UNKNOWN | VT_BYREF)) ||
5067 (V_VT(&varresult) == (VT_DISPATCH | VT_BYREF)))
5069 if(*V_UNKNOWNREF(&varresult))
5070 IUnknown_Release(*V_UNKNOWNREF(&varresult));
5077 if ((func_desc->elemdescFunc.tdesc.vt == VT_HRESULT) && FAILED(res)) {
5078 WARN("invoked function failed with error 0x%08lx\n", res);
5079 hres = DISP_E_EXCEPTION;
5080 if (pExcepInfo) pExcepInfo->scode = res;
5083 HeapFree(GetProcessHeap(), 0, rgvarg);
5084 HeapFree(GetProcessHeap(),0,args2);
5085 HeapFree(GetProcessHeap(),0,args);
5088 case FUNC_DISPATCH: {
5091 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
5092 if (SUCCEEDED(hres)) {
5093 FIXME("Calling Invoke in IDispatch iface. untested!\n");
5094 hres = IDispatch_Invoke(
5095 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
5096 pVarResult,pExcepInfo,pArgErr
5099 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
5100 IDispatch_Release(disp);
5102 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
5106 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
5111 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
5112 TRACE("-- 0x%08lx\n", hres);
5115 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
5118 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
5119 if(FAILED(hres)) return hres;
5121 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
5122 dump_VARDESC(var_desc);
5123 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
5127 /* not found, look for it in inherited interfaces */
5128 ITypeInfo2_GetTypeKind(iface, &type_kind);
5129 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
5131 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
5132 /* recursive search */
5134 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
5135 if(SUCCEEDED(hres)){
5136 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
5137 ITypeInfo_Release(pTInfo);
5140 WARN("Could not search inherited interface!\n");
5143 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
5144 return DISP_E_MEMBERNOTFOUND;
5147 /* ITypeInfo::GetDocumentation
5149 * Retrieves the documentation string, the complete Help file name and path,
5150 * and the context ID for the Help topic for a specified type description.
5152 * (Can be tested by the Visual Basic Editor in Word for instance.)
5154 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
5155 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
5156 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
5158 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5159 TLBFuncDesc * pFDesc;
5160 TLBVarDesc * pVDesc;
5161 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
5162 " HelpContext(%p) HelpFile(%p)\n",
5163 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
5164 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5166 *pBstrName=SysAllocString(This->Name);
5168 *pBstrDocString=SysAllocString(This->DocString);
5170 *pdwHelpContext=This->dwHelpContext;
5172 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5174 }else {/* for a member */
5175 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5176 if(pFDesc->funcdesc.memid==memid){
5178 *pBstrName = SysAllocString(pFDesc->Name);
5180 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5182 *pdwHelpContext=pFDesc->helpcontext;
5185 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5186 if(pVDesc->vardesc.memid==memid){
5188 *pBstrName = SysAllocString(pVDesc->Name);
5190 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5192 *pdwHelpContext=pVDesc->HelpContext;
5196 WARN("member %ld not found\n", memid);
5197 return TYPE_E_ELEMENTNOTFOUND;
5200 /* ITypeInfo::GetDllEntry
5202 * Retrieves a description or specification of an entry point for a function
5205 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5206 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5209 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5210 TLBFuncDesc *pFDesc;
5212 TRACE("(%p)->(memid %lx, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5214 if (pBstrDllName) *pBstrDllName = NULL;
5215 if (pBstrName) *pBstrName = NULL;
5216 if (pwOrdinal) *pwOrdinal = 0;
5218 if (This->TypeAttr.typekind != TKIND_MODULE)
5219 return TYPE_E_BADMODULEKIND;
5221 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5222 if(pFDesc->funcdesc.memid==memid){
5223 dump_TypeInfo(This);
5224 dump_TLBFuncDescOne(pFDesc);
5227 *pBstrDllName = SysAllocString(This->DllName);
5229 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5231 *pBstrName = SysAllocString(pFDesc->Entry);
5239 *pwOrdinal = (DWORD)pFDesc->Entry;
5242 return TYPE_E_ELEMENTNOTFOUND;
5245 /* ITypeInfo::GetRefTypeInfo
5247 * If a type description references other type descriptions, it retrieves
5248 * the referenced type descriptions.
5250 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5253 ITypeInfo **ppTInfo)
5255 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5256 HRESULT result = E_FAIL;
5258 if (hRefType == -1 &&
5259 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5260 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5262 /* when we meet a DUAL dispinterface, we must create the interface
5265 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5268 /* the interface version contains the same information as the dispinterface
5269 * copy the contents of the structs.
5271 *pTypeInfoImpl = *This;
5272 pTypeInfoImpl->ref = 1;
5274 /* change the type to interface */
5275 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5277 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5279 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5284 TLBRefType *pRefType;
5285 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5286 if(pRefType->reference == hRefType)
5290 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5291 if(pRefType && hRefType != -1) {
5292 ITypeLib *pTLib = NULL;
5294 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5296 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5298 if(pRefType->pImpTLInfo->pImpTypeLib) {
5299 TRACE("typeinfo in imported typelib that is already loaded\n");
5300 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5301 ITypeLib2_AddRef((ITypeLib*) pTLib);
5304 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5305 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5306 pRefType->pImpTLInfo->wVersionMajor,
5307 pRefType->pImpTLInfo->wVersionMinor,
5308 pRefType->pImpTLInfo->lcid,
5311 if(!SUCCEEDED(result)) {
5312 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5313 result=LoadTypeLib(libnam, &pTLib);
5314 SysFreeString(libnam);
5316 if(SUCCEEDED(result)) {
5317 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5318 ITypeLib2_AddRef(pTLib);
5322 if(SUCCEEDED(result)) {
5323 if(pRefType->index == TLB_REF_USE_GUID)
5324 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5328 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5332 ITypeLib2_Release(pTLib);
5336 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5337 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5341 /* ITypeInfo::AddressOfMember
5343 * Retrieves the addresses of static functions or variables, such as those
5346 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5347 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5349 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5350 FIXME("(%p) stub!\n", This);
5354 /* ITypeInfo::CreateInstance
5356 * Creates a new instance of a type that describes a component object class
5359 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5360 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5362 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5363 FIXME("(%p) stub!\n", This);
5367 /* ITypeInfo::GetMops
5369 * Retrieves marshalling information.
5371 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5374 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5375 FIXME("(%p) stub!\n", This);
5379 /* ITypeInfo::GetContainingTypeLib
5381 * Retrieves the containing type library and the index of the type description
5382 * within that type library.
5384 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5385 ITypeLib * *ppTLib, UINT *pIndex)
5387 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5389 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5391 *pIndex=This->index;
5392 TRACE("returning pIndex=%d\n", *pIndex);
5396 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5397 ITypeLib2_AddRef(*ppTLib);
5398 TRACE("returning ppTLib=%p\n", *ppTLib);
5404 /* ITypeInfo::ReleaseTypeAttr
5406 * Releases a TYPEATTR previously returned by GetTypeAttr.
5409 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5410 TYPEATTR* pTypeAttr)
5412 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5413 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5414 if(This->TypeAttr.typekind == TKIND_ALIAS)
5415 free_deep_typedesc(&pTypeAttr->tdescAlias);
5416 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5419 /* ITypeInfo::ReleaseFuncDesc
5421 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5423 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5425 FUNCDESC *pFuncDesc)
5427 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5428 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5431 /* ITypeInfo::ReleaseVarDesc
5433 * Releases a VARDESC previously returned by GetVarDesc.
5435 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5438 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5439 TRACE("(%p)->(%p)\n", This, pVarDesc);
5442 /* ITypeInfo2::GetTypeKind
5444 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5447 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5448 TYPEKIND *pTypeKind)
5450 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5451 *pTypeKind=This->TypeAttr.typekind;
5452 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5456 /* ITypeInfo2::GetTypeFlags
5458 * Returns the type flags without any allocations. This returns a DWORD type
5459 * flag, which expands the type flags without growing the TYPEATTR (type
5463 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5465 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5466 *pTypeFlags=This->TypeAttr.wTypeFlags;
5467 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5471 /* ITypeInfo2::GetFuncIndexOfMemId
5472 * Binds to a specific member based on a known DISPID, where the member name
5473 * is not known (for example, when binding to a default member).
5476 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5477 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5479 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5480 TLBFuncDesc *pFuncInfo;
5484 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5485 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5491 result = TYPE_E_ELEMENTNOTFOUND;
5493 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5494 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5498 /* TypeInfo2::GetVarIndexOfMemId
5500 * Binds to a specific member based on a known DISPID, where the member name
5501 * is not known (for example, when binding to a default member).
5504 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5505 MEMBERID memid, UINT *pVarIndex)
5507 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5508 TLBVarDesc *pVarInfo;
5511 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5512 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5518 result = TYPE_E_ELEMENTNOTFOUND;
5520 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5521 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5525 /* ITypeInfo2::GetCustData
5527 * Gets the custom data
5529 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5534 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5535 TLBCustData *pCData;
5537 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5538 if( IsEqualIID(guid, &pCData->guid)) break;
5540 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5544 VariantInit( pVarVal);
5545 VariantCopy( pVarVal, &pCData->data);
5548 return E_INVALIDARG; /* FIXME: correct? */
5551 /* ITypeInfo2::GetFuncCustData
5553 * Gets the custom data
5555 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5561 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5562 TLBCustData *pCData=NULL;
5563 TLBFuncDesc * pFDesc;
5565 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5566 pFDesc=pFDesc->next);
5569 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5570 if( IsEqualIID(guid, &pCData->guid)) break;
5572 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5575 VariantInit( pVarVal);
5576 VariantCopy( pVarVal, &pCData->data);
5579 return E_INVALIDARG; /* FIXME: correct? */
5582 /* ITypeInfo2::GetParamCustData
5584 * Gets the custom data
5586 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5593 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5594 TLBCustData *pCData=NULL;
5595 TLBFuncDesc * pFDesc;
5598 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5600 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5601 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5602 pCData = pCData->next)
5603 if( IsEqualIID(guid, &pCData->guid)) break;
5605 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5609 VariantInit( pVarVal);
5610 VariantCopy( pVarVal, &pCData->data);
5613 return E_INVALIDARG; /* FIXME: correct? */
5616 /* ITypeInfo2::GetVarCustData
5618 * Gets the custom data
5620 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5626 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5627 TLBCustData *pCData=NULL;
5628 TLBVarDesc * pVDesc;
5631 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5635 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5637 if( IsEqualIID(guid, &pCData->guid)) break;
5641 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5645 VariantInit( pVarVal);
5646 VariantCopy( pVarVal, &pCData->data);
5649 return E_INVALIDARG; /* FIXME: correct? */
5652 /* ITypeInfo2::GetImplCustData
5654 * Gets the custom data
5656 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5662 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5663 TLBCustData *pCData=NULL;
5664 TLBImplType * pRDesc;
5667 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5671 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5673 if( IsEqualIID(guid, &pCData->guid)) break;
5677 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5681 VariantInit( pVarVal);
5682 VariantCopy( pVarVal, &pCData->data);
5685 return E_INVALIDARG; /* FIXME: correct? */
5688 /* ITypeInfo2::GetDocumentation2
5690 * Retrieves the documentation string, the complete Help file name and path,
5691 * the localization context to use, and the context ID for the library Help
5692 * topic in the Help file.
5695 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5699 BSTR *pbstrHelpString,
5700 DWORD *pdwHelpStringContext,
5701 BSTR *pbstrHelpStringDll)
5703 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5704 TLBFuncDesc * pFDesc;
5705 TLBVarDesc * pVDesc;
5706 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5707 "HelpStringContext(%p) HelpStringDll(%p)\n",
5708 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5709 pbstrHelpStringDll );
5710 /* the help string should be obtained from the helpstringdll,
5711 * using the _DLLGetDocumentation function, based on the supplied
5712 * lcid. Nice to do sometime...
5714 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5716 *pbstrHelpString=SysAllocString(This->Name);
5717 if(pdwHelpStringContext)
5718 *pdwHelpStringContext=This->dwHelpStringContext;
5719 if(pbstrHelpStringDll)
5720 *pbstrHelpStringDll=
5721 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5723 }else {/* for a member */
5724 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5725 if(pFDesc->funcdesc.memid==memid){
5727 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5728 if(pdwHelpStringContext)
5729 *pdwHelpStringContext=pFDesc->HelpStringContext;
5730 if(pbstrHelpStringDll)
5731 *pbstrHelpStringDll=
5732 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5735 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5736 if(pVDesc->vardesc.memid==memid){
5738 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5739 if(pdwHelpStringContext)
5740 *pdwHelpStringContext=pVDesc->HelpStringContext;
5741 if(pbstrHelpStringDll)
5742 *pbstrHelpStringDll=
5743 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5747 return TYPE_E_ELEMENTNOTFOUND;
5750 /* ITypeInfo2::GetAllCustData
5752 * Gets all custom data items for the Type info.
5755 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5757 CUSTDATA *pCustData)
5759 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5760 TLBCustData *pCData;
5763 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5765 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5766 if(pCustData->prgCustData ){
5767 pCustData->cCustData=This->ctCustData;
5768 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5769 pCustData->prgCustData[i].guid=pCData->guid;
5770 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5773 ERR(" OUT OF MEMORY! \n");
5774 return E_OUTOFMEMORY;
5779 /* ITypeInfo2::GetAllFuncCustData
5781 * Gets all custom data items for the specified Function
5784 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5787 CUSTDATA *pCustData)
5789 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5790 TLBCustData *pCData;
5791 TLBFuncDesc * pFDesc;
5793 TRACE("(%p) index %d\n", This, index);
5794 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5795 pFDesc=pFDesc->next)
5798 pCustData->prgCustData =
5799 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5800 if(pCustData->prgCustData ){
5801 pCustData->cCustData=pFDesc->ctCustData;
5802 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5803 pCData = pCData->next){
5804 pCustData->prgCustData[i].guid=pCData->guid;
5805 VariantCopy(& pCustData->prgCustData[i].varValue,
5809 ERR(" OUT OF MEMORY! \n");
5810 return E_OUTOFMEMORY;
5814 return TYPE_E_ELEMENTNOTFOUND;
5817 /* ITypeInfo2::GetAllParamCustData
5819 * Gets all custom data items for the Functions
5822 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5823 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5825 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5826 TLBCustData *pCData=NULL;
5827 TLBFuncDesc * pFDesc;
5829 TRACE("(%p) index %d\n", This, indexFunc);
5830 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5831 pFDesc=pFDesc->next)
5833 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5834 pCustData->prgCustData =
5835 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5836 sizeof(CUSTDATAITEM));
5837 if(pCustData->prgCustData ){
5838 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5839 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5840 pCData; i++, pCData = pCData->next){
5841 pCustData->prgCustData[i].guid=pCData->guid;
5842 VariantCopy(& pCustData->prgCustData[i].varValue,
5846 ERR(" OUT OF MEMORY! \n");
5847 return E_OUTOFMEMORY;
5851 return TYPE_E_ELEMENTNOTFOUND;
5854 /* ITypeInfo2::GetAllVarCustData
5856 * Gets all custom data items for the specified Variable
5859 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5860 UINT index, CUSTDATA *pCustData)
5862 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5863 TLBCustData *pCData;
5864 TLBVarDesc * pVDesc;
5866 TRACE("(%p) index %d\n", This, index);
5867 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5868 pVDesc=pVDesc->next)
5871 pCustData->prgCustData =
5872 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5873 if(pCustData->prgCustData ){
5874 pCustData->cCustData=pVDesc->ctCustData;
5875 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5876 pCData = pCData->next){
5877 pCustData->prgCustData[i].guid=pCData->guid;
5878 VariantCopy(& pCustData->prgCustData[i].varValue,
5882 ERR(" OUT OF MEMORY! \n");
5883 return E_OUTOFMEMORY;
5887 return TYPE_E_ELEMENTNOTFOUND;
5890 /* ITypeInfo2::GetAllImplCustData
5892 * Gets all custom data items for the specified implementation type
5895 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5898 CUSTDATA *pCustData)
5900 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5901 TLBCustData *pCData;
5902 TLBImplType * pRDesc;
5904 TRACE("(%p) index %d\n", This, index);
5905 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5906 pRDesc=pRDesc->next)
5909 pCustData->prgCustData =
5910 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5911 if(pCustData->prgCustData ){
5912 pCustData->cCustData=pRDesc->ctCustData;
5913 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5914 pCData = pCData->next){
5915 pCustData->prgCustData[i].guid=pCData->guid;
5916 VariantCopy(& pCustData->prgCustData[i].varValue,
5920 ERR(" OUT OF MEMORY! \n");
5921 return E_OUTOFMEMORY;
5925 return TYPE_E_ELEMENTNOTFOUND;
5928 static const ITypeInfo2Vtbl tinfvt =
5931 ITypeInfo_fnQueryInterface,
5933 ITypeInfo_fnRelease,
5935 ITypeInfo_fnGetTypeAttr,
5936 ITypeInfo_fnGetTypeComp,
5937 ITypeInfo_fnGetFuncDesc,
5938 ITypeInfo_fnGetVarDesc,
5939 ITypeInfo_fnGetNames,
5940 ITypeInfo_fnGetRefTypeOfImplType,
5941 ITypeInfo_fnGetImplTypeFlags,
5942 ITypeInfo_fnGetIDsOfNames,
5944 ITypeInfo_fnGetDocumentation,
5945 ITypeInfo_fnGetDllEntry,
5946 ITypeInfo_fnGetRefTypeInfo,
5947 ITypeInfo_fnAddressOfMember,
5948 ITypeInfo_fnCreateInstance,
5949 ITypeInfo_fnGetMops,
5950 ITypeInfo_fnGetContainingTypeLib,
5951 ITypeInfo_fnReleaseTypeAttr,
5952 ITypeInfo_fnReleaseFuncDesc,
5953 ITypeInfo_fnReleaseVarDesc,
5955 ITypeInfo2_fnGetTypeKind,
5956 ITypeInfo2_fnGetTypeFlags,
5957 ITypeInfo2_fnGetFuncIndexOfMemId,
5958 ITypeInfo2_fnGetVarIndexOfMemId,
5959 ITypeInfo2_fnGetCustData,
5960 ITypeInfo2_fnGetFuncCustData,
5961 ITypeInfo2_fnGetParamCustData,
5962 ITypeInfo2_fnGetVarCustData,
5963 ITypeInfo2_fnGetImplTypeCustData,
5964 ITypeInfo2_fnGetDocumentation2,
5965 ITypeInfo2_fnGetAllCustData,
5966 ITypeInfo2_fnGetAllFuncCustData,
5967 ITypeInfo2_fnGetAllParamCustData,
5968 ITypeInfo2_fnGetAllVarCustData,
5969 ITypeInfo2_fnGetAllImplTypeCustData,
5972 /******************************************************************************
5973 * CreateDispTypeInfo [OLEAUT32.31]
5975 * Build type information for an object so it can be called through an
5976 * IDispatch interface.
5979 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5980 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5983 * This call allows an objects methods to be accessed through IDispatch, by
5984 * building an ITypeInfo object that IDispatch can use to call through.
5986 HRESULT WINAPI CreateDispTypeInfo(
5987 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5988 LCID lcid, /* [I] Locale Id */
5989 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5991 ITypeInfoImpl *pTIImpl;
5993 TLBFuncDesc **ppFuncDesc;
5995 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5996 pTIImpl->pTypeLib = NULL;
5998 pTIImpl->Name = NULL;
5999 pTIImpl->dwHelpContext = -1;
6000 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
6001 pTIImpl->TypeAttr.lcid = lcid;
6002 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
6003 pTIImpl->TypeAttr.wMajorVerNum = 0;
6004 pTIImpl->TypeAttr.wMinorVerNum = 0;
6005 pTIImpl->TypeAttr.cbAlignment = 2;
6006 pTIImpl->TypeAttr.cbSizeInstance = -1;
6007 pTIImpl->TypeAttr.cbSizeVft = -1;
6008 pTIImpl->TypeAttr.cFuncs = 0;
6009 pTIImpl->TypeAttr.cImplTypes = 1;
6010 pTIImpl->TypeAttr.cVars = 0;
6011 pTIImpl->TypeAttr.wTypeFlags = 0;
6013 ppFuncDesc = &pTIImpl->funclist;
6014 for(func = 0; func < pidata->cMembers; func++) {
6015 METHODDATA *md = pidata->pmethdata + func;
6016 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
6017 (*ppFuncDesc)->Name = SysAllocString(md->szName);
6018 (*ppFuncDesc)->funcdesc.memid = md->dispid;
6019 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
6020 (*ppFuncDesc)->funcdesc.callconv = md->cc;
6021 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
6022 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
6023 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
6024 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
6025 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
6026 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6027 md->cArgs * sizeof(ELEMDESC));
6028 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
6029 md->cArgs * sizeof(TLBParDesc));
6030 for(param = 0; param < md->cArgs; param++) {
6031 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
6032 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
6034 ppFuncDesc = &(*ppFuncDesc)->next;
6036 *pptinfo = (ITypeInfo*)pTIImpl;
6041 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
6043 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6045 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
6048 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
6050 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6052 return ITypeInfo_AddRef((ITypeInfo *)This);
6055 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
6057 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6059 return ITypeInfo_Release((ITypeInfo *)This);
6062 static HRESULT WINAPI ITypeComp_fnBind(
6067 ITypeInfo ** ppTInfo,
6068 DESCKIND * pDescKind,
6071 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
6072 TLBFuncDesc * pFDesc;
6073 TLBVarDesc * pVDesc;
6075 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6077 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
6078 if (pFDesc->funcdesc.invkind & wFlags)
6079 if (!strcmpW(pFDesc->Name, szName)) {
6085 *pDescKind = DESCKIND_FUNCDESC;
6086 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
6087 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6090 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
6092 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
6093 if (!strcmpW(pVDesc->Name, szName)) {
6094 *pDescKind = DESCKIND_VARDESC;
6095 pBindPtr->lpvardesc = &pVDesc->vardesc;
6096 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6102 /* not found, look for it in inherited interfaces */
6103 if (This->TypeAttr.cImplTypes &&
6104 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
6105 /* recursive search */
6109 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
6112 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
6113 ITypeInfo_Release(pTInfo);
6117 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
6118 ITypeComp_Release(pTComp);
6121 WARN("Could not search inherited interface!\n");
6123 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
6124 *pDescKind = DESCKIND_NONE;
6125 pBindPtr->lpfuncdesc = NULL;
6127 return DISP_E_MEMBERNOTFOUND;
6130 static HRESULT WINAPI ITypeComp_fnBindType(
6134 ITypeInfo ** ppTInfo,
6135 ITypeComp ** ppTComp)
6137 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
6139 /* strange behaviour (does nothing) but like the
6142 if (!ppTInfo || !ppTComp)
6151 static const ITypeCompVtbl tcompvt =
6154 ITypeComp_fnQueryInterface,
6156 ITypeComp_fnRelease,
6159 ITypeComp_fnBindType