4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * --------------------------------------------------------------------------------------
24 * Known problems (2000, Francois Jacques)
26 * - Tested using OLEVIEW (Platform SDK tool) only.
28 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
29 * creating by doing a straight copy of the dispinterface instance and just changing
30 * its typekind. Pointed structures aren't copied - only the address of the pointers.
31 * So when you release the dispinterface, you delete the vtable-interface structures
32 * as well... fortunately, clean up of structures is not implemented.
34 * - locale stuff is partially implemented but hasn't been tested.
36 * - typelib file is still read in its entirety, but it is released now.
37 * - some garbage is read from function names on some very rare occasions.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. there are a number of stubs in ITypeLib and ITypeInfo interfaces. Most
45 * of them I don't know yet how to implement them.
46 * -. Most error return values are just guessed not checked with windows
48 * -. didn't bother with a c++ interface
49 * -. lousy fatal error handling
50 * -. some methods just return pointers to internal data structures, this is
51 * partly laziness, partly I want to check how windows does it.
56 #include "wine/port.h"
65 #define NONAMELESSUNION
66 #define NONAMELESSSTRUCT
75 #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 /****************************************************************************
91 * Takes p_iVal (which is in little endian) and returns it
92 * in the host machine's byte order.
94 #ifdef WORDS_BIGENDIAN
95 static WORD FromLEWord(WORD p_iVal)
97 return (((p_iVal & 0x00FF) << 8) |
98 ((p_iVal & 0xFF00) >> 8));
102 static DWORD FromLEDWord(DWORD p_iVal)
104 return (((p_iVal & 0x000000FF) << 24) |
105 ((p_iVal & 0x0000FF00) << 8) |
106 ((p_iVal & 0x00FF0000) >> 8) |
107 ((p_iVal & 0xFF000000) >> 24));
110 #define FromLEWord(X) (X)
111 #define FromLEDWord(X) (X)
115 /****************************************************************************
118 * Fix byte order in any structure if necessary
120 #ifdef WORDS_BIGENDIAN
121 static void FromLEWords(void *p_Val, int p_iSize)
125 p_iSize /= sizeof(WORD);
128 *Val = FromLEWord(*Val);
135 static void FromLEDWords(void *p_Val, int p_iSize)
139 p_iSize /= sizeof(DWORD);
142 *Val = FromLEDWord(*Val);
148 #define FromLEWords(X,Y) /*nothing*/
149 #define FromLEDWords(X,Y) /*nothing*/
152 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
153 /* buffer must be at least 60 characters long */
154 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
156 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
157 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
159 memcpy( buffer, TypelibW, sizeof(TypelibW) );
160 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
161 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
165 /* get the path of an interface key, in the form "Interface\\<guid>" */
166 /* buffer must be at least 50 characters long */
167 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
169 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
171 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
172 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
176 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
177 /* buffer must be at least 16 characters long */
178 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
180 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
181 static const WCHAR win16W[] = {'w','i','n','1','6',0};
182 static const WCHAR win32W[] = {'w','i','n','3','2',0};
184 sprintfW( buffer, LcidFormatW, lcid );
187 case SYS_WIN16: strcatW( buffer, win16W ); break;
188 case SYS_WIN32: strcatW( buffer, win32W ); break;
190 TRACE("Typelib is for unsupported syskind %i\n", syskind);
197 /****************************************************************************
198 * QueryPathOfRegTypeLib [OLEAUT32.164]
203 QueryPathOfRegTypeLib(
204 REFGUID guid, /* [in] referenced guid */
205 WORD wMaj, /* [in] major version */
206 WORD wMin, /* [in] minor version */
207 LCID lcid, /* [in] locale id */
208 LPBSTR path ) /* [out] path of typelib */
214 WCHAR Path[MAX_PATH];
218 FIXME("(guid %p,%d,%d,0x%04lx,%p),stub!\n", guid, wMaj, wMin, lcid, path);
222 get_typelib_key( guid, wMaj, wMin, buffer );
224 if (RegOpenKeyW( HKEY_CLASSES_ROOT, buffer, &hkey ) != ERROR_SUCCESS)
226 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
232 DWORD dwPathLen = sizeof(Path);
234 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
236 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
240 else if (myLCID == lcid)
242 /* try with sub-langid */
243 myLCID = SUBLANGID(lcid);
245 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
247 /* try with system langid */
257 *path = SysAllocString( Path );
265 /******************************************************************************
266 * CreateTypeLib [OLEAUT32.160] creates a typelib
272 HRESULT WINAPI CreateTypeLib(
273 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
275 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
278 /******************************************************************************
279 * LoadTypeLib [OLEAUT32.161]
280 * Loads and registers a type library
282 * Docs: OLECHAR FAR* szFile
283 * Docs: iTypeLib FAR* FAR* pptLib
289 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
291 HRESULT WINAPI LoadTypeLib(
292 const OLECHAR *szFile,/* [in] Name of file to load from */
293 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
296 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
299 /******************************************************************************
300 * LoadTypeLibEx [OLEAUT32.183]
301 * Loads and optionally registers a type library
307 HRESULT WINAPI LoadTypeLibEx(
308 LPCOLESTR szFile, /* [in] Name of file to load from */
309 REGKIND regkind, /* [in] Specify kind of registration */
310 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
312 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
317 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
320 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
323 /* Look for a trailing '\\' followed by an index */
324 pIndexStr = strrchrW(szFile, '\\');
325 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
326 index = atoiW(pIndexStr);
327 memcpy(szFileCopy, szFile,
328 (pIndexStr - szFile - 1) * sizeof(WCHAR));
329 szFileCopy[pIndexStr - szFile - 1] = '\0';
330 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
332 return TYPE_E_CANTLOADLIBRARY;
333 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
334 return TYPE_E_CANTLOADLIBRARY;
337 static const WCHAR stdole32tlb[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
340 lstrcpyW(tstpath,szFile);
342 for (i=0;i<strlenW(tstpath);i++) {
343 if (tstpath[i] == 's') {
344 if (!strcmpW(tstpath+i,stdole32tlb)) {
346 MESSAGE("**************************************************************************\n");
347 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
348 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
349 MESSAGE("on the Microsoft Download Pages.\n");
350 MESSAGE("**************************************************************************\n");
355 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
356 return TYPE_E_CANTLOADLIBRARY;
360 TRACE("File %s index %d\n", debugstr_w(szPath), index);
362 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
367 case REGKIND_DEFAULT:
368 /* don't register typelibs supplied with full path. Experimentation confirms the following */
370 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
371 (szFile[0] && (szFile[1] == ':'))) break;
372 /* else fall-through */
374 case REGKIND_REGISTER:
375 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
377 IUnknown_Release(*pptLib);
385 TRACE(" returns %08lx\n",res);
389 /******************************************************************************
390 * LoadRegTypeLib [OLEAUT32.162]
392 HRESULT WINAPI LoadRegTypeLib(
393 REFGUID rguid, /* [in] referenced guid */
394 WORD wVerMajor, /* [in] major version */
395 WORD wVerMinor, /* [in] minor version */
396 LCID lcid, /* [in] locale id */
397 ITypeLib **ppTLib) /* [out] path of typelib */
400 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
404 res= LoadTypeLib(bstr, ppTLib);
408 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
414 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
415 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
416 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
417 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
418 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
419 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
421 /******************************************************************************
422 * RegisterTypeLib [OLEAUT32.163]
423 * Adds information about a type library to the System Registry
425 * Docs: ITypeLib FAR * ptlib
426 * Docs: OLECHAR FAR* szFullPath
427 * Docs: OLECHAR FAR* szHelpDir
433 HRESULT WINAPI RegisterTypeLib(
434 ITypeLib * ptlib, /* [in] Pointer to the library*/
435 OLECHAR * szFullPath, /* [in] full Path of the library*/
436 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
439 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
440 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
441 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
451 if (ptlib == NULL || szFullPath == NULL)
454 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
457 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
460 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
461 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
465 /* Set the human-readable name of the typelib */
466 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
468 if (RegSetValueExW(key, NULL, 0, REG_SZ,
469 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
477 /* Make up the name of the typelib path subkey */
478 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
480 /* Create the typelib path subkey */
481 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
482 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
484 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
485 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
493 /* Create the flags subkey */
494 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
495 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
497 /* FIXME: is %u correct? */
498 static const WCHAR formatW[] = {'%','u',0};
500 sprintfW(buf, formatW, attr->wLibFlags);
501 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
502 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
510 /* create the helpdir subkey */
511 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
512 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
514 BOOL freeHelpDir = FALSE;
517 /* if we created a new key, and helpDir was null, set the helpdir
518 to the directory which contains the typelib. However,
519 if we just opened an existing key, we leave the helpdir alone */
520 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
521 szHelpDir = SysAllocString(szFullPath);
522 pIndexStr = strrchrW(szHelpDir, '\\');
529 /* if we have an szHelpDir, set it! */
530 if (szHelpDir != NULL) {
531 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
532 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
538 if (freeHelpDir) SysFreeString(szHelpDir);
550 /* register OLE Automation-compatible interfaces for this typelib */
551 types = ITypeLib_GetTypeInfoCount(ptlib);
552 for (tidx=0; tidx<types; tidx++) {
553 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
554 LPOLESTR name = NULL;
555 ITypeInfo *tinfo = NULL;
557 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
560 case TKIND_INTERFACE:
561 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
562 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
566 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
567 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
571 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
576 TYPEATTR *tattr = NULL;
577 ITypeInfo_GetTypeAttr(tinfo, &tattr);
580 TRACE_(typelib)("guid=%s, flags=%04x (",
581 debugstr_guid(&tattr->guid),
584 if (TRACE_ON(typelib)) {
585 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
606 * FIXME: The 1 is just here until we implement rpcrt4
607 * stub/proxy handling. Until then it helps IShield
610 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
612 if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
613 FIXME("Registering non-oleautomation interface!\n");
616 /* register interface<->typelib coupling */
617 get_interface_key( &tattr->guid, keyName );
618 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
619 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
622 RegSetValueExW(key, NULL, 0, REG_SZ,
623 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
625 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
626 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
627 RegSetValueExW(subKey, NULL, 0, REG_SZ,
628 (BYTE*)PSOA, sizeof PSOA);
632 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
633 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
634 RegSetValueExW(subKey, NULL, 0, REG_SZ,
635 (BYTE*)PSOA, sizeof PSOA);
639 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
640 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
643 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
644 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
646 StringFromGUID2(&attr->guid, buffer, 40);
647 RegSetValueExW(subKey, NULL, 0, REG_SZ,
648 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
649 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
650 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
651 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
659 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
662 ITypeInfo_Release(tinfo);
669 ITypeLib_ReleaseTLibAttr(ptlib, attr);
675 /******************************************************************************
676 * UnRegisterTypeLib [OLEAUT32.186]
677 * Removes information about a type library from the System Registry
684 HRESULT WINAPI UnRegisterTypeLib(
685 REFGUID libid, /* [in] Guid of the library */
686 WORD wVerMajor, /* [in] major version */
687 WORD wVerMinor, /* [in] minor version */
688 LCID lcid, /* [in] locale id */
691 BSTR tlibPath = NULL;
694 WCHAR subKeyName[50];
697 BOOL deleteOtherStuff;
700 TYPEATTR* typeAttr = NULL;
702 ITypeInfo* typeInfo = NULL;
703 ITypeLib* typeLib = NULL;
706 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
708 /* Create the path to the key */
709 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
711 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
713 TRACE("Unsupported syskind %i\n", syskind);
714 result = E_INVALIDARG;
718 /* get the path to the typelib on disk */
719 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
720 result = E_INVALIDARG;
724 /* Try and open the key to the type library. */
725 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
726 result = E_INVALIDARG;
730 /* Try and load the type library */
731 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
732 result = TYPE_E_INVALIDSTATE;
736 /* remove any types registered with this typelib */
737 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
738 for (i=0; i<numTypes; i++) {
739 /* get the kind of type */
740 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
744 /* skip non-interfaces, and get type info for the type */
745 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
748 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
751 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
755 /* the path to the type */
756 get_interface_key( &typeAttr->guid, subKeyName );
758 /* Delete its bits */
759 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
762 RegDeleteKeyW(subKey, ProxyStubClsidW);
763 RegDeleteKeyW(subKey, ProxyStubClsid32W);
764 RegDeleteKeyW(subKey, TypeLibW);
767 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
770 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
772 if (typeInfo) ITypeInfo_Release(typeInfo);
776 /* Now, delete the type library path subkey */
777 get_lcid_subkey( lcid, syskind, subKeyName );
778 RegDeleteKeyW(key, subKeyName);
779 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
780 RegDeleteKeyW(key, subKeyName);
782 /* check if there is anything besides the FLAGS/HELPDIR keys.
783 If there is, we don't delete them */
784 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
785 deleteOtherStuff = TRUE;
787 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
788 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
790 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
791 if (!strcmpW(subKeyName, FLAGSW)) continue;
792 if (!strcmpW(subKeyName, HELPDIRW)) continue;
793 deleteOtherStuff = FALSE;
797 /* only delete the other parts of the key if we're absolutely sure */
798 if (deleteOtherStuff) {
799 RegDeleteKeyW(key, FLAGSW);
800 RegDeleteKeyW(key, HELPDIRW);
804 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
805 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
806 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
810 if (tlibPath) SysFreeString(tlibPath);
811 if (typeLib) ITypeLib_Release(typeLib);
812 if (subKey) RegCloseKey(subKey);
813 if (key) RegCloseKey(key);
817 /*======================= ITypeLib implementation =======================*/
819 typedef struct tagTLBCustData
823 struct tagTLBCustData* next;
826 /* data structure for import typelibs */
827 typedef struct tagTLBImpLib
829 int offset; /* offset in the file (MSFT)
830 offset in nametable (SLTG)
831 just used to identify library while reading
833 GUID guid; /* libid */
834 BSTR name; /* name */
836 LCID lcid; /* lcid of imported typelib */
838 WORD wVersionMajor; /* major version number */
839 WORD wVersionMinor; /* minor version number */
841 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
842 NULL if not yet loaded */
843 struct tagTLBImpLib * next;
846 /* internal ITypeLib data */
847 typedef struct tagITypeLibImpl
849 ITypeLib2Vtbl *lpVtbl;
850 ITypeCompVtbl *lpVtblTypeComp;
852 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
854 /* strings can be stored in tlb as multibyte strings BUT they are *always*
855 * exported to the application as a UNICODE string.
861 unsigned long dwHelpContext;
862 int TypeInfoCount; /* nr of typeinfo's in librarry */
863 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
864 int ctCustData; /* number of items in cust data list */
865 TLBCustData * pCustData; /* linked list to cust data */
866 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
867 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
868 libary. Only used while read MSFT
871 /* typelibs are cached, keyed by path, so store the linked list info within them */
872 struct tagITypeLibImpl *next, *prev;
876 static struct ITypeLib2Vtbl tlbvt;
877 static struct ITypeCompVtbl tlbtcvt;
879 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
880 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
882 /* ITypeLib methods */
883 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
884 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
886 /*======================= ITypeInfo implementation =======================*/
888 /* data for refernced types */
889 typedef struct tagTLBRefType
891 INT index; /* Type index for internal ref or for external ref
892 it the format is SLTG. -2 indicates to
895 GUID guid; /* guid of the referenced type */
896 /* if index == TLB_REF_USE_GUID */
898 HREFTYPE reference; /* The href of this ref */
899 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
900 TLB_REF_INTERNAL for internal refs
901 TLB_REF_NOT_FOUND for broken refs */
903 struct tagTLBRefType * next;
906 #define TLB_REF_USE_GUID -2
908 #define TLB_REF_INTERNAL (void*)-2
909 #define TLB_REF_NOT_FOUND (void*)-1
911 /* internal Parameter data */
912 typedef struct tagTLBParDesc
916 TLBCustData * pCustData; /* linked list to cust data */
919 /* internal Function data */
920 typedef struct tagTLBFuncDesc
922 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
923 BSTR Name; /* the name of this function */
924 TLBParDesc *pParamDesc; /* array with param names and custom data */
926 int HelpStringContext;
928 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
930 TLBCustData * pCustData; /* linked list to cust data; */
931 struct tagTLBFuncDesc * next;
934 /* internal Variable data */
935 typedef struct tagTLBVarDesc
937 VARDESC vardesc; /* lots of info on the variable and its attributes. */
938 BSTR Name; /* the name of this variable */
940 int HelpStringContext; /* FIXME: where? */
943 TLBCustData * pCustData;/* linked list to cust data; */
944 struct tagTLBVarDesc * next;
947 /* internal implemented interface data */
948 typedef struct tagTLBImplType
950 HREFTYPE hRef; /* hRef of interface */
951 int implflags; /* IMPLFLAG_*s */
953 TLBCustData * pCustData;/* linked list to custom data; */
954 struct tagTLBImplType *next;
957 /* internal TypeInfo data */
958 typedef struct tagITypeInfoImpl
960 ITypeInfo2Vtbl *lpVtbl;
961 ITypeCompVtbl *lpVtblTypeComp;
963 TYPEATTR TypeAttr ; /* _lots_ of type information. */
964 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
965 int index; /* index in this typelib; */
966 /* type libs seem to store the doc strings in ascii
967 * so why should we do it in unicode?
971 unsigned long dwHelpContext;
972 unsigned long dwHelpStringContext;
975 TLBFuncDesc * funclist; /* linked list with function descriptions */
978 TLBVarDesc * varlist; /* linked list with variable descriptions */
980 /* Implemented Interfaces */
981 TLBImplType * impltypelist;
983 TLBRefType * reflist;
985 TLBCustData * pCustData; /* linked list to cust data; */
986 struct tagITypeInfoImpl * next;
989 static struct ITypeInfo2Vtbl tinfvt;
990 static struct ITypeCompVtbl tcompvt;
992 static ITypeInfo2 * WINAPI ITypeInfo_Constructor();
994 typedef struct tagTLBContext
996 unsigned int oStart; /* start of TLB in file */
997 unsigned int pos; /* current pos */
998 unsigned int length; /* total length */
999 void *mapping; /* memory mapping */
1000 MSFT_SegDir * pTblDir;
1001 ITypeLibImpl* pLibInfo;
1005 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1010 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1011 if (pTD->vt & VT_RESERVED)
1012 szVarType += strlen(strcpy(szVarType, "reserved | "));
1013 if (pTD->vt & VT_BYREF)
1014 szVarType += strlen(strcpy(szVarType, "ref to "));
1015 if (pTD->vt & VT_ARRAY)
1016 szVarType += strlen(strcpy(szVarType, "array of "));
1017 if (pTD->vt & VT_VECTOR)
1018 szVarType += strlen(strcpy(szVarType, "vector of "));
1019 switch(pTD->vt & VT_TYPEMASK) {
1020 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1021 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1022 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1023 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1024 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1025 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1026 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1027 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1028 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1029 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1030 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1031 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1032 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1033 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1034 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1035 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1036 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1037 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1038 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1039 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1040 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1041 pTD->u.hreftype); break;
1042 case VT_PTR: sprintf(szVarType, "ptr to ");
1043 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1045 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1046 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1048 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1049 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1050 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1053 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1057 void dump_ELEMDESC(ELEMDESC *edesc) {
1059 dump_TypeDesc(&edesc->tdesc,buf);
1060 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1061 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1062 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1064 void dump_FUNCDESC(FUNCDESC *funcdesc) {
1066 MESSAGE("memid is %08lx\n",funcdesc->memid);
1067 for (i=0;i<funcdesc->cParams;i++) {
1068 MESSAGE("Param %d:\n",i);
1069 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1071 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1072 switch (funcdesc->funckind) {
1073 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1074 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1075 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1076 case FUNC_STATIC: MESSAGE("static");break;
1077 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1078 default: MESSAGE("unknown");break;
1080 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1081 switch (funcdesc->invkind) {
1082 case INVOKE_FUNC: MESSAGE("func");break;
1083 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1084 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1085 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1087 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1088 switch (funcdesc->callconv) {
1089 case CC_CDECL: MESSAGE("cdecl");break;
1090 case CC_PASCAL: MESSAGE("pascal");break;
1091 case CC_STDCALL: MESSAGE("stdcall");break;
1092 case CC_SYSCALL: MESSAGE("syscall");break;
1095 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1096 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1097 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1099 MESSAGE("\telemdescFunc (return value type):\n");
1100 dump_ELEMDESC(&funcdesc->elemdescFunc);
1103 void dump_IDLDESC(IDLDESC *idl) {
1104 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
1107 static const char * typekind_desc[] =
1120 void dump_TYPEATTR(TYPEATTR *tattr) {
1122 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1123 MESSAGE("\tlcid: %ld\n",tattr->lcid);
1124 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1125 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1126 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1127 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1128 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1129 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1130 MESSAGE("\tcVars: %d\n", tattr->cVars);
1131 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1132 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1133 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1134 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1135 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1136 dump_TypeDesc(&tattr->tdescAlias,buf);
1137 MESSAGE("\ttypedesc: %s\n", buf);
1138 dump_IDLDESC(&tattr->idldescType);
1141 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1144 if (!TRACE_ON(typelib))
1146 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1147 for (i=0;i<pfd->funcdesc.cParams;i++)
1148 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1151 dump_FUNCDESC(&(pfd->funcdesc));
1153 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1154 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1156 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1160 dump_TLBFuncDescOne(pfd);
1164 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1168 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1173 static void dump_TLBImpLib(TLBImpLib *import)
1175 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1176 debugstr_w(import->name));
1177 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1178 import->wVersionMinor, import->lcid, import->offset);
1181 static void dump_TLBRefType(TLBRefType * prt)
1185 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1186 if(prt->index == -1)
1187 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1189 TRACE_(typelib)("type no: %d\n", prt->index);
1191 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1192 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1193 TRACE_(typelib)("in lib\n");
1194 dump_TLBImpLib(prt->pImpTLInfo);
1200 static void dump_TLBImplType(TLBImplType * impl)
1204 "implementing/inheriting interface hRef = %lx implflags %x\n",
1205 impl->hRef, impl->implflags);
1210 void dump_Variant(VARIANT * pvar)
1214 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1218 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1219 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1221 TRACE(",%p", V_BYREF(pvar));
1223 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1227 else switch (V_TYPE(pvar))
1229 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1230 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1231 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1232 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1234 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1236 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1237 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1238 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1239 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1240 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1241 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1242 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1243 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1244 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1245 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1246 V_CY(pvar).s.Lo); break;
1248 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1249 TRACE(",<invalid>");
1251 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1252 st.wHour, st.wMinute, st.wSecond);
1256 case VT_USERDEFINED:
1258 case VT_NULL: break;
1259 default: TRACE(",?"); break;
1265 static void dump_DispParms(DISPPARAMS * pdp)
1269 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1271 while (index < pdp->cArgs)
1273 dump_Variant( &pdp->rgvarg[index] );
1278 static void dump_TypeInfo(ITypeInfoImpl * pty)
1280 TRACE("%p ref=%u\n", pty, pty->ref);
1281 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1282 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1283 TRACE("fct:%u var:%u impl:%u\n",
1284 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1285 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1286 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1287 dump_TLBFuncDesc(pty->funclist);
1288 dump_TLBVarDesc(pty->varlist);
1289 dump_TLBImplType(pty->impltypelist);
1292 void dump_VARDESC(VARDESC *v)
1294 MESSAGE("memid %ld\n",v->memid);
1295 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1296 MESSAGE("oInst %ld\n",v->u.oInst);
1297 dump_ELEMDESC(&(v->elemdescVar));
1298 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1299 MESSAGE("varkind %d\n",v->varkind);
1302 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1304 /* VT_LPWSTR is largest type that */
1305 /* may appear in type description*/
1306 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1307 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1308 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1309 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1310 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1311 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1315 static void TLB_abort()
1319 static void * TLB_Alloc(unsigned size)
1322 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1324 ERR("cannot allocate memory\n");
1329 static void TLB_Free(void * ptr)
1331 HeapFree(GetProcessHeap(), 0, ptr);
1334 /* deep copy a typedesc */
1335 static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in)
1340 out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC));
1341 copy_typedesc(out->u.lptdesc, in->u.lptdesc);
1343 case VT_USERDEFINED:
1344 out->u.hreftype = in->u.hreftype;
1347 out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) +
1348 (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND));
1349 copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem);
1350 out->u.lpadesc->cDims = in->u.lpadesc->cDims;
1351 memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND));
1358 /* free()s any allocated memory pointed to by the tdesc. NB does not
1359 free the tdesc itself - this is because the tdesc is typically part
1360 of a larger structure */
1361 static void free_deep_typedesc(TYPEDESC *tdesc)
1365 free_deep_typedesc(tdesc->u.lptdesc);
1366 HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);
1367 tdesc->u.lptdesc = NULL;
1370 free_deep_typedesc(&tdesc->u.lpadesc->tdescElem);
1371 HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);
1372 tdesc->u.lpadesc = NULL;
1379 /**********************************************************************
1381 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1384 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1386 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1387 pcx->pos, count, pcx->oStart, pcx->length, where);
1389 if (where != DO_NOT_SEEK)
1391 where += pcx->oStart;
1392 if (where > pcx->length)
1395 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1400 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1401 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1406 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1411 ret = MSFT_Read(buffer, count, pcx, where);
1412 FromLEDWords(buffer, ret);
1417 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1422 ret = MSFT_Read(buffer, count, pcx, where);
1423 FromLEWords(buffer, ret);
1428 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1430 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1431 memset(pGuid,0, sizeof(GUID));
1434 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1435 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1436 pGuid->Data2 = FromLEWord(pGuid->Data2);
1437 pGuid->Data3 = FromLEWord(pGuid->Data3);
1438 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1441 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1444 MSFT_NameIntro niName;
1446 WCHAR* pwstring = NULL;
1447 BSTR bstrName = NULL;
1449 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1450 pcx->pTblDir->pNametab.offset+offset);
1451 niName.namelen &= 0xFF; /* FIXME: correct ? */
1452 name=TLB_Alloc((niName.namelen & 0xff) +1);
1453 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1454 name[niName.namelen & 0xff]='\0';
1456 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1459 /* no invalid characters in string */
1462 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1464 /* don't check for invalid character since this has been done previously */
1465 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1467 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1468 lengthInChars = SysStringLen(bstrName);
1469 HeapFree(GetProcessHeap(), 0, pwstring);
1472 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1476 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1483 if(offset<0) return NULL;
1484 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1485 if(length <= 0) return 0;
1486 string=TLB_Alloc(length +1);
1487 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1488 string[length]='\0';
1490 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1491 string, -1, NULL, 0);
1493 /* no invalid characters in string */
1496 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1498 /* don't check for invalid character since this has been done previously */
1499 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1501 bstr = SysAllocStringLen(pwstring, lengthInChars);
1502 lengthInChars = SysStringLen(bstr);
1503 HeapFree(GetProcessHeap(), 0, pwstring);
1506 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1510 * read a value and fill a VARIANT structure
1512 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1516 TRACE_(typelib)("\n");
1518 if(offset <0) { /* data are packed in here */
1519 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1520 V_UNION(pVar, iVal) = offset & 0xffff;
1523 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1524 pcx->pTblDir->pCustData.offset + offset );
1525 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1526 switch (V_VT(pVar)){
1527 case VT_EMPTY: /* FIXME: is this right? */
1528 case VT_NULL: /* FIXME: is this right? */
1529 case VT_I2 : /* this should not happen */
1540 case VT_VOID : /* FIXME: is this right? */
1548 case VT_DECIMAL : /* FIXME: is this right? */
1551 /* pointer types with known behaviour */
1554 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1556 FIXME("BSTR length = %d?\n", size);
1558 ptr=TLB_Alloc(size);/* allocate temp buffer */
1559 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1560 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1561 /* FIXME: do we need a AtoW conversion here? */
1562 V_UNION(pVar, bstrVal[size])=L'\0';
1563 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1568 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1575 case VT_USERDEFINED :
1581 case VT_STREAMED_OBJECT :
1582 case VT_STORED_OBJECT :
1583 case VT_BLOB_OBJECT :
1588 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1592 if(size>0) /* (big|small) endian correct? */
1593 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1597 * create a linked list with custom data
1599 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1605 TRACE_(typelib)("\n");
1609 pNew=TLB_Alloc(sizeof(TLBCustData));
1610 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1611 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1612 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1613 /* add new custom data at head of the list */
1614 pNew->next=*ppCustData;
1616 offset = entry.next;
1621 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1625 pTd->vt=type & VT_TYPEMASK;
1627 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1629 if(pTd->vt == VT_USERDEFINED)
1630 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1632 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1636 MSFT_DoFuncs(TLBContext* pcx,
1641 TLBFuncDesc** pptfd)
1644 * member information is stored in a data structure at offset
1645 * indicated by the memoffset field of the typeinfo structure
1646 * There are several distinctive parts.
1647 * the first part starts with a field that holds the total length
1648 * of this (first) part excluding this field. Then follow the records,
1649 * for each member there is one record.
1651 * First entry is always the length of the record (excluding this
1653 * Rest of the record depends on the type of the member. If there is
1654 * a field indicating the member type (function variable intereface etc)
1655 * I have not found it yet. At this time we depend on the information
1656 * in the type info and the usual order how things are stored.
1658 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1661 * Third is a equal sized array with file offsets to the name entry
1664 * Forth and last (?) part is an array with offsets to the records in the
1665 * first part of this file segment.
1668 int infolen, nameoffset, reclength, nrattributes, i;
1669 int recoffset = offset + sizeof(INT);
1672 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1674 TRACE_(typelib)("\n");
1676 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1678 for ( i = 0; i < cFuncs ; i++ )
1680 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1682 /* name, eventually add to a hash table */
1683 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1684 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1686 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1688 /* read the function information record */
1689 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1693 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1695 /* do the attributes */
1696 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1699 if ( nrattributes > 0 )
1701 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1703 if ( nrattributes > 1 )
1705 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1706 pFuncRec->OptAttr[1]) ;
1708 if ( nrattributes > 2 )
1710 if ( pFuncRec->FKCCIC & 0x2000 )
1712 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1716 (*pptfd)->Entry = MSFT_ReadString(pcx,
1717 pFuncRec->OptAttr[2]);
1719 if( nrattributes > 5 )
1721 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1723 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1726 pFuncRec->OptAttr[6],
1727 &(*pptfd)->pCustData);
1734 /* fill the FuncDesc Structure */
1735 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1736 offset + infolen + ( i + 1) * sizeof(INT));
1738 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1739 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1740 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1741 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1742 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1743 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1744 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1748 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1751 /* do the parameters/arguments */
1752 if(pFuncRec->nrargs)
1755 MSFT_ParameterInfo paraminfo;
1757 (*pptfd)->funcdesc.lprgelemdescParam =
1758 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1760 (*pptfd)->pParamDesc =
1761 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1763 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1764 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1766 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1768 TYPEDESC* lpArgTypeDesc = 0;
1772 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1775 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1777 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1779 /* SEEK value = jump to offset,
1780 * from there jump to the end of record,
1781 * go back by (j-1) arguments
1783 MSFT_ReadLEDWords( ¶minfo ,
1784 sizeof(MSFT_ParameterInfo), pcx,
1785 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1786 * sizeof(MSFT_ParameterInfo)));
1788 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1790 while ( lpArgTypeDesc != NULL )
1792 switch ( lpArgTypeDesc->vt )
1795 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1799 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1802 case VT_USERDEFINED:
1803 MSFT_DoRefType(pcx, pTI,
1804 lpArgTypeDesc->u.hreftype);
1806 lpArgTypeDesc = NULL;
1810 lpArgTypeDesc = NULL;
1816 /* parameter is the return value! */
1817 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1819 TYPEDESC* lpArgTypeDesc;
1821 (*pptfd)->funcdesc.elemdescFunc =
1822 (*pptfd)->funcdesc.lprgelemdescParam[j];
1824 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1826 while ( lpArgTypeDesc != NULL )
1828 switch ( lpArgTypeDesc->vt )
1831 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1835 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1839 case VT_USERDEFINED:
1842 lpArgTypeDesc->u.hreftype);
1844 lpArgTypeDesc = NULL;
1848 lpArgTypeDesc = NULL;
1853 /* second time around */
1854 for(j=0;j<pFuncRec->nrargs;j++)
1857 (*pptfd)->pParamDesc[j].Name =
1858 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1861 if ( (PARAMFLAG_FHASDEFAULT &
1862 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1863 ((pFuncRec->FKCCIC) & 0x1000) )
1865 INT* pInt = (INT *)((char *)pFuncRec +
1867 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1869 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1871 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1872 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1874 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1878 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1881 pFuncRec->OptAttr[7+j],
1882 &(*pptfd)->pParamDesc[j].pCustData);
1887 /* scode is not used: archaic win16 stuff FIXME: right? */
1888 (*pptfd)->funcdesc.cScodes = 0 ;
1889 (*pptfd)->funcdesc.lprgscode = NULL ;
1891 pptfd = & ((*pptfd)->next);
1892 recoffset += reclength;
1896 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1897 int cVars, int offset, TLBVarDesc ** pptvd)
1899 int infolen, nameoffset, reclength;
1901 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1905 TRACE_(typelib)("\n");
1907 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1908 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1909 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1910 recoffset += offset+sizeof(INT);
1911 for(i=0;i<cVars;i++){
1912 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1913 /* name, eventually add to a hash table */
1914 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1915 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1916 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1917 /* read the variable information record */
1918 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1920 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1922 if(reclength >(6*sizeof(INT)) )
1923 (*pptvd)->HelpContext=pVarRec->HelpContext;
1924 if(reclength >(7*sizeof(INT)) )
1925 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1926 if(reclength >(8*sizeof(INT)) )
1927 if(reclength >(9*sizeof(INT)) )
1928 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1929 /* fill the VarDesc Structure */
1930 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1931 offset + infolen + ( i + 1) * sizeof(INT));
1932 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1933 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1934 MSFT_GetTdesc(pcx, pVarRec->DataType,
1935 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1936 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1937 if(pVarRec->VarKind == VAR_CONST ){
1938 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1939 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1940 pVarRec->OffsValue, pcx);
1942 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1943 pptvd=&((*pptvd)->next);
1944 recoffset += reclength;
1947 /* fill in data for a hreftype (offset). When the refernced type is contained
1948 * in the typelib, it's just an (file) offset in the type info base dir.
1949 * If comes from import, it's an offset+1 in the ImpInfo table
1951 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1955 TLBRefType **ppRefType = &pTI->reflist;
1957 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1960 if((*ppRefType)->reference == offset)
1962 ppRefType = &(*ppRefType)->next;
1965 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1966 sizeof(**ppRefType));
1968 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1969 /* external typelib */
1970 MSFT_ImpInfo impinfo;
1971 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1973 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1975 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1976 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1977 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1978 if(pImpLib->offset==impinfo.oImpFile) break;
1979 pImpLib=pImpLib->next;
1982 (*ppRefType)->reference=offset;
1983 (*ppRefType)->pImpTLInfo = pImpLib;
1984 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1985 (*ppRefType)->index = TLB_REF_USE_GUID;
1987 ERR("Cannot find a reference\n");
1988 (*ppRefType)->reference=-1;
1989 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1992 /* in this typelib */
1993 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1994 (*ppRefType)->reference=offset;
1995 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1999 /* process Implemented Interfaces of a com class */
2000 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2004 MSFT_RefRecord refrec;
2005 TLBImplType **ppImpl = &pTI->impltypelist;
2007 TRACE_(typelib)("\n");
2009 for(i=0;i<count;i++){
2010 if(offset<0) break; /* paranoia */
2011 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2012 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2013 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2014 (*ppImpl)->hRef = refrec.reftype;
2015 (*ppImpl)->implflags=refrec.flags;
2016 (*ppImpl)->ctCustData=
2017 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2018 offset=refrec.onext;
2019 ppImpl=&((*ppImpl)->next);
2023 * process a typeinfo record
2025 ITypeInfoImpl * MSFT_DoTypeInfo(
2028 ITypeLibImpl * pLibInfo)
2030 MSFT_TypeInfoBase tiBase;
2031 ITypeInfoImpl *ptiRet;
2033 TRACE_(typelib)("count=%u\n", count);
2035 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2036 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2037 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2038 /* this is where we are coming from */
2039 ptiRet->pTypeLib = pLibInfo;
2040 ptiRet->index=count;
2041 /* fill in the typeattr fields */
2042 WARN("Assign constructor/destructor memid\n");
2044 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2045 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2046 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2047 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2048 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2049 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2050 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2051 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2052 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2053 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2054 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2055 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2056 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2057 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2058 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2059 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2060 MSFT_GetTdesc(pcx, tiBase.datatype1,
2061 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2064 /* IDLDESC idldescType; *//* never saw this one != zero */
2066 /* name, eventually add to a hash table */
2067 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2068 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2070 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2071 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2072 ptiRet->dwHelpContext=tiBase.helpcontext;
2073 /* note: InfoType's Help file and HelpStringDll come from the containing
2074 * library. Further HelpString and Docstring appear to be the same thing :(
2077 if(ptiRet->TypeAttr.cFuncs >0 )
2078 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2079 ptiRet->TypeAttr.cVars,
2080 tiBase.memoffset, & ptiRet->funclist);
2082 if(ptiRet->TypeAttr.cVars >0 )
2083 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2084 ptiRet->TypeAttr.cVars,
2085 tiBase.memoffset, & ptiRet->varlist);
2086 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2087 switch(ptiRet->TypeAttr.typekind)
2090 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2093 case TKIND_DISPATCH:
2094 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2096 if (tiBase.datatype1 != -1)
2098 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2099 ptiRet->impltypelist->hRef = tiBase.datatype1;
2102 { /* FIXME: This is a really bad hack to add IDispatch */
2103 const char* szStdOle = "stdole2.tlb\0";
2104 int nStdOleLen = strlen(szStdOle);
2105 TLBRefType **ppRef = &ptiRet->reflist;
2108 if((*ppRef)->reference == -1)
2110 ppRef = &(*ppRef)->next;
2113 *ppRef = TLB_Alloc(sizeof(**ppRef));
2114 (*ppRef)->guid = IID_IDispatch;
2115 (*ppRef)->reference = -1;
2116 (*ppRef)->index = TLB_REF_USE_GUID;
2117 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2118 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2119 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2122 MultiByteToWideChar(CP_ACP,
2126 (*ppRef)->pImpTLInfo->name,
2127 SysStringLen((*ppRef)->pImpTLInfo->name));
2129 (*ppRef)->pImpTLInfo->lcid = 0;
2130 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2131 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2136 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2137 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2138 ptiRet->impltypelist->hRef = tiBase.datatype1;
2143 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2145 TRACE_(typelib)("%s guid: %s kind:%s\n",
2146 debugstr_w(ptiRet->Name),
2147 debugstr_guid(&ptiRet->TypeAttr.guid),
2148 typekind_desc[ptiRet->TypeAttr.typekind]);
2153 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2154 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2155 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2158 static ITypeLibImpl *tlb_cache_first;
2159 static CRITICAL_SECTION cache_section;
2160 static CRITICAL_SECTION_DEBUG cache_section_debug =
2162 0, 0, &cache_section,
2163 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2164 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
2166 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2169 /****************************************************************************
2172 * find the type of the typelib file and map the typelib resource into
2175 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2176 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2177 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2179 ITypeLibImpl *entry;
2180 int ret = TYPE_E_CANTLOADLIBRARY;
2181 DWORD dwSignature = 0;
2184 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2188 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2189 EnterCriticalSection(&cache_section);
2190 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2192 if (!strcmpiW(entry->path, pszFileName))
2194 TRACE("cache hit\n");
2195 *ppTypeLib = (ITypeLib2*)entry;
2196 ITypeLib_AddRef(*ppTypeLib);
2197 LeaveCriticalSection(&cache_section);
2201 LeaveCriticalSection(&cache_section);
2203 /* check the signature of the file */
2204 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2205 if (INVALID_HANDLE_VALUE != hFile)
2207 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2210 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2213 /* retrieve file size */
2214 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2216 /* first try to load as *.tlb */
2217 dwSignature = FromLEDWord(*((DWORD*) pBase));
2218 if ( dwSignature == MSFT_SIGNATURE)
2220 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2222 else if ( dwSignature == SLTG_SIGNATURE)
2224 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2226 UnmapViewOfFile(pBase);
2228 CloseHandle(hMapping);
2233 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2235 /* find the typelibrary resource*/
2236 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2237 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2240 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2241 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2244 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2247 LPVOID pBase = LockResource(hGlobal);
2248 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2252 /* try to load as incore resource */
2253 dwSignature = FromLEDWord(*((DWORD*) pBase));
2254 if ( dwSignature == MSFT_SIGNATURE)
2256 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2258 else if ( dwSignature == SLTG_SIGNATURE)
2260 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2264 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2267 FreeResource( hGlobal );
2270 FreeLibrary(hinstDLL);
2275 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2277 TRACE("adding to cache\n");
2278 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2279 lstrcpyW(impl->path, pszFileName);
2280 /* We should really canonicalise the path here. */
2282 /* FIXME: check if it has added already in the meantime */
2283 EnterCriticalSection(&cache_section);
2284 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2286 tlb_cache_first = impl;
2287 LeaveCriticalSection(&cache_section);
2290 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2295 /*================== ITypeLib(2) Methods ===================================*/
2297 /****************************************************************************
2298 * ITypeLib2_Constructor_MSFT
2300 * loading an MSFT typelib from an in-memory image
2302 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2306 MSFT_Header tlbHeader;
2307 MSFT_SegDir tlbSegDir;
2308 ITypeLibImpl * pTypeLibImpl;
2310 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2312 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2313 if (!pTypeLibImpl) return NULL;
2315 pTypeLibImpl->lpVtbl = &tlbvt;
2316 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2317 pTypeLibImpl->ref = 1;
2319 /* get pointer to beginning of typelib data */
2323 cx.pLibInfo = pTypeLibImpl;
2324 cx.length = dwTLBLength;
2327 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2329 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2330 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2331 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2334 /* there is a small amount of information here until the next important
2336 * the segment directory . Try to calculate the amount of data */
2337 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2339 /* now read the segment directory */
2340 TRACE("read segment directory (at %ld)\n",lPSegDir);
2341 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2342 cx.pTblDir = &tlbSegDir;
2344 /* just check two entries */
2345 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2347 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2348 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2352 /* now fill our internal data */
2353 /* TLIBATTR fields */
2354 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2356 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2357 /* Windows seems to have zero here, is this correct? */
2358 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2359 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2361 pTypeLibImpl->LibAttr.lcid = 0;
2363 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2364 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2365 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2366 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2368 /* name, eventually add to a hash table */
2369 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2372 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2373 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2375 if( tlbHeader.varflags & HELPDLLFLAG)
2378 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2379 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2382 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2385 if(tlbHeader.CustomDataOffset >= 0)
2387 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2390 /* fill in typedescriptions */
2391 if(tlbSegDir.pTypdescTab.length > 0)
2393 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2395 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2396 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2399 /* FIXME: add several sanity checks here */
2400 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2401 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2403 /* FIXME: check safearray */
2405 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2407 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2409 else if(td[0] == VT_CARRAY)
2411 /* array descr table here */
2412 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2414 else if(td[0] == VT_USERDEFINED)
2416 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2418 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2421 /* second time around to fill the array subscript info */
2424 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2425 if(tlbSegDir.pArrayDescriptions.offset>0)
2427 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2428 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2431 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2433 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2435 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2437 for(j = 0; j<td[2]; j++)
2439 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2440 sizeof(INT), &cx, DO_NOT_SEEK);
2441 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2442 sizeof(INT), &cx, DO_NOT_SEEK);
2447 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2448 ERR("didn't find array description data\n");
2453 /* imported type libs */
2454 if(tlbSegDir.pImpFiles.offset>0)
2456 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2457 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2460 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2465 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2466 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2467 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2469 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2470 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2471 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2472 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2475 name = TLB_Alloc(size+1);
2476 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2477 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2478 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2479 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2482 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2483 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2485 ppImpLib = &(*ppImpLib)->next;
2490 if(tlbHeader.nrtypeinfos >= 0 )
2492 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2493 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2496 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2498 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2500 ppTI = &((*ppTI)->next);
2501 (pTypeLibImpl->TypeInfoCount)++;
2505 TRACE("(%p)\n", pTypeLibImpl);
2506 return (ITypeLib2*) pTypeLibImpl;
2510 static BSTR TLB_MultiByteToBSTR(char *ptr)
2516 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2517 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2518 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2519 ret = SysAllocString(nameW);
2520 HeapFree(GetProcessHeap(), 0, nameW);
2524 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2530 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2531 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2535 guid->Data4[0] = s >> 8;
2536 guid->Data4[1] = s & 0xff;
2539 for(i = 0; i < 6; i++) {
2540 memcpy(b, str + 24 + 2 * i, 2);
2541 guid->Data4[i + 2] = strtol(b, NULL, 16);
2546 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2553 bytelen = *(WORD*)ptr;
2554 if(bytelen == 0xffff) return 2;
2555 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2556 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2557 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2558 *pBstr = SysAllocStringLen(nameW, len);
2559 HeapFree(GetProcessHeap(), 0, nameW);
2563 static WORD SLTG_ReadStringA(char *ptr, char **str)
2568 bytelen = *(WORD*)ptr;
2569 if(bytelen == 0xffff) return 2;
2570 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2571 memcpy(*str, ptr + 2, bytelen);
2572 (*str)[bytelen] = '\0';
2576 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2578 char *ptr = pLibBlk;
2581 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2582 FIXME("libblk magic = %04x\n", w);
2587 if((w = *(WORD*)ptr) != 0xffff) {
2588 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2593 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2595 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2597 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2600 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2603 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2604 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2606 pTypeLibImpl->LibAttr.lcid = 0;
2609 ptr += 4; /* skip res12 */
2611 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2614 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2617 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2620 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2621 ptr += sizeof(GUID);
2623 return ptr - (char*)pLibBlk;
2626 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2629 TYPEDESC *pTD = &pElem->tdesc;
2631 /* Handle [in/out] first */
2632 if((*pType & 0xc000) == 0xc000)
2633 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2634 else if(*pType & 0x8000)
2635 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2636 else if(*pType & 0x4000)
2637 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2639 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2642 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2645 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2648 if((*pType & 0xe00) == 0xe00) {
2650 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2652 pTD = pTD->u.lptdesc;
2654 switch(*pType & 0x7f) {
2657 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2659 pTD = pTD->u.lptdesc;
2662 case VT_USERDEFINED:
2663 pTD->vt = VT_USERDEFINED;
2664 pTD->u.hreftype = *(++pType) / 4;
2670 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2673 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2675 pTD->vt = VT_CARRAY;
2676 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2678 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2679 pTD->u.lpadesc->cDims = pSA->cDims;
2680 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2681 pSA->cDims * sizeof(SAFEARRAYBOUND));
2683 pTD = &pTD->u.lpadesc->tdescElem;
2689 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2693 pTD->vt = VT_SAFEARRAY;
2694 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2696 pTD = pTD->u.lptdesc;
2700 pTD->vt = *pType & 0x7f;
2710 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2715 TLBRefType **ppRefType;
2717 if(pRef->magic != SLTG_REF_MAGIC) {
2718 FIXME("Ref magic = %x\n", pRef->magic);
2721 name = ( (char*)(&pRef->names) + pRef->number);
2723 ppRefType = &pTI->reflist;
2724 for(ref = 0; ref < pRef->number >> 3; ref++) {
2726 unsigned int lib_offs, type_num;
2728 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2729 sizeof(**ppRefType));
2731 name += SLTG_ReadStringA(name, &refname);
2732 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2733 FIXME("Can't sscanf ref\n");
2734 if(lib_offs != 0xffff) {
2735 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2738 if((*import)->offset == lib_offs)
2740 import = &(*import)->next;
2743 char fname[MAX_PATH+1];
2746 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2748 (*import)->offset = lib_offs;
2749 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2751 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2752 &(*import)->wVersionMajor,
2753 &(*import)->wVersionMinor,
2754 &(*import)->lcid, fname) != 4) {
2755 FIXME("can't sscanf ref %s\n",
2756 pNameTable + lib_offs + 40);
2758 len = strlen(fname);
2759 if(fname[len-1] != '#')
2760 FIXME("fname = %s\n", fname);
2761 fname[len-1] = '\0';
2762 (*import)->name = TLB_MultiByteToBSTR(fname);
2764 (*ppRefType)->pImpTLInfo = *import;
2765 } else { /* internal ref */
2766 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2768 (*ppRefType)->reference = ref;
2769 (*ppRefType)->index = type_num;
2771 HeapFree(GetProcessHeap(), 0, refname);
2772 ppRefType = &(*ppRefType)->next;
2774 if((BYTE)*name != SLTG_REF_MAGIC)
2775 FIXME("End of ref block magic = %x\n", *name);
2776 dump_TLBRefType(pTI->reflist);
2779 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2782 SLTG_ImplInfo *info;
2783 TLBImplType **ppImplType = &pTI->impltypelist;
2784 /* I don't really get this structure, usually it's 0x16 bytes
2785 long, but iuser.tlb contains some that are 0x18 bytes long.
2786 That's ok because we can use the next ptr to jump to the next
2787 one. But how do we know the length of the last one? The WORD
2788 at offs 0x8 might be the clue. For now I'm just assuming that
2789 the last one is the regular 0x16 bytes. */
2791 info = (SLTG_ImplInfo*)pBlk;
2793 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2794 sizeof(**ppImplType));
2795 (*ppImplType)->hRef = info->ref;
2796 (*ppImplType)->implflags = info->impltypeflags;
2797 pTI->TypeAttr.cImplTypes++;
2798 ppImplType = &(*ppImplType)->next;
2800 if(info->next == 0xffff)
2803 FIXME("Interface inheriting more than one interface\n");
2804 info = (SLTG_ImplInfo*)(pBlk + info->next);
2806 info++; /* see comment at top of function */
2810 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2813 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2814 SLTG_MemberHeader *pMemHeader;
2815 char *pFirstItem, *pNextItem;
2817 if(pTIHeader->href_table != 0xffffffff) {
2818 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2823 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2825 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2827 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2828 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2831 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2835 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2838 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2839 SLTG_MemberHeader *pMemHeader;
2840 SLTG_Function *pFunc;
2841 char *pFirstItem, *pNextItem;
2842 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2845 if(pTIHeader->href_table != 0xffffffff) {
2846 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, TRUE);
2858 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2859 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2864 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2865 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2866 FIXME("func magic = %02x\n", pFunc->magic);
2869 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2870 sizeof(**ppFuncDesc));
2871 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2873 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2874 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2875 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2876 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2877 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2878 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2880 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2881 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2883 if(pFunc->retnextopt & 0x80)
2884 pType = &pFunc->rettype;
2886 pType = (WORD*)(pFirstItem + pFunc->rettype);
2889 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2891 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2892 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2893 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2894 (*ppFuncDesc)->pParamDesc =
2895 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2896 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2898 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2900 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2901 char *paramName = pNameTable + *pArg;
2903 /* If arg type follows then paramName points to the 2nd
2904 letter of the name, else the next WORD is an offset to
2905 the arg type and paramName points to the first letter.
2906 So let's take one char off paramName and see if we're
2907 pointing at an alpha-numeric char. However if *pArg is
2908 0xffff or 0xfffe then the param has no name, the former
2909 meaning that the next WORD is the type, the latter
2910 meaning the the next WORD is an offset to the type. */
2915 else if(*pArg == 0xfffe) {
2919 else if(!isalnum(*(paramName-1)))
2924 if(HaveOffs) { /* the next word is an offset to type */
2925 pType = (WORD*)(pFirstItem + *pArg);
2926 SLTG_DoType(pType, pFirstItem,
2927 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2932 pArg = SLTG_DoType(pArg, pFirstItem,
2933 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2936 /* Are we an optional param ? */
2937 if((*ppFuncDesc)->funcdesc.cParams - param <=
2938 (*ppFuncDesc)->funcdesc.cParamsOpt)
2939 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2942 (*ppFuncDesc)->pParamDesc[param].Name =
2943 TLB_MultiByteToBSTR(paramName);
2947 ppFuncDesc = &((*ppFuncDesc)->next);
2948 if(pFunc->next == 0xffff) break;
2950 pTI->TypeAttr.cFuncs = num;
2951 dump_TLBFuncDesc(pTI->funclist);
2952 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2955 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2958 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2959 SLTG_MemberHeader *pMemHeader;
2960 SLTG_RecordItem *pItem;
2962 TLBVarDesc **ppVarDesc = &pTI->varlist;
2967 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2969 pFirstItem = (char*)(pMemHeader + 1);
2970 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2971 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2972 if(pItem->magic != SLTG_RECORD_MAGIC) {
2973 FIXME("record magic = %02x\n", pItem->magic);
2976 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2977 sizeof(**ppVarDesc));
2978 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2979 (*ppVarDesc)->vardesc.memid = pItem->memid;
2980 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2981 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2983 if(pItem->typepos == 0x02)
2984 pType = &pItem->type;
2985 else if(pItem->typepos == 0x00)
2986 pType = (WORD*)(pFirstItem + pItem->type);
2988 FIXME("typepos = %02x\n", pItem->typepos);
2992 SLTG_DoType(pType, pFirstItem,
2993 &(*ppVarDesc)->vardesc.elemdescVar);
2995 /* FIXME("helpcontext, helpstring\n"); */
2997 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2999 ppVarDesc = &((*ppVarDesc)->next);
3000 if(pItem->next == 0xffff) break;
3002 pTI->TypeAttr.cVars = num;
3003 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3006 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3009 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3010 SLTG_MemberHeader *pMemHeader;
3011 SLTG_AliasItem *pItem;
3014 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3015 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3018 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3019 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3020 if (pItem->vt == 0xffff) {
3021 if (i<(pMemHeader->cbExtra/4-1))
3022 FIXME("Endmarker too early in process alias data!\n");
3026 FIXME("Chain extends over last entry?\n");
3029 if (pItem->vt == VT_USERDEFINED) {
3030 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3031 /* guessing here ... */
3032 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3033 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3036 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3037 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3041 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3044 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3047 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3048 SLTG_MemberHeader *pMemHeader;
3049 SLTG_AliasItem *pItem;
3051 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3052 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3053 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3054 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3055 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3058 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3061 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3062 SLTG_MemberHeader *pMemHeader;
3063 SLTG_EnumItem *pItem;
3065 TLBVarDesc **ppVarDesc = &pTI->varlist;
3068 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3070 pFirstItem = (char*)(pMemHeader + 1);
3071 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3072 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3073 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3074 FIXME("enumitem magic = %04x\n", pItem->magic);
3077 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3078 sizeof(**ppVarDesc));
3079 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3080 (*ppVarDesc)->vardesc.memid = pItem->memid;
3081 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3083 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3084 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3085 *(INT*)(pItem->value + pFirstItem);
3086 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3087 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3088 /* FIXME("helpcontext, helpstring\n"); */
3090 ppVarDesc = &((*ppVarDesc)->next);
3091 if(pItem->next == 0xffff) break;
3093 pTI->TypeAttr.cVars = num;
3094 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3097 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
3098 managable copy of it into this */
3111 } SLTG_InternalOtherTypeInfo;
3113 /****************************************************************************
3114 * ITypeLib2_Constructor_SLTG
3116 * loading a SLTG typelib from an in-memory image
3118 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3120 ITypeLibImpl *pTypeLibImpl;
3121 SLTG_Header *pHeader;
3122 SLTG_BlkEntry *pBlkEntry;
3126 LPVOID pBlk, pFirstBlk;
3127 SLTG_LibBlk *pLibBlk;
3128 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3129 char *pAfterOTIBlks = NULL;
3130 char *pNameTable, *ptr;
3133 ITypeInfoImpl **ppTypeInfoImpl;
3135 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3137 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3138 if (!pTypeLibImpl) return NULL;
3140 pTypeLibImpl->lpVtbl = &tlbvt;
3141 pTypeLibImpl->ref = 1;
3146 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3147 pHeader->nrOfFileBlks );
3148 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3149 FIXME("Header type magic 0x%08lx not supported.\n",
3150 pHeader->SLTG_magic);
3154 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3155 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3157 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3158 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3160 /* Next we have a magic block */
3161 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3163 /* Let's see if we're still in sync */
3164 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3165 sizeof(SLTG_COMPOBJ_MAGIC))) {
3166 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3169 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3170 sizeof(SLTG_DIR_MAGIC))) {
3171 FIXME("dir magic = %s\n", pMagic->dir_magic);
3175 pIndex = (SLTG_Index*)(pMagic+1);
3177 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3179 pFirstBlk = (LPVOID)(pPad9 + 1);
3181 /* We'll set up a ptr to the main library block, which is the last one. */
3183 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3184 pBlkEntry[order].next != 0;
3185 order = pBlkEntry[order].next - 1, i++) {
3186 pBlk = (char*)pBlk + pBlkEntry[order].len;
3190 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3192 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3197 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3199 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3200 sizeof(*pOtherTypeInfoBlks) *
3201 pTypeLibImpl->TypeInfoCount);
3204 ptr = (char*)pLibBlk + len;
3206 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3210 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3212 w = *(WORD*)(ptr + 2);
3215 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3217 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3218 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3220 w = *(WORD*)(ptr + 4 + len);
3222 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3224 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3226 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3227 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3229 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3230 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3231 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3233 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3235 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3238 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3239 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3240 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3241 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3242 len += sizeof(SLTG_OtherTypeInfo);
3246 pAfterOTIBlks = ptr;
3248 /* Skip this WORD and get the next DWORD */
3249 len = *(DWORD*)(pAfterOTIBlks + 2);
3251 /* Now add this to pLibBLk look at what we're pointing at and
3252 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3253 dust and we should be pointing at the beginning of the name
3256 pNameTable = (char*)pLibBlk + len;
3258 switch(*(WORD*)pNameTable) {
3265 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3269 pNameTable += 0x216;
3273 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3275 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3278 /* Hopefully we now have enough ptrs set up to actually read in
3279 some TypeInfos. It's not clear which order to do them in, so
3280 I'll just follow the links along the BlkEntry chain and read
3281 them in in the order in which they're in the file */
3283 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3285 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3286 pBlkEntry[order].next != 0;
3287 order = pBlkEntry[order].next - 1, i++) {
3289 SLTG_TypeInfoHeader *pTIHeader;
3290 SLTG_TypeInfoTail *pTITail;
3292 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3293 pOtherTypeInfoBlks[i].index_name)) {
3294 FIXME("Index strings don't match\n");
3299 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3300 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3303 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3304 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3305 (*ppTypeInfoImpl)->index = i;
3306 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3307 pOtherTypeInfoBlks[i].name_offs +
3309 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3310 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3312 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3313 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3314 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3315 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3316 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3318 if((pTIHeader->typeflags1 & 7) != 2)
3319 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3320 if(pTIHeader->typeflags3 != 2)
3321 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3323 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3324 debugstr_w((*ppTypeInfoImpl)->Name),
3325 typekind_desc[pTIHeader->typekind],
3326 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3327 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3329 switch(pTIHeader->typekind) {
3331 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3335 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3338 case TKIND_INTERFACE:
3339 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3343 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3347 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3348 if (pTITail->tdescalias_vt)
3349 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3352 case TKIND_DISPATCH:
3353 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3357 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3363 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3364 but we've already set those */
3365 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3366 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3367 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3369 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3391 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3392 pBlk = (char*)pBlk + pBlkEntry[order].len;
3395 if(i != pTypeLibImpl->TypeInfoCount) {
3396 FIXME("Somehow processed %d TypeInfos\n", i);
3400 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3401 return (ITypeLib2*)pTypeLibImpl;
3404 /* ITypeLib::QueryInterface
3406 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3411 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3413 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3416 if(IsEqualIID(riid, &IID_IUnknown) ||
3417 IsEqualIID(riid,&IID_ITypeLib)||
3418 IsEqualIID(riid,&IID_ITypeLib2))
3425 ITypeLib2_AddRef(iface);
3426 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3429 TRACE("-- Interface: E_NOINTERFACE\n");
3430 return E_NOINTERFACE;
3435 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3437 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3439 TRACE("(%p)->ref was %u\n",This, This->ref);
3441 return ++(This->ref);
3444 /* ITypeLib::Release
3446 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3448 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3452 TRACE("(%p)->(%u)\n",This, This->ref);
3456 /* remove cache entry */
3457 TRACE("removing from cache list\n");
3458 EnterCriticalSection(&cache_section);
3459 if (This->next) This->next->prev = This->prev;
3460 if (This->prev) This->prev->next = This->next;
3461 else tlb_cache_first = This->next;
3462 LeaveCriticalSection(&cache_section);
3464 /* FIXME destroy child objects */
3465 TRACE(" destroying ITypeLib(%p)\n",This);
3469 SysFreeString(This->Name);
3473 if (This->DocString)
3475 SysFreeString(This->DocString);
3476 This->DocString = NULL;
3481 SysFreeString(This->HelpFile);
3482 This->HelpFile = NULL;
3485 if (This->HelpStringDll)
3487 SysFreeString(This->HelpStringDll);
3488 This->HelpStringDll = NULL;
3491 if (This->pTypeInfo) /* can be NULL */
3492 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3493 HeapFree(GetProcessHeap(),0,This);
3500 /* ITypeLib::GetTypeInfoCount
3502 * Returns the number of type descriptions in the type library
3504 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3506 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3507 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3508 return This->TypeInfoCount;
3511 /* ITypeLib::GetTypeInfo
3513 * retrieves the specified type description in the library.
3515 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3518 ITypeInfo **ppTInfo)
3522 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3523 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3525 TRACE("(%p)->(index=%d) \n", This, index);
3527 if (!ppTInfo) return E_INVALIDARG;
3529 /* search element n in list */
3530 for(i=0; i < index; i++)
3532 pTypeInfo = pTypeInfo->next;
3535 TRACE("-- element not found\n");
3536 return TYPE_E_ELEMENTNOTFOUND;
3540 *ppTInfo = (ITypeInfo *) pTypeInfo;
3542 ITypeInfo_AddRef(*ppTInfo);
3543 TRACE("-- found (%p)\n",*ppTInfo);
3548 /* ITypeLibs::GetTypeInfoType
3550 * Retrieves the type of a type description.
3552 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3557 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3559 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3561 TRACE("(%p) index %d \n",This, index);
3563 if(!pTKind) return E_INVALIDARG;
3565 /* search element n in list */
3566 for(i=0; i < index; i++)
3570 TRACE("-- element not found\n");
3571 return TYPE_E_ELEMENTNOTFOUND;
3573 pTInfo = pTInfo->next;
3576 *pTKind = pTInfo->TypeAttr.typekind;
3577 TRACE("-- found Type (%d)\n", *pTKind);
3581 /* ITypeLib::GetTypeInfoOfGuid
3583 * Retrieves the type description that corresponds to the specified GUID.
3586 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3589 ITypeInfo **ppTInfo)
3591 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3592 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3594 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3596 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3598 /* search linked list for guid */
3599 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3601 pTypeInfo = pTypeInfo->next;
3605 /* end of list reached */
3606 TRACE("-- element not found\n");
3607 return TYPE_E_ELEMENTNOTFOUND;
3611 TRACE("-- found (%p, %s)\n",
3613 debugstr_w(pTypeInfo->Name));
3615 *ppTInfo = (ITypeInfo*)pTypeInfo;
3616 ITypeInfo_AddRef(*ppTInfo);
3620 /* ITypeLib::GetLibAttr
3622 * Retrieves the structure that contains the library's attributes.
3625 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3627 LPTLIBATTR *ppTLibAttr)
3629 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3630 TRACE("(%p)\n",This);
3631 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3632 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3636 /* ITypeLib::GetTypeComp
3638 * Enables a client compiler to bind to a library's types, variables,
3639 * constants, and global functions.
3642 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3644 ITypeComp **ppTComp)
3646 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3648 TRACE("(%p)->(%p)\n",This,ppTComp);
3649 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3650 ITypeComp_AddRef(*ppTComp);
3655 /* ITypeLib::GetDocumentation
3657 * Retrieves the library's documentation string, the complete Help file name
3658 * and path, and the context identifier for the library Help topic in the Help
3661 * On a successful return all non-null BSTR pointers will have been set,
3664 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3668 BSTR *pBstrDocString,
3669 DWORD *pdwHelpContext,
3670 BSTR *pBstrHelpFile)
3672 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3674 HRESULT result = E_INVALIDARG;
3679 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3681 pBstrName, pBstrDocString,
3682 pdwHelpContext, pBstrHelpFile);
3686 /* documentation for the typelib */
3690 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3696 if (This->DocString)
3697 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3698 else if (This->Name)
3699 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3701 *pBstrDocString = NULL;
3705 *pdwHelpContext = This->dwHelpContext;
3710 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3712 *pBstrHelpFile = NULL;
3719 /* for a typeinfo */
3720 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3722 if(SUCCEEDED(result))
3724 result = ITypeInfo_GetDocumentation(pTInfo,
3728 pdwHelpContext, pBstrHelpFile);
3730 ITypeInfo_Release(pTInfo);
3735 if (pBstrDocString) SysFreeString (*pBstrDocString);
3737 if (pBstrName) SysFreeString (*pBstrName);
3739 return STG_E_INSUFFICIENTMEMORY;
3744 * Indicates whether a passed-in string contains the name of a type or member
3745 * described in the library.
3748 static HRESULT WINAPI ITypeLib2_fnIsName(
3754 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3755 ITypeInfoImpl *pTInfo;
3756 TLBFuncDesc *pFInfo;
3759 UINT nNameBufLen = SysStringLen(szNameBuf);
3761 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3765 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3766 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3767 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3768 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3769 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3770 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3771 goto ITypeLib2_fnIsName_exit;
3773 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3774 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3779 ITypeLib2_fnIsName_exit:
3780 TRACE("(%p)slow! search for %s: %s found!\n", This,
3781 debugstr_w(szNameBuf), *pfName?"NOT":"");
3786 /* ITypeLib::FindName
3788 * Finds occurrences of a type description in a type library. This may be used
3789 * to quickly verify that a name exists in a type library.
3792 static HRESULT WINAPI ITypeLib2_fnFindName(
3796 ITypeInfo **ppTInfo,
3800 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3801 ITypeInfoImpl *pTInfo;
3802 TLBFuncDesc *pFInfo;
3806 UINT nNameBufLen = SysStringLen(szNameBuf);
3808 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3809 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3810 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3811 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3812 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3813 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3814 goto ITypeLib2_fnFindName_exit;
3816 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3817 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3819 ITypeLib2_fnFindName_exit:
3820 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3821 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3824 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3825 This, *pcFound, debugstr_w(szNameBuf), j);
3832 /* ITypeLib::ReleaseTLibAttr
3834 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3837 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3839 TLIBATTR *pTLibAttr)
3841 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3842 TRACE("freeing (%p)\n",This);
3843 HeapFree(GetProcessHeap(),0,pTLibAttr);
3847 /* ITypeLib2::GetCustData
3849 * gets the custom data
3851 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3856 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3857 TLBCustData *pCData;
3859 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3861 if( IsEqualIID(guid, &pCData->guid)) break;
3864 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3868 VariantInit( pVarVal);
3869 VariantCopy( pVarVal, &pCData->data);
3872 return E_INVALIDARG; /* FIXME: correct? */
3875 /* ITypeLib2::GetLibStatistics
3877 * Returns statistics about a type library that are required for efficient
3878 * sizing of hash tables.
3881 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3883 ULONG *pcUniqueNames,
3884 ULONG *pcchUniqueNames)
3886 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3888 FIXME("(%p): stub!\n", This);
3890 if(pcUniqueNames) *pcUniqueNames=1;
3891 if(pcchUniqueNames) *pcchUniqueNames=1;
3895 /* ITypeLib2::GetDocumentation2
3897 * Retrieves the library's documentation string, the complete Help file name
3898 * and path, the localization context to use, and the context ID for the
3899 * library Help topic in the Help file.
3902 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3906 BSTR *pbstrHelpString,
3907 DWORD *pdwHelpStringContext,
3908 BSTR *pbstrHelpStringDll)
3910 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3914 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3916 /* the help string should be obtained from the helpstringdll,
3917 * using the _DLLGetDocumentation function, based on the supplied
3918 * lcid. Nice to do sometime...
3922 /* documentation for the typelib */
3924 *pbstrHelpString=SysAllocString(This->DocString);
3925 if(pdwHelpStringContext)
3926 *pdwHelpStringContext=This->dwHelpContext;
3927 if(pbstrHelpStringDll)
3928 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3934 /* for a typeinfo */
3935 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3937 if(SUCCEEDED(result))
3939 ITypeInfo2 * pTInfo2;
3940 result = ITypeInfo_QueryInterface(pTInfo,
3942 (LPVOID*) &pTInfo2);
3944 if(SUCCEEDED(result))
3946 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3950 pdwHelpStringContext,
3951 pbstrHelpStringDll);
3953 ITypeInfo2_Release(pTInfo2);
3956 ITypeInfo_Release(pTInfo);
3962 /* ITypeLib2::GetAllCustData
3964 * Gets all custom data items for the library.
3967 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3969 CUSTDATA *pCustData)
3971 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3972 TLBCustData *pCData;
3974 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3975 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3976 if(pCustData->prgCustData ){
3977 pCustData->cCustData=This->ctCustData;
3978 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3979 pCustData->prgCustData[i].guid=pCData->guid;
3980 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3983 ERR(" OUT OF MEMORY! \n");
3984 return E_OUTOFMEMORY;
3989 static ITypeLib2Vtbl tlbvt = {
3990 ITypeLib2_fnQueryInterface,
3992 ITypeLib2_fnRelease,
3993 ITypeLib2_fnGetTypeInfoCount,
3994 ITypeLib2_fnGetTypeInfo,
3995 ITypeLib2_fnGetTypeInfoType,
3996 ITypeLib2_fnGetTypeInfoOfGuid,
3997 ITypeLib2_fnGetLibAttr,
3998 ITypeLib2_fnGetTypeComp,
3999 ITypeLib2_fnGetDocumentation,
4001 ITypeLib2_fnFindName,
4002 ITypeLib2_fnReleaseTLibAttr,
4004 ITypeLib2_fnGetCustData,
4005 ITypeLib2_fnGetLibStatistics,
4006 ITypeLib2_fnGetDocumentation2,
4007 ITypeLib2_fnGetAllCustData
4011 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4013 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4015 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
4018 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4020 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4022 return ITypeInfo_AddRef((ITypeInfo *)This);
4025 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4027 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4029 return ITypeInfo_Release((ITypeInfo *)This);
4032 static HRESULT WINAPI ITypeLibComp_fnBind(
4037 ITypeInfo ** ppTInfo,
4038 DESCKIND * pDescKind,
4041 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4045 static HRESULT WINAPI ITypeLibComp_fnBindType(
4049 ITypeInfo ** ppTInfo,
4050 ITypeComp ** ppTComp)
4052 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4056 static ITypeCompVtbl tlbtcvt =
4059 ITypeLibComp_fnQueryInterface,
4060 ITypeLibComp_fnAddRef,
4061 ITypeLibComp_fnRelease,
4063 ITypeLibComp_fnBind,
4064 ITypeLibComp_fnBindType
4067 /*================== ITypeInfo(2) Methods ===================================*/
4068 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4070 ITypeInfoImpl * pTypeInfoImpl;
4072 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4075 pTypeInfoImpl->lpVtbl = &tinfvt;
4076 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4077 pTypeInfoImpl->ref=1;
4079 TRACE("(%p)\n", pTypeInfoImpl);
4080 return (ITypeInfo2*) pTypeInfoImpl;
4083 /* ITypeInfo::QueryInterface
4085 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4090 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4092 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4095 if(IsEqualIID(riid, &IID_IUnknown) ||
4096 IsEqualIID(riid,&IID_ITypeInfo)||
4097 IsEqualIID(riid,&IID_ITypeInfo2))
4101 ITypeInfo_AddRef(iface);
4102 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4105 TRACE("-- Interface: E_NOINTERFACE\n");
4106 return E_NOINTERFACE;
4109 /* ITypeInfo::AddRef
4111 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4113 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4116 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4118 TRACE("(%p)->ref is %u\n",This, This->ref);
4122 /* ITypeInfo::Release
4124 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4126 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4130 TRACE("(%p)->(%u)\n",This, This->ref);
4133 /* We don't release ITypeLib when ref=0 becouse
4134 it means that funtion is called by ITypeLi2_Release */
4135 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4137 FIXME("destroy child objects\n");
4139 TRACE("destroying ITypeInfo(%p)\n",This);
4142 SysFreeString(This->Name);
4146 if (This->DocString)
4148 SysFreeString(This->DocString);
4149 This->DocString = 0;
4154 ITypeInfo_Release((ITypeInfo*)This->next);
4157 HeapFree(GetProcessHeap(),0,This);
4163 /* ITypeInfo::GetTypeAttr
4165 * Retrieves a TYPEATTR structure that contains the attributes of the type
4169 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4170 LPTYPEATTR *ppTypeAttr)
4172 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4173 TRACE("(%p)\n",This);
4174 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr));
4175 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4177 if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */
4178 copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias);
4180 if((*ppTypeAttr)->typekind == TKIND_DISPATCH && (*ppTypeAttr)->wTypeFlags & TYPEFLAG_FDUAL) {
4181 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4183 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4184 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4189 /* ITypeInfo::GetTypeComp
4191 * Retrieves the ITypeComp interface for the type description, which enables a
4192 * client compiler to bind to the type description's members.
4195 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4196 ITypeComp * *ppTComp)
4198 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4200 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4202 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4203 ITypeComp_AddRef(*ppTComp);
4207 /* ITypeInfo::GetFuncDesc
4209 * Retrieves the FUNCDESC structure that contains information about a
4210 * specified function.
4213 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4214 LPFUNCDESC *ppFuncDesc)
4216 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4218 TLBFuncDesc * pFDesc;
4219 TRACE("(%p) index %d\n", This, index);
4220 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4223 /* FIXME: must do a copy here */
4224 *ppFuncDesc=&pFDesc->funcdesc;
4227 return E_INVALIDARG;
4230 /* ITypeInfo::GetVarDesc
4232 * Retrieves a VARDESC structure that describes the specified variable.
4235 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4236 LPVARDESC *ppVarDesc)
4238 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4240 TLBVarDesc * pVDesc;
4241 TRACE("(%p) index %d\n", This, index);
4242 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4245 /* FIXME: must do a copy here */
4246 *ppVarDesc=&pVDesc->vardesc;
4249 return E_INVALIDARG;
4252 /* ITypeInfo_GetNames
4254 * Retrieves the variable with the specified member ID (or the name of the
4255 * property or method and its parameters) that correspond to the specified
4258 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4259 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4261 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4262 TLBFuncDesc * pFDesc;
4263 TLBVarDesc * pVDesc;
4265 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4266 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4269 /* function found, now return function and parameter names */
4270 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4273 *rgBstrNames=SysAllocString(pFDesc->Name);
4275 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4281 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4284 *rgBstrNames=SysAllocString(pVDesc->Name);
4289 if(This->TypeAttr.cImplTypes &&
4290 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4291 /* recursive search */
4294 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4296 if(SUCCEEDED(result))
4298 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4299 ITypeInfo_Release(pTInfo);
4302 WARN("Could not search inherited interface!\n");
4306 WARN("no names found\n");
4309 return TYPE_E_ELEMENTNOTFOUND;
4316 /* ITypeInfo::GetRefTypeOfImplType
4318 * If a type description describes a COM class, it retrieves the type
4319 * description of the implemented interface types. For an interface,
4320 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4324 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4329 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4331 TLBImplType *pImpl = This->impltypelist;
4333 TRACE("(%p) index %d\n", This, index);
4334 if (TRACE_ON(ole)) dump_TypeInfo(This);
4338 /* only valid on dual interfaces;
4339 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4341 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4343 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4344 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4350 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4351 *pRefType = pImpl->hRef;
4356 /* get element n from linked list */
4357 for(i=0; pImpl && i<index; i++)
4359 pImpl = pImpl->next;
4362 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4364 *pRefType = pImpl->hRef;
4366 TRACE("-- 0x%08lx\n", pImpl->hRef );
4373 /* ITypeInfo::GetImplTypeFlags
4375 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4376 * or base interface in a type description.
4378 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4379 UINT index, INT *pImplTypeFlags)
4381 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4385 TRACE("(%p) index %d\n", This, index);
4386 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4387 i++, pImpl=pImpl->next)
4389 if(i==index && pImpl){
4390 *pImplTypeFlags=pImpl->implflags;
4394 return TYPE_E_ELEMENTNOTFOUND;
4398 * Maps between member names and member IDs, and parameter names and
4401 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4402 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4404 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4405 TLBFuncDesc * pFDesc;
4406 TLBVarDesc * pVDesc;
4409 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4411 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4413 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4414 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4415 for(i=1; i < cNames; i++){
4416 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4417 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4419 if( j<pFDesc->funcdesc.cParams)
4422 ret=DISP_E_UNKNOWNNAME;
4427 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4428 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4429 if(cNames) *pMemId=pVDesc->vardesc.memid;
4433 /* not found, see if this is and interface with an inheritance */
4434 if(This->TypeAttr.cImplTypes &&
4435 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4436 /* recursive search */
4438 ret=ITypeInfo_GetRefTypeInfo(iface,
4439 This->impltypelist->hRef, &pTInfo);
4441 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4442 ITypeInfo_Release(pTInfo);
4445 WARN("Could not search inherited interface!\n");
4447 WARN("no names found\n");
4448 return DISP_E_UNKNOWNNAME;
4451 /* ITypeInfo::Invoke
4453 * Invokes a method, or accesses a property of an object, that implements the
4454 * interface described by the type description.
4457 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4460 if (TRACE_ON(ole)) {
4462 TRACE("Calling %p(",func);
4463 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4475 res = func(args[0]);
4478 res = func(args[0],args[1]);
4481 res = func(args[0],args[1],args[2]);
4484 res = func(args[0],args[1],args[2],args[3]);
4487 res = func(args[0],args[1],args[2],args[3],args[4]);
4490 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4493 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4496 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4499 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4502 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4505 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4508 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4514 FIXME("unsupported calling convention %d\n",callconv);
4518 TRACE("returns %08lx\n",res);
4522 extern int _argsize(DWORD vt);
4524 /****************************************************************************
4525 * Helper functions for Dispcall / Invoke, which copies one variant
4526 * with target type onto the argument stack.
4529 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4530 DWORD *argpos, VARIANT *arg, VARTYPE vt
4532 UINT arglen = _argsize(vt)*sizeof(DWORD);
4536 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4537 memcpy(argpos,&arg,sizeof(void*));
4541 if (V_VT(arg) == vt) {
4542 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4546 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4547 memcpy(argpos, &V_UNION(arg,parray), sizeof(SAFEARRAY*));
4551 if (vt == VT_VARIANT) {
4552 memcpy(argpos, arg, arglen);
4555 /* Deref BYREF vars if there is need */
4556 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4557 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4560 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4561 /* in this context, if the type lib specifies IUnknown*, giving an
4562 IDispatch* is correct; so, don't invoke VariantChangeType */
4563 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4566 if ((vt == VT_PTR) && tdesc)
4567 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4569 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4570 ITypeInfo *tinfo2 = NULL;
4571 TYPEATTR *tattr = NULL;
4574 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4576 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4577 "while coercing from vt 0x%x. Copying 4 byte.\n",
4578 tdesc->u.hreftype,V_VT(arg));
4579 memcpy(argpos, &V_UNION(arg,lVal), 4);
4582 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4585 ERR("GetTypeAttr failed\n");
4586 ITypeInfo_Release(tinfo2);
4589 switch (tattr->typekind) {
4591 switch ( V_VT( arg ) ) {
4593 *argpos = V_UNION(arg,iVal);
4597 memcpy(argpos, &V_UNION(arg,lVal), 4);
4601 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4608 tdesc = &(tattr->tdescAlias);
4609 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4612 case TKIND_INTERFACE:
4613 if (V_VT(arg) == VT_DISPATCH) {
4615 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4616 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4620 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),
4621 &IID_IDispatch,(LPVOID*)&disp);
4622 if (SUCCEEDED(hres)) {
4623 memcpy(argpos,&disp,4);
4624 IUnknown_Release(V_UNION(arg,pdispVal));
4628 FIXME("Failed to query IDispatch interface from %s while "
4629 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4633 if (V_VT(arg) == VT_UNKNOWN) {
4634 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4638 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4639 V_VT(arg),debugstr_guid(&(tattr->guid)));
4643 case TKIND_DISPATCH:
4644 if (V_VT(arg) == VT_DISPATCH) {
4645 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4650 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4654 FIXME("TKIND_RECORD unhandled.\n");
4658 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4662 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4663 ITypeInfo_Release(tinfo2);
4669 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4670 memcpy(argpos,&V_UNION(&va,lVal), arglen);
4671 FIXME("Should not use VariantChangeType here."
4672 " (conversion from 0x%x -> 0x%x) %08lx\n",
4673 V_VT(arg), vt, *argpos
4677 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4681 /***********************************************************************
4682 * DispCallFunc (OLEAUT32.@)
4686 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4687 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4689 int i, argsize, argspos;
4693 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4694 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4696 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4697 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4699 for (i=0;i<cActuals;i++) {
4700 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4701 dump_Variant(prgpvarg[i]);
4702 argsize += _argsize(prgvt[i]);
4704 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4705 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4707 for (i=0;i<cActuals;i++) {
4708 VARIANT *arg = prgpvarg[i];
4709 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4710 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4711 argspos += _argsize(prgvt[i]);
4714 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4716 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4721 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4722 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4723 FIXME("Method returned %lx\n",hres);
4725 HeapFree(GetProcessHeap(),0,args);
4729 static HRESULT WINAPI ITypeInfo_fnInvoke(
4734 DISPPARAMS *pDispParams,
4735 VARIANT *pVarResult,
4736 EXCEPINFO *pExcepInfo,
4739 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4741 unsigned int func_index, var_index;
4745 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4746 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4748 dump_DispParms(pDispParams);
4750 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4751 if (SUCCEEDED(hres)) {
4752 FUNCDESC *func_desc;
4754 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4755 if(FAILED(hres)) return hres;
4757 switch (func_desc->funckind) {
4758 case FUNC_PUREVIRTUAL:
4759 case FUNC_VIRTUAL: {
4761 int numargs, numargs2, argspos, args2pos;
4762 DWORD *args , *args2;
4763 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4764 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4767 numargs = 1; numargs2 = 0;
4768 for (i = 0; i < func_desc->cParams; i++) {
4769 if (i<pDispParams->cArgs)
4770 numargs += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4772 numargs += 1; /* sizeof(lpvoid) */
4773 numargs2 += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4777 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4778 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4780 args[0] = (DWORD)pIUnk;
4781 argspos = 1; args2pos = 0;
4782 for (i = 0; i < func_desc->cParams; i++) {
4783 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4784 if (i<pDispParams->cArgs) {
4785 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4786 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4787 USHORT paramFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
4788 if (paramFlags & PARAMFLAG_FOPT) {
4789 if(i < func_desc->cParams - func_desc->cParamsOpt)
4790 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4791 if(V_VT(arg) == VT_EMPTY
4792 || ((V_VT(arg) & VT_BYREF) && !V_BYREF(arg))) {
4793 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4794 How to determine it? */
4796 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4797 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4798 V_VT(arg) = VT_ERROR;
4799 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4800 arglen = _argsize(VT_ERROR);
4803 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4804 if (FAILED(hres)) goto func_fail;
4806 } else if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) {
4807 VARIANT *arg = &rgvarg[i];
4808 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4809 if(i < func_desc->cParams - func_desc->cParamsOpt)
4810 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4811 if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4812 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4813 V_VT(arg) = VT_ERROR;
4814 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4815 arglen = _argsize(VT_ERROR);
4816 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4817 if (FAILED(hres)) goto func_fail;
4820 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i].tdesc);
4821 if (tdesc->vt != VT_PTR)
4822 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4823 /*FIXME: give pointers for the rest, so propertyget works*/
4824 args[argspos] = (DWORD)&args2[args2pos];
4826 /* If pointer to variant, pass reference it. */
4827 if ((tdesc->vt == VT_PTR) &&
4828 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4831 args[argspos]= (DWORD)pVarResult;
4836 if (func_desc->cParamsOpt < 0)
4837 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
4839 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
4840 func_desc->callconv,
4845 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4847 for (i = 0; i < func_desc->cParams - pDispParams->cArgs; i++) {
4848 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4849 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i + pDispParams->cArgs].tdesc);
4851 i4_tdesc.vt = VT_I4;
4853 /* If we are a pointer to a variant, we are done already */
4854 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4857 VariantInit(pVarResult);
4858 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4860 if (tdesc->vt == VT_PTR)
4861 tdesc = tdesc->u.lptdesc;
4862 if (tdesc->vt == VT_USERDEFINED) {
4866 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4868 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4871 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4872 switch (tattr->typekind) {
4874 /* force the return type to be VT_I4 */
4878 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4879 tdesc = &(tattr->tdescAlias);
4882 case TKIND_INTERFACE:
4883 FIXME("TKIND_INTERFACE unhandled.\n");
4885 case TKIND_DISPATCH:
4886 FIXME("TKIND_DISPATCH unhandled.\n");
4889 FIXME("TKIND_RECORD unhandled.\n");
4892 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4895 ITypeInfo_Release(tinfo2);
4897 V_VT(pVarResult) = tdesc->vt;
4899 /* HACK: VB5 likes this.
4900 * I do not know why. There is 1 example in MSDN which uses
4901 * this which appears broken (mixes int vals and
4904 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4905 V_VT(pVarResult) = VT_DISPATCH;
4906 TRACE("storing into variant:\n");
4907 dump_Variant(pVarResult);
4912 HeapFree(GetProcessHeap(), 0, rgvarg);
4913 HeapFree(GetProcessHeap(),0,args2);
4914 HeapFree(GetProcessHeap(),0,args);
4917 case FUNC_DISPATCH: {
4920 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4921 if (SUCCEEDED(hres)) {
4922 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4923 hres = IDispatch_Invoke(
4924 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4925 pVarResult,pExcepInfo,pArgErr
4928 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
4929 IDispatch_Release(disp);
4931 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4935 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
4940 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
4943 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
4946 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
4947 if(FAILED(hres)) return hres;
4949 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
4950 dump_VARDESC(var_desc);
4951 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
4955 /* not found, look for it in inherited interfaces */
4956 ITypeInfo2_GetTypeKind(iface, &type_kind);
4957 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
4959 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
4960 /* recursive search */
4962 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
4963 if(SUCCEEDED(hres)){
4964 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4965 ITypeInfo_Release(pTInfo);
4968 WARN("Could not search inherited interface!\n");
4971 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
4972 return DISP_E_MEMBERNOTFOUND;
4975 /* ITypeInfo::GetDocumentation
4977 * Retrieves the documentation string, the complete Help file name and path,
4978 * and the context ID for the Help topic for a specified type description.
4980 * (Can be tested by the Visual Basic Editor in Word for instance.)
4982 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4983 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4984 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4986 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4987 TLBFuncDesc * pFDesc;
4988 TLBVarDesc * pVDesc;
4989 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4990 " HelpContext(%p) HelpFile(%p)\n",
4991 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4992 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4994 *pBstrName=SysAllocString(This->Name);
4996 *pBstrDocString=SysAllocString(This->DocString);
4998 *pdwHelpContext=This->dwHelpContext;
5000 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5002 }else {/* for a member */
5003 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5004 if(pFDesc->funcdesc.memid==memid){
5006 *pBstrName = SysAllocString(pFDesc->Name);
5008 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5010 *pdwHelpContext=pFDesc->helpcontext;
5013 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5014 if(pVDesc->vardesc.memid==memid){
5016 *pBstrName = SysAllocString(pVDesc->Name);
5018 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5020 *pdwHelpContext=pVDesc->HelpContext;
5024 return TYPE_E_ELEMENTNOTFOUND;
5027 /* ITypeInfo::GetDllEntry
5029 * Retrieves a description or specification of an entry point for a function
5032 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5033 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5036 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5037 TLBFuncDesc *pFDesc;
5039 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5041 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5042 if(pFDesc->funcdesc.memid==memid){
5043 dump_TypeInfo(This);
5044 dump_TLBFuncDescOne(pFDesc);
5046 /* FIXME: This is wrong, but how do you find that out? */
5048 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5049 *pBstrDllName = SysAllocString(oleaut32W);
5052 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5054 *pBstrName = SysAllocString(pFDesc->Entry);
5062 *pwOrdinal = (DWORD)pFDesc->Entry;
5068 /* ITypeInfo::GetRefTypeInfo
5070 * If a type description references other type descriptions, it retrieves
5071 * the referenced type descriptions.
5073 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5076 ITypeInfo **ppTInfo)
5078 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5079 HRESULT result = E_FAIL;
5082 if (hRefType == -1 &&
5083 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5084 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5086 /* when we meet a DUAL dispinterface, we must create the interface
5089 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5092 /* the interface version contains the same information as the dispinterface
5093 * copy the contents of the structs.
5095 *pTypeInfoImpl = *This;
5096 pTypeInfoImpl->ref = 1;
5098 /* change the type to interface */
5099 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5101 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5103 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5108 TLBRefType *pRefType;
5109 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5110 if(pRefType->reference == hRefType)
5114 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5115 if(pRefType && hRefType != -1) {
5116 ITypeLib *pTLib = NULL;
5118 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5120 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5122 if(pRefType->pImpTLInfo->pImpTypeLib) {
5123 TRACE("typeinfo in imported typelib that is already loaded\n");
5124 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5125 ITypeLib2_AddRef((ITypeLib*) pTLib);
5128 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5129 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5130 pRefType->pImpTLInfo->wVersionMajor,
5131 pRefType->pImpTLInfo->wVersionMinor,
5132 pRefType->pImpTLInfo->lcid,
5135 if(!SUCCEEDED(result)) {
5136 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5137 result=LoadTypeLib(libnam, &pTLib);
5138 SysFreeString(libnam);
5140 if(SUCCEEDED(result)) {
5141 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5142 ITypeLib2_AddRef(pTLib);
5146 if(SUCCEEDED(result)) {
5147 if(pRefType->index == TLB_REF_USE_GUID)
5148 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5152 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5156 ITypeLib2_Release(pTLib);
5160 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5161 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5165 /* ITypeInfo::AddressOfMember
5167 * Retrieves the addresses of static functions or variables, such as those
5170 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5171 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5173 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5174 FIXME("(%p) stub!\n", This);
5178 /* ITypeInfo::CreateInstance
5180 * Creates a new instance of a type that describes a component object class
5183 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5184 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5186 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5187 FIXME("(%p) stub!\n", This);
5191 /* ITypeInfo::GetMops
5193 * Retrieves marshalling information.
5195 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5198 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5199 FIXME("(%p) stub!\n", This);
5203 /* ITypeInfo::GetContainingTypeLib
5205 * Retrieves the containing type library and the index of the type description
5206 * within that type library.
5208 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5209 ITypeLib * *ppTLib, UINT *pIndex)
5211 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5213 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5215 *pIndex=This->index;
5216 TRACE("returning pIndex=%d\n", *pIndex);
5220 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5221 ITypeLib2_AddRef(*ppTLib);
5222 TRACE("returning ppTLib=%p\n", *ppTLib);
5228 /* ITypeInfo::ReleaseTypeAttr
5230 * Releases a TYPEATTR previously returned by GetTypeAttr.
5233 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5234 TYPEATTR* pTypeAttr)
5236 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5237 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5238 if(This->TypeAttr.typekind == TKIND_ALIAS)
5239 free_deep_typedesc(&pTypeAttr->tdescAlias);
5240 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5243 /* ITypeInfo::ReleaseFuncDesc
5245 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5247 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5249 FUNCDESC *pFuncDesc)
5251 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5252 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5255 /* ITypeInfo::ReleaseVarDesc
5257 * Releases a VARDESC previously returned by GetVarDesc.
5259 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5262 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5263 TRACE("(%p)->(%p)\n", This, pVarDesc);
5266 /* ITypeInfo2::GetTypeKind
5268 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5271 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5272 TYPEKIND *pTypeKind)
5274 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5275 *pTypeKind=This->TypeAttr.typekind;
5276 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5280 /* ITypeInfo2::GetTypeFlags
5282 * Returns the type flags without any allocations. This returns a DWORD type
5283 * flag, which expands the type flags without growing the TYPEATTR (type
5287 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5289 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5290 *pTypeFlags=This->TypeAttr.wTypeFlags;
5291 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5295 /* ITypeInfo2::GetFuncIndexOfMemId
5296 * Binds to a specific member based on a known DISPID, where the member name
5297 * is not known (for example, when binding to a default member).
5300 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5301 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5303 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5304 TLBFuncDesc *pFuncInfo;
5308 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5309 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5315 result = TYPE_E_ELEMENTNOTFOUND;
5317 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5318 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5322 /* TypeInfo2::GetVarIndexOfMemId
5324 * Binds to a specific member based on a known DISPID, where the member name
5325 * is not known (for example, when binding to a default member).
5328 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5329 MEMBERID memid, UINT *pVarIndex)
5331 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5332 TLBVarDesc *pVarInfo;
5335 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5336 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5342 result = TYPE_E_ELEMENTNOTFOUND;
5344 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5345 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5349 /* ITypeInfo2::GetCustData
5351 * Gets the custom data
5353 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5358 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5359 TLBCustData *pCData;
5361 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5362 if( IsEqualIID(guid, &pCData->guid)) break;
5364 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5368 VariantInit( pVarVal);
5369 VariantCopy( pVarVal, &pCData->data);
5372 return E_INVALIDARG; /* FIXME: correct? */
5375 /* ITypeInfo2::GetFuncCustData
5377 * Gets the custom data
5379 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5385 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5386 TLBCustData *pCData=NULL;
5387 TLBFuncDesc * pFDesc;
5389 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5390 pFDesc=pFDesc->next);
5393 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5394 if( IsEqualIID(guid, &pCData->guid)) break;
5396 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5399 VariantInit( pVarVal);
5400 VariantCopy( pVarVal, &pCData->data);
5403 return E_INVALIDARG; /* FIXME: correct? */
5406 /* ITypeInfo2::GetParamCustData
5408 * Gets the custom data
5410 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5417 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5418 TLBCustData *pCData=NULL;
5419 TLBFuncDesc * pFDesc;
5422 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5424 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5425 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5426 pCData = pCData->next)
5427 if( IsEqualIID(guid, &pCData->guid)) break;
5429 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5433 VariantInit( pVarVal);
5434 VariantCopy( pVarVal, &pCData->data);
5437 return E_INVALIDARG; /* FIXME: correct? */
5440 /* ITypeInfo2::GetVarCustData
5442 * Gets the custom data
5444 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5450 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5451 TLBCustData *pCData=NULL;
5452 TLBVarDesc * pVDesc;
5455 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5459 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5461 if( IsEqualIID(guid, &pCData->guid)) break;
5465 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5469 VariantInit( pVarVal);
5470 VariantCopy( pVarVal, &pCData->data);
5473 return E_INVALIDARG; /* FIXME: correct? */
5476 /* ITypeInfo2::GetImplCustData
5478 * Gets the custom data
5480 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5486 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5487 TLBCustData *pCData=NULL;
5488 TLBImplType * pRDesc;
5491 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5495 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5497 if( IsEqualIID(guid, &pCData->guid)) break;
5501 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5505 VariantInit( pVarVal);
5506 VariantCopy( pVarVal, &pCData->data);
5509 return E_INVALIDARG; /* FIXME: correct? */
5512 /* ITypeInfo2::GetDocumentation2
5514 * Retrieves the documentation string, the complete Help file name and path,
5515 * the localization context to use, and the context ID for the library Help
5516 * topic in the Help file.
5519 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5523 BSTR *pbstrHelpString,
5524 DWORD *pdwHelpStringContext,
5525 BSTR *pbstrHelpStringDll)
5527 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5528 TLBFuncDesc * pFDesc;
5529 TLBVarDesc * pVDesc;
5530 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5531 "HelpStringContext(%p) HelpStringDll(%p)\n",
5532 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5533 pbstrHelpStringDll );
5534 /* the help string should be obtained from the helpstringdll,
5535 * using the _DLLGetDocumentation function, based on the supplied
5536 * lcid. Nice to do sometime...
5538 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5540 *pbstrHelpString=SysAllocString(This->Name);
5541 if(pdwHelpStringContext)
5542 *pdwHelpStringContext=This->dwHelpStringContext;
5543 if(pbstrHelpStringDll)
5544 *pbstrHelpStringDll=
5545 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5547 }else {/* for a member */
5548 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5549 if(pFDesc->funcdesc.memid==memid){
5551 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5552 if(pdwHelpStringContext)
5553 *pdwHelpStringContext=pFDesc->HelpStringContext;
5554 if(pbstrHelpStringDll)
5555 *pbstrHelpStringDll=
5556 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5559 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5560 if(pVDesc->vardesc.memid==memid){
5562 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5563 if(pdwHelpStringContext)
5564 *pdwHelpStringContext=pVDesc->HelpStringContext;
5565 if(pbstrHelpStringDll)
5566 *pbstrHelpStringDll=
5567 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5571 return TYPE_E_ELEMENTNOTFOUND;
5574 /* ITypeInfo2::GetAllCustData
5576 * Gets all custom data items for the Type info.
5579 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5581 CUSTDATA *pCustData)
5583 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5584 TLBCustData *pCData;
5587 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5589 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5590 if(pCustData->prgCustData ){
5591 pCustData->cCustData=This->ctCustData;
5592 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5593 pCustData->prgCustData[i].guid=pCData->guid;
5594 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5597 ERR(" OUT OF MEMORY! \n");
5598 return E_OUTOFMEMORY;
5603 /* ITypeInfo2::GetAllFuncCustData
5605 * Gets all custom data items for the specified Function
5608 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5611 CUSTDATA *pCustData)
5613 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5614 TLBCustData *pCData;
5615 TLBFuncDesc * pFDesc;
5617 TRACE("(%p) index %d\n", This, index);
5618 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5619 pFDesc=pFDesc->next)
5622 pCustData->prgCustData =
5623 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5624 if(pCustData->prgCustData ){
5625 pCustData->cCustData=pFDesc->ctCustData;
5626 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5627 pCData = pCData->next){
5628 pCustData->prgCustData[i].guid=pCData->guid;
5629 VariantCopy(& pCustData->prgCustData[i].varValue,
5633 ERR(" OUT OF MEMORY! \n");
5634 return E_OUTOFMEMORY;
5638 return TYPE_E_ELEMENTNOTFOUND;
5641 /* ITypeInfo2::GetAllParamCustData
5643 * Gets all custom data items for the Functions
5646 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5647 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5649 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5650 TLBCustData *pCData=NULL;
5651 TLBFuncDesc * pFDesc;
5653 TRACE("(%p) index %d\n", This, indexFunc);
5654 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5655 pFDesc=pFDesc->next)
5657 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5658 pCustData->prgCustData =
5659 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5660 sizeof(CUSTDATAITEM));
5661 if(pCustData->prgCustData ){
5662 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5663 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5664 pCData; i++, pCData = pCData->next){
5665 pCustData->prgCustData[i].guid=pCData->guid;
5666 VariantCopy(& pCustData->prgCustData[i].varValue,
5670 ERR(" OUT OF MEMORY! \n");
5671 return E_OUTOFMEMORY;
5675 return TYPE_E_ELEMENTNOTFOUND;
5678 /* ITypeInfo2::GetAllVarCustData
5680 * Gets all custom data items for the specified Variable
5683 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5684 UINT index, CUSTDATA *pCustData)
5686 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5687 TLBCustData *pCData;
5688 TLBVarDesc * pVDesc;
5690 TRACE("(%p) index %d\n", This, index);
5691 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5692 pVDesc=pVDesc->next)
5695 pCustData->prgCustData =
5696 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5697 if(pCustData->prgCustData ){
5698 pCustData->cCustData=pVDesc->ctCustData;
5699 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5700 pCData = pCData->next){
5701 pCustData->prgCustData[i].guid=pCData->guid;
5702 VariantCopy(& pCustData->prgCustData[i].varValue,
5706 ERR(" OUT OF MEMORY! \n");
5707 return E_OUTOFMEMORY;
5711 return TYPE_E_ELEMENTNOTFOUND;
5714 /* ITypeInfo2::GetAllImplCustData
5716 * Gets all custom data items for the specified implementation type
5719 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5722 CUSTDATA *pCustData)
5724 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5725 TLBCustData *pCData;
5726 TLBImplType * pRDesc;
5728 TRACE("(%p) index %d\n", This, index);
5729 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5730 pRDesc=pRDesc->next)
5733 pCustData->prgCustData =
5734 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5735 if(pCustData->prgCustData ){
5736 pCustData->cCustData=pRDesc->ctCustData;
5737 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5738 pCData = pCData->next){
5739 pCustData->prgCustData[i].guid=pCData->guid;
5740 VariantCopy(& pCustData->prgCustData[i].varValue,
5744 ERR(" OUT OF MEMORY! \n");
5745 return E_OUTOFMEMORY;
5749 return TYPE_E_ELEMENTNOTFOUND;
5752 static ITypeInfo2Vtbl tinfvt =
5755 ITypeInfo_fnQueryInterface,
5757 ITypeInfo_fnRelease,
5759 ITypeInfo_fnGetTypeAttr,
5760 ITypeInfo_fnGetTypeComp,
5761 ITypeInfo_fnGetFuncDesc,
5762 ITypeInfo_fnGetVarDesc,
5763 ITypeInfo_fnGetNames,
5764 ITypeInfo_fnGetRefTypeOfImplType,
5765 ITypeInfo_fnGetImplTypeFlags,
5766 ITypeInfo_fnGetIDsOfNames,
5768 ITypeInfo_fnGetDocumentation,
5769 ITypeInfo_fnGetDllEntry,
5770 ITypeInfo_fnGetRefTypeInfo,
5771 ITypeInfo_fnAddressOfMember,
5772 ITypeInfo_fnCreateInstance,
5773 ITypeInfo_fnGetMops,
5774 ITypeInfo_fnGetContainingTypeLib,
5775 ITypeInfo_fnReleaseTypeAttr,
5776 ITypeInfo_fnReleaseFuncDesc,
5777 ITypeInfo_fnReleaseVarDesc,
5779 ITypeInfo2_fnGetTypeKind,
5780 ITypeInfo2_fnGetTypeFlags,
5781 ITypeInfo2_fnGetFuncIndexOfMemId,
5782 ITypeInfo2_fnGetVarIndexOfMemId,
5783 ITypeInfo2_fnGetCustData,
5784 ITypeInfo2_fnGetFuncCustData,
5785 ITypeInfo2_fnGetParamCustData,
5786 ITypeInfo2_fnGetVarCustData,
5787 ITypeInfo2_fnGetImplTypeCustData,
5788 ITypeInfo2_fnGetDocumentation2,
5789 ITypeInfo2_fnGetAllCustData,
5790 ITypeInfo2_fnGetAllFuncCustData,
5791 ITypeInfo2_fnGetAllParamCustData,
5792 ITypeInfo2_fnGetAllVarCustData,
5793 ITypeInfo2_fnGetAllImplTypeCustData,
5796 /******************************************************************************
5797 * CreateDispTypeInfo [OLEAUT32.31]
5799 * Build type information for an object so it can be called through an
5800 * IDispatch interface.
5803 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5804 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5807 * This call allows an objects methods to be accessed through IDispatch, by
5808 * building an ITypeInfo object that IDispatch can use to call through.
5810 HRESULT WINAPI CreateDispTypeInfo(
5811 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5812 LCID lcid, /* [I] Locale Id */
5813 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5815 ITypeInfoImpl *pTIImpl;
5817 TLBFuncDesc **ppFuncDesc;
5819 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5820 pTIImpl->pTypeLib = NULL;
5822 pTIImpl->Name = NULL;
5823 pTIImpl->dwHelpContext = -1;
5824 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
5825 pTIImpl->TypeAttr.lcid = lcid;
5826 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
5827 pTIImpl->TypeAttr.wMajorVerNum = 0;
5828 pTIImpl->TypeAttr.wMinorVerNum = 0;
5829 pTIImpl->TypeAttr.cbAlignment = 2;
5830 pTIImpl->TypeAttr.cbSizeInstance = -1;
5831 pTIImpl->TypeAttr.cbSizeVft = -1;
5832 pTIImpl->TypeAttr.cFuncs = 0;
5833 pTIImpl->TypeAttr.cImplTypes = 1;
5834 pTIImpl->TypeAttr.cVars = 0;
5835 pTIImpl->TypeAttr.wTypeFlags = 0;
5837 ppFuncDesc = &pTIImpl->funclist;
5838 for(func = 0; func < pidata->cMembers; func++) {
5839 METHODDATA *md = pidata->pmethdata + func;
5840 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
5841 (*ppFuncDesc)->Name = SysAllocString(md->szName);
5842 (*ppFuncDesc)->funcdesc.memid = md->dispid;
5843 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
5844 (*ppFuncDesc)->funcdesc.callconv = md->cc;
5845 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
5846 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
5847 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
5848 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
5849 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
5850 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5851 md->cArgs * sizeof(ELEMDESC));
5852 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5853 md->cArgs * sizeof(TLBParDesc));
5854 for(param = 0; param < md->cArgs; param++) {
5855 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
5856 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
5858 ppFuncDesc = &(*ppFuncDesc)->next;
5860 *pptinfo = (ITypeInfo*)pTIImpl;
5865 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5867 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5869 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5872 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5874 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5876 return ITypeInfo_AddRef((ITypeInfo *)This);
5879 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5881 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5883 return ITypeInfo_Release((ITypeInfo *)This);
5886 static HRESULT WINAPI ITypeComp_fnBind(
5891 ITypeInfo ** ppTInfo,
5892 DESCKIND * pDescKind,
5895 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5896 TLBFuncDesc * pFDesc;
5897 TLBVarDesc * pVDesc;
5899 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5901 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5902 if (pFDesc->funcdesc.invkind & wFlags)
5903 if (!strcmpW(pFDesc->Name, szName)) {
5909 *pDescKind = DESCKIND_FUNCDESC;
5910 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5911 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5914 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5916 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5917 if (!strcmpW(pVDesc->Name, szName)) {
5918 *pDescKind = DESCKIND_VARDESC;
5919 pBindPtr->lpvardesc = &pVDesc->vardesc;
5920 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5926 /* not found, look for it in inherited interfaces */
5927 if (This->TypeAttr.cImplTypes &&
5928 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5929 /* recursive search */
5933 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5936 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5937 ITypeInfo_Release(pTInfo);
5941 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5942 ITypeComp_Release(pTComp);
5945 WARN("Could not search inherited interface!\n");
5947 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5948 *pDescKind = DESCKIND_NONE;
5949 pBindPtr->lpfuncdesc = NULL;
5951 return DISP_E_MEMBERNOTFOUND;
5954 static HRESULT WINAPI ITypeComp_fnBindType(
5958 ITypeInfo ** ppTInfo,
5959 ITypeComp ** ppTComp)
5961 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5963 /* strange behaviour (does nothing) but like the
5966 if (!ppTInfo || !ppTComp)
5975 static ITypeCompVtbl tcompvt =
5978 ITypeComp_fnQueryInterface,
5980 ITypeComp_fnRelease,
5983 ITypeComp_fnBindType