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"
78 #include "wine/debug.h"
81 WINE_DEFAULT_DEBUG_CHANNEL(ole);
82 WINE_DECLARE_DEBUG_CHANNEL(typelib);
84 /* The OLE Automation ProxyStub Interface Class (aka Typelib Marshaler) */
85 const GUID CLSID_PSOAInterface = { 0x00020424, 0, 0, { 0xC0, 0, 0, 0, 0, 0, 0, 0x46 } };
87 /****************************************************************************
90 * Takes p_iVal (which is in little endian) and returns it
91 * in the host machine's byte order.
93 #ifdef WORDS_BIGENDIAN
94 static WORD FromLEWord(WORD p_iVal)
96 return (((p_iVal & 0x00FF) << 8) |
97 ((p_iVal & 0xFF00) >> 8));
101 static DWORD FromLEDWord(DWORD p_iVal)
103 return (((p_iVal & 0x000000FF) << 24) |
104 ((p_iVal & 0x0000FF00) << 8) |
105 ((p_iVal & 0x00FF0000) >> 8) |
106 ((p_iVal & 0xFF000000) >> 24));
109 #define FromLEWord(X) (X)
110 #define FromLEDWord(X) (X)
114 /****************************************************************************
117 * Fix byte order in any structure if necessary
119 #ifdef WORDS_BIGENDIAN
120 static void FromLEWords(void *p_Val, int p_iSize)
124 p_iSize /= sizeof(WORD);
127 *Val = FromLEWord(*Val);
134 static void FromLEDWords(void *p_Val, int p_iSize)
138 p_iSize /= sizeof(DWORD);
141 *Val = FromLEDWord(*Val);
147 #define FromLEWords(X,Y) /*nothing*/
148 #define FromLEDWords(X,Y) /*nothing*/
151 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
152 /* buffer must be at least 60 characters long */
153 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
155 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
156 static const WCHAR VersionFormatW[] = {'\\','%','u','.','%','u',0};
158 memcpy( buffer, TypelibW, sizeof(TypelibW) );
159 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
160 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
164 /* get the path of an interface key, in the form "Interface\\<guid>" */
165 /* buffer must be at least 50 characters long */
166 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
168 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
170 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
171 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
175 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
176 /* buffer must be at least 16 characters long */
177 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
179 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
180 static const WCHAR win16W[] = {'w','i','n','1','6',0};
181 static const WCHAR win32W[] = {'w','i','n','3','2',0};
183 sprintfW( buffer, LcidFormatW, lcid );
186 case SYS_WIN16: strcatW( buffer, win16W ); break;
187 case SYS_WIN32: strcatW( buffer, win32W ); break;
189 TRACE("Typelib is for unsupported syskind %i\n", syskind);
196 /****************************************************************************
197 * QueryPathOfRegTypeLib [OLEAUT32.164]
202 QueryPathOfRegTypeLib(
203 REFGUID guid, /* [in] referenced guid */
204 WORD wMaj, /* [in] major version */
205 WORD wMin, /* [in] minor version */
206 LCID lcid, /* [in] locale id */
207 LPBSTR path ) /* [out] path of typelib */
213 WCHAR Path[MAX_PATH];
217 FIXME("(guid %p,%d,%d,0x%04lx,%p),stub!\n", guid, wMaj, wMin, lcid, path);
221 get_typelib_key( guid, wMaj, wMin, buffer );
223 if (RegOpenKeyW( HKEY_CLASSES_ROOT, buffer, &hkey ) != ERROR_SUCCESS)
225 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
231 DWORD dwPathLen = sizeof(Path);
233 get_lcid_subkey( myLCID, SYS_WIN32, buffer );
235 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
239 else if (myLCID == lcid)
241 /* try with sub-langid */
242 myLCID = SUBLANGID(lcid);
244 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
246 /* try with system langid */
256 *path = SysAllocString( Path );
264 /******************************************************************************
265 * CreateTypeLib [OLEAUT32.160] creates a typelib
271 HRESULT WINAPI CreateTypeLib(
272 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
274 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
277 /******************************************************************************
278 * LoadTypeLib [OLEAUT32.161]
279 * Loads and registers a type library
281 * Docs: OLECHAR FAR* szFile
282 * Docs: iTypeLib FAR* FAR* pptLib
288 int TLB_ReadTypeLib(LPCWSTR file, INT index, ITypeLib2 **ppTypelib);
290 HRESULT WINAPI LoadTypeLib(
291 const OLECHAR *szFile,/* [in] Name of file to load from */
292 ITypeLib * *pptLib) /* [out] Pointer to pointer to loaded type library */
295 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
298 /******************************************************************************
299 * LoadTypeLibEx [OLEAUT32.183]
300 * Loads and optionally registers a type library
306 HRESULT WINAPI LoadTypeLibEx(
307 LPCOLESTR szFile, /* [in] Name of file to load from */
308 REGKIND regkind, /* [in] Specify kind of registration */
309 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
311 WCHAR szPath[MAX_PATH+1], szFileCopy[MAX_PATH+1];
316 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
319 if(!SearchPathW(NULL,szFile,NULL,sizeof(szPath)/sizeof(WCHAR),szPath,
322 /* Look for a trailing '\\' followed by an index */
323 pIndexStr = strrchrW(szFile, '\\');
324 if(pIndexStr && pIndexStr != szFile && *++pIndexStr != '\0') {
325 index = atoiW(pIndexStr);
326 memcpy(szFileCopy, szFile,
327 (pIndexStr - szFile - 1) * sizeof(WCHAR));
328 szFileCopy[pIndexStr - szFile - 1] = '\0';
329 if(!SearchPathW(NULL,szFileCopy,NULL,sizeof(szPath)/sizeof(WCHAR),
331 return TYPE_E_CANTLOADLIBRARY;
332 if (GetFileAttributesW(szFileCopy) & FILE_ATTRIBUTE_DIRECTORY)
333 return TYPE_E_CANTLOADLIBRARY;
336 static const WCHAR stdole32tlb[] = { 's','t','d','o','l','e','3','2','.','t','l','b',0 };
339 lstrcpyW(tstpath,szFile);
341 for (i=0;i<strlenW(tstpath);i++) {
342 if (tstpath[i] == 's') {
343 if (!strcmpW(tstpath+i,stdole32tlb)) {
345 MESSAGE("**************************************************************************\n");
346 MESSAGE("You must copy a 'stdole32.tlb' file to your Windows\\System directory!\n");
347 MESSAGE("You can get one from a Windows installation, or look for the DCOM95 package\n");
348 MESSAGE("on the Microsoft Download Pages.\n");
349 MESSAGE("**************************************************************************\n");
354 FIXME("Wanted to load %s as typelib, but file was not found.\n",debugstr_w(szFile));
355 return TYPE_E_CANTLOADLIBRARY;
359 TRACE("File %s index %d\n", debugstr_w(szPath), index);
361 res = TLB_ReadTypeLib(szPath, index, (ITypeLib2**)pptLib);
366 case REGKIND_DEFAULT:
367 /* don't register typelibs supplied with full path. Experimentation confirms the following */
369 ((szFile[0] == '\\') && (szFile[1] == '\\')) ||
370 (szFile[0] && (szFile[1] == ':'))) break;
371 /* else fall-through */
373 case REGKIND_REGISTER:
374 if (!SUCCEEDED(res = RegisterTypeLib(*pptLib, (LPOLESTR)szPath, NULL)))
376 IUnknown_Release(*pptLib);
384 TRACE(" returns %08lx\n",res);
388 /******************************************************************************
389 * LoadRegTypeLib [OLEAUT32.162]
391 HRESULT WINAPI LoadRegTypeLib(
392 REFGUID rguid, /* [in] referenced guid */
393 WORD wVerMajor, /* [in] major version */
394 WORD wVerMinor, /* [in] minor version */
395 LCID lcid, /* [in] locale id */
396 ITypeLib **ppTLib) /* [out] path of typelib */
399 HRESULT res=QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
403 res= LoadTypeLib(bstr, ppTLib);
407 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
413 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
414 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
415 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
416 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
417 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
418 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
420 /******************************************************************************
421 * RegisterTypeLib [OLEAUT32.163]
422 * Adds information about a type library to the System Registry
424 * Docs: ITypeLib FAR * ptlib
425 * Docs: OLECHAR FAR* szFullPath
426 * Docs: OLECHAR FAR* szHelpDir
432 HRESULT WINAPI RegisterTypeLib(
433 ITypeLib * ptlib, /* [in] Pointer to the library*/
434 OLECHAR * szFullPath, /* [in] full Path of the library*/
435 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
438 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
439 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
440 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
450 if (ptlib == NULL || szFullPath == NULL)
453 if (!SUCCEEDED(ITypeLib_GetLibAttr(ptlib, &attr)))
456 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
459 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
460 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
464 /* Set the human-readable name of the typelib */
465 if (SUCCEEDED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
467 if (RegSetValueExW(key, NULL, 0, REG_SZ,
468 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
476 /* Make up the name of the typelib path subkey */
477 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
479 /* Create the typelib path subkey */
480 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
481 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
483 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
484 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
492 /* Create the flags subkey */
493 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
494 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
496 /* FIXME: is %u correct? */
497 static const WCHAR formatW[] = {'%','u',0};
499 sprintfW(buf, formatW, attr->wLibFlags);
500 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
501 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
509 /* create the helpdir subkey */
510 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
511 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
513 BOOL freeHelpDir = FALSE;
516 /* if we created a new key, and helpDir was null, set the helpdir
517 to the directory which contains the typelib. However,
518 if we just opened an existing key, we leave the helpdir alone */
519 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
520 szHelpDir = SysAllocString(szFullPath);
521 pIndexStr = strrchrW(szHelpDir, '\\');
528 /* if we have an szHelpDir, set it! */
529 if (szHelpDir != NULL) {
530 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
531 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
537 if (freeHelpDir) SysFreeString(szHelpDir);
549 /* register OLE Automation-compatible interfaces for this typelib */
550 types = ITypeLib_GetTypeInfoCount(ptlib);
551 for (tidx=0; tidx<types; tidx++) {
552 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
553 LPOLESTR name = NULL;
554 ITypeInfo *tinfo = NULL;
556 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
559 case TKIND_INTERFACE:
560 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
561 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
565 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
566 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
570 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
575 TYPEATTR *tattr = NULL;
576 ITypeInfo_GetTypeAttr(tinfo, &tattr);
579 TRACE_(typelib)("guid=%s, flags=%04x (",
580 debugstr_guid(&tattr->guid),
583 if (TRACE_ON(typelib)) {
584 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
605 * FIXME: The 1 is just here until we implement rpcrt4
606 * stub/proxy handling. Until then it helps IShield
609 if (1 || (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION))
611 if (!(tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) {
612 FIXME("Registering non-oleautomation interface!\n");
615 /* register interface<->typelib coupling */
616 get_interface_key( &tattr->guid, keyName );
617 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
618 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
621 RegSetValueExW(key, NULL, 0, REG_SZ,
622 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
624 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
625 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
626 RegSetValueExW(subKey, NULL, 0, REG_SZ,
627 (BYTE*)PSOA, sizeof PSOA);
631 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
632 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
633 RegSetValueExW(subKey, NULL, 0, REG_SZ,
634 (BYTE*)PSOA, sizeof PSOA);
638 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
639 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
642 static const WCHAR fmtver[] = {'%','u','.','%','u',0 };
643 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
645 StringFromGUID2(&attr->guid, buffer, 40);
646 RegSetValueExW(subKey, NULL, 0, REG_SZ,
647 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
648 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
649 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
650 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
658 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
661 ITypeInfo_Release(tinfo);
668 ITypeLib_ReleaseTLibAttr(ptlib, attr);
674 /******************************************************************************
675 * UnRegisterTypeLib [OLEAUT32.186]
676 * Removes information about a type library from the System Registry
683 HRESULT WINAPI UnRegisterTypeLib(
684 REFGUID libid, /* [in] Guid of the library */
685 WORD wVerMajor, /* [in] major version */
686 WORD wVerMinor, /* [in] minor version */
687 LCID lcid, /* [in] locale id */
690 BSTR tlibPath = NULL;
693 WCHAR subKeyName[50];
696 BOOL deleteOtherStuff;
699 TYPEATTR* typeAttr = NULL;
701 ITypeInfo* typeInfo = NULL;
702 ITypeLib* typeLib = NULL;
705 TRACE("(IID: %s): stub\n",debugstr_guid(libid));
707 /* Create the path to the key */
708 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
710 if (syskind != SYS_WIN16 && syskind != SYS_WIN32)
712 TRACE("Unsupported syskind %i\n", syskind);
713 result = E_INVALIDARG;
717 /* get the path to the typelib on disk */
718 if (QueryPathOfRegTypeLib(libid, wVerMajor, wVerMinor, lcid, &tlibPath) != S_OK) {
719 result = E_INVALIDARG;
723 /* Try and open the key to the type library. */
724 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != S_OK) {
725 result = E_INVALIDARG;
729 /* Try and load the type library */
730 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
731 result = TYPE_E_INVALIDSTATE;
735 /* remove any types registered with this typelib */
736 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
737 for (i=0; i<numTypes; i++) {
738 /* get the kind of type */
739 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
743 /* skip non-interfaces, and get type info for the type */
744 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
747 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
750 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
754 /* the path to the type */
755 get_interface_key( &typeAttr->guid, subKeyName );
757 /* Delete its bits */
758 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != S_OK) {
761 RegDeleteKeyW(subKey, ProxyStubClsidW);
762 RegDeleteKeyW(subKey, ProxyStubClsid32W);
763 RegDeleteKeyW(subKey, TypeLibW);
766 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
769 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
771 if (typeInfo) ITypeInfo_Release(typeInfo);
775 /* Now, delete the type library path subkey */
776 get_lcid_subkey( lcid, syskind, subKeyName );
777 RegDeleteKeyW(key, subKeyName);
778 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
779 RegDeleteKeyW(key, subKeyName);
781 /* check if there is anything besides the FLAGS/HELPDIR keys.
782 If there is, we don't delete them */
783 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
784 deleteOtherStuff = TRUE;
786 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == S_OK) {
787 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
789 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
790 if (!strcmpW(subKeyName, FLAGSW)) continue;
791 if (!strcmpW(subKeyName, HELPDIRW)) continue;
792 deleteOtherStuff = FALSE;
796 /* only delete the other parts of the key if we're absolutely sure */
797 if (deleteOtherStuff) {
798 RegDeleteKeyW(key, FLAGSW);
799 RegDeleteKeyW(key, HELPDIRW);
803 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
804 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
805 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
809 if (tlibPath) SysFreeString(tlibPath);
810 if (typeLib) ITypeLib_Release(typeLib);
811 if (subKey) RegCloseKey(subKey);
812 if (key) RegCloseKey(key);
816 /*======================= ITypeLib implementation =======================*/
818 typedef struct tagTLBCustData
822 struct tagTLBCustData* next;
825 /* data structure for import typelibs */
826 typedef struct tagTLBImpLib
828 int offset; /* offset in the file (MSFT)
829 offset in nametable (SLTG)
830 just used to identify library while reading
832 GUID guid; /* libid */
833 BSTR name; /* name */
835 LCID lcid; /* lcid of imported typelib */
837 WORD wVersionMajor; /* major version number */
838 WORD wVersionMinor; /* minor version number */
840 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
841 NULL if not yet loaded */
842 struct tagTLBImpLib * next;
845 /* internal ITypeLib data */
846 typedef struct tagITypeLibImpl
848 ITypeLib2Vtbl *lpVtbl;
849 ITypeCompVtbl *lpVtblTypeComp;
851 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
853 /* strings can be stored in tlb as multibyte strings BUT they are *always*
854 * exported to the application as a UNICODE string.
860 unsigned long dwHelpContext;
861 int TypeInfoCount; /* nr of typeinfo's in librarry */
862 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
863 int ctCustData; /* number of items in cust data list */
864 TLBCustData * pCustData; /* linked list to cust data */
865 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
866 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
867 libary. Only used while read MSFT
870 /* typelibs are cached, keyed by path, so store the linked list info within them */
871 struct tagITypeLibImpl *next, *prev;
875 static struct ITypeLib2Vtbl tlbvt;
876 static struct ITypeCompVtbl tlbtcvt;
878 #define _ITypeComp_Offset(impl) ((int)(&(((impl*)0)->lpVtblTypeComp)))
879 #define ICOM_THIS_From_ITypeComp(impl, iface) impl* This = (impl*)(((char*)iface)-_ITypeComp_Offset(impl))
881 /* ITypeLib methods */
882 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
883 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
885 /*======================= ITypeInfo implementation =======================*/
887 /* data for refernced types */
888 typedef struct tagTLBRefType
890 INT index; /* Type index for internal ref or for external ref
891 it the format is SLTG. -2 indicates to
894 GUID guid; /* guid of the referenced type */
895 /* if index == TLB_REF_USE_GUID */
897 HREFTYPE reference; /* The href of this ref */
898 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
899 TLB_REF_INTERNAL for internal refs
900 TLB_REF_NOT_FOUND for broken refs */
902 struct tagTLBRefType * next;
905 #define TLB_REF_USE_GUID -2
907 #define TLB_REF_INTERNAL (void*)-2
908 #define TLB_REF_NOT_FOUND (void*)-1
910 /* internal Parameter data */
911 typedef struct tagTLBParDesc
915 TLBCustData * pCustData; /* linked list to cust data */
918 /* internal Function data */
919 typedef struct tagTLBFuncDesc
921 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
922 BSTR Name; /* the name of this function */
923 TLBParDesc *pParamDesc; /* array with param names and custom data */
925 int HelpStringContext;
927 BSTR Entry; /* if its Hiword==0, it numeric; -1 is not present*/
929 TLBCustData * pCustData; /* linked list to cust data; */
930 struct tagTLBFuncDesc * next;
933 /* internal Variable data */
934 typedef struct tagTLBVarDesc
936 VARDESC vardesc; /* lots of info on the variable and its attributes. */
937 BSTR Name; /* the name of this variable */
939 int HelpStringContext; /* FIXME: where? */
942 TLBCustData * pCustData;/* linked list to cust data; */
943 struct tagTLBVarDesc * next;
946 /* internal implemented interface data */
947 typedef struct tagTLBImplType
949 HREFTYPE hRef; /* hRef of interface */
950 int implflags; /* IMPLFLAG_*s */
952 TLBCustData * pCustData;/* linked list to custom data; */
953 struct tagTLBImplType *next;
956 /* internal TypeInfo data */
957 typedef struct tagITypeInfoImpl
959 ITypeInfo2Vtbl *lpVtbl;
960 ITypeCompVtbl *lpVtblTypeComp;
962 TYPEATTR TypeAttr ; /* _lots_ of type information. */
963 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
964 int index; /* index in this typelib; */
965 /* type libs seem to store the doc strings in ascii
966 * so why should we do it in unicode?
970 unsigned long dwHelpContext;
971 unsigned long dwHelpStringContext;
974 TLBFuncDesc * funclist; /* linked list with function descriptions */
977 TLBVarDesc * varlist; /* linked list with variable descriptions */
979 /* Implemented Interfaces */
980 TLBImplType * impltypelist;
982 TLBRefType * reflist;
984 TLBCustData * pCustData; /* linked list to cust data; */
985 struct tagITypeInfoImpl * next;
988 static struct ITypeInfo2Vtbl tinfvt;
989 static struct ITypeCompVtbl tcompvt;
991 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void);
993 typedef struct tagTLBContext
995 unsigned int oStart; /* start of TLB in file */
996 unsigned int pos; /* current pos */
997 unsigned int length; /* total length */
998 void *mapping; /* memory mapping */
999 MSFT_SegDir * pTblDir;
1000 ITypeLibImpl* pLibInfo;
1004 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI, int offset);
1009 static void dump_TypeDesc(TYPEDESC *pTD,char *szVarType) {
1010 if (pTD->vt & VT_RESERVED)
1011 szVarType += strlen(strcpy(szVarType, "reserved | "));
1012 if (pTD->vt & VT_BYREF)
1013 szVarType += strlen(strcpy(szVarType, "ref to "));
1014 if (pTD->vt & VT_ARRAY)
1015 szVarType += strlen(strcpy(szVarType, "array of "));
1016 if (pTD->vt & VT_VECTOR)
1017 szVarType += strlen(strcpy(szVarType, "vector of "));
1018 switch(pTD->vt & VT_TYPEMASK) {
1019 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1020 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1021 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1022 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1023 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1024 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1025 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1026 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1027 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1028 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1029 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1030 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1031 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1032 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1033 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1034 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1035 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1036 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1037 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1038 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1039 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %lx",
1040 pTD->u.hreftype); break;
1041 case VT_PTR: sprintf(szVarType, "ptr to ");
1042 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1044 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1045 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1047 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1048 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1049 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1052 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1056 void dump_ELEMDESC(ELEMDESC *edesc) {
1058 dump_TypeDesc(&edesc->tdesc,buf);
1059 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1060 MESSAGE("\t\tu.parmadesc.flags %x\n",edesc->u.paramdesc.wParamFlags);
1061 MESSAGE("\t\tu.parmadesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1063 void dump_FUNCDESC(FUNCDESC *funcdesc) {
1065 MESSAGE("memid is %08lx\n",funcdesc->memid);
1066 for (i=0;i<funcdesc->cParams;i++) {
1067 MESSAGE("Param %d:\n",i);
1068 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1070 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1071 switch (funcdesc->funckind) {
1072 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1073 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1074 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1075 case FUNC_STATIC: MESSAGE("static");break;
1076 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1077 default: MESSAGE("unknown");break;
1079 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1080 switch (funcdesc->invkind) {
1081 case INVOKE_FUNC: MESSAGE("func");break;
1082 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1083 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1084 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1086 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1087 switch (funcdesc->callconv) {
1088 case CC_CDECL: MESSAGE("cdecl");break;
1089 case CC_PASCAL: MESSAGE("pascal");break;
1090 case CC_STDCALL: MESSAGE("stdcall");break;
1091 case CC_SYSCALL: MESSAGE("syscall");break;
1094 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1095 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1096 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1098 MESSAGE("\telemdescFunc (return value type):\n");
1099 dump_ELEMDESC(&funcdesc->elemdescFunc);
1102 void dump_IDLDESC(IDLDESC *idl) {
1103 MESSAGE("\t\twIdlflags: %d\n",idl->wIDLFlags);
1106 static const char * typekind_desc[] =
1119 void dump_TYPEATTR(TYPEATTR *tattr) {
1121 MESSAGE("\tguid: %s\n",debugstr_guid(&tattr->guid));
1122 MESSAGE("\tlcid: %ld\n",tattr->lcid);
1123 MESSAGE("\tmemidConstructor: %ld\n",tattr->memidConstructor);
1124 MESSAGE("\tmemidDestructor: %ld\n",tattr->memidDestructor);
1125 MESSAGE("\tschema: %s\n",debugstr_w(tattr->lpstrSchema));
1126 MESSAGE("\tsizeInstance: %ld\n",tattr->cbSizeInstance);
1127 MESSAGE("\tkind:%s\n", typekind_desc[tattr->typekind]);
1128 MESSAGE("\tcFuncs: %d\n", tattr->cFuncs);
1129 MESSAGE("\tcVars: %d\n", tattr->cVars);
1130 MESSAGE("\tcImplTypes: %d\n", tattr->cImplTypes);
1131 MESSAGE("\tcbSizeVft: %d\n", tattr->cbSizeVft);
1132 MESSAGE("\tcbAlignment: %d\n", tattr->cbAlignment);
1133 MESSAGE("\twTypeFlags: %d\n", tattr->wTypeFlags);
1134 MESSAGE("\tVernum: %d.%d\n", tattr->wMajorVerNum,tattr->wMinorVerNum);
1135 dump_TypeDesc(&tattr->tdescAlias,buf);
1136 MESSAGE("\ttypedesc: %s\n", buf);
1137 dump_IDLDESC(&tattr->idldescType);
1140 static void dump_TLBFuncDescOne(TLBFuncDesc * pfd)
1143 if (!TRACE_ON(typelib))
1145 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1146 for (i=0;i<pfd->funcdesc.cParams;i++)
1147 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1150 dump_FUNCDESC(&(pfd->funcdesc));
1152 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1153 MESSAGE("\tentry: %s\n", debugstr_w(pfd->Entry));
1155 static void dump_TLBFuncDesc(TLBFuncDesc * pfd)
1159 dump_TLBFuncDescOne(pfd);
1163 static void dump_TLBVarDesc(TLBVarDesc * pvd)
1167 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1172 static void dump_TLBImpLib(TLBImpLib *import)
1174 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1175 debugstr_w(import->name));
1176 TRACE_(typelib)("v%d.%d lcid=%lx offset=%x\n", import->wVersionMajor,
1177 import->wVersionMinor, import->lcid, import->offset);
1180 static void dump_TLBRefType(TLBRefType * prt)
1184 TRACE_(typelib)("href:0x%08lx\n", prt->reference);
1185 if(prt->index == -1)
1186 TRACE_(typelib)("%s\n", debugstr_guid(&(prt->guid)));
1188 TRACE_(typelib)("type no: %d\n", prt->index);
1190 if(prt->pImpTLInfo != TLB_REF_INTERNAL &&
1191 prt->pImpTLInfo != TLB_REF_NOT_FOUND) {
1192 TRACE_(typelib)("in lib\n");
1193 dump_TLBImpLib(prt->pImpTLInfo);
1199 static void dump_TLBImplType(TLBImplType * impl)
1203 "implementing/inheriting interface hRef = %lx implflags %x\n",
1204 impl->hRef, impl->implflags);
1209 void dump_Variant(VARIANT * pvar)
1213 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1217 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1218 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1220 TRACE(",%p", V_BYREF(pvar));
1222 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1226 else switch (V_TYPE(pvar))
1228 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1229 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1230 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1231 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1233 case VT_I4: TRACE(",%ld", V_I4(pvar)); break;
1235 case VT_UI4: TRACE(",%ld", V_UI4(pvar)); break;
1236 case VT_I8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_I8(pvar) >> 32),
1237 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1238 case VT_UI8: TRACE(",0x%08lx,0x%08lx", (ULONG)(V_UI8(pvar) >> 32),
1239 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1240 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1241 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1242 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1243 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1244 case VT_CY: TRACE(",0x%08lx,0x%08lx", V_CY(pvar).s.Hi,
1245 V_CY(pvar).s.Lo); break;
1247 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1248 TRACE(",<invalid>");
1250 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1251 st.wHour, st.wMinute, st.wSecond);
1255 case VT_USERDEFINED:
1257 case VT_NULL: break;
1258 default: TRACE(",?"); break;
1264 static void dump_DispParms(DISPPARAMS * pdp)
1268 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1270 while (index < pdp->cArgs)
1272 dump_Variant( &pdp->rgvarg[index] );
1277 static void dump_TypeInfo(ITypeInfoImpl * pty)
1279 TRACE("%p ref=%u\n", pty, pty->ref);
1280 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1281 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1282 TRACE("fct:%u var:%u impl:%u\n",
1283 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1284 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1285 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1286 dump_TLBFuncDesc(pty->funclist);
1287 dump_TLBVarDesc(pty->varlist);
1288 dump_TLBImplType(pty->impltypelist);
1291 void dump_VARDESC(VARDESC *v)
1293 MESSAGE("memid %ld\n",v->memid);
1294 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1295 MESSAGE("oInst %ld\n",v->u.oInst);
1296 dump_ELEMDESC(&(v->elemdescVar));
1297 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1298 MESSAGE("varkind %d\n",v->varkind);
1301 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1303 /* VT_LPWSTR is largest type that */
1304 /* may appear in type description*/
1305 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1306 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1307 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1308 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1309 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1310 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1314 static void TLB_abort()
1318 static void * TLB_Alloc(unsigned size)
1321 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1323 ERR("cannot allocate memory\n");
1328 static void TLB_Free(void * ptr)
1330 HeapFree(GetProcessHeap(), 0, ptr);
1333 /* deep copy a typedesc */
1334 static void copy_typedesc(TYPEDESC *out, const TYPEDESC *in)
1339 out->u.lptdesc = HeapAlloc(GetProcessHeap(), 0, sizeof(TYPEDESC));
1340 copy_typedesc(out->u.lptdesc, in->u.lptdesc);
1342 case VT_USERDEFINED:
1343 out->u.hreftype = in->u.hreftype;
1346 out->u.lpadesc = HeapAlloc(GetProcessHeap(), 0, sizeof(ARRAYDESC) +
1347 (in->u.lpadesc->cDims - 1) * sizeof(SAFEARRAYBOUND));
1348 copy_typedesc(&out->u.lpadesc->tdescElem, &in->u.lpadesc->tdescElem);
1349 out->u.lpadesc->cDims = in->u.lpadesc->cDims;
1350 memcpy(out->u.lpadesc->rgbounds, in->u.lpadesc->rgbounds, in->u.lpadesc->cDims * sizeof(SAFEARRAYBOUND));
1357 /* free()s any allocated memory pointed to by the tdesc. NB does not
1358 free the tdesc itself - this is because the tdesc is typically part
1359 of a larger structure */
1360 static void free_deep_typedesc(TYPEDESC *tdesc)
1364 free_deep_typedesc(tdesc->u.lptdesc);
1365 HeapFree(GetProcessHeap(), 0, tdesc->u.lptdesc);
1366 tdesc->u.lptdesc = NULL;
1369 free_deep_typedesc(&tdesc->u.lpadesc->tdescElem);
1370 HeapFree(GetProcessHeap(), 0, tdesc->u.lpadesc);
1371 tdesc->u.lpadesc = NULL;
1378 /**********************************************************************
1380 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1383 DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, long where )
1385 TRACE_(typelib)("pos=0x%08x len=0x%08lx 0x%08x 0x%08x 0x%08lx\n",
1386 pcx->pos, count, pcx->oStart, pcx->length, where);
1388 if (where != DO_NOT_SEEK)
1390 where += pcx->oStart;
1391 if (where > pcx->length)
1394 ERR("seek beyond end (%ld/%d)\n", where, pcx->length );
1399 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1400 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1405 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1410 ret = MSFT_Read(buffer, count, pcx, where);
1411 FromLEDWords(buffer, ret);
1416 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1421 ret = MSFT_Read(buffer, count, pcx, where);
1422 FromLEWords(buffer, ret);
1427 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1429 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1430 memset(pGuid,0, sizeof(GUID));
1433 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1434 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1435 pGuid->Data2 = FromLEWord(pGuid->Data2);
1436 pGuid->Data3 = FromLEWord(pGuid->Data3);
1437 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1440 BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1443 MSFT_NameIntro niName;
1445 WCHAR* pwstring = NULL;
1446 BSTR bstrName = NULL;
1448 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1449 pcx->pTblDir->pNametab.offset+offset);
1450 niName.namelen &= 0xFF; /* FIXME: correct ? */
1451 name=TLB_Alloc((niName.namelen & 0xff) +1);
1452 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1453 name[niName.namelen & 0xff]='\0';
1455 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1458 /* no invalid characters in string */
1461 pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1463 /* don't check for invalid character since this has been done previously */
1464 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, pwstring, lengthInChars);
1466 bstrName = SysAllocStringLen(pwstring, lengthInChars);
1467 lengthInChars = SysStringLen(bstrName);
1468 HeapFree(GetProcessHeap(), 0, pwstring);
1471 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1475 BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1482 if(offset<0) return NULL;
1483 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1484 if(length <= 0) return 0;
1485 string=TLB_Alloc(length +1);
1486 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1487 string[length]='\0';
1489 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1490 string, -1, NULL, 0);
1492 /* no invalid characters in string */
1495 WCHAR* pwstring = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*lengthInChars);
1497 /* don't check for invalid character since this has been done previously */
1498 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, pwstring, lengthInChars);
1500 bstr = SysAllocStringLen(pwstring, lengthInChars);
1501 lengthInChars = SysStringLen(bstr);
1502 HeapFree(GetProcessHeap(), 0, pwstring);
1505 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1509 * read a value and fill a VARIANT structure
1511 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1515 TRACE_(typelib)("\n");
1517 if(offset <0) { /* data are packed in here */
1518 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1519 V_UNION(pVar, iVal) = offset & 0xffff;
1522 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1523 pcx->pTblDir->pCustData.offset + offset );
1524 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1525 switch (V_VT(pVar)){
1526 case VT_EMPTY: /* FIXME: is this right? */
1527 case VT_NULL: /* FIXME: is this right? */
1528 case VT_I2 : /* this should not happen */
1539 case VT_VOID : /* FIXME: is this right? */
1547 case VT_DECIMAL : /* FIXME: is this right? */
1550 /* pointer types with known behaviour */
1553 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1555 FIXME("BSTR length = %d?\n", size);
1557 ptr=TLB_Alloc(size);/* allocate temp buffer */
1558 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1559 V_UNION(pVar, bstrVal)=SysAllocStringLen(NULL,size);
1560 /* FIXME: do we need a AtoW conversion here? */
1561 V_UNION(pVar, bstrVal[size])=L'\0';
1562 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1567 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1574 case VT_USERDEFINED :
1580 case VT_STREAMED_OBJECT :
1581 case VT_STORED_OBJECT :
1582 case VT_BLOB_OBJECT :
1587 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1591 if(size>0) /* (big|small) endian correct? */
1592 MSFT_Read(&(V_UNION(pVar, iVal)), size, pcx, DO_NOT_SEEK );
1596 * create a linked list with custom data
1598 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1604 TRACE_(typelib)("\n");
1608 pNew=TLB_Alloc(sizeof(TLBCustData));
1609 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1610 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1611 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1612 /* add new custom data at head of the list */
1613 pNew->next=*ppCustData;
1615 offset = entry.next;
1620 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1624 pTd->vt=type & VT_TYPEMASK;
1626 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1628 if(pTd->vt == VT_USERDEFINED)
1629 MSFT_DoRefType(pcx, pTI, pTd->u.hreftype);
1631 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1635 MSFT_DoFuncs(TLBContext* pcx,
1640 TLBFuncDesc** pptfd)
1643 * member information is stored in a data structure at offset
1644 * indicated by the memoffset field of the typeinfo structure
1645 * There are several distinctive parts.
1646 * the first part starts with a field that holds the total length
1647 * of this (first) part excluding this field. Then follow the records,
1648 * for each member there is one record.
1650 * First entry is always the length of the record (including this
1652 * Rest of the record depends on the type of the member. If there is
1653 * a field indicating the member type (function variable intereface etc)
1654 * I have not found it yet. At this time we depend on the information
1655 * in the type info and the usual order how things are stored.
1657 * Second follows an array sized nrMEM*sizeof(INT) with a memeber id
1660 * Third is a equal sized array with file offsets to the name entry
1663 * Forth and last (?) part is an array with offsets to the records in the
1664 * first part of this file segment.
1667 int infolen, nameoffset, reclength, nrattributes, i;
1668 int recoffset = offset + sizeof(INT);
1671 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1673 TRACE_(typelib)("\n");
1675 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1677 for ( i = 0; i < cFuncs ; i++ )
1679 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1681 /* name, eventually add to a hash table */
1682 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1683 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1685 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1687 /* read the function information record */
1688 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1692 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1694 /* do the attributes */
1695 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1698 if ( nrattributes > 0 )
1700 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1702 if ( nrattributes > 1 )
1704 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1705 pFuncRec->OptAttr[1]) ;
1707 if ( nrattributes > 2 )
1709 if ( pFuncRec->FKCCIC & 0x2000 )
1711 (*pptfd)->Entry = (WCHAR*) pFuncRec->OptAttr[2] ;
1715 (*pptfd)->Entry = MSFT_ReadString(pcx,
1716 pFuncRec->OptAttr[2]);
1718 if( nrattributes > 5 )
1720 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1722 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1725 pFuncRec->OptAttr[6],
1726 &(*pptfd)->pCustData);
1733 /* fill the FuncDesc Structure */
1734 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1735 offset + infolen + ( i + 1) * sizeof(INT));
1737 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1738 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1739 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1740 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1741 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1742 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset ;
1743 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1747 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1750 /* do the parameters/arguments */
1751 if(pFuncRec->nrargs)
1754 MSFT_ParameterInfo paraminfo;
1756 (*pptfd)->funcdesc.lprgelemdescParam =
1757 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1759 (*pptfd)->pParamDesc =
1760 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1762 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1763 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1765 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1767 TYPEDESC* lpArgTypeDesc = 0;
1771 &(*pptfd)->funcdesc.lprgelemdescParam[j].tdesc,
1774 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags = paraminfo.Flags;
1776 (*pptfd)->pParamDesc[j].Name = (void *) paraminfo.oName;
1778 /* SEEK value = jump to offset,
1779 * from there jump to the end of record,
1780 * go back by (j-1) arguments
1782 MSFT_ReadLEDWords( ¶minfo ,
1783 sizeof(MSFT_ParameterInfo), pcx,
1784 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
1785 * sizeof(MSFT_ParameterInfo)));
1787 & ((*pptfd)->funcdesc.lprgelemdescParam[j].tdesc);
1789 while ( lpArgTypeDesc != NULL )
1791 switch ( lpArgTypeDesc->vt )
1794 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1798 lpArgTypeDesc = & (lpArgTypeDesc->u.lpadesc->tdescElem);
1801 case VT_USERDEFINED:
1802 MSFT_DoRefType(pcx, pTI,
1803 lpArgTypeDesc->u.hreftype);
1805 lpArgTypeDesc = NULL;
1809 lpArgTypeDesc = NULL;
1815 /* parameter is the return value! */
1816 if ( paraminfo.Flags & PARAMFLAG_FRETVAL )
1818 TYPEDESC* lpArgTypeDesc;
1820 (*pptfd)->funcdesc.elemdescFunc =
1821 (*pptfd)->funcdesc.lprgelemdescParam[j];
1823 lpArgTypeDesc = & ((*pptfd)->funcdesc.elemdescFunc.tdesc) ;
1825 while ( lpArgTypeDesc != NULL )
1827 switch ( lpArgTypeDesc->vt )
1830 lpArgTypeDesc = lpArgTypeDesc->u.lptdesc;
1834 & (lpArgTypeDesc->u.lpadesc->tdescElem);
1838 case VT_USERDEFINED:
1841 lpArgTypeDesc->u.hreftype);
1843 lpArgTypeDesc = NULL;
1847 lpArgTypeDesc = NULL;
1852 /* second time around */
1853 for(j=0;j<pFuncRec->nrargs;j++)
1856 (*pptfd)->pParamDesc[j].Name =
1857 MSFT_ReadName( pcx, (int)(*pptfd)->pParamDesc[j].Name );
1860 if ( (PARAMFLAG_FHASDEFAULT &
1861 (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc.wParamFlags) &&
1862 ((pFuncRec->FKCCIC) & 0x1000) )
1864 INT* pInt = (INT *)((char *)pFuncRec +
1866 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
1868 PARAMDESC* pParamDesc = & (*pptfd)->funcdesc.lprgelemdescParam[j].u.paramdesc;
1870 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
1871 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
1873 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
1877 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
1880 pFuncRec->OptAttr[7+j],
1881 &(*pptfd)->pParamDesc[j].pCustData);
1886 /* scode is not used: archaic win16 stuff FIXME: right? */
1887 (*pptfd)->funcdesc.cScodes = 0 ;
1888 (*pptfd)->funcdesc.lprgscode = NULL ;
1890 pptfd = & ((*pptfd)->next);
1891 recoffset += reclength;
1895 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
1896 int cVars, int offset, TLBVarDesc ** pptvd)
1898 int infolen, nameoffset, reclength;
1900 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
1904 TRACE_(typelib)("\n");
1906 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
1907 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
1908 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
1909 recoffset += offset+sizeof(INT);
1910 for(i=0;i<cVars;i++){
1911 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
1912 /* name, eventually add to a hash table */
1913 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1914 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1915 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
1916 /* read the variable information record */
1917 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1919 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1921 if(reclength >(6*sizeof(INT)) )
1922 (*pptvd)->HelpContext=pVarRec->HelpContext;
1923 if(reclength >(7*sizeof(INT)) )
1924 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
1925 if(reclength >(8*sizeof(INT)) )
1926 if(reclength >(9*sizeof(INT)) )
1927 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
1928 /* fill the VarDesc Structure */
1929 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
1930 offset + infolen + ( i + 1) * sizeof(INT));
1931 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
1932 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
1933 MSFT_GetTdesc(pcx, pVarRec->DataType,
1934 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
1935 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
1936 if(pVarRec->VarKind == VAR_CONST ){
1937 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
1938 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
1939 pVarRec->OffsValue, pcx);
1941 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
1942 pptvd=&((*pptvd)->next);
1943 recoffset += reclength;
1946 /* fill in data for a hreftype (offset). When the refernced type is contained
1947 * in the typelib, it's just an (file) offset in the type info base dir.
1948 * If comes from import, it's an offset+1 in the ImpInfo table
1950 static void MSFT_DoRefType(TLBContext *pcx, ITypeInfoImpl *pTI,
1954 TLBRefType **ppRefType = &pTI->reflist;
1956 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
1959 if((*ppRefType)->reference == offset)
1961 ppRefType = &(*ppRefType)->next;
1964 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
1965 sizeof(**ppRefType));
1967 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
1968 /* external typelib */
1969 MSFT_ImpInfo impinfo;
1970 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
1972 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
1974 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
1975 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
1976 for(j=0;pImpLib;j++){ /* search the known offsets of all import libraries */
1977 if(pImpLib->offset==impinfo.oImpFile) break;
1978 pImpLib=pImpLib->next;
1981 (*ppRefType)->reference=offset;
1982 (*ppRefType)->pImpTLInfo = pImpLib;
1983 MSFT_ReadGuid(&(*ppRefType)->guid, impinfo.oGuid, pcx);
1984 (*ppRefType)->index = TLB_REF_USE_GUID;
1986 ERR("Cannot find a reference\n");
1987 (*ppRefType)->reference=-1;
1988 (*ppRefType)->pImpTLInfo=TLB_REF_NOT_FOUND;
1991 /* in this typelib */
1992 (*ppRefType)->index = MSFT_HREFTYPE_INDEX(offset);
1993 (*ppRefType)->reference=offset;
1994 (*ppRefType)->pImpTLInfo=TLB_REF_INTERNAL;
1998 /* process Implemented Interfaces of a com class */
1999 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2003 MSFT_RefRecord refrec;
2004 TLBImplType **ppImpl = &pTI->impltypelist;
2006 TRACE_(typelib)("\n");
2008 for(i=0;i<count;i++){
2009 if(offset<0) break; /* paranoia */
2010 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2011 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2012 MSFT_DoRefType(pcx, pTI, refrec.reftype);
2013 (*ppImpl)->hRef = refrec.reftype;
2014 (*ppImpl)->implflags=refrec.flags;
2015 (*ppImpl)->ctCustData=
2016 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2017 offset=refrec.onext;
2018 ppImpl=&((*ppImpl)->next);
2022 * process a typeinfo record
2024 ITypeInfoImpl * MSFT_DoTypeInfo(
2027 ITypeLibImpl * pLibInfo)
2029 MSFT_TypeInfoBase tiBase;
2030 ITypeInfoImpl *ptiRet;
2032 TRACE_(typelib)("count=%u\n", count);
2034 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2035 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2036 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2037 /* this is where we are coming from */
2038 ptiRet->pTypeLib = pLibInfo;
2039 ptiRet->index=count;
2040 /* fill in the typeattr fields */
2041 WARN("Assign constructor/destructor memid\n");
2043 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2044 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2045 ptiRet->TypeAttr.memidConstructor=MEMBERID_NIL ;/* FIXME */
2046 ptiRet->TypeAttr.memidDestructor=MEMBERID_NIL ; /* FIXME */
2047 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2048 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2049 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2050 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2051 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2052 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2053 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2054 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2055 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2056 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2057 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2058 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2059 MSFT_GetTdesc(pcx, tiBase.datatype1,
2060 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2063 /* IDLDESC idldescType; *//* never saw this one != zero */
2065 /* name, eventually add to a hash table */
2066 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2067 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2069 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2070 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2071 ptiRet->dwHelpContext=tiBase.helpcontext;
2072 /* note: InfoType's Help file and HelpStringDll come from the containing
2073 * library. Further HelpString and Docstring appear to be the same thing :(
2076 if(ptiRet->TypeAttr.cFuncs >0 )
2077 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2078 ptiRet->TypeAttr.cVars,
2079 tiBase.memoffset, & ptiRet->funclist);
2081 if(ptiRet->TypeAttr.cVars >0 )
2082 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2083 ptiRet->TypeAttr.cVars,
2084 tiBase.memoffset, & ptiRet->varlist);
2085 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2086 switch(ptiRet->TypeAttr.typekind)
2089 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2092 case TKIND_DISPATCH:
2093 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2095 if (tiBase.datatype1 != -1)
2097 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2098 ptiRet->impltypelist->hRef = tiBase.datatype1;
2101 { /* FIXME: This is a really bad hack to add IDispatch */
2102 const char* szStdOle = "stdole2.tlb\0";
2103 int nStdOleLen = strlen(szStdOle);
2104 TLBRefType **ppRef = &ptiRet->reflist;
2107 if((*ppRef)->reference == -1)
2109 ppRef = &(*ppRef)->next;
2112 *ppRef = TLB_Alloc(sizeof(**ppRef));
2113 (*ppRef)->guid = IID_IDispatch;
2114 (*ppRef)->reference = -1;
2115 (*ppRef)->index = TLB_REF_USE_GUID;
2116 (*ppRef)->pImpTLInfo = TLB_Alloc(sizeof(TLBImpLib));
2117 (*ppRef)->pImpTLInfo->guid = IID_StdOle;
2118 (*ppRef)->pImpTLInfo->name = SysAllocStringLen(NULL,
2121 MultiByteToWideChar(CP_ACP,
2125 (*ppRef)->pImpTLInfo->name,
2126 SysStringLen((*ppRef)->pImpTLInfo->name));
2128 (*ppRef)->pImpTLInfo->lcid = 0;
2129 (*ppRef)->pImpTLInfo->wVersionMajor = 2;
2130 (*ppRef)->pImpTLInfo->wVersionMinor = 0;
2135 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2136 MSFT_DoRefType(pcx, ptiRet, tiBase.datatype1);
2137 ptiRet->impltypelist->hRef = tiBase.datatype1;
2142 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2144 TRACE_(typelib)("%s guid: %s kind:%s\n",
2145 debugstr_w(ptiRet->Name),
2146 debugstr_guid(&ptiRet->TypeAttr.guid),
2147 typekind_desc[ptiRet->TypeAttr.typekind]);
2152 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2153 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2154 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2157 static ITypeLibImpl *tlb_cache_first;
2158 static CRITICAL_SECTION cache_section;
2159 static CRITICAL_SECTION_DEBUG cache_section_debug =
2161 0, 0, &cache_section,
2162 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2163 0, 0, { 0, (DWORD)(__FILE__ ": typelib loader cache") }
2165 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2168 /****************************************************************************
2171 * find the type of the typelib file and map the typelib resource into
2174 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2175 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2176 int TLB_ReadTypeLib(LPCWSTR pszFileName, INT index, ITypeLib2 **ppTypeLib)
2178 ITypeLibImpl *entry;
2179 int ret = TYPE_E_CANTLOADLIBRARY;
2180 DWORD dwSignature = 0;
2183 TRACE_(typelib)("%s:%d\n", debugstr_w(pszFileName), index);
2187 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2188 EnterCriticalSection(&cache_section);
2189 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2191 if (!strcmpiW(entry->path, pszFileName))
2193 TRACE("cache hit\n");
2194 *ppTypeLib = (ITypeLib2*)entry;
2195 ITypeLib_AddRef(*ppTypeLib);
2196 LeaveCriticalSection(&cache_section);
2200 LeaveCriticalSection(&cache_section);
2202 /* check the signature of the file */
2203 hFile = CreateFileW( pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0 );
2204 if (INVALID_HANDLE_VALUE != hFile)
2206 HANDLE hMapping = CreateFileMappingW( hFile, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL );
2209 LPVOID pBase = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
2212 /* retrieve file size */
2213 DWORD dwTLBLength = GetFileSize(hFile, NULL);
2215 /* first try to load as *.tlb */
2216 dwSignature = FromLEDWord(*((DWORD*) pBase));
2217 if ( dwSignature == MSFT_SIGNATURE)
2219 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2221 else if ( dwSignature == SLTG_SIGNATURE)
2223 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2225 UnmapViewOfFile(pBase);
2227 CloseHandle(hMapping);
2232 if( (WORD)dwSignature == IMAGE_DOS_SIGNATURE )
2234 /* find the typelibrary resource*/
2235 HINSTANCE hinstDLL = LoadLibraryExW(pszFileName, 0, DONT_RESOLVE_DLL_REFERENCES|
2236 LOAD_LIBRARY_AS_DATAFILE|LOAD_WITH_ALTERED_SEARCH_PATH);
2239 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2240 HRSRC hrsrc = FindResourceW(hinstDLL, MAKEINTRESOURCEW(index), TYPELIBW);
2243 HGLOBAL hGlobal = LoadResource(hinstDLL, hrsrc);
2246 LPVOID pBase = LockResource(hGlobal);
2247 DWORD dwTLBLength = SizeofResource(hinstDLL, hrsrc);
2251 /* try to load as incore resource */
2252 dwSignature = FromLEDWord(*((DWORD*) pBase));
2253 if ( dwSignature == MSFT_SIGNATURE)
2255 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2257 else if ( dwSignature == SLTG_SIGNATURE)
2259 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2263 FIXME("Header type magic 0x%08lx not supported.\n",dwSignature);
2266 FreeResource( hGlobal );
2269 FreeLibrary(hinstDLL);
2274 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2276 TRACE("adding to cache\n");
2277 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszFileName)+1) * sizeof(WCHAR));
2278 lstrcpyW(impl->path, pszFileName);
2279 /* We should really canonicalise the path here. */
2281 /* FIXME: check if it has added already in the meantime */
2282 EnterCriticalSection(&cache_section);
2283 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2285 tlb_cache_first = impl;
2286 LeaveCriticalSection(&cache_section);
2289 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName), GetLastError());
2294 /*================== ITypeLib(2) Methods ===================================*/
2296 /****************************************************************************
2297 * ITypeLib2_Constructor_MSFT
2299 * loading an MSFT typelib from an in-memory image
2301 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2305 MSFT_Header tlbHeader;
2306 MSFT_SegDir tlbSegDir;
2307 ITypeLibImpl * pTypeLibImpl;
2309 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
2311 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2312 if (!pTypeLibImpl) return NULL;
2314 pTypeLibImpl->lpVtbl = &tlbvt;
2315 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2316 pTypeLibImpl->ref = 1;
2318 /* get pointer to beginning of typelib data */
2322 cx.pLibInfo = pTypeLibImpl;
2323 cx.length = dwTLBLength;
2326 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2328 TRACE("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2329 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2330 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2333 /* there is a small amount of information here until the next important
2335 * the segment directory . Try to calculate the amount of data */
2336 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2338 /* now read the segment directory */
2339 TRACE("read segment directory (at %ld)\n",lPSegDir);
2340 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2341 cx.pTblDir = &tlbSegDir;
2343 /* just check two entries */
2344 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2346 ERR("cannot find the table directory, ptr=0x%lx\n",lPSegDir);
2347 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2351 /* now fill our internal data */
2352 /* TLIBATTR fields */
2353 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2355 /* pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid;*/
2356 /* Windows seems to have zero here, is this correct? */
2357 if(SUBLANGID(tlbHeader.lcid) == SUBLANG_NEUTRAL)
2358 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(tlbHeader.lcid),0),0);
2360 pTypeLibImpl->LibAttr.lcid = 0;
2362 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2363 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2364 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2365 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2367 /* name, eventually add to a hash table */
2368 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2371 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2372 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2374 if( tlbHeader.varflags & HELPDLLFLAG)
2377 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2378 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2381 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2384 if(tlbHeader.CustomDataOffset >= 0)
2386 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2389 /* fill in typedescriptions */
2390 if(tlbSegDir.pTypdescTab.length > 0)
2392 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2394 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2395 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2398 /* FIXME: add several sanity checks here */
2399 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2400 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2402 /* FIXME: check safearray */
2404 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2406 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2408 else if(td[0] == VT_CARRAY)
2410 /* array descr table here */
2411 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)((int) td[2]); /* temp store offset in*/
2413 else if(td[0] == VT_USERDEFINED)
2415 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2417 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2420 /* second time around to fill the array subscript info */
2423 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2424 if(tlbSegDir.pArrayDescriptions.offset>0)
2426 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (int) pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2427 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2430 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2432 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = stndTypeDesc[td[0]/8];
2434 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2436 for(j = 0; j<td[2]; j++)
2438 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2439 sizeof(INT), &cx, DO_NOT_SEEK);
2440 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2441 sizeof(INT), &cx, DO_NOT_SEEK);
2446 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2447 ERR("didn't find array description data\n");
2452 /* imported type libs */
2453 if(tlbSegDir.pImpFiles.offset>0)
2455 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2456 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2459 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2464 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2465 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2466 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2468 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2469 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2470 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2471 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
2474 name = TLB_Alloc(size+1);
2475 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
2476 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0 );
2477 (*ppImpLib)->name = TLB_Alloc(len * sizeof(WCHAR));
2478 MultiByteToWideChar(CP_ACP, 0, name, -1, (*ppImpLib)->name, len );
2481 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
2482 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
2484 ppImpLib = &(*ppImpLib)->next;
2489 if(tlbHeader.nrtypeinfos >= 0 )
2491 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
2492 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
2495 for(i = 0; i<(int)tlbHeader.nrtypeinfos; i++)
2497 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
2499 ppTI = &((*ppTI)->next);
2500 (pTypeLibImpl->TypeInfoCount)++;
2504 TRACE("(%p)\n", pTypeLibImpl);
2505 return (ITypeLib2*) pTypeLibImpl;
2509 static BSTR TLB_MultiByteToBSTR(char *ptr)
2515 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
2516 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2517 MultiByteToWideChar(CP_ACP, 0, ptr, -1, nameW, len);
2518 ret = SysAllocString(nameW);
2519 HeapFree(GetProcessHeap(), 0, nameW);
2523 static BOOL TLB_GUIDFromString(char *str, GUID *guid)
2529 if(sscanf(str, "%lx-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
2530 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
2534 guid->Data4[0] = s >> 8;
2535 guid->Data4[1] = s & 0xff;
2538 for(i = 0; i < 6; i++) {
2539 memcpy(b, str + 24 + 2 * i, 2);
2540 guid->Data4[i + 2] = strtol(b, NULL, 16);
2545 static WORD SLTG_ReadString(char *ptr, BSTR *pBstr)
2552 bytelen = *(WORD*)ptr;
2553 if(bytelen == 0xffff) return 2;
2554 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
2555 nameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2556 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, nameW, len);
2557 *pBstr = SysAllocStringLen(nameW, len);
2558 HeapFree(GetProcessHeap(), 0, nameW);
2562 static WORD SLTG_ReadStringA(char *ptr, char **str)
2567 bytelen = *(WORD*)ptr;
2568 if(bytelen == 0xffff) return 2;
2569 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
2570 memcpy(*str, ptr + 2, bytelen);
2571 (*str)[bytelen] = '\0';
2575 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
2577 char *ptr = pLibBlk;
2580 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
2581 FIXME("libblk magic = %04x\n", w);
2586 if((w = *(WORD*)ptr) != 0xffff) {
2587 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
2592 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
2594 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
2596 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
2599 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
2602 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
2603 pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
2605 pTypeLibImpl->LibAttr.lcid = 0;
2608 ptr += 4; /* skip res12 */
2610 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
2613 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
2616 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
2619 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
2620 ptr += sizeof(GUID);
2622 return ptr - (char*)pLibBlk;
2625 static WORD *SLTG_DoType(WORD *pType, char *pBlk, ELEMDESC *pElem)
2628 TYPEDESC *pTD = &pElem->tdesc;
2630 /* Handle [in/out] first */
2631 if((*pType & 0xc000) == 0xc000)
2632 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
2633 else if(*pType & 0x8000)
2634 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
2635 else if(*pType & 0x4000)
2636 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
2638 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
2641 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
2644 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
2647 if((*pType & 0xe00) == 0xe00) {
2649 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2651 pTD = pTD->u.lptdesc;
2653 switch(*pType & 0x7f) {
2656 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2658 pTD = pTD->u.lptdesc;
2661 case VT_USERDEFINED:
2662 pTD->vt = VT_USERDEFINED;
2663 pTD->u.hreftype = *(++pType) / 4;
2669 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
2672 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
2674 pTD->vt = VT_CARRAY;
2675 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2677 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
2678 pTD->u.lpadesc->cDims = pSA->cDims;
2679 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
2680 pSA->cDims * sizeof(SAFEARRAYBOUND));
2682 pTD = &pTD->u.lpadesc->tdescElem;
2688 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
2692 pTD->vt = VT_SAFEARRAY;
2693 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2695 pTD = pTD->u.lptdesc;
2699 pTD->vt = *pType & 0x7f;
2709 static void SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeInfoImpl *pTI,
2714 TLBRefType **ppRefType;
2716 if(pRef->magic != SLTG_REF_MAGIC) {
2717 FIXME("Ref magic = %x\n", pRef->magic);
2720 name = ( (char*)(&pRef->names) + pRef->number);
2722 ppRefType = &pTI->reflist;
2723 for(ref = 0; ref < pRef->number >> 3; ref++) {
2725 unsigned int lib_offs, type_num;
2727 *ppRefType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2728 sizeof(**ppRefType));
2730 name += SLTG_ReadStringA(name, &refname);
2731 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
2732 FIXME("Can't sscanf ref\n");
2733 if(lib_offs != 0xffff) {
2734 TLBImpLib **import = &pTI->pTypeLib->pImpLibs;
2737 if((*import)->offset == lib_offs)
2739 import = &(*import)->next;
2742 char fname[MAX_PATH+1];
2745 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2747 (*import)->offset = lib_offs;
2748 TLB_GUIDFromString( pNameTable + lib_offs + 4,
2750 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%lx#%s",
2751 &(*import)->wVersionMajor,
2752 &(*import)->wVersionMinor,
2753 &(*import)->lcid, fname) != 4) {
2754 FIXME("can't sscanf ref %s\n",
2755 pNameTable + lib_offs + 40);
2757 len = strlen(fname);
2758 if(fname[len-1] != '#')
2759 FIXME("fname = %s\n", fname);
2760 fname[len-1] = '\0';
2761 (*import)->name = TLB_MultiByteToBSTR(fname);
2763 (*ppRefType)->pImpTLInfo = *import;
2764 } else { /* internal ref */
2765 (*ppRefType)->pImpTLInfo = TLB_REF_INTERNAL;
2767 (*ppRefType)->reference = ref;
2768 (*ppRefType)->index = type_num;
2770 HeapFree(GetProcessHeap(), 0, refname);
2771 ppRefType = &(*ppRefType)->next;
2773 if((BYTE)*name != SLTG_REF_MAGIC)
2774 FIXME("End of ref block magic = %x\n", *name);
2775 dump_TLBRefType(pTI->reflist);
2778 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
2781 SLTG_ImplInfo *info;
2782 TLBImplType **ppImplType = &pTI->impltypelist;
2783 /* I don't really get this structure, usually it's 0x16 bytes
2784 long, but iuser.tlb contains some that are 0x18 bytes long.
2785 That's ok because we can use the next ptr to jump to the next
2786 one. But how do we know the length of the last one? The WORD
2787 at offs 0x8 might be the clue. For now I'm just assuming that
2788 the last one is the regular 0x16 bytes. */
2790 info = (SLTG_ImplInfo*)pBlk;
2792 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2793 sizeof(**ppImplType));
2794 (*ppImplType)->hRef = info->ref;
2795 (*ppImplType)->implflags = info->impltypeflags;
2796 pTI->TypeAttr.cImplTypes++;
2797 ppImplType = &(*ppImplType)->next;
2799 if(info->next == 0xffff)
2802 FIXME("Interface inheriting more than one interface\n");
2803 info = (SLTG_ImplInfo*)(pBlk + info->next);
2805 info++; /* see comment at top of function */
2809 static SLTG_TypeInfoTail *SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
2812 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2813 SLTG_MemberHeader *pMemHeader;
2814 char *pFirstItem, *pNextItem;
2816 if(pTIHeader->href_table != 0xffffffff) {
2817 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2822 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2824 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2826 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2827 pNextItem = SLTG_DoImpls(pFirstItem, pTI, FALSE);
2830 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2834 static SLTG_TypeInfoTail *SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
2837 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2838 SLTG_MemberHeader *pMemHeader;
2839 SLTG_Function *pFunc;
2840 char *pFirstItem, *pNextItem;
2841 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
2844 if(pTIHeader->href_table != 0xffffffff) {
2845 SLTG_DoRefs((SLTG_RefInfo*)(pBlk + pTIHeader->href_table), pTI,
2849 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2851 pFirstItem = pNextItem = (char*)(pMemHeader + 1);
2853 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
2854 pNextItem = SLTG_DoImpls(pFirstItem, pTI, TRUE);
2857 for(pFunc = (SLTG_Function*)pNextItem, num = 1; 1;
2858 pFunc = (SLTG_Function*)(pFirstItem + pFunc->next), num++) {
2863 if(pFunc->magic != SLTG_FUNCTION_MAGIC &&
2864 pFunc->magic != SLTG_FUNCTION_WITH_FLAGS_MAGIC) {
2865 FIXME("func magic = %02x\n", pFunc->magic);
2868 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2869 sizeof(**ppFuncDesc));
2870 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
2872 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
2873 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
2874 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
2875 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
2876 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
2877 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
2879 if(pFunc->magic == SLTG_FUNCTION_WITH_FLAGS_MAGIC)
2880 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
2882 if(pFunc->retnextopt & 0x80)
2883 pType = &pFunc->rettype;
2885 pType = (WORD*)(pFirstItem + pFunc->rettype);
2888 SLTG_DoType(pType, pFirstItem, &(*ppFuncDesc)->funcdesc.elemdescFunc);
2890 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
2891 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2892 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
2893 (*ppFuncDesc)->pParamDesc =
2894 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2895 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
2897 pArg = (WORD*)(pFirstItem + pFunc->arg_off);
2899 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
2900 char *paramName = pNameTable + *pArg;
2902 /* If arg type follows then paramName points to the 2nd
2903 letter of the name, else the next WORD is an offset to
2904 the arg type and paramName points to the first letter.
2905 So let's take one char off paramName and see if we're
2906 pointing at an alpha-numeric char. However if *pArg is
2907 0xffff or 0xfffe then the param has no name, the former
2908 meaning that the next WORD is the type, the latter
2909 meaning the the next WORD is an offset to the type. */
2914 else if(*pArg == 0xfffe) {
2918 else if(!isalnum(*(paramName-1)))
2923 if(HaveOffs) { /* the next word is an offset to type */
2924 pType = (WORD*)(pFirstItem + *pArg);
2925 SLTG_DoType(pType, pFirstItem,
2926 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2931 pArg = SLTG_DoType(pArg, pFirstItem,
2932 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param]);
2935 /* Are we an optional param ? */
2936 if((*ppFuncDesc)->funcdesc.cParams - param <=
2937 (*ppFuncDesc)->funcdesc.cParamsOpt)
2938 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
2941 (*ppFuncDesc)->pParamDesc[param].Name =
2942 TLB_MultiByteToBSTR(paramName);
2946 ppFuncDesc = &((*ppFuncDesc)->next);
2947 if(pFunc->next == 0xffff) break;
2949 pTI->TypeAttr.cFuncs = num;
2950 dump_TLBFuncDesc(pTI->funclist);
2951 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
2954 static SLTG_TypeInfoTail *SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
2957 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
2958 SLTG_MemberHeader *pMemHeader;
2959 SLTG_RecordItem *pItem;
2961 TLBVarDesc **ppVarDesc = &pTI->varlist;
2966 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
2968 pFirstItem = (char*)(pMemHeader + 1);
2969 for(pItem = (SLTG_RecordItem *)pFirstItem, num = 1; 1;
2970 pItem = (SLTG_RecordItem *)(pFirstItem + pItem->next), num++) {
2971 if(pItem->magic != SLTG_RECORD_MAGIC) {
2972 FIXME("record magic = %02x\n", pItem->magic);
2975 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
2976 sizeof(**ppVarDesc));
2977 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
2978 (*ppVarDesc)->vardesc.memid = pItem->memid;
2979 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
2980 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
2982 if(pItem->typepos == 0x02)
2983 pType = &pItem->type;
2984 else if(pItem->typepos == 0x00)
2985 pType = (WORD*)(pFirstItem + pItem->type);
2987 FIXME("typepos = %02x\n", pItem->typepos);
2991 SLTG_DoType(pType, pFirstItem,
2992 &(*ppVarDesc)->vardesc.elemdescVar);
2994 /* FIXME("helpcontext, helpstring\n"); */
2996 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
2998 ppVarDesc = &((*ppVarDesc)->next);
2999 if(pItem->next == 0xffff) break;
3001 pTI->TypeAttr.cVars = num;
3002 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3005 static SLTG_TypeInfoTail *SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3008 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3009 SLTG_MemberHeader *pMemHeader;
3010 SLTG_AliasItem *pItem;
3013 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3014 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3017 /* This is used for creating a TYPEDESC chain in case of VT_USERDEFINED */
3018 for (i = 0 ; i<pMemHeader->cbExtra/4 ; i++) {
3019 if (pItem->vt == 0xffff) {
3020 if (i<(pMemHeader->cbExtra/4-1))
3021 FIXME("Endmarker too early in process alias data!\n");
3025 FIXME("Chain extends over last entry?\n");
3028 if (pItem->vt == VT_USERDEFINED) {
3029 pTI->TypeAttr.tdescAlias.vt = pItem->vt;
3030 /* guessing here ... */
3031 FIXME("Guessing TKIND_ALIAS of VT_USERDEFINED with hreftype 0x%x\n",pItem->res02);
3032 pTI->TypeAttr.tdescAlias.u.hreftype = pItem->res02;
3035 FIXME("alias %d: 0x%x\n",i,pItem->vt);
3036 FIXME("alias %d: 0x%x\n",i,pItem->res02);
3040 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3043 static SLTG_TypeInfoTail *SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3046 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3047 SLTG_MemberHeader *pMemHeader;
3048 SLTG_AliasItem *pItem;
3050 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3051 pItem = (SLTG_AliasItem*)(pMemHeader + 1);
3052 FIXME("memh.cbExtra is %ld\n",pMemHeader->cbExtra);
3053 FIXME("offset 0 0x%x\n",*(WORD*)pItem);
3054 return (SLTG_TypeInfoTail*)((char*)(pMemHeader + 1)+pMemHeader->cbExtra);
3057 static SLTG_TypeInfoTail *SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3060 SLTG_TypeInfoHeader *pTIHeader = (SLTG_TypeInfoHeader*)pBlk;
3061 SLTG_MemberHeader *pMemHeader;
3062 SLTG_EnumItem *pItem;
3064 TLBVarDesc **ppVarDesc = &pTI->varlist;
3067 pMemHeader = (SLTG_MemberHeader*)(pBlk + pTIHeader->elem_table);
3069 pFirstItem = (char*)(pMemHeader + 1);
3070 for(pItem = (SLTG_EnumItem *)pFirstItem, num = 1; 1;
3071 pItem = (SLTG_EnumItem *)(pFirstItem + pItem->next), num++) {
3072 if(pItem->magic != SLTG_ENUMITEM_MAGIC) {
3073 FIXME("enumitem magic = %04x\n", pItem->magic);
3076 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3077 sizeof(**ppVarDesc));
3078 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3079 (*ppVarDesc)->vardesc.memid = pItem->memid;
3080 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3082 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3083 V_UNION((*ppVarDesc)->vardesc.u.lpvarValue, intVal) =
3084 *(INT*)(pItem->value + pFirstItem);
3085 (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt = VT_I4;
3086 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3087 /* FIXME("helpcontext, helpstring\n"); */
3089 ppVarDesc = &((*ppVarDesc)->next);
3090 if(pItem->next == 0xffff) break;
3092 pTI->TypeAttr.cVars = num;
3093 return (SLTG_TypeInfoTail*)(pFirstItem + pMemHeader->cbExtra);
3096 /* Because SLTG_OtherTypeInfo is such a painfull struct, we make a more
3097 managable copy of it into this */
3110 } SLTG_InternalOtherTypeInfo;
3112 /****************************************************************************
3113 * ITypeLib2_Constructor_SLTG
3115 * loading a SLTG typelib from an in-memory image
3117 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3119 ITypeLibImpl *pTypeLibImpl;
3120 SLTG_Header *pHeader;
3121 SLTG_BlkEntry *pBlkEntry;
3125 LPVOID pBlk, pFirstBlk;
3126 SLTG_LibBlk *pLibBlk;
3127 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3128 char *pAfterOTIBlks = NULL;
3129 char *pNameTable, *ptr;
3132 ITypeInfoImpl **ppTypeInfoImpl;
3134 TRACE("%p, TLB length = %ld\n", pLib, dwTLBLength);
3136 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
3137 if (!pTypeLibImpl) return NULL;
3139 pTypeLibImpl->lpVtbl = &tlbvt;
3140 pTypeLibImpl->ref = 1;
3145 TRACE("\tmagic=0x%08lx, file blocks = %d\n", pHeader->SLTG_magic,
3146 pHeader->nrOfFileBlks );
3147 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3148 FIXME("Header type magic 0x%08lx not supported.\n",
3149 pHeader->SLTG_magic);
3153 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3154 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3156 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3157 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3159 /* Next we have a magic block */
3160 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3162 /* Let's see if we're still in sync */
3163 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3164 sizeof(SLTG_COMPOBJ_MAGIC))) {
3165 FIXME("CompObj magic = %s\n", pMagic->CompObj_magic);
3168 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3169 sizeof(SLTG_DIR_MAGIC))) {
3170 FIXME("dir magic = %s\n", pMagic->dir_magic);
3174 pIndex = (SLTG_Index*)(pMagic+1);
3176 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3178 pFirstBlk = (LPVOID)(pPad9 + 1);
3180 /* We'll set up a ptr to the main library block, which is the last one. */
3182 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3183 pBlkEntry[order].next != 0;
3184 order = pBlkEntry[order].next - 1, i++) {
3185 pBlk = (char*)pBlk + pBlkEntry[order].len;
3189 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3191 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3196 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3198 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3199 sizeof(*pOtherTypeInfoBlks) *
3200 pTypeLibImpl->TypeInfoCount);
3203 ptr = (char*)pLibBlk + len;
3205 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3209 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3211 w = *(WORD*)(ptr + 2);
3214 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3216 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3217 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3219 w = *(WORD*)(ptr + 4 + len);
3221 TRACE("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3223 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3225 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3226 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3228 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3229 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3230 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3232 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3234 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3237 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3238 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3239 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3240 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3241 len += sizeof(SLTG_OtherTypeInfo);
3245 pAfterOTIBlks = ptr;
3247 /* Skip this WORD and get the next DWORD */
3248 len = *(DWORD*)(pAfterOTIBlks + 2);
3250 /* Now add this to pLibBLk look at what we're pointing at and
3251 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3252 dust and we should be pointing at the beginning of the name
3255 pNameTable = (char*)pLibBlk + len;
3257 switch(*(WORD*)pNameTable) {
3264 FIXME("pNameTable jump = %x\n", *(WORD*)pNameTable);
3268 pNameTable += 0x216;
3272 TRACE("Library name is %s\n", pNameTable + pLibBlk->name);
3274 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3277 /* Hopefully we now have enough ptrs set up to actually read in
3278 some TypeInfos. It's not clear which order to do them in, so
3279 I'll just follow the links along the BlkEntry chain and read
3280 them in in the order in which they're in the file */
3282 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3284 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3285 pBlkEntry[order].next != 0;
3286 order = pBlkEntry[order].next - 1, i++) {
3288 SLTG_TypeInfoHeader *pTIHeader;
3289 SLTG_TypeInfoTail *pTITail;
3291 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3292 pOtherTypeInfoBlks[i].index_name)) {
3293 FIXME("Index strings don't match\n");
3298 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3299 FIXME("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3302 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3303 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3304 (*ppTypeInfoImpl)->index = i;
3305 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3306 pOtherTypeInfoBlks[i].name_offs +
3308 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3309 memcpy(&((*ppTypeInfoImpl)->TypeAttr.guid), &pOtherTypeInfoBlks[i].uuid,
3311 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3312 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3313 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3314 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3315 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3317 if((pTIHeader->typeflags1 & 7) != 2)
3318 FIXME("typeflags1 = %02x\n", pTIHeader->typeflags1);
3319 if(pTIHeader->typeflags3 != 2)
3320 FIXME("typeflags3 = %02x\n", pTIHeader->typeflags3);
3322 TRACE("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3323 debugstr_w((*ppTypeInfoImpl)->Name),
3324 typekind_desc[pTIHeader->typekind],
3325 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3326 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3328 switch(pTIHeader->typekind) {
3330 pTITail = SLTG_ProcessEnum(pBlk, *ppTypeInfoImpl, pNameTable);
3334 pTITail = SLTG_ProcessRecord(pBlk, *ppTypeInfoImpl, pNameTable);
3337 case TKIND_INTERFACE:
3338 pTITail = SLTG_ProcessInterface(pBlk, *ppTypeInfoImpl, pNameTable);
3342 pTITail = SLTG_ProcessCoClass(pBlk, *ppTypeInfoImpl, pNameTable);
3346 pTITail = SLTG_ProcessAlias(pBlk, *ppTypeInfoImpl, pNameTable);
3347 if (pTITail->tdescalias_vt)
3348 (*ppTypeInfoImpl)->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3351 case TKIND_DISPATCH:
3352 pTITail = SLTG_ProcessDispatch(pBlk, *ppTypeInfoImpl, pNameTable);
3356 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
3362 if(pTITail) { /* could get cFuncs, cVars and cImplTypes from here
3363 but we've already set those */
3364 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3365 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3366 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3368 #define X(x) TRACE("tt "#x": %x\n",pTITail->res##x);
3390 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
3391 pBlk = (char*)pBlk + pBlkEntry[order].len;
3394 if(i != pTypeLibImpl->TypeInfoCount) {
3395 FIXME("Somehow processed %d TypeInfos\n", i);
3399 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
3400 return (ITypeLib2*)pTypeLibImpl;
3403 /* ITypeLib::QueryInterface
3405 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
3410 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3412 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
3415 if(IsEqualIID(riid, &IID_IUnknown) ||
3416 IsEqualIID(riid,&IID_ITypeLib)||
3417 IsEqualIID(riid,&IID_ITypeLib2))
3424 ITypeLib2_AddRef(iface);
3425 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
3428 TRACE("-- Interface: E_NOINTERFACE\n");
3429 return E_NOINTERFACE;
3434 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
3436 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3438 TRACE("(%p)->ref was %u\n",This, This->ref);
3440 return ++(This->ref);
3443 /* ITypeLib::Release
3445 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
3447 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3451 TRACE("(%p)->(%u)\n",This, This->ref);
3455 /* remove cache entry */
3456 TRACE("removing from cache list\n");
3457 EnterCriticalSection(&cache_section);
3458 if (This->next) This->next->prev = This->prev;
3459 if (This->prev) This->prev->next = This->next;
3460 else tlb_cache_first = This->next;
3461 LeaveCriticalSection(&cache_section);
3463 /* FIXME destroy child objects */
3464 TRACE(" destroying ITypeLib(%p)\n",This);
3468 SysFreeString(This->Name);
3472 if (This->DocString)
3474 SysFreeString(This->DocString);
3475 This->DocString = NULL;
3480 SysFreeString(This->HelpFile);
3481 This->HelpFile = NULL;
3484 if (This->HelpStringDll)
3486 SysFreeString(This->HelpStringDll);
3487 This->HelpStringDll = NULL;
3490 if (This->pTypeInfo) /* can be NULL */
3491 ITypeInfo_Release((ITypeInfo*) This->pTypeInfo);
3492 HeapFree(GetProcessHeap(),0,This);
3499 /* ITypeLib::GetTypeInfoCount
3501 * Returns the number of type descriptions in the type library
3503 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
3505 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3506 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
3507 return This->TypeInfoCount;
3510 /* ITypeLib::GetTypeInfo
3512 * retrieves the specified type description in the library.
3514 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
3517 ITypeInfo **ppTInfo)
3521 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3522 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
3524 TRACE("(%p)->(index=%d) \n", This, index);
3526 if (!ppTInfo) return E_INVALIDARG;
3528 /* search element n in list */
3529 for(i=0; i < index; i++)
3531 pTypeInfo = pTypeInfo->next;
3534 TRACE("-- element not found\n");
3535 return TYPE_E_ELEMENTNOTFOUND;
3539 *ppTInfo = (ITypeInfo *) pTypeInfo;
3541 ITypeInfo_AddRef(*ppTInfo);
3542 TRACE("-- found (%p)\n",*ppTInfo);
3547 /* ITypeLibs::GetTypeInfoType
3549 * Retrieves the type of a type description.
3551 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
3556 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3558 ITypeInfoImpl *pTInfo = This->pTypeInfo;
3560 TRACE("(%p) index %d \n",This, index);
3562 if(!pTKind) return E_INVALIDARG;
3564 /* search element n in list */
3565 for(i=0; i < index; i++)
3569 TRACE("-- element not found\n");
3570 return TYPE_E_ELEMENTNOTFOUND;
3572 pTInfo = pTInfo->next;
3575 *pTKind = pTInfo->TypeAttr.typekind;
3576 TRACE("-- found Type (%d)\n", *pTKind);
3580 /* ITypeLib::GetTypeInfoOfGuid
3582 * Retrieves the type description that corresponds to the specified GUID.
3585 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
3588 ITypeInfo **ppTInfo)
3590 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3591 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
3593 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
3595 if (!pTypeInfo) return TYPE_E_ELEMENTNOTFOUND;
3597 /* search linked list for guid */
3598 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
3600 pTypeInfo = pTypeInfo->next;
3604 /* end of list reached */
3605 TRACE("-- element not found\n");
3606 return TYPE_E_ELEMENTNOTFOUND;
3610 TRACE("-- found (%p, %s)\n",
3612 debugstr_w(pTypeInfo->Name));
3614 *ppTInfo = (ITypeInfo*)pTypeInfo;
3615 ITypeInfo_AddRef(*ppTInfo);
3619 /* ITypeLib::GetLibAttr
3621 * Retrieves the structure that contains the library's attributes.
3624 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
3626 LPTLIBATTR *ppTLibAttr)
3628 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3629 TRACE("(%p)\n",This);
3630 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
3631 memcpy(*ppTLibAttr, &This->LibAttr, sizeof(**ppTLibAttr));
3635 /* ITypeLib::GetTypeComp
3637 * Enables a client compiler to bind to a library's types, variables,
3638 * constants, and global functions.
3641 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
3643 ITypeComp **ppTComp)
3645 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3647 TRACE("(%p)->(%p)\n",This,ppTComp);
3648 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
3649 ITypeComp_AddRef(*ppTComp);
3654 /* ITypeLib::GetDocumentation
3656 * Retrieves the library's documentation string, the complete Help file name
3657 * and path, and the context identifier for the library Help topic in the Help
3660 * On a successful return all non-null BSTR pointers will have been set,
3663 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
3667 BSTR *pBstrDocString,
3668 DWORD *pdwHelpContext,
3669 BSTR *pBstrHelpFile)
3671 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3673 HRESULT result = E_INVALIDARG;
3678 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
3680 pBstrName, pBstrDocString,
3681 pdwHelpContext, pBstrHelpFile);
3685 /* documentation for the typelib */
3689 if(!(*pBstrName = SysAllocString(This->Name))) goto memerr1;else;
3695 if (This->DocString)
3696 if(!(*pBstrDocString = SysAllocString(This->DocString))) goto memerr2;else;
3697 else if (This->Name)
3698 if(!(*pBstrDocString = SysAllocString(This->Name))) goto memerr2;else;
3700 *pBstrDocString = NULL;
3704 *pdwHelpContext = This->dwHelpContext;
3709 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile))) goto memerr3;else;
3711 *pBstrHelpFile = NULL;
3718 /* for a typeinfo */
3719 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
3721 if(SUCCEEDED(result))
3723 result = ITypeInfo_GetDocumentation(pTInfo,
3727 pdwHelpContext, pBstrHelpFile);
3729 ITypeInfo_Release(pTInfo);
3734 if (pBstrDocString) SysFreeString (*pBstrDocString);
3736 if (pBstrName) SysFreeString (*pBstrName);
3738 return STG_E_INSUFFICIENTMEMORY;
3743 * Indicates whether a passed-in string contains the name of a type or member
3744 * described in the library.
3747 static HRESULT WINAPI ITypeLib2_fnIsName(
3753 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3754 ITypeInfoImpl *pTInfo;
3755 TLBFuncDesc *pFInfo;
3758 UINT nNameBufLen = SysStringLen(szNameBuf);
3760 TRACE("(%p)->(%s,%08lx,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
3764 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
3765 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3766 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3767 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3768 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3769 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
3770 goto ITypeLib2_fnIsName_exit;
3772 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3773 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
3778 ITypeLib2_fnIsName_exit:
3779 TRACE("(%p)slow! search for %s: %s found!\n", This,
3780 debugstr_w(szNameBuf), *pfName?"NOT":"");
3785 /* ITypeLib::FindName
3787 * Finds occurrences of a type description in a type library. This may be used
3788 * to quickly verify that a name exists in a type library.
3791 static HRESULT WINAPI ITypeLib2_fnFindName(
3795 ITypeInfo **ppTInfo,
3799 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3800 ITypeInfoImpl *pTInfo;
3801 TLBFuncDesc *pFInfo;
3805 UINT nNameBufLen = SysStringLen(szNameBuf);
3807 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
3808 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3809 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
3810 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3811 for(i=0;i<pFInfo->funcdesc.cParams;i++)
3812 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
3813 goto ITypeLib2_fnFindName_exit;
3815 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
3816 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
3818 ITypeLib2_fnFindName_exit:
3819 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
3820 ppTInfo[j]=(LPTYPEINFO)pTInfo;
3823 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
3824 This, *pcFound, debugstr_w(szNameBuf), j);
3831 /* ITypeLib::ReleaseTLibAttr
3833 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
3836 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
3838 TLIBATTR *pTLibAttr)
3840 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3841 TRACE("freeing (%p)\n",This);
3842 HeapFree(GetProcessHeap(),0,pTLibAttr);
3846 /* ITypeLib2::GetCustData
3848 * gets the custom data
3850 static HRESULT WINAPI ITypeLib2_fnGetCustData(
3855 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3856 TLBCustData *pCData;
3858 for(pCData=This->pCustData; pCData; pCData = pCData->next)
3860 if( IsEqualIID(guid, &pCData->guid)) break;
3863 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
3867 VariantInit( pVarVal);
3868 VariantCopy( pVarVal, &pCData->data);
3871 return E_INVALIDARG; /* FIXME: correct? */
3874 /* ITypeLib2::GetLibStatistics
3876 * Returns statistics about a type library that are required for efficient
3877 * sizing of hash tables.
3880 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
3882 ULONG *pcUniqueNames,
3883 ULONG *pcchUniqueNames)
3885 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3887 FIXME("(%p): stub!\n", This);
3889 if(pcUniqueNames) *pcUniqueNames=1;
3890 if(pcchUniqueNames) *pcchUniqueNames=1;
3894 /* ITypeLib2::GetDocumentation2
3896 * Retrieves the library's documentation string, the complete Help file name
3897 * and path, the localization context to use, and the context ID for the
3898 * library Help topic in the Help file.
3901 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
3905 BSTR *pbstrHelpString,
3906 DWORD *pdwHelpStringContext,
3907 BSTR *pbstrHelpStringDll)
3909 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3913 FIXME("(%p) index %d lcid %ld half implemented stub!\n", This, index, lcid);
3915 /* the help string should be obtained from the helpstringdll,
3916 * using the _DLLGetDocumentation function, based on the supplied
3917 * lcid. Nice to do sometime...
3921 /* documentation for the typelib */
3923 *pbstrHelpString=SysAllocString(This->DocString);
3924 if(pdwHelpStringContext)
3925 *pdwHelpStringContext=This->dwHelpContext;
3926 if(pbstrHelpStringDll)
3927 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
3933 /* for a typeinfo */
3934 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
3936 if(SUCCEEDED(result))
3938 ITypeInfo2 * pTInfo2;
3939 result = ITypeInfo_QueryInterface(pTInfo,
3941 (LPVOID*) &pTInfo2);
3943 if(SUCCEEDED(result))
3945 result = ITypeInfo2_GetDocumentation2(pTInfo2,
3949 pdwHelpStringContext,
3950 pbstrHelpStringDll);
3952 ITypeInfo2_Release(pTInfo2);
3955 ITypeInfo_Release(pTInfo);
3961 /* ITypeLib2::GetAllCustData
3963 * Gets all custom data items for the library.
3966 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
3968 CUSTDATA *pCustData)
3970 ITypeLibImpl *This = (ITypeLibImpl *)iface;
3971 TLBCustData *pCData;
3973 TRACE("(%p) returning %d items\n", This, This->ctCustData);
3974 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
3975 if(pCustData->prgCustData ){
3976 pCustData->cCustData=This->ctCustData;
3977 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
3978 pCustData->prgCustData[i].guid=pCData->guid;
3979 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
3982 ERR(" OUT OF MEMORY! \n");
3983 return E_OUTOFMEMORY;
3988 static ITypeLib2Vtbl tlbvt = {
3989 ITypeLib2_fnQueryInterface,
3991 ITypeLib2_fnRelease,
3992 ITypeLib2_fnGetTypeInfoCount,
3993 ITypeLib2_fnGetTypeInfo,
3994 ITypeLib2_fnGetTypeInfoType,
3995 ITypeLib2_fnGetTypeInfoOfGuid,
3996 ITypeLib2_fnGetLibAttr,
3997 ITypeLib2_fnGetTypeComp,
3998 ITypeLib2_fnGetDocumentation,
4000 ITypeLib2_fnFindName,
4001 ITypeLib2_fnReleaseTLibAttr,
4003 ITypeLib2_fnGetCustData,
4004 ITypeLib2_fnGetLibStatistics,
4005 ITypeLib2_fnGetDocumentation2,
4006 ITypeLib2_fnGetAllCustData
4010 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4012 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4014 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
4017 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4019 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4021 return ITypeInfo_AddRef((ITypeInfo *)This);
4024 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4026 ICOM_THIS_From_ITypeComp(ITypeLibImpl, iface);
4028 return ITypeInfo_Release((ITypeInfo *)This);
4031 static HRESULT WINAPI ITypeLibComp_fnBind(
4036 ITypeInfo ** ppTInfo,
4037 DESCKIND * pDescKind,
4040 FIXME("(%s, %lx, 0x%x, %p, %p, %p): stub\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4044 static HRESULT WINAPI ITypeLibComp_fnBindType(
4048 ITypeInfo ** ppTInfo,
4049 ITypeComp ** ppTComp)
4051 FIXME("(%s, %lx, %p, %p): stub\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4055 static ITypeCompVtbl tlbtcvt =
4058 ITypeLibComp_fnQueryInterface,
4059 ITypeLibComp_fnAddRef,
4060 ITypeLibComp_fnRelease,
4062 ITypeLibComp_fnBind,
4063 ITypeLibComp_fnBindType
4066 /*================== ITypeInfo(2) Methods ===================================*/
4067 static ITypeInfo2 * WINAPI ITypeInfo_Constructor(void)
4069 ITypeInfoImpl * pTypeInfoImpl;
4071 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4074 pTypeInfoImpl->lpVtbl = &tinfvt;
4075 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4076 pTypeInfoImpl->ref=1;
4078 TRACE("(%p)\n", pTypeInfoImpl);
4079 return (ITypeInfo2*) pTypeInfoImpl;
4082 /* ITypeInfo::QueryInterface
4084 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4089 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4091 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4094 if(IsEqualIID(riid, &IID_IUnknown) ||
4095 IsEqualIID(riid,&IID_ITypeInfo)||
4096 IsEqualIID(riid,&IID_ITypeInfo2))
4100 ITypeInfo_AddRef(iface);
4101 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4104 TRACE("-- Interface: E_NOINTERFACE\n");
4105 return E_NOINTERFACE;
4108 /* ITypeInfo::AddRef
4110 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4112 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4115 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4117 TRACE("(%p)->ref is %u\n",This, This->ref);
4121 /* ITypeInfo::Release
4123 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
4125 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4129 TRACE("(%p)->(%u)\n",This, This->ref);
4132 /* We don't release ITypeLib when ref=0 becouse
4133 it means that funtion is called by ITypeLi2_Release */
4134 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
4136 FIXME("destroy child objects\n");
4138 TRACE("destroying ITypeInfo(%p)\n",This);
4141 SysFreeString(This->Name);
4145 if (This->DocString)
4147 SysFreeString(This->DocString);
4148 This->DocString = 0;
4153 ITypeInfo_Release((ITypeInfo*)This->next);
4156 HeapFree(GetProcessHeap(),0,This);
4162 /* ITypeInfo::GetTypeAttr
4164 * Retrieves a TYPEATTR structure that contains the attributes of the type
4168 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
4169 LPTYPEATTR *ppTypeAttr)
4171 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4172 TRACE("(%p)\n",This);
4173 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTypeAttr));
4174 memcpy(*ppTypeAttr, &This->TypeAttr, sizeof(**ppTypeAttr));
4176 if(This->TypeAttr.typekind == TKIND_ALIAS) /* need to deep copy typedesc */
4177 copy_typedesc(&(*ppTypeAttr)->tdescAlias, &This->TypeAttr.tdescAlias);
4179 if((*ppTypeAttr)->typekind == TKIND_DISPATCH && (*ppTypeAttr)->wTypeFlags & TYPEFLAG_FDUAL) {
4180 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / 4; /* This should include all the inherited
4182 (*ppTypeAttr)->cbSizeVft = 28; /* This is always the size of IDispatch's vtbl */
4183 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
4188 /* ITypeInfo::GetTypeComp
4190 * Retrieves the ITypeComp interface for the type description, which enables a
4191 * client compiler to bind to the type description's members.
4194 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
4195 ITypeComp * *ppTComp)
4197 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4199 TRACE("(%p)->(%p) stub!\n", This, ppTComp);
4201 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4202 ITypeComp_AddRef(*ppTComp);
4206 /* ITypeInfo::GetFuncDesc
4208 * Retrieves the FUNCDESC structure that contains information about a
4209 * specified function.
4212 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
4213 LPFUNCDESC *ppFuncDesc)
4215 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4217 TLBFuncDesc * pFDesc;
4218 TRACE("(%p) index %d\n", This, index);
4219 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
4222 /* FIXME: must do a copy here */
4223 *ppFuncDesc=&pFDesc->funcdesc;
4226 return E_INVALIDARG;
4229 /* ITypeInfo::GetVarDesc
4231 * Retrieves a VARDESC structure that describes the specified variable.
4234 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
4235 LPVARDESC *ppVarDesc)
4237 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4239 TLBVarDesc * pVDesc;
4240 TRACE("(%p) index %d\n", This, index);
4241 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
4244 /* FIXME: must do a copy here */
4245 *ppVarDesc=&pVDesc->vardesc;
4248 return E_INVALIDARG;
4251 /* ITypeInfo_GetNames
4253 * Retrieves the variable with the specified member ID (or the name of the
4254 * property or method and its parameters) that correspond to the specified
4257 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
4258 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
4260 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4261 TLBFuncDesc * pFDesc;
4262 TLBVarDesc * pVDesc;
4264 TRACE("(%p) memid=0x%08lx Maxname=%d\n", This, memid, cMaxNames);
4265 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
4268 /* function found, now return function and parameter names */
4269 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
4272 *rgBstrNames=SysAllocString(pFDesc->Name);
4274 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
4280 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
4283 *rgBstrNames=SysAllocString(pVDesc->Name);
4288 if(This->TypeAttr.cImplTypes &&
4289 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4290 /* recursive search */
4293 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
4295 if(SUCCEEDED(result))
4297 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
4298 ITypeInfo_Release(pTInfo);
4301 WARN("Could not search inherited interface!\n");
4305 WARN("no names found\n");
4308 return TYPE_E_ELEMENTNOTFOUND;
4315 /* ITypeInfo::GetRefTypeOfImplType
4317 * If a type description describes a COM class, it retrieves the type
4318 * description of the implemented interface types. For an interface,
4319 * GetRefTypeOfImplType returns the type information for inherited interfaces,
4323 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
4328 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4330 TLBImplType *pImpl = This->impltypelist;
4332 TRACE("(%p) index %d\n", This, index);
4333 if (TRACE_ON(ole)) dump_TypeInfo(This);
4337 /* only valid on dual interfaces;
4338 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
4340 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
4342 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDISPATCHABLE &&
4343 This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL )
4349 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4350 *pRefType = pImpl->hRef;
4355 /* get element n from linked list */
4356 for(i=0; pImpl && i<index; i++)
4358 pImpl = pImpl->next;
4361 if (!pImpl) return TYPE_E_ELEMENTNOTFOUND;
4363 *pRefType = pImpl->hRef;
4365 TRACE("-- 0x%08lx\n", pImpl->hRef );
4372 /* ITypeInfo::GetImplTypeFlags
4374 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
4375 * or base interface in a type description.
4377 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
4378 UINT index, INT *pImplTypeFlags)
4380 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4384 TRACE("(%p) index %d\n", This, index);
4385 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
4386 i++, pImpl=pImpl->next)
4388 if(i==index && pImpl){
4389 *pImplTypeFlags=pImpl->implflags;
4393 return TYPE_E_ELEMENTNOTFOUND;
4397 * Maps between member names and member IDs, and parameter names and
4400 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
4401 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
4403 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4404 TLBFuncDesc * pFDesc;
4405 TLBVarDesc * pVDesc;
4408 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
4410 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
4412 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
4413 if(cNames) *pMemId=pFDesc->funcdesc.memid;
4414 for(i=1; i < cNames; i++){
4415 for(j=0; j<pFDesc->funcdesc.cParams; j++)
4416 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
4418 if( j<pFDesc->funcdesc.cParams)
4421 ret=DISP_E_UNKNOWNNAME;
4426 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
4427 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
4428 if(cNames) *pMemId=pVDesc->vardesc.memid;
4432 /* not found, see if this is and interface with an inheritance */
4433 if(This->TypeAttr.cImplTypes &&
4434 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
4435 /* recursive search */
4437 ret=ITypeInfo_GetRefTypeInfo(iface,
4438 This->impltypelist->hRef, &pTInfo);
4440 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
4441 ITypeInfo_Release(pTInfo);
4444 WARN("Could not search inherited interface!\n");
4446 WARN("no names found\n");
4447 return DISP_E_UNKNOWNNAME;
4450 /* ITypeInfo::Invoke
4452 * Invokes a method, or accesses a property of an object, that implements the
4453 * interface described by the type description.
4456 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
4459 if (TRACE_ON(ole)) {
4461 TRACE("Calling %p(",func);
4462 for (i=0;i<nrargs;i++) TRACE("%08lx,",args[i]);
4474 res = func(args[0]);
4477 res = func(args[0],args[1]);
4480 res = func(args[0],args[1],args[2]);
4483 res = func(args[0],args[1],args[2],args[3]);
4486 res = func(args[0],args[1],args[2],args[3],args[4]);
4489 res = func(args[0],args[1],args[2],args[3],args[4],args[5]);
4492 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6]);
4495 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7]);
4498 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8]);
4501 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9]);
4504 res = func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],args[9],args[10]);
4507 FIXME("unsupported number of arguments %d in stdcall\n",nrargs);
4513 FIXME("unsupported calling convention %d\n",callconv);
4517 TRACE("returns %08lx\n",res);
4521 extern int _argsize(DWORD vt);
4523 /****************************************************************************
4524 * Helper functions for Dispcall / Invoke, which copies one variant
4525 * with target type onto the argument stack.
4528 _copy_arg( ITypeInfo2 *tinfo, TYPEDESC *tdesc,
4529 DWORD *argpos, VARIANT *arg, VARTYPE vt
4531 UINT arglen = _argsize(vt)*sizeof(DWORD);
4535 if ((vt==VT_PTR) && tdesc && (tdesc->u.lptdesc->vt == VT_VARIANT)) {
4536 memcpy(argpos,&arg,sizeof(void*));
4540 if (V_VT(arg) == vt) {
4541 memcpy(argpos, &V_UNION(arg,lVal), arglen);
4545 if (V_ISARRAY(arg) && (vt == VT_SAFEARRAY)) {
4546 memcpy(argpos, &V_UNION(arg,parray), sizeof(SAFEARRAY*));
4550 if (vt == VT_VARIANT) {
4551 memcpy(argpos, arg, arglen);
4554 /* Deref BYREF vars if there is need */
4555 if(V_ISBYREF(arg) && ((V_VT(arg) & ~VT_BYREF)==vt)) {
4556 memcpy(argpos,(void*)V_UNION(arg,lVal), arglen);
4559 if (vt==VT_UNKNOWN && V_VT(arg)==VT_DISPATCH) {
4560 /* in this context, if the type lib specifies IUnknown*, giving an
4561 IDispatch* is correct; so, don't invoke VariantChangeType */
4562 memcpy(argpos,&V_UNION(arg,lVal), arglen);
4565 if ((vt == VT_PTR) && tdesc)
4566 return _copy_arg(tinfo, tdesc->u.lptdesc, argpos, arg, tdesc->u.lptdesc->vt);
4568 if ((vt == VT_USERDEFINED) && tdesc && tinfo) {
4569 ITypeInfo *tinfo2 = NULL;
4570 TYPEATTR *tattr = NULL;
4573 hres = ITypeInfo_GetRefTypeInfo(tinfo,tdesc->u.hreftype,&tinfo2);
4575 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, "
4576 "while coercing from vt 0x%x. Copying 4 byte.\n",
4577 tdesc->u.hreftype,V_VT(arg));
4578 memcpy(argpos, &V_UNION(arg,lVal), 4);
4581 hres = ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4584 ERR("GetTypeAttr failed\n");
4585 ITypeInfo_Release(tinfo2);
4588 switch (tattr->typekind) {
4590 switch ( V_VT( arg ) ) {
4592 *argpos = V_UNION(arg,iVal);
4596 memcpy(argpos, &V_UNION(arg,lVal), 4);
4600 FIXME("vt 0x%x -> TKIND_ENUM unhandled.\n",V_VT(arg));
4607 tdesc = &(tattr->tdescAlias);
4608 hres = _copy_arg((ITypeInfo2*)tinfo2, tdesc, argpos, arg, tdesc->vt);
4611 case TKIND_INTERFACE:
4612 if (V_VT(arg) == VT_DISPATCH) {
4614 if (IsEqualIID(&IID_IDispatch,&(tattr->guid))) {
4615 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4619 hres=IUnknown_QueryInterface(V_UNION(arg,pdispVal),
4620 &IID_IDispatch,(LPVOID*)&disp);
4621 if (SUCCEEDED(hres)) {
4622 memcpy(argpos,&disp,4);
4623 IUnknown_Release(V_UNION(arg,pdispVal));
4627 FIXME("Failed to query IDispatch interface from %s while "
4628 "converting to VT_DISPATCH!\n",debugstr_guid(&(tattr->guid)));
4632 if (V_VT(arg) == VT_UNKNOWN) {
4633 memcpy(argpos, &V_UNION(arg,punkVal), 4);
4637 FIXME("vt 0x%x -> TKIND_INTERFACE(%s) unhandled\n",
4638 V_VT(arg),debugstr_guid(&(tattr->guid)));
4642 case TKIND_DISPATCH:
4643 if (V_VT(arg) == VT_DISPATCH) {
4644 memcpy(argpos, &V_UNION(arg,pdispVal), 4);
4649 FIXME("TKIND_DISPATCH unhandled for target vt 0x%x.\n",V_VT(arg));
4653 FIXME("TKIND_RECORD unhandled.\n");
4657 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4661 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
4662 ITypeInfo_Release(tinfo2);
4668 if (VariantChangeType(&va,arg,0,vt)==S_OK) {
4669 memcpy(argpos,&V_UNION(&va,lVal), arglen);
4670 FIXME("Should not use VariantChangeType here."
4671 " (conversion from 0x%x -> 0x%x) %08lx\n",
4672 V_VT(arg), vt, *argpos
4676 ERR("Set arg to disparg type 0x%x vs 0x%x\n",V_VT(arg),vt);
4680 /***********************************************************************
4681 * DispCallFunc (OLEAUT32.@)
4685 void* pvInstance, ULONG oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
4686 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult
4688 int i, argsize, argspos;
4692 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
4693 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult)
4695 /* DispCallFunc is only used to invoke methods belonging to an IDispatch-derived COM interface.
4696 So we need to add a first parameter to the list of arguments, to supply the interface pointer */
4698 for (i=0;i<cActuals;i++) {
4699 TRACE("arg %d: type %d, size %d\n",i,prgvt[i],_argsize(prgvt[i]));
4700 dump_Variant(prgpvarg[i]);
4701 argsize += _argsize(prgvt[i]);
4703 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
4704 args[0] = (DWORD)pvInstance; /* this is the fake IDispatch interface pointer */
4706 for (i=0;i<cActuals;i++) {
4707 VARIANT *arg = prgpvarg[i];
4708 TRACE("Storing arg %d (%d as %d)\n",i,V_VT(arg),prgvt[i]);
4709 _copy_arg(NULL, NULL, &args[argspos], arg, prgvt[i]);
4710 argspos += _argsize(prgvt[i]);
4713 if(pvargResult!=NULL && V_VT(pvargResult)==VT_EMPTY)
4715 _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4720 FIXME("Do not know how to handle pvargResult %p. Expect crash ...\n",pvargResult);
4721 hres = _invoke((*(FARPROC**)pvInstance)[oVft/4],cc,argsize,args);
4722 FIXME("Method returned %lx\n",hres);
4724 HeapFree(GetProcessHeap(),0,args);
4728 static HRESULT WINAPI ITypeInfo_fnInvoke(
4733 DISPPARAMS *pDispParams,
4734 VARIANT *pVarResult,
4735 EXCEPINFO *pExcepInfo,
4738 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4740 unsigned int func_index, var_index;
4744 TRACE("(%p)(%p,id=%ld,flags=0x%08x,%p,%p,%p,%p) partial stub!\n",
4745 This,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
4747 dump_DispParms(pDispParams);
4749 hres = ITypeInfo2_GetFuncIndexOfMemId(iface, memid, dwFlags, &func_index);
4750 if (SUCCEEDED(hres)) {
4751 FUNCDESC *func_desc;
4753 hres = ITypeInfo2_GetFuncDesc(iface, func_index, &func_desc);
4754 if(FAILED(hres)) return hres;
4756 switch (func_desc->funckind) {
4757 case FUNC_PUREVIRTUAL:
4758 case FUNC_VIRTUAL: {
4760 int numargs, numargs2, argspos, args2pos;
4761 DWORD *args , *args2;
4762 VARIANT *rgvarg = HeapAlloc(GetProcessHeap(), 0, sizeof(VARIANT) * func_desc->cParams);
4763 memcpy(rgvarg,pDispParams->rgvarg,sizeof(VARIANT)*pDispParams->cArgs);
4766 numargs = 1; numargs2 = 0;
4767 for (i = 0; i < func_desc->cParams; i++) {
4768 if (i<pDispParams->cArgs)
4769 numargs += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4771 numargs += 1; /* sizeof(lpvoid) */
4772 numargs2 += _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4776 args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs);
4777 args2 = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*numargs2);
4779 args[0] = (DWORD)pIUnk;
4780 argspos = 1; args2pos = 0;
4781 for (i = 0; i < func_desc->cParams; i++) {
4782 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4783 if (i<pDispParams->cArgs) {
4784 VARIANT *arg = &rgvarg[pDispParams->cArgs-i-1];
4785 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4786 USHORT paramFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
4787 if (paramFlags & PARAMFLAG_FOPT) {
4788 if(i < func_desc->cParams - func_desc->cParamsOpt)
4789 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4790 if(V_VT(arg) == VT_EMPTY
4791 || ((V_VT(arg) & VT_BYREF) && !V_BYREF(arg))) {
4792 /* FIXME: Documentation says that we do this when parameter is left unspecified.
4793 How to determine it? */
4795 if(paramFlags & PARAMFLAG_FHASDEFAULT)
4796 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4797 V_VT(arg) = VT_ERROR;
4798 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4799 arglen = _argsize(VT_ERROR);
4802 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4803 if (FAILED(hres)) goto func_fail;
4805 } else if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FOPT) {
4806 VARIANT *arg = &rgvarg[i];
4807 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
4808 if(i < func_desc->cParams - func_desc->cParamsOpt)
4809 ERR("Parameter has PARAMFLAG_FOPT flag but is not one of last cParamOpt parameters\n");
4810 if(func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4811 FIXME("PARAMFLAG_FHASDEFAULT flag not supported\n");
4812 V_VT(arg) = VT_ERROR;
4813 V_ERROR(arg) = DISP_E_PARAMNOTFOUND;
4814 arglen = _argsize(VT_ERROR);
4815 hres = _copy_arg(iface, tdesc, &args[argspos], arg, tdesc->vt);
4816 if (FAILED(hres)) goto func_fail;
4819 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i].tdesc);
4820 if (tdesc->vt != VT_PTR)
4821 FIXME("set %d to pointer for get (type is %d)\n",i,tdesc->vt);
4822 /*FIXME: give pointers for the rest, so propertyget works*/
4823 args[argspos] = (DWORD)&args2[args2pos];
4825 /* If pointer to variant, pass reference it. */
4826 if ((tdesc->vt == VT_PTR) &&
4827 (tdesc->u.lptdesc->vt == VT_VARIANT) &&
4830 args[argspos]= (DWORD)pVarResult;
4835 if (func_desc->cParamsOpt < 0)
4836 FIXME("Does not support optional parameters (%d)\n", func_desc->cParamsOpt);
4838 res = _invoke((*(FARPROC**)pIUnk)[func_desc->oVft/4],
4839 func_desc->callconv,
4844 if (pVarResult && (dwFlags & (DISPATCH_PROPERTYGET))) {
4846 for (i = 0; i < func_desc->cParams - pDispParams->cArgs; i++) {
4847 int arglen = _argsize(func_desc->lprgelemdescParam[i].tdesc.vt);
4848 TYPEDESC *tdesc = &(func_desc->lprgelemdescParam[i + pDispParams->cArgs].tdesc);
4850 i4_tdesc.vt = VT_I4;
4852 /* If we are a pointer to a variant, we are done already */
4853 if ((tdesc->vt==VT_PTR)&&(tdesc->u.lptdesc->vt==VT_VARIANT))
4856 VariantInit(pVarResult);
4857 memcpy(&V_UNION(pVarResult,intVal),&args2[args2pos],arglen*sizeof(DWORD));
4859 if (tdesc->vt == VT_PTR)
4860 tdesc = tdesc->u.lptdesc;
4861 if (tdesc->vt == VT_USERDEFINED) {
4865 hres = ITypeInfo_GetRefTypeInfo(iface,tdesc->u.hreftype,&tinfo2);
4867 FIXME("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, while coercing. Copying 4 byte.\n",tdesc->u.hreftype);
4870 ITypeInfo_GetTypeAttr(tinfo2,&tattr);
4871 switch (tattr->typekind) {
4873 /* force the return type to be VT_I4 */
4877 TRACE("TKIND_ALIAS to vt 0x%x\n",tattr->tdescAlias.vt);
4878 tdesc = &(tattr->tdescAlias);
4881 case TKIND_INTERFACE:
4882 FIXME("TKIND_INTERFACE unhandled.\n");
4884 case TKIND_DISPATCH:
4885 FIXME("TKIND_DISPATCH unhandled.\n");
4888 FIXME("TKIND_RECORD unhandled.\n");
4891 FIXME("TKIND %d unhandled.\n",tattr->typekind);
4894 ITypeInfo_Release(tinfo2);
4896 V_VT(pVarResult) = tdesc->vt;
4898 /* HACK: VB5 likes this.
4899 * I do not know why. There is 1 example in MSDN which uses
4900 * this which appears broken (mixes int vals and
4903 if ((tdesc->vt == VT_PTR) && (dwFlags & DISPATCH_METHOD))
4904 V_VT(pVarResult) = VT_DISPATCH;
4905 TRACE("storing into variant:\n");
4906 dump_Variant(pVarResult);
4911 HeapFree(GetProcessHeap(), 0, rgvarg);
4912 HeapFree(GetProcessHeap(),0,args2);
4913 HeapFree(GetProcessHeap(),0,args);
4916 case FUNC_DISPATCH: {
4919 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
4920 if (SUCCEEDED(hres)) {
4921 FIXME("Calling Invoke in IDispatch iface. untested!\n");
4922 hres = IDispatch_Invoke(
4923 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,dwFlags,pDispParams,
4924 pVarResult,pExcepInfo,pArgErr
4927 FIXME("IDispatch::Invoke failed with %08lx. (Could be not a real error?)\n", hres);
4928 IDispatch_Release(disp);
4930 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
4934 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
4939 ITypeInfo2_ReleaseFuncDesc(iface, func_desc);
4942 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
4945 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
4946 if(FAILED(hres)) return hres;
4948 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
4949 dump_VARDESC(var_desc);
4950 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
4954 /* not found, look for it in inherited interfaces */
4955 ITypeInfo2_GetTypeKind(iface, &type_kind);
4956 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
4958 if(SUCCEEDED(ITypeInfo2_GetRefTypeOfImplType(iface, 0, &ref_type))) {
4959 /* recursive search */
4961 hres = ITypeInfo_GetRefTypeInfo(iface, ref_type, &pTInfo);
4962 if(SUCCEEDED(hres)){
4963 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,dwFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
4964 ITypeInfo_Release(pTInfo);
4967 WARN("Could not search inherited interface!\n");
4970 ERR("did not find member id %08lx, flags %d!\n", memid, dwFlags);
4971 return DISP_E_MEMBERNOTFOUND;
4974 /* ITypeInfo::GetDocumentation
4976 * Retrieves the documentation string, the complete Help file name and path,
4977 * and the context ID for the Help topic for a specified type description.
4979 * (Can be tested by the Visual Basic Editor in Word for instance.)
4981 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
4982 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
4983 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
4985 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4986 TLBFuncDesc * pFDesc;
4987 TLBVarDesc * pVDesc;
4988 TRACE("(%p) memid %ld Name(%p) DocString(%p)"
4989 " HelpContext(%p) HelpFile(%p)\n",
4990 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
4991 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
4993 *pBstrName=SysAllocString(This->Name);
4995 *pBstrDocString=SysAllocString(This->DocString);
4997 *pdwHelpContext=This->dwHelpContext;
4999 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
5001 }else {/* for a member */
5002 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5003 if(pFDesc->funcdesc.memid==memid){
5005 *pBstrName = SysAllocString(pFDesc->Name);
5007 *pBstrDocString=SysAllocString(pFDesc->HelpString);
5009 *pdwHelpContext=pFDesc->helpcontext;
5012 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5013 if(pVDesc->vardesc.memid==memid){
5015 *pBstrName = SysAllocString(pVDesc->Name);
5017 *pBstrDocString=SysAllocString(pVDesc->HelpString);
5019 *pdwHelpContext=pVDesc->HelpContext;
5023 return TYPE_E_ELEMENTNOTFOUND;
5026 /* ITypeInfo::GetDllEntry
5028 * Retrieves a description or specification of an entry point for a function
5031 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
5032 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
5035 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5036 TLBFuncDesc *pFDesc;
5038 FIXME("(%p, memid %lx, %d, %p, %p, %p), partial stub!\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
5040 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5041 if(pFDesc->funcdesc.memid==memid){
5042 dump_TypeInfo(This);
5043 dump_TLBFuncDescOne(pFDesc);
5045 /* FIXME: This is wrong, but how do you find that out? */
5047 static const WCHAR oleaut32W[] = {'O','L','E','A','U','T','3','2','.','D','L','L',0};
5048 *pBstrDllName = SysAllocString(oleaut32W);
5051 if (HIWORD(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
5053 *pBstrName = SysAllocString(pFDesc->Entry);
5061 *pwOrdinal = (DWORD)pFDesc->Entry;
5067 /* ITypeInfo::GetRefTypeInfo
5069 * If a type description references other type descriptions, it retrieves
5070 * the referenced type descriptions.
5072 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
5075 ITypeInfo **ppTInfo)
5077 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5078 HRESULT result = E_FAIL;
5081 if (hRefType == -1 &&
5082 (((ITypeInfoImpl*) This)->TypeAttr.typekind == TKIND_DISPATCH) &&
5083 (((ITypeInfoImpl*) This)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
5085 /* when we meet a DUAL dispinterface, we must create the interface
5088 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
5091 /* the interface version contains the same information as the dispinterface
5092 * copy the contents of the structs.
5094 *pTypeInfoImpl = *This;
5095 pTypeInfoImpl->ref = 1;
5097 /* change the type to interface */
5098 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
5100 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
5102 ITypeInfo_AddRef((ITypeInfo*) pTypeInfoImpl);
5107 TLBRefType *pRefType;
5108 for(pRefType = This->reflist; pRefType; pRefType = pRefType->next) {
5109 if(pRefType->reference == hRefType)
5113 FIXME("Can't find pRefType for ref %lx\n", hRefType);
5114 if(pRefType && hRefType != -1) {
5115 ITypeLib *pTLib = NULL;
5117 if(pRefType->pImpTLInfo == TLB_REF_INTERNAL) {
5119 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
5121 if(pRefType->pImpTLInfo->pImpTypeLib) {
5122 TRACE("typeinfo in imported typelib that is already loaded\n");
5123 pTLib = (ITypeLib*)pRefType->pImpTLInfo->pImpTypeLib;
5124 ITypeLib2_AddRef((ITypeLib*) pTLib);
5127 TRACE("typeinfo in imported typelib that isn't already loaded\n");
5128 result = LoadRegTypeLib( &pRefType->pImpTLInfo->guid,
5129 pRefType->pImpTLInfo->wVersionMajor,
5130 pRefType->pImpTLInfo->wVersionMinor,
5131 pRefType->pImpTLInfo->lcid,
5134 if(!SUCCEEDED(result)) {
5135 BSTR libnam=SysAllocString(pRefType->pImpTLInfo->name);
5136 result=LoadTypeLib(libnam, &pTLib);
5137 SysFreeString(libnam);
5139 if(SUCCEEDED(result)) {
5140 pRefType->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
5141 ITypeLib2_AddRef(pTLib);
5145 if(SUCCEEDED(result)) {
5146 if(pRefType->index == TLB_REF_USE_GUID)
5147 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
5151 result = ITypeLib2_GetTypeInfo(pTLib, pRefType->index,
5155 ITypeLib2_Release(pTLib);
5159 TRACE("(%p) hreftype 0x%04lx loaded %s (%p)\n", This, hRefType,
5160 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
5164 /* ITypeInfo::AddressOfMember
5166 * Retrieves the addresses of static functions or variables, such as those
5169 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
5170 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
5172 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5173 FIXME("(%p) stub!\n", This);
5177 /* ITypeInfo::CreateInstance
5179 * Creates a new instance of a type that describes a component object class
5182 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
5183 IUnknown *pUnk, REFIID riid, VOID **ppvObj)
5185 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5186 FIXME("(%p) stub!\n", This);
5190 /* ITypeInfo::GetMops
5192 * Retrieves marshalling information.
5194 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
5197 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5198 FIXME("(%p) stub!\n", This);
5202 /* ITypeInfo::GetContainingTypeLib
5204 * Retrieves the containing type library and the index of the type description
5205 * within that type library.
5207 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
5208 ITypeLib * *ppTLib, UINT *pIndex)
5210 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5212 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
5214 *pIndex=This->index;
5215 TRACE("returning pIndex=%d\n", *pIndex);
5219 *ppTLib=(LPTYPELIB )(This->pTypeLib);
5220 ITypeLib2_AddRef(*ppTLib);
5221 TRACE("returning ppTLib=%p\n", *ppTLib);
5227 /* ITypeInfo::ReleaseTypeAttr
5229 * Releases a TYPEATTR previously returned by GetTypeAttr.
5232 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
5233 TYPEATTR* pTypeAttr)
5235 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5236 TRACE("(%p)->(%p)\n", This, pTypeAttr);
5237 if(This->TypeAttr.typekind == TKIND_ALIAS)
5238 free_deep_typedesc(&pTypeAttr->tdescAlias);
5239 HeapFree(GetProcessHeap(), 0, pTypeAttr);
5242 /* ITypeInfo::ReleaseFuncDesc
5244 * Releases a FUNCDESC previously returned by GetFuncDesc. *
5246 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
5248 FUNCDESC *pFuncDesc)
5250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5251 TRACE("(%p)->(%p)\n", This, pFuncDesc);
5254 /* ITypeInfo::ReleaseVarDesc
5256 * Releases a VARDESC previously returned by GetVarDesc.
5258 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
5261 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5262 TRACE("(%p)->(%p)\n", This, pVarDesc);
5265 /* ITypeInfo2::GetTypeKind
5267 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
5270 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
5271 TYPEKIND *pTypeKind)
5273 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5274 *pTypeKind=This->TypeAttr.typekind;
5275 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
5279 /* ITypeInfo2::GetTypeFlags
5281 * Returns the type flags without any allocations. This returns a DWORD type
5282 * flag, which expands the type flags without growing the TYPEATTR (type
5286 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
5288 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5289 *pTypeFlags=This->TypeAttr.wTypeFlags;
5290 TRACE("(%p) flags 0x%lx\n", This,*pTypeFlags);
5294 /* ITypeInfo2::GetFuncIndexOfMemId
5295 * Binds to a specific member based on a known DISPID, where the member name
5296 * is not known (for example, when binding to a default member).
5299 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
5300 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
5302 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5303 TLBFuncDesc *pFuncInfo;
5307 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
5308 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
5314 result = TYPE_E_ELEMENTNOTFOUND;
5316 TRACE("(%p) memid 0x%08lx invKind 0x%04x -> %s\n", This,
5317 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5321 /* TypeInfo2::GetVarIndexOfMemId
5323 * Binds to a specific member based on a known DISPID, where the member name
5324 * is not known (for example, when binding to a default member).
5327 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
5328 MEMBERID memid, UINT *pVarIndex)
5330 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5331 TLBVarDesc *pVarInfo;
5334 for(i=0, pVarInfo=This->varlist; pVarInfo &&
5335 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
5341 result = TYPE_E_ELEMENTNOTFOUND;
5343 TRACE("(%p) memid 0x%08lx -> %s\n", This,
5344 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
5348 /* ITypeInfo2::GetCustData
5350 * Gets the custom data
5352 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
5357 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5358 TLBCustData *pCData;
5360 for(pCData=This->pCustData; pCData; pCData = pCData->next)
5361 if( IsEqualIID(guid, &pCData->guid)) break;
5363 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5367 VariantInit( pVarVal);
5368 VariantCopy( pVarVal, &pCData->data);
5371 return E_INVALIDARG; /* FIXME: correct? */
5374 /* ITypeInfo2::GetFuncCustData
5376 * Gets the custom data
5378 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
5384 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5385 TLBCustData *pCData=NULL;
5386 TLBFuncDesc * pFDesc;
5388 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5389 pFDesc=pFDesc->next);
5392 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
5393 if( IsEqualIID(guid, &pCData->guid)) break;
5395 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5398 VariantInit( pVarVal);
5399 VariantCopy( pVarVal, &pCData->data);
5402 return E_INVALIDARG; /* FIXME: correct? */
5405 /* ITypeInfo2::GetParamCustData
5407 * Gets the custom data
5409 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
5416 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5417 TLBCustData *pCData=NULL;
5418 TLBFuncDesc * pFDesc;
5421 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
5423 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams)
5424 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
5425 pCData = pCData->next)
5426 if( IsEqualIID(guid, &pCData->guid)) break;
5428 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5432 VariantInit( pVarVal);
5433 VariantCopy( pVarVal, &pCData->data);
5436 return E_INVALIDARG; /* FIXME: correct? */
5439 /* ITypeInfo2::GetVarCustData
5441 * Gets the custom data
5443 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
5449 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5450 TLBCustData *pCData=NULL;
5451 TLBVarDesc * pVDesc;
5454 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
5458 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
5460 if( IsEqualIID(guid, &pCData->guid)) break;
5464 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5468 VariantInit( pVarVal);
5469 VariantCopy( pVarVal, &pCData->data);
5472 return E_INVALIDARG; /* FIXME: correct? */
5475 /* ITypeInfo2::GetImplCustData
5477 * Gets the custom data
5479 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
5485 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5486 TLBCustData *pCData=NULL;
5487 TLBImplType * pRDesc;
5490 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
5494 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
5496 if( IsEqualIID(guid, &pCData->guid)) break;
5500 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
5504 VariantInit( pVarVal);
5505 VariantCopy( pVarVal, &pCData->data);
5508 return E_INVALIDARG; /* FIXME: correct? */
5511 /* ITypeInfo2::GetDocumentation2
5513 * Retrieves the documentation string, the complete Help file name and path,
5514 * the localization context to use, and the context ID for the library Help
5515 * topic in the Help file.
5518 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
5522 BSTR *pbstrHelpString,
5523 DWORD *pdwHelpStringContext,
5524 BSTR *pbstrHelpStringDll)
5526 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5527 TLBFuncDesc * pFDesc;
5528 TLBVarDesc * pVDesc;
5529 TRACE("(%p) memid %ld lcid(0x%lx) HelpString(%p) "
5530 "HelpStringContext(%p) HelpStringDll(%p)\n",
5531 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
5532 pbstrHelpStringDll );
5533 /* the help string should be obtained from the helpstringdll,
5534 * using the _DLLGetDocumentation function, based on the supplied
5535 * lcid. Nice to do sometime...
5537 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
5539 *pbstrHelpString=SysAllocString(This->Name);
5540 if(pdwHelpStringContext)
5541 *pdwHelpStringContext=This->dwHelpStringContext;
5542 if(pbstrHelpStringDll)
5543 *pbstrHelpStringDll=
5544 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5546 }else {/* for a member */
5547 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
5548 if(pFDesc->funcdesc.memid==memid){
5550 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
5551 if(pdwHelpStringContext)
5552 *pdwHelpStringContext=pFDesc->HelpStringContext;
5553 if(pbstrHelpStringDll)
5554 *pbstrHelpStringDll=
5555 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5558 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
5559 if(pVDesc->vardesc.memid==memid){
5561 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
5562 if(pdwHelpStringContext)
5563 *pdwHelpStringContext=pVDesc->HelpStringContext;
5564 if(pbstrHelpStringDll)
5565 *pbstrHelpStringDll=
5566 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
5570 return TYPE_E_ELEMENTNOTFOUND;
5573 /* ITypeInfo2::GetAllCustData
5575 * Gets all custom data items for the Type info.
5578 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
5580 CUSTDATA *pCustData)
5582 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5583 TLBCustData *pCData;
5586 TRACE("(%p) returning %d items\n", This, This->ctCustData);
5588 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
5589 if(pCustData->prgCustData ){
5590 pCustData->cCustData=This->ctCustData;
5591 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
5592 pCustData->prgCustData[i].guid=pCData->guid;
5593 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
5596 ERR(" OUT OF MEMORY! \n");
5597 return E_OUTOFMEMORY;
5602 /* ITypeInfo2::GetAllFuncCustData
5604 * Gets all custom data items for the specified Function
5607 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
5610 CUSTDATA *pCustData)
5612 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5613 TLBCustData *pCData;
5614 TLBFuncDesc * pFDesc;
5616 TRACE("(%p) index %d\n", This, index);
5617 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
5618 pFDesc=pFDesc->next)
5621 pCustData->prgCustData =
5622 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
5623 if(pCustData->prgCustData ){
5624 pCustData->cCustData=pFDesc->ctCustData;
5625 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
5626 pCData = pCData->next){
5627 pCustData->prgCustData[i].guid=pCData->guid;
5628 VariantCopy(& pCustData->prgCustData[i].varValue,
5632 ERR(" OUT OF MEMORY! \n");
5633 return E_OUTOFMEMORY;
5637 return TYPE_E_ELEMENTNOTFOUND;
5640 /* ITypeInfo2::GetAllParamCustData
5642 * Gets all custom data items for the Functions
5645 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
5646 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
5648 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5649 TLBCustData *pCData=NULL;
5650 TLBFuncDesc * pFDesc;
5652 TRACE("(%p) index %d\n", This, indexFunc);
5653 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
5654 pFDesc=pFDesc->next)
5656 if(pFDesc && indexParam >=0 && indexParam<pFDesc->funcdesc.cParams){
5657 pCustData->prgCustData =
5658 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
5659 sizeof(CUSTDATAITEM));
5660 if(pCustData->prgCustData ){
5661 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
5662 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
5663 pCData; i++, pCData = pCData->next){
5664 pCustData->prgCustData[i].guid=pCData->guid;
5665 VariantCopy(& pCustData->prgCustData[i].varValue,
5669 ERR(" OUT OF MEMORY! \n");
5670 return E_OUTOFMEMORY;
5674 return TYPE_E_ELEMENTNOTFOUND;
5677 /* ITypeInfo2::GetAllVarCustData
5679 * Gets all custom data items for the specified Variable
5682 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
5683 UINT index, CUSTDATA *pCustData)
5685 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5686 TLBCustData *pCData;
5687 TLBVarDesc * pVDesc;
5689 TRACE("(%p) index %d\n", This, index);
5690 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
5691 pVDesc=pVDesc->next)
5694 pCustData->prgCustData =
5695 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
5696 if(pCustData->prgCustData ){
5697 pCustData->cCustData=pVDesc->ctCustData;
5698 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
5699 pCData = pCData->next){
5700 pCustData->prgCustData[i].guid=pCData->guid;
5701 VariantCopy(& pCustData->prgCustData[i].varValue,
5705 ERR(" OUT OF MEMORY! \n");
5706 return E_OUTOFMEMORY;
5710 return TYPE_E_ELEMENTNOTFOUND;
5713 /* ITypeInfo2::GetAllImplCustData
5715 * Gets all custom data items for the specified implementation type
5718 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
5721 CUSTDATA *pCustData)
5723 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5724 TLBCustData *pCData;
5725 TLBImplType * pRDesc;
5727 TRACE("(%p) index %d\n", This, index);
5728 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
5729 pRDesc=pRDesc->next)
5732 pCustData->prgCustData =
5733 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
5734 if(pCustData->prgCustData ){
5735 pCustData->cCustData=pRDesc->ctCustData;
5736 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
5737 pCData = pCData->next){
5738 pCustData->prgCustData[i].guid=pCData->guid;
5739 VariantCopy(& pCustData->prgCustData[i].varValue,
5743 ERR(" OUT OF MEMORY! \n");
5744 return E_OUTOFMEMORY;
5748 return TYPE_E_ELEMENTNOTFOUND;
5751 static ITypeInfo2Vtbl tinfvt =
5754 ITypeInfo_fnQueryInterface,
5756 ITypeInfo_fnRelease,
5758 ITypeInfo_fnGetTypeAttr,
5759 ITypeInfo_fnGetTypeComp,
5760 ITypeInfo_fnGetFuncDesc,
5761 ITypeInfo_fnGetVarDesc,
5762 ITypeInfo_fnGetNames,
5763 ITypeInfo_fnGetRefTypeOfImplType,
5764 ITypeInfo_fnGetImplTypeFlags,
5765 ITypeInfo_fnGetIDsOfNames,
5767 ITypeInfo_fnGetDocumentation,
5768 ITypeInfo_fnGetDllEntry,
5769 ITypeInfo_fnGetRefTypeInfo,
5770 ITypeInfo_fnAddressOfMember,
5771 ITypeInfo_fnCreateInstance,
5772 ITypeInfo_fnGetMops,
5773 ITypeInfo_fnGetContainingTypeLib,
5774 ITypeInfo_fnReleaseTypeAttr,
5775 ITypeInfo_fnReleaseFuncDesc,
5776 ITypeInfo_fnReleaseVarDesc,
5778 ITypeInfo2_fnGetTypeKind,
5779 ITypeInfo2_fnGetTypeFlags,
5780 ITypeInfo2_fnGetFuncIndexOfMemId,
5781 ITypeInfo2_fnGetVarIndexOfMemId,
5782 ITypeInfo2_fnGetCustData,
5783 ITypeInfo2_fnGetFuncCustData,
5784 ITypeInfo2_fnGetParamCustData,
5785 ITypeInfo2_fnGetVarCustData,
5786 ITypeInfo2_fnGetImplTypeCustData,
5787 ITypeInfo2_fnGetDocumentation2,
5788 ITypeInfo2_fnGetAllCustData,
5789 ITypeInfo2_fnGetAllFuncCustData,
5790 ITypeInfo2_fnGetAllParamCustData,
5791 ITypeInfo2_fnGetAllVarCustData,
5792 ITypeInfo2_fnGetAllImplTypeCustData,
5795 /******************************************************************************
5796 * CreateDispTypeInfo [OLEAUT32.31]
5798 * Build type information for an object so it can be called through an
5799 * IDispatch interface.
5802 * Success: S_OK. pptinfo contains the created ITypeInfo object.
5803 * Failure: E_INVALIDARG, if one or more arguments is invalid.
5806 * This call allows an objects methods to be accessed through IDispatch, by
5807 * building an ITypeInfo object that IDispatch can use to call through.
5809 HRESULT WINAPI CreateDispTypeInfo(
5810 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
5811 LCID lcid, /* [I] Locale Id */
5812 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
5814 ITypeInfoImpl *pTIImpl;
5816 TLBFuncDesc **ppFuncDesc;
5818 pTIImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
5819 pTIImpl->pTypeLib = NULL;
5821 pTIImpl->Name = NULL;
5822 pTIImpl->dwHelpContext = -1;
5823 memset(&pTIImpl->TypeAttr.guid, 0, sizeof(GUID));
5824 pTIImpl->TypeAttr.lcid = lcid;
5825 pTIImpl->TypeAttr.typekind = TKIND_COCLASS;
5826 pTIImpl->TypeAttr.wMajorVerNum = 0;
5827 pTIImpl->TypeAttr.wMinorVerNum = 0;
5828 pTIImpl->TypeAttr.cbAlignment = 2;
5829 pTIImpl->TypeAttr.cbSizeInstance = -1;
5830 pTIImpl->TypeAttr.cbSizeVft = -1;
5831 pTIImpl->TypeAttr.cFuncs = 0;
5832 pTIImpl->TypeAttr.cImplTypes = 1;
5833 pTIImpl->TypeAttr.cVars = 0;
5834 pTIImpl->TypeAttr.wTypeFlags = 0;
5836 ppFuncDesc = &pTIImpl->funclist;
5837 for(func = 0; func < pidata->cMembers; func++) {
5838 METHODDATA *md = pidata->pmethdata + func;
5839 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
5840 (*ppFuncDesc)->Name = SysAllocString(md->szName);
5841 (*ppFuncDesc)->funcdesc.memid = md->dispid;
5842 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
5843 (*ppFuncDesc)->funcdesc.callconv = md->cc;
5844 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
5845 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
5846 (*ppFuncDesc)->funcdesc.oVft = md->iMeth;
5847 (*ppFuncDesc)->funcdesc.wFuncFlags = 0; /*??*/
5848 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
5849 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5850 md->cArgs * sizeof(ELEMDESC));
5851 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
5852 md->cArgs * sizeof(TLBParDesc));
5853 for(param = 0; param < md->cArgs; param++) {
5854 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
5855 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
5857 ppFuncDesc = &(*ppFuncDesc)->next;
5859 *pptinfo = (ITypeInfo*)pTIImpl;
5864 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
5866 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5868 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
5871 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
5873 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5875 return ITypeInfo_AddRef((ITypeInfo *)This);
5878 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
5880 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5882 return ITypeInfo_Release((ITypeInfo *)This);
5885 static HRESULT WINAPI ITypeComp_fnBind(
5890 ITypeInfo ** ppTInfo,
5891 DESCKIND * pDescKind,
5894 ICOM_THIS_From_ITypeComp(ITypeInfoImpl, iface);
5895 TLBFuncDesc * pFDesc;
5896 TLBVarDesc * pVDesc;
5898 TRACE("(%s, %lx, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5900 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
5901 if (pFDesc->funcdesc.invkind & wFlags)
5902 if (!strcmpW(pFDesc->Name, szName)) {
5908 *pDescKind = DESCKIND_FUNCDESC;
5909 pBindPtr->lpfuncdesc = &pFDesc->funcdesc;
5910 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5913 if (!(wFlags & ~(INVOKE_PROPERTYGET)))
5915 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
5916 if (!strcmpW(pVDesc->Name, szName)) {
5917 *pDescKind = DESCKIND_VARDESC;
5918 pBindPtr->lpvardesc = &pVDesc->vardesc;
5919 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
5925 /* not found, look for it in inherited interfaces */
5926 if (This->TypeAttr.cImplTypes &&
5927 (This->TypeAttr.typekind == TKIND_INTERFACE || This->TypeAttr.typekind == TKIND_DISPATCH)) {
5928 /* recursive search */
5932 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
5935 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
5936 ITypeInfo_Release(pTInfo);
5940 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
5941 ITypeComp_Release(pTComp);
5944 WARN("Could not search inherited interface!\n");
5946 ERR("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
5947 *pDescKind = DESCKIND_NONE;
5948 pBindPtr->lpfuncdesc = NULL;
5950 return DISP_E_MEMBERNOTFOUND;
5953 static HRESULT WINAPI ITypeComp_fnBindType(
5957 ITypeInfo ** ppTInfo,
5958 ITypeComp ** ppTComp)
5960 TRACE("(%s, %lx, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
5962 /* strange behaviour (does nothing) but like the
5965 if (!ppTInfo || !ppTComp)
5974 static ITypeCompVtbl tcompvt =
5977 ITypeComp_fnQueryInterface,
5979 ITypeComp_fnRelease,
5982 ITypeComp_fnBindType