4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2005 Robert Shearman, for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * --------------------------------------------------------------------------------------
25 * Known problems (2000, Francois Jacques)
27 * - Tested using OLEVIEW (Platform SDK tool) only.
29 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
30 * creating by doing a straight copy of the dispinterface instance and just changing
31 * its typekind. Pointed structures aren't copied - only the address of the pointers.
33 * - locale stuff is partially implemented but hasn't been tested.
35 * - typelib file is still read in its entirety, but it is released now.
37 * --------------------------------------------------------------------------------------
38 * Known problems left from previous implementation (1999, Rein Klazes) :
40 * -. Data structures are straightforward, but slow for look-ups.
41 * -. (related) nothing is hashed
42 * -. Most error return values are just guessed not checked with windows
44 * -. lousy fatal error handling
49 #include "wine/port.h"
58 #define NONAMELESSUNION
59 #define NONAMELESSSTRUCT
69 #include "wine/unicode.h"
72 #include "wine/debug.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib);
91 WORD type_id; /* Type identifier */
92 WORD count; /* Number of resources of this type */
93 DWORD resloader; /* SetResourceHandler() */
99 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt);
100 static HRESULT TLB_AllocAndInitVarDesc(const VARDESC *src, VARDESC **dest_ptr);
102 /****************************************************************************
105 * Takes p_iVal (which is in little endian) and returns it
106 * in the host machine's byte order.
108 #ifdef WORDS_BIGENDIAN
109 static WORD FromLEWord(WORD p_iVal)
111 return (((p_iVal & 0x00FF) << 8) |
112 ((p_iVal & 0xFF00) >> 8));
116 static DWORD FromLEDWord(DWORD p_iVal)
118 return (((p_iVal & 0x000000FF) << 24) |
119 ((p_iVal & 0x0000FF00) << 8) |
120 ((p_iVal & 0x00FF0000) >> 8) |
121 ((p_iVal & 0xFF000000) >> 24));
124 #define FromLEWord(X) (X)
125 #define FromLEDWord(X) (X)
128 #define DISPATCH_HREF_OFFSET 0x01000000
129 #define DISPATCH_HREF_MASK 0xff000000
131 /****************************************************************************
134 * Fix byte order in any structure if necessary
136 #ifdef WORDS_BIGENDIAN
137 static void FromLEWords(void *p_Val, int p_iSize)
141 p_iSize /= sizeof(WORD);
144 *Val = FromLEWord(*Val);
151 static void FromLEDWords(void *p_Val, int p_iSize)
155 p_iSize /= sizeof(DWORD);
158 *Val = FromLEDWord(*Val);
164 #define FromLEWords(X,Y) /*nothing*/
165 #define FromLEDWords(X,Y) /*nothing*/
169 * Find a typelib key which matches a requested maj.min version.
171 static BOOL find_typelib_key( REFGUID guid, WORD *wMaj, WORD *wMin )
173 static const WCHAR typelibW[] = {'T','y','p','e','l','i','b','\\',0};
177 INT best_maj = -1, best_min = -1;
180 memcpy( buffer, typelibW, sizeof(typelibW) );
181 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
183 if (RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey ) != ERROR_SUCCESS)
186 len = sizeof(key_name);
188 while (RegEnumKeyExA(hkey, i++, key_name, &len, NULL, NULL, NULL, NULL) == ERROR_SUCCESS)
192 if (sscanf(key_name, "%x.%x", &v_maj, &v_min) == 2)
194 TRACE("found %s: %x.%x\n", debugstr_w(buffer), v_maj, v_min);
196 if (*wMaj == 0xffff && *wMin == 0xffff)
198 if (v_maj > best_maj) best_maj = v_maj;
199 if (v_min > best_min) best_min = v_min;
201 else if (*wMaj == v_maj)
208 break; /* exact match */
210 if (*wMin != 0xffff && v_min > best_min) best_min = v_min;
213 len = sizeof(key_name);
217 TRACE("found best_maj %d, best_min %d\n", best_maj, best_min);
219 if (*wMaj == 0xffff && *wMin == 0xffff)
221 if (best_maj >= 0 && best_min >= 0)
229 if (*wMaj == best_maj && best_min >= 0)
237 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
238 /* buffer must be at least 60 characters long */
239 static WCHAR *get_typelib_key( REFGUID guid, WORD wMaj, WORD wMin, WCHAR *buffer )
241 static const WCHAR TypelibW[] = {'T','y','p','e','l','i','b','\\',0};
242 static const WCHAR VersionFormatW[] = {'\\','%','x','.','%','x',0};
244 memcpy( buffer, TypelibW, sizeof(TypelibW) );
245 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
246 sprintfW( buffer + strlenW(buffer), VersionFormatW, wMaj, wMin );
250 /* get the path of an interface key, in the form "Interface\\<guid>" */
251 /* buffer must be at least 50 characters long */
252 static WCHAR *get_interface_key( REFGUID guid, WCHAR *buffer )
254 static const WCHAR InterfaceW[] = {'I','n','t','e','r','f','a','c','e','\\',0};
256 memcpy( buffer, InterfaceW, sizeof(InterfaceW) );
257 StringFromGUID2( guid, buffer + strlenW(buffer), 40 );
261 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
262 /* buffer must be at least 16 characters long */
263 static WCHAR *get_lcid_subkey( LCID lcid, SYSKIND syskind, WCHAR *buffer )
265 static const WCHAR LcidFormatW[] = {'%','l','x','\\',0};
266 static const WCHAR win16W[] = {'w','i','n','1','6',0};
267 static const WCHAR win32W[] = {'w','i','n','3','2',0};
268 static const WCHAR win64W[] = {'w','i','n','6','4',0};
270 sprintfW( buffer, LcidFormatW, lcid );
273 case SYS_WIN16: strcatW( buffer, win16W ); break;
274 case SYS_WIN32: strcatW( buffer, win32W ); break;
275 case SYS_WIN64: strcatW( buffer, win64W ); break;
277 TRACE("Typelib is for unsupported syskind %i\n", syskind);
283 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib);
286 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
287 static HRESULT query_typelib_path( REFGUID guid, WORD wMaj, WORD wMin,
288 SYSKIND syskind, LCID lcid, LPBSTR path )
290 HRESULT hr = TYPE_E_LIBNOTREGISTERED;
294 WCHAR Path[MAX_PATH];
297 TRACE_(typelib)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid), wMaj, wMin, lcid, path);
299 if (!find_typelib_key( guid, &wMaj, &wMin )) return TYPE_E_LIBNOTREGISTERED;
300 get_typelib_key( guid, wMaj, wMin, buffer );
302 res = RegOpenKeyExW( HKEY_CLASSES_ROOT, buffer, 0, KEY_READ, &hkey );
303 if (res == ERROR_FILE_NOT_FOUND)
305 TRACE_(typelib)("%s not found\n", debugstr_w(buffer));
306 return TYPE_E_LIBNOTREGISTERED;
308 else if (res != ERROR_SUCCESS)
310 TRACE_(typelib)("failed to open %s for read access\n", debugstr_w(buffer));
311 return TYPE_E_REGISTRYACCESS;
316 LONG dwPathLen = sizeof(Path);
318 get_lcid_subkey( myLCID, syskind, buffer );
320 if (RegQueryValueW(hkey, buffer, Path, &dwPathLen))
324 else if (myLCID == lcid)
326 /* try with sub-langid */
327 myLCID = SUBLANGID(lcid);
329 else if ((myLCID == SUBLANGID(lcid)) && myLCID)
331 /* try with system langid */
341 *path = SysAllocString( Path );
346 TRACE_(typelib)("-- 0x%08x\n", hr);
350 /****************************************************************************
351 * QueryPathOfRegTypeLib [OLEAUT32.164]
353 * Gets the path to a registered type library.
356 * guid [I] referenced guid
357 * wMaj [I] major version
358 * wMin [I] minor version
360 * path [O] path of typelib
364 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
365 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
368 HRESULT WINAPI QueryPathOfRegTypeLib( REFGUID guid, WORD wMaj, WORD wMin, LCID lcid, LPBSTR path )
370 return query_typelib_path( guid, wMaj, wMin, SYS_WIN32, lcid, path );
373 /******************************************************************************
374 * CreateTypeLib [OLEAUT32.160] creates a typelib
380 HRESULT WINAPI CreateTypeLib(
381 SYSKIND syskind, LPCOLESTR szFile, ICreateTypeLib** ppctlib
383 FIXME("(%d,%s,%p), stub!\n",syskind,debugstr_w(szFile),ppctlib);
387 /******************************************************************************
388 * LoadTypeLib [OLEAUT32.161]
390 * Loads a type library
393 * szFile [I] Name of file to load from.
394 * pptLib [O] Pointer that receives ITypeLib object on success.
401 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
403 HRESULT WINAPI LoadTypeLib(const OLECHAR *szFile, ITypeLib * *pptLib)
405 TRACE("(%s,%p)\n",debugstr_w(szFile), pptLib);
406 return LoadTypeLibEx(szFile, REGKIND_DEFAULT, pptLib);
409 /******************************************************************************
410 * LoadTypeLibEx [OLEAUT32.183]
412 * Loads and optionally registers a type library
418 HRESULT WINAPI LoadTypeLibEx(
419 LPCOLESTR szFile, /* [in] Name of file to load from */
420 REGKIND regkind, /* [in] Specify kind of registration */
421 ITypeLib **pptLib) /* [out] Pointer to pointer to loaded type library */
423 WCHAR szPath[MAX_PATH+1];
426 TRACE("(%s,%d,%p)\n",debugstr_w(szFile), regkind, pptLib);
430 res = TLB_ReadTypeLib(szFile, szPath, MAX_PATH + 1, (ITypeLib2**)pptLib);
435 case REGKIND_DEFAULT:
436 /* don't register typelibs supplied with full path. Experimentation confirms the following */
437 if (((szFile[0] == '\\') && (szFile[1] == '\\')) ||
438 (szFile[0] && (szFile[1] == ':'))) break;
439 /* else fall-through */
441 case REGKIND_REGISTER:
442 if (FAILED(res = RegisterTypeLib(*pptLib, szPath, NULL)))
444 IUnknown_Release(*pptLib);
452 TRACE(" returns %08x\n",res);
456 /******************************************************************************
457 * LoadRegTypeLib [OLEAUT32.162]
459 * Loads a registered type library.
462 * rguid [I] GUID of the registered type library.
463 * wVerMajor [I] major version.
464 * wVerMinor [I] minor version.
465 * lcid [I] locale ID.
466 * ppTLib [O] pointer that receives an ITypeLib object on success.
470 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
473 HRESULT WINAPI LoadRegTypeLib(
485 res = QueryPathOfRegTypeLib( rguid, wVerMajor, wVerMinor, lcid, &bstr);
489 res= LoadTypeLib(bstr, ppTLib);
493 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid), SUCCEEDED(res)? "SUCCESS":"FAILED", *ppTLib);
499 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
500 static const WCHAR TypeLibW[] = {'T','y','p','e','L','i','b',0};
501 static const WCHAR FLAGSW[] = {'F','L','A','G','S',0};
502 static const WCHAR HELPDIRW[] = {'H','E','L','P','D','I','R',0};
503 static const WCHAR ProxyStubClsidW[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
504 static const WCHAR ProxyStubClsid32W[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
506 /******************************************************************************
507 * RegisterTypeLib [OLEAUT32.163]
508 * Adds information about a type library to the System Registry
510 * Docs: ITypeLib FAR * ptlib
511 * Docs: OLECHAR FAR* szFullPath
512 * Docs: OLECHAR FAR* szHelpDir
518 HRESULT WINAPI RegisterTypeLib(
519 ITypeLib * ptlib, /* [in] Pointer to the library*/
520 OLECHAR * szFullPath, /* [in] full Path of the library*/
521 OLECHAR * szHelpDir) /* [in] dir to the helpfile for the library,
524 static const WCHAR PSOA[] = {'{','0','0','0','2','0','4','2','4','-',
525 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
526 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
536 if (ptlib == NULL || szFullPath == NULL)
539 if (FAILED(ITypeLib_GetLibAttr(ptlib, &attr)))
543 if (attr->syskind != SYS_WIN64) return TYPE_E_BADMODULEKIND;
545 if (attr->syskind != SYS_WIN32 && attr->syskind != SYS_WIN16) return TYPE_E_BADMODULEKIND;
548 get_typelib_key( &attr->guid, attr->wMajorVerNum, attr->wMinorVerNum, keyName );
551 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
552 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
556 /* Set the human-readable name of the typelib */
557 if (FAILED(ITypeLib_GetDocumentation(ptlib, -1, NULL, &doc, NULL, NULL)))
561 if (RegSetValueExW(key, NULL, 0, REG_SZ,
562 (BYTE *)doc, (lstrlenW(doc)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
568 /* Make up the name of the typelib path subkey */
569 if (!get_lcid_subkey( attr->lcid, attr->syskind, tmp )) res = E_FAIL;
571 /* Create the typelib path subkey */
572 if (res == S_OK && RegCreateKeyExW(key, tmp, 0, NULL, 0,
573 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
575 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
576 (BYTE *)szFullPath, (lstrlenW(szFullPath)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS)
584 /* Create the flags subkey */
585 if (res == S_OK && RegCreateKeyExW(key, FLAGSW, 0, NULL, 0,
586 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
588 /* FIXME: is %u correct? */
589 static const WCHAR formatW[] = {'%','u',0};
591 sprintfW(buf, formatW, attr->wLibFlags);
592 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
593 (BYTE *)buf, (strlenW(buf) + 1)*sizeof(WCHAR) ) != ERROR_SUCCESS)
601 /* create the helpdir subkey */
602 if (res == S_OK && RegCreateKeyExW(key, HELPDIRW, 0, NULL, 0,
603 KEY_WRITE, NULL, &subKey, &disposition) == ERROR_SUCCESS)
605 BOOL freeHelpDir = FALSE;
608 /* if we created a new key, and helpDir was null, set the helpdir
609 to the directory which contains the typelib. However,
610 if we just opened an existing key, we leave the helpdir alone */
611 if ((disposition == REG_CREATED_NEW_KEY) && (szHelpDir == NULL)) {
612 szHelpDir = SysAllocString(szFullPath);
613 pIndexStr = strrchrW(szHelpDir, '\\');
620 /* if we have an szHelpDir, set it! */
621 if (szHelpDir != NULL) {
622 if (RegSetValueExW(subKey, NULL, 0, REG_SZ,
623 (BYTE *)szHelpDir, (lstrlenW(szHelpDir)+1) * sizeof(OLECHAR)) != ERROR_SUCCESS) {
629 if (freeHelpDir) SysFreeString(szHelpDir);
641 /* register OLE Automation-compatible interfaces for this typelib */
642 types = ITypeLib_GetTypeInfoCount(ptlib);
643 for (tidx=0; tidx<types; tidx++) {
644 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib, tidx, &kind))) {
645 LPOLESTR name = NULL;
646 ITypeInfo *tinfo = NULL;
648 ITypeLib_GetDocumentation(ptlib, tidx, &name, NULL, NULL, NULL);
651 case TKIND_INTERFACE:
652 TRACE_(typelib)("%d: interface %s\n", tidx, debugstr_w(name));
653 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
657 TRACE_(typelib)("%d: dispinterface %s\n", tidx, debugstr_w(name));
658 ITypeLib_GetTypeInfo(ptlib, tidx, &tinfo);
662 TRACE_(typelib)("%d: %s\n", tidx, debugstr_w(name));
667 TYPEATTR *tattr = NULL;
668 ITypeInfo_GetTypeAttr(tinfo, &tattr);
671 TRACE_(typelib)("guid=%s, flags=%04x (",
672 debugstr_guid(&tattr->guid),
675 if (TRACE_ON(typelib)) {
676 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
696 /* Register all dispinterfaces (which includes dual interfaces) and
697 oleautomation interfaces */
698 if ((kind == TKIND_INTERFACE && (tattr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
699 kind == TKIND_DISPATCH)
701 /* register interface<->typelib coupling */
702 get_interface_key( &tattr->guid, keyName );
703 if (RegCreateKeyExW(HKEY_CLASSES_ROOT, keyName, 0, NULL, 0,
704 KEY_WRITE, NULL, &key, NULL) == ERROR_SUCCESS)
707 RegSetValueExW(key, NULL, 0, REG_SZ,
708 (BYTE *)name, (strlenW(name)+1) * sizeof(OLECHAR));
710 if (RegCreateKeyExW(key, ProxyStubClsidW, 0, NULL, 0,
711 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
712 RegSetValueExW(subKey, NULL, 0, REG_SZ,
713 (const BYTE *)PSOA, sizeof PSOA);
717 if (RegCreateKeyExW(key, ProxyStubClsid32W, 0, NULL, 0,
718 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS) {
719 RegSetValueExW(subKey, NULL, 0, REG_SZ,
720 (const BYTE *)PSOA, sizeof PSOA);
724 if (RegCreateKeyExW(key, TypeLibW, 0, NULL, 0,
725 KEY_WRITE, NULL, &subKey, NULL) == ERROR_SUCCESS)
728 static const WCHAR fmtver[] = {'%','x','.','%','x',0 };
729 static const WCHAR VersionW[] = {'V','e','r','s','i','o','n',0};
731 StringFromGUID2(&attr->guid, buffer, 40);
732 RegSetValueExW(subKey, NULL, 0, REG_SZ,
733 (BYTE *)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
734 sprintfW(buffer, fmtver, attr->wMajorVerNum, attr->wMinorVerNum);
735 RegSetValueExW(subKey, VersionW, 0, REG_SZ,
736 (BYTE*)buffer, (strlenW(buffer)+1) * sizeof(WCHAR));
744 ITypeInfo_ReleaseTypeAttr(tinfo, tattr);
747 ITypeInfo_Release(tinfo);
754 ITypeLib_ReleaseTLibAttr(ptlib, attr);
760 /******************************************************************************
761 * UnRegisterTypeLib [OLEAUT32.186]
762 * Removes information about a type library from the System Registry
769 HRESULT WINAPI UnRegisterTypeLib(
770 REFGUID libid, /* [in] Guid of the library */
771 WORD wVerMajor, /* [in] major version */
772 WORD wVerMinor, /* [in] minor version */
773 LCID lcid, /* [in] locale id */
776 BSTR tlibPath = NULL;
779 WCHAR subKeyName[50];
782 BOOL deleteOtherStuff;
785 TYPEATTR* typeAttr = NULL;
787 ITypeInfo* typeInfo = NULL;
788 ITypeLib* typeLib = NULL;
791 TRACE("(IID: %s)\n",debugstr_guid(libid));
793 /* Create the path to the key */
794 get_typelib_key( libid, wVerMajor, wVerMinor, keyName );
796 if (syskind != SYS_WIN16 && syskind != SYS_WIN32 && syskind != SYS_WIN64)
798 TRACE("Unsupported syskind %i\n", syskind);
799 result = E_INVALIDARG;
803 /* get the path to the typelib on disk */
804 if (query_typelib_path(libid, wVerMajor, wVerMinor, syskind, lcid, &tlibPath) != S_OK) {
805 result = E_INVALIDARG;
809 /* Try and open the key to the type library. */
810 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, keyName, 0, KEY_READ | KEY_WRITE, &key) != ERROR_SUCCESS) {
811 result = E_INVALIDARG;
815 /* Try and load the type library */
816 if (LoadTypeLibEx(tlibPath, REGKIND_NONE, &typeLib)) {
817 result = TYPE_E_INVALIDSTATE;
821 /* remove any types registered with this typelib */
822 numTypes = ITypeLib_GetTypeInfoCount(typeLib);
823 for (i=0; i<numTypes; i++) {
824 /* get the kind of type */
825 if (ITypeLib_GetTypeInfoType(typeLib, i, &kind) != S_OK) {
829 /* skip non-interfaces, and get type info for the type */
830 if ((kind != TKIND_INTERFACE) && (kind != TKIND_DISPATCH)) {
833 if (ITypeLib_GetTypeInfo(typeLib, i, &typeInfo) != S_OK) {
836 if (ITypeInfo_GetTypeAttr(typeInfo, &typeAttr) != S_OK) {
840 if ((kind == TKIND_INTERFACE && (typeAttr->wTypeFlags & TYPEFLAG_FOLEAUTOMATION)) ||
841 kind == TKIND_DISPATCH)
843 /* the path to the type */
844 get_interface_key( &typeAttr->guid, subKeyName );
846 /* Delete its bits */
847 if (RegOpenKeyExW(HKEY_CLASSES_ROOT, subKeyName, 0, KEY_WRITE, &subKey) != ERROR_SUCCESS)
850 RegDeleteKeyW(subKey, ProxyStubClsidW);
851 RegDeleteKeyW(subKey, ProxyStubClsid32W);
852 RegDeleteKeyW(subKey, TypeLibW);
855 RegDeleteKeyW(HKEY_CLASSES_ROOT, subKeyName);
859 if (typeAttr) ITypeInfo_ReleaseTypeAttr(typeInfo, typeAttr);
861 if (typeInfo) ITypeInfo_Release(typeInfo);
865 /* Now, delete the type library path subkey */
866 get_lcid_subkey( lcid, syskind, subKeyName );
867 RegDeleteKeyW(key, subKeyName);
868 *strrchrW( subKeyName, '\\' ) = 0; /* remove last path component */
869 RegDeleteKeyW(key, subKeyName);
871 /* check if there is anything besides the FLAGS/HELPDIR keys.
872 If there is, we don't delete them */
873 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
874 deleteOtherStuff = TRUE;
876 while(RegEnumKeyExW(key, i++, subKeyName, &tmpLength, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
877 tmpLength = sizeof(subKeyName)/sizeof(WCHAR);
879 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
880 if (!strcmpW(subKeyName, FLAGSW)) continue;
881 if (!strcmpW(subKeyName, HELPDIRW)) continue;
882 deleteOtherStuff = FALSE;
886 /* only delete the other parts of the key if we're absolutely sure */
887 if (deleteOtherStuff) {
888 RegDeleteKeyW(key, FLAGSW);
889 RegDeleteKeyW(key, HELPDIRW);
893 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
894 *strrchrW( keyName, '\\' ) = 0; /* remove last path component */
895 RegDeleteKeyW(HKEY_CLASSES_ROOT, keyName);
899 SysFreeString(tlibPath);
900 if (typeLib) ITypeLib_Release(typeLib);
901 if (subKey) RegCloseKey(subKey);
902 if (key) RegCloseKey(key);
906 /*======================= ITypeLib implementation =======================*/
908 typedef struct tagTLBCustData
912 struct tagTLBCustData* next;
915 /* data structure for import typelibs */
916 typedef struct tagTLBImpLib
918 int offset; /* offset in the file (MSFT)
919 offset in nametable (SLTG)
920 just used to identify library while reading
922 GUID guid; /* libid */
923 BSTR name; /* name */
925 LCID lcid; /* lcid of imported typelib */
927 WORD wVersionMajor; /* major version number */
928 WORD wVersionMinor; /* minor version number */
930 struct tagITypeLibImpl *pImpTypeLib; /* pointer to loaded typelib, or
931 NULL if not yet loaded */
932 struct tagTLBImpLib * next;
935 /* internal ITypeLib data */
936 typedef struct tagITypeLibImpl
938 const ITypeLib2Vtbl *lpVtbl;
939 const ITypeCompVtbl *lpVtblTypeComp;
941 TLIBATTR LibAttr; /* guid,lcid,syskind,version,flags */
944 /* strings can be stored in tlb as multibyte strings BUT they are *always*
945 * exported to the application as a UNICODE string.
952 int TypeInfoCount; /* nr of typeinfo's in librarry */
953 struct tagITypeInfoImpl *pTypeInfo; /* linked list of type info data */
954 int ctCustData; /* number of items in cust data list */
955 TLBCustData * pCustData; /* linked list to cust data */
956 TLBImpLib * pImpLibs; /* linked list to all imported typelibs */
957 int ctTypeDesc; /* number of items in type desc array */
958 TYPEDESC * pTypeDesc; /* array of TypeDescriptions found in the
959 library. Only used while reading MSFT
961 struct list ref_list; /* list of ref types in this typelib */
962 HREFTYPE dispatch_href; /* reference to IDispatch, -1 if unused */
965 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
966 struct tagITypeLibImpl *next, *prev;
971 static const ITypeLib2Vtbl tlbvt;
972 static const ITypeCompVtbl tlbtcvt;
974 static inline ITypeLibImpl *impl_from_ITypeComp( ITypeComp *iface )
976 return (ITypeLibImpl *)((char*)iface - FIELD_OFFSET(ITypeLibImpl, lpVtblTypeComp));
979 /* ITypeLib methods */
980 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength);
981 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength);
983 /*======================= ITypeInfo implementation =======================*/
985 /* data for referenced types */
986 typedef struct tagTLBRefType
988 INT index; /* Type index for internal ref or for external ref
989 it the format is SLTG. -2 indicates to
992 GUID guid; /* guid of the referenced type */
993 /* if index == TLB_REF_USE_GUID */
995 HREFTYPE reference; /* The href of this ref */
996 TLBImpLib *pImpTLInfo; /* If ref is external ptr to library data
997 TLB_REF_INTERNAL for internal refs
998 TLB_REF_NOT_FOUND for broken refs */
1003 #define TLB_REF_USE_GUID -2
1005 #define TLB_REF_INTERNAL (void*)-2
1006 #define TLB_REF_NOT_FOUND (void*)-1
1008 /* internal Parameter data */
1009 typedef struct tagTLBParDesc
1013 TLBCustData * pCustData; /* linked list to cust data */
1016 /* internal Function data */
1017 typedef struct tagTLBFuncDesc
1019 FUNCDESC funcdesc; /* lots of info on the function and its attributes. */
1020 BSTR Name; /* the name of this function */
1021 TLBParDesc *pParamDesc; /* array with param names and custom data */
1023 int HelpStringContext;
1025 BSTR Entry; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1027 TLBCustData * pCustData; /* linked list to cust data; */
1028 struct tagTLBFuncDesc * next;
1031 /* internal Variable data */
1032 typedef struct tagTLBVarDesc
1034 VARDESC vardesc; /* lots of info on the variable and its attributes. */
1035 BSTR Name; /* the name of this variable */
1037 int HelpStringContext; /* FIXME: where? */
1040 TLBCustData * pCustData;/* linked list to cust data; */
1041 struct tagTLBVarDesc * next;
1044 /* internal implemented interface data */
1045 typedef struct tagTLBImplType
1047 HREFTYPE hRef; /* hRef of interface */
1048 int implflags; /* IMPLFLAG_*s */
1050 TLBCustData * pCustData;/* linked list to custom data; */
1051 struct tagTLBImplType *next;
1054 /* internal TypeInfo data */
1055 typedef struct tagITypeInfoImpl
1057 const ITypeInfo2Vtbl *lpVtbl;
1058 const ITypeCompVtbl *lpVtblTypeComp;
1060 BOOL not_attached_to_typelib;
1061 TYPEATTR TypeAttr ; /* _lots_ of type information. */
1062 ITypeLibImpl * pTypeLib; /* back pointer to typelib */
1063 int index; /* index in this typelib; */
1064 HREFTYPE hreftype; /* hreftype for app object binding */
1065 /* type libs seem to store the doc strings in ascii
1066 * so why should we do it in unicode?
1071 DWORD dwHelpContext;
1072 DWORD dwHelpStringContext;
1075 TLBFuncDesc * funclist; /* linked list with function descriptions */
1078 TLBVarDesc * varlist; /* linked list with variable descriptions */
1080 /* Implemented Interfaces */
1081 TLBImplType * impltypelist;
1084 TLBCustData * pCustData; /* linked list to cust data; */
1085 struct tagITypeInfoImpl * next;
1088 static inline ITypeInfoImpl *info_impl_from_ITypeComp( ITypeComp *iface )
1090 return (ITypeInfoImpl *)((char*)iface - FIELD_OFFSET(ITypeInfoImpl, lpVtblTypeComp));
1093 static const ITypeInfo2Vtbl tinfvt;
1094 static const ITypeCompVtbl tcompvt;
1096 static ITypeInfo2 * ITypeInfo_Constructor(void);
1097 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This);
1099 typedef struct tagTLBContext
1101 unsigned int oStart; /* start of TLB in file */
1102 unsigned int pos; /* current pos */
1103 unsigned int length; /* total length */
1104 void *mapping; /* memory mapping */
1105 MSFT_SegDir * pTblDir;
1106 ITypeLibImpl* pLibInfo;
1110 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL, int offset);
1115 static void dump_TypeDesc(const TYPEDESC *pTD,char *szVarType) {
1116 if (pTD->vt & VT_RESERVED)
1117 szVarType += strlen(strcpy(szVarType, "reserved | "));
1118 if (pTD->vt & VT_BYREF)
1119 szVarType += strlen(strcpy(szVarType, "ref to "));
1120 if (pTD->vt & VT_ARRAY)
1121 szVarType += strlen(strcpy(szVarType, "array of "));
1122 if (pTD->vt & VT_VECTOR)
1123 szVarType += strlen(strcpy(szVarType, "vector of "));
1124 switch(pTD->vt & VT_TYPEMASK) {
1125 case VT_UI1: sprintf(szVarType, "VT_UI1"); break;
1126 case VT_I2: sprintf(szVarType, "VT_I2"); break;
1127 case VT_I4: sprintf(szVarType, "VT_I4"); break;
1128 case VT_R4: sprintf(szVarType, "VT_R4"); break;
1129 case VT_R8: sprintf(szVarType, "VT_R8"); break;
1130 case VT_BOOL: sprintf(szVarType, "VT_BOOL"); break;
1131 case VT_ERROR: sprintf(szVarType, "VT_ERROR"); break;
1132 case VT_CY: sprintf(szVarType, "VT_CY"); break;
1133 case VT_DATE: sprintf(szVarType, "VT_DATE"); break;
1134 case VT_BSTR: sprintf(szVarType, "VT_BSTR"); break;
1135 case VT_UNKNOWN: sprintf(szVarType, "VT_UNKNOWN"); break;
1136 case VT_DISPATCH: sprintf(szVarType, "VT_DISPATCH"); break;
1137 case VT_I1: sprintf(szVarType, "VT_I1"); break;
1138 case VT_UI2: sprintf(szVarType, "VT_UI2"); break;
1139 case VT_UI4: sprintf(szVarType, "VT_UI4"); break;
1140 case VT_INT: sprintf(szVarType, "VT_INT"); break;
1141 case VT_UINT: sprintf(szVarType, "VT_UINT"); break;
1142 case VT_VARIANT: sprintf(szVarType, "VT_VARIANT"); break;
1143 case VT_VOID: sprintf(szVarType, "VT_VOID"); break;
1144 case VT_HRESULT: sprintf(szVarType, "VT_HRESULT"); break;
1145 case VT_USERDEFINED: sprintf(szVarType, "VT_USERDEFINED ref = %x",
1146 pTD->u.hreftype); break;
1147 case VT_LPSTR: sprintf(szVarType, "VT_LPSTR"); break;
1148 case VT_LPWSTR: sprintf(szVarType, "VT_LPWSTR"); break;
1149 case VT_PTR: sprintf(szVarType, "ptr to ");
1150 dump_TypeDesc(pTD->u.lptdesc, szVarType + 7);
1152 case VT_SAFEARRAY: sprintf(szVarType, "safearray of ");
1153 dump_TypeDesc(pTD->u.lptdesc, szVarType + 13);
1155 case VT_CARRAY: sprintf(szVarType, "%d dim array of ",
1156 pTD->u.lpadesc->cDims); /* FIXME print out sizes */
1157 dump_TypeDesc(&pTD->u.lpadesc->tdescElem, szVarType + strlen(szVarType));
1160 default: sprintf(szVarType, "unknown(%d)", pTD->vt & VT_TYPEMASK); break;
1164 static void dump_ELEMDESC(const ELEMDESC *edesc) {
1166 USHORT flags = edesc->u.paramdesc.wParamFlags;
1167 dump_TypeDesc(&edesc->tdesc,buf);
1168 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc->tdesc.vt,buf);
1169 MESSAGE("\t\tu.paramdesc.wParamFlags");
1170 if (!flags) MESSAGE(" PARAMFLAGS_NONE");
1171 if (flags & PARAMFLAG_FIN) MESSAGE(" PARAMFLAG_FIN");
1172 if (flags & PARAMFLAG_FOUT) MESSAGE(" PARAMFLAG_FOUT");
1173 if (flags & PARAMFLAG_FLCID) MESSAGE(" PARAMFLAG_FLCID");
1174 if (flags & PARAMFLAG_FRETVAL) MESSAGE(" PARAMFLAG_FRETVAL");
1175 if (flags & PARAMFLAG_FOPT) MESSAGE(" PARAMFLAG_FOPT");
1176 if (flags & PARAMFLAG_FHASDEFAULT) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1177 if (flags & PARAMFLAG_FHASCUSTDATA) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1178 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc->u.paramdesc.pparamdescex);
1180 static void dump_FUNCDESC(const FUNCDESC *funcdesc) {
1182 MESSAGE("memid is %08x\n",funcdesc->memid);
1183 for (i=0;i<funcdesc->cParams;i++) {
1184 MESSAGE("Param %d:\n",i);
1185 dump_ELEMDESC(funcdesc->lprgelemdescParam+i);
1187 MESSAGE("\tfunckind: %d (",funcdesc->funckind);
1188 switch (funcdesc->funckind) {
1189 case FUNC_VIRTUAL: MESSAGE("virtual");break;
1190 case FUNC_PUREVIRTUAL: MESSAGE("pure virtual");break;
1191 case FUNC_NONVIRTUAL: MESSAGE("nonvirtual");break;
1192 case FUNC_STATIC: MESSAGE("static");break;
1193 case FUNC_DISPATCH: MESSAGE("dispatch");break;
1194 default: MESSAGE("unknown");break;
1196 MESSAGE(")\n\tinvkind: %d (",funcdesc->invkind);
1197 switch (funcdesc->invkind) {
1198 case INVOKE_FUNC: MESSAGE("func");break;
1199 case INVOKE_PROPERTYGET: MESSAGE("property get");break;
1200 case INVOKE_PROPERTYPUT: MESSAGE("property put");break;
1201 case INVOKE_PROPERTYPUTREF: MESSAGE("property put ref");break;
1203 MESSAGE(")\n\tcallconv: %d (",funcdesc->callconv);
1204 switch (funcdesc->callconv) {
1205 case CC_CDECL: MESSAGE("cdecl");break;
1206 case CC_PASCAL: MESSAGE("pascal");break;
1207 case CC_STDCALL: MESSAGE("stdcall");break;
1208 case CC_SYSCALL: MESSAGE("syscall");break;
1211 MESSAGE(")\n\toVft: %d\n", funcdesc->oVft);
1212 MESSAGE("\tcParamsOpt: %d\n", funcdesc->cParamsOpt);
1213 MESSAGE("\twFlags: %x\n", funcdesc->wFuncFlags);
1215 MESSAGE("\telemdescFunc (return value type):\n");
1216 dump_ELEMDESC(&funcdesc->elemdescFunc);
1219 static const char * const typekind_desc[] =
1232 static void dump_TLBFuncDescOne(const TLBFuncDesc * pfd)
1235 MESSAGE("%s(%u)\n", debugstr_w(pfd->Name), pfd->funcdesc.cParams);
1236 for (i=0;i<pfd->funcdesc.cParams;i++)
1237 MESSAGE("\tparm%d: %s\n",i,debugstr_w(pfd->pParamDesc[i].Name));
1240 dump_FUNCDESC(&(pfd->funcdesc));
1242 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd->HelpString));
1243 MESSAGE("\tentry: %s\n", (pfd->Entry == (void *)-1) ? "invalid" : debugstr_w(pfd->Entry));
1245 static void dump_TLBFuncDesc(const TLBFuncDesc * pfd)
1249 dump_TLBFuncDescOne(pfd);
1253 static void dump_TLBVarDesc(const TLBVarDesc * pvd)
1257 TRACE_(typelib)("%s\n", debugstr_w(pvd->Name));
1262 static void dump_TLBImpLib(const TLBImpLib *import)
1264 TRACE_(typelib)("%s %s\n", debugstr_guid(&(import->guid)),
1265 debugstr_w(import->name));
1266 TRACE_(typelib)("v%d.%d lcid=%x offset=%x\n", import->wVersionMajor,
1267 import->wVersionMinor, import->lcid, import->offset);
1270 static void dump_TLBRefType(const ITypeLibImpl *pTL)
1274 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
1276 TRACE_(typelib)("href:0x%08x\n", ref->reference);
1277 if(ref->index == -1)
1278 TRACE_(typelib)("%s\n", debugstr_guid(&(ref->guid)));
1280 TRACE_(typelib)("type no: %d\n", ref->index);
1282 if(ref->pImpTLInfo != TLB_REF_INTERNAL && ref->pImpTLInfo != TLB_REF_NOT_FOUND)
1284 TRACE_(typelib)("in lib\n");
1285 dump_TLBImpLib(ref->pImpTLInfo);
1290 static void dump_TLBImplType(const TLBImplType * impl)
1294 "implementing/inheriting interface hRef = %x implflags %x\n",
1295 impl->hRef, impl->implflags);
1300 static void dump_Variant(const VARIANT * pvar)
1304 TRACE("%p->{%s%s", pvar, debugstr_VT(pvar), debugstr_VF(pvar));
1308 if (V_ISBYREF(pvar) || V_TYPE(pvar) == VT_UNKNOWN ||
1309 V_TYPE(pvar) == VT_DISPATCH || V_TYPE(pvar) == VT_RECORD)
1311 TRACE(",%p", V_BYREF(pvar));
1313 else if (V_ISARRAY(pvar) || V_ISVECTOR(pvar))
1315 TRACE(",%p", V_ARRAY(pvar));
1317 else switch (V_TYPE(pvar))
1319 case VT_I1: TRACE(",%d", V_I1(pvar)); break;
1320 case VT_UI1: TRACE(",%d", V_UI1(pvar)); break;
1321 case VT_I2: TRACE(",%d", V_I2(pvar)); break;
1322 case VT_UI2: TRACE(",%d", V_UI2(pvar)); break;
1324 case VT_I4: TRACE(",%d", V_I4(pvar)); break;
1326 case VT_UI4: TRACE(",%d", V_UI4(pvar)); break;
1327 case VT_I8: TRACE(",0x%08x,0x%08x", (ULONG)(V_I8(pvar) >> 32),
1328 (ULONG)(V_I8(pvar) & 0xffffffff)); break;
1329 case VT_UI8: TRACE(",0x%08x,0x%08x", (ULONG)(V_UI8(pvar) >> 32),
1330 (ULONG)(V_UI8(pvar) & 0xffffffff)); break;
1331 case VT_R4: TRACE(",%3.3e", V_R4(pvar)); break;
1332 case VT_R8: TRACE(",%3.3e", V_R8(pvar)); break;
1333 case VT_BOOL: TRACE(",%s", V_BOOL(pvar) ? "TRUE" : "FALSE"); break;
1334 case VT_BSTR: TRACE(",%s", debugstr_w(V_BSTR(pvar))); break;
1335 case VT_CY: TRACE(",0x%08x,0x%08x", V_CY(pvar).s.Hi,
1336 V_CY(pvar).s.Lo); break;
1338 if(!VariantTimeToSystemTime(V_DATE(pvar), &st))
1339 TRACE(",<invalid>");
1341 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st.wYear, st.wMonth, st.wDay,
1342 st.wHour, st.wMinute, st.wSecond);
1346 case VT_USERDEFINED:
1348 case VT_NULL: break;
1349 default: TRACE(",?"); break;
1355 static void dump_DispParms(const DISPPARAMS * pdp)
1359 TRACE("args=%u named args=%u\n", pdp->cArgs, pdp->cNamedArgs);
1361 if (pdp->cNamedArgs && pdp->rgdispidNamedArgs)
1363 TRACE("named args:\n");
1364 for (index = 0; index < pdp->cNamedArgs; index++)
1365 TRACE( "\t0x%x\n", pdp->rgdispidNamedArgs[index] );
1368 if (pdp->cArgs && pdp->rgvarg)
1371 for (index = 0; index < pdp->cArgs; index++)
1372 dump_Variant( &pdp->rgvarg[index] );
1376 static void dump_TypeInfo(const ITypeInfoImpl * pty)
1378 TRACE("%p ref=%u\n", pty, pty->ref);
1379 TRACE("%s %s\n", debugstr_w(pty->Name), debugstr_w(pty->DocString));
1380 TRACE("attr:%s\n", debugstr_guid(&(pty->TypeAttr.guid)));
1381 TRACE("kind:%s\n", typekind_desc[pty->TypeAttr.typekind]);
1382 TRACE("fct:%u var:%u impl:%u\n",
1383 pty->TypeAttr.cFuncs, pty->TypeAttr.cVars, pty->TypeAttr.cImplTypes);
1384 TRACE("wTypeFlags: 0x%04x\n", pty->TypeAttr.wTypeFlags);
1385 TRACE("parent tlb:%p index in TLB:%u\n",pty->pTypeLib, pty->index);
1386 if (pty->TypeAttr.typekind == TKIND_MODULE) TRACE("dllname:%s\n", debugstr_w(pty->DllName));
1388 dump_TLBFuncDesc(pty->funclist);
1389 dump_TLBVarDesc(pty->varlist);
1390 dump_TLBImplType(pty->impltypelist);
1393 static void dump_VARDESC(const VARDESC *v)
1395 MESSAGE("memid %d\n",v->memid);
1396 MESSAGE("lpstrSchema %s\n",debugstr_w(v->lpstrSchema));
1397 MESSAGE("oInst %d\n",v->u.oInst);
1398 dump_ELEMDESC(&(v->elemdescVar));
1399 MESSAGE("wVarFlags %x\n",v->wVarFlags);
1400 MESSAGE("varkind %d\n",v->varkind);
1403 static TYPEDESC stndTypeDesc[VT_LPWSTR+1]=
1405 /* VT_LPWSTR is largest type that */
1406 /* may appear in type description*/
1407 {{0}, 0},{{0}, 1},{{0}, 2},{{0}, 3},{{0}, 4},
1408 {{0}, 5},{{0}, 6},{{0}, 7},{{0}, 8},{{0}, 9},
1409 {{0},10},{{0},11},{{0},12},{{0},13},{{0},14},
1410 {{0},15},{{0},16},{{0},17},{{0},18},{{0},19},
1411 {{0},20},{{0},21},{{0},22},{{0},23},{{0},24},
1412 {{0},25},{{0},26},{{0},27},{{0},28},{{0},29},
1416 static void TLB_abort(void)
1421 static void * TLB_Alloc(unsigned size) __WINE_ALLOC_SIZE(1);
1422 static void * TLB_Alloc(unsigned size)
1425 if((ret=HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,size))==NULL){
1427 ERR("cannot allocate memory\n");
1432 static void TLB_Free(void * ptr)
1434 HeapFree(GetProcessHeap(), 0, ptr);
1437 /* returns the size required for a deep copy of a typedesc into a
1439 static SIZE_T TLB_SizeTypeDesc( const TYPEDESC *tdesc, BOOL alloc_initial_space )
1443 if (alloc_initial_space)
1444 size += sizeof(TYPEDESC);
1450 size += TLB_SizeTypeDesc(tdesc->u.lptdesc, TRUE);
1453 size += FIELD_OFFSET(ARRAYDESC, rgbounds[tdesc->u.lpadesc->cDims]);
1454 size += TLB_SizeTypeDesc(&tdesc->u.lpadesc->tdescElem, FALSE);
1460 /* deep copy a typedesc into a flat buffer */
1461 static void *TLB_CopyTypeDesc( TYPEDESC *dest, const TYPEDESC *src, void *buffer )
1466 buffer = (char *)buffer + sizeof(TYPEDESC);
1475 dest->u.lptdesc = buffer;
1476 buffer = TLB_CopyTypeDesc(NULL, src->u.lptdesc, buffer);
1479 dest->u.lpadesc = buffer;
1480 memcpy(dest->u.lpadesc, src->u.lpadesc, FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]));
1481 buffer = (char *)buffer + FIELD_OFFSET(ARRAYDESC, rgbounds[src->u.lpadesc->cDims]);
1482 buffer = TLB_CopyTypeDesc(&dest->u.lpadesc->tdescElem, &src->u.lpadesc->tdescElem, buffer);
1488 /* free custom data allocated by MSFT_CustData */
1489 static inline void TLB_FreeCustData(TLBCustData *pCustData)
1491 TLBCustData *pCustDataNext;
1492 for (; pCustData; pCustData = pCustDataNext)
1494 VariantClear(&pCustData->data);
1496 pCustDataNext = pCustData->next;
1497 TLB_Free(pCustData);
1501 static BSTR TLB_MultiByteToBSTR(const char *ptr)
1506 len = MultiByteToWideChar(CP_ACP, 0, ptr, -1, NULL, 0);
1507 ret = SysAllocStringLen(NULL, len - 1);
1508 if (!ret) return ret;
1509 MultiByteToWideChar(CP_ACP, 0, ptr, -1, ret, len);
1513 /**********************************************************************
1515 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1517 static inline unsigned int MSFT_Tell(const TLBContext *pcx)
1522 static inline void MSFT_Seek(TLBContext *pcx, LONG where)
1524 if (where != DO_NOT_SEEK)
1526 where += pcx->oStart;
1527 if (where > pcx->length)
1530 ERR("seek beyond end (%d/%d)\n", where, pcx->length );
1538 static DWORD MSFT_Read(void *buffer, DWORD count, TLBContext *pcx, LONG where )
1540 TRACE_(typelib)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1541 pcx->pos, count, pcx->oStart, pcx->length, where);
1543 MSFT_Seek(pcx, where);
1544 if (pcx->pos + count > pcx->length) count = pcx->length - pcx->pos;
1545 memcpy( buffer, (char *)pcx->mapping + pcx->pos, count );
1550 static DWORD MSFT_ReadLEDWords(void *buffer, DWORD count, TLBContext *pcx,
1555 ret = MSFT_Read(buffer, count, pcx, where);
1556 FromLEDWords(buffer, ret);
1561 static DWORD MSFT_ReadLEWords(void *buffer, DWORD count, TLBContext *pcx,
1566 ret = MSFT_Read(buffer, count, pcx, where);
1567 FromLEWords(buffer, ret);
1572 static void MSFT_ReadGuid( GUID *pGuid, int offset, TLBContext *pcx)
1574 if(offset<0 || pcx->pTblDir->pGuidTab.offset <0){
1575 memset(pGuid,0, sizeof(GUID));
1578 MSFT_Read(pGuid, sizeof(GUID), pcx, pcx->pTblDir->pGuidTab.offset+offset );
1579 pGuid->Data1 = FromLEDWord(pGuid->Data1);
1580 pGuid->Data2 = FromLEWord(pGuid->Data2);
1581 pGuid->Data3 = FromLEWord(pGuid->Data3);
1582 TRACE_(typelib)("%s\n", debugstr_guid(pGuid));
1585 static HREFTYPE MSFT_ReadHreftype( TLBContext *pcx, int offset )
1587 MSFT_NameIntro niName;
1591 ERR_(typelib)("bad offset %d\n", offset);
1595 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1596 pcx->pTblDir->pNametab.offset+offset);
1598 return niName.hreftype;
1601 static BSTR MSFT_ReadName( TLBContext *pcx, int offset)
1604 MSFT_NameIntro niName;
1606 BSTR bstrName = NULL;
1610 ERR_(typelib)("bad offset %d\n", offset);
1613 MSFT_ReadLEDWords(&niName, sizeof(niName), pcx,
1614 pcx->pTblDir->pNametab.offset+offset);
1615 niName.namelen &= 0xFF; /* FIXME: correct ? */
1616 name=TLB_Alloc((niName.namelen & 0xff) +1);
1617 MSFT_Read(name, (niName.namelen & 0xff), pcx, DO_NOT_SEEK);
1618 name[niName.namelen & 0xff]='\0';
1620 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1623 /* no invalid characters in string */
1626 bstrName = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1628 /* don't check for invalid character since this has been done previously */
1629 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, name, -1, bstrName, lengthInChars);
1633 TRACE_(typelib)("%s %d\n", debugstr_w(bstrName), lengthInChars);
1637 static BSTR MSFT_ReadString( TLBContext *pcx, int offset)
1644 if(offset<0) return NULL;
1645 MSFT_ReadLEWords(&length, sizeof(INT16), pcx, pcx->pTblDir->pStringtab.offset+offset);
1646 if(length <= 0) return 0;
1647 string=TLB_Alloc(length +1);
1648 MSFT_Read(string, length, pcx, DO_NOT_SEEK);
1649 string[length]='\0';
1651 lengthInChars = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED | MB_ERR_INVALID_CHARS,
1652 string, -1, NULL, 0);
1654 /* no invalid characters in string */
1657 bstr = SysAllocStringByteLen(NULL, lengthInChars * sizeof(WCHAR));
1659 /* don't check for invalid character since this has been done previously */
1660 MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, string, -1, bstr, lengthInChars);
1664 TRACE_(typelib)("%s %d\n", debugstr_w(bstr), lengthInChars);
1668 * read a value and fill a VARIANT structure
1670 static void MSFT_ReadValue( VARIANT * pVar, int offset, TLBContext *pcx )
1674 TRACE_(typelib)("\n");
1676 if(offset <0) { /* data are packed in here */
1677 V_VT(pVar) = (offset & 0x7c000000 )>> 26;
1678 V_I4(pVar) = offset & 0x3ffffff;
1681 MSFT_ReadLEWords(&(V_VT(pVar)), sizeof(VARTYPE), pcx,
1682 pcx->pTblDir->pCustData.offset + offset );
1683 TRACE_(typelib)("Vartype = %x\n", V_VT(pVar));
1684 switch (V_VT(pVar)){
1685 case VT_EMPTY: /* FIXME: is this right? */
1686 case VT_NULL: /* FIXME: is this right? */
1687 case VT_I2 : /* this should not happen */
1698 case VT_VOID : /* FIXME: is this right? */
1706 case VT_DECIMAL : /* FIXME: is this right? */
1709 /* pointer types with known behaviour */
1712 MSFT_ReadLEDWords(&size, sizeof(INT), pcx, DO_NOT_SEEK );
1715 DWORD origPos = MSFT_Tell(pcx), nullPos;
1718 MSFT_Read(&next, 1, pcx, DO_NOT_SEEK);
1720 nullPos = MSFT_Tell(pcx);
1721 size = nullPos - origPos;
1722 MSFT_Seek(pcx, origPos);
1724 ptr=TLB_Alloc(size);/* allocate temp buffer */
1725 MSFT_Read(ptr, size, pcx, DO_NOT_SEEK);/* read string (ANSI) */
1726 V_BSTR(pVar)=SysAllocStringLen(NULL,size);
1727 /* FIXME: do we need a AtoW conversion here? */
1728 V_UNION(pVar, bstrVal[size])='\0';
1729 while(size--) V_UNION(pVar, bstrVal[size])=ptr[size];
1733 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1740 case VT_USERDEFINED :
1746 case VT_STREAMED_OBJECT :
1747 case VT_STORED_OBJECT :
1748 case VT_BLOB_OBJECT :
1753 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1757 if(size>0) /* (big|small) endian correct? */
1758 MSFT_Read(&(V_I2(pVar)), size, pcx, DO_NOT_SEEK );
1762 * create a linked list with custom data
1764 static int MSFT_CustData( TLBContext *pcx, int offset, TLBCustData** ppCustData )
1770 TRACE_(typelib)("\n");
1774 pNew=TLB_Alloc(sizeof(TLBCustData));
1775 MSFT_ReadLEDWords(&entry, sizeof(entry), pcx, pcx->pTblDir->pCDGuids.offset+offset);
1776 MSFT_ReadGuid(&(pNew->guid), entry.GuidOffset , pcx);
1777 MSFT_ReadValue(&(pNew->data), entry.DataOffset, pcx);
1778 /* add new custom data at head of the list */
1779 pNew->next=*ppCustData;
1781 offset = entry.next;
1786 static void MSFT_GetTdesc(TLBContext *pcx, INT type, TYPEDESC *pTd,
1790 pTd->vt=type & VT_TYPEMASK;
1792 *pTd=pcx->pLibInfo->pTypeDesc[type/(2*sizeof(INT))];
1794 if(pTd->vt == VT_USERDEFINED)
1795 MSFT_DoRefType(pcx, pTI->pTypeLib, pTd->u.hreftype);
1797 TRACE_(typelib)("vt type = %X\n", pTd->vt);
1800 static void MSFT_ResolveReferencedTypes(TLBContext *pcx, ITypeInfoImpl *pTI, TYPEDESC *lpTypeDesc)
1802 /* resolve referenced type if any */
1805 switch (lpTypeDesc->vt)
1808 lpTypeDesc = lpTypeDesc->u.lptdesc;
1812 lpTypeDesc = & (lpTypeDesc->u.lpadesc->tdescElem);
1815 case VT_USERDEFINED:
1816 MSFT_DoRefType(pcx, pTI->pTypeLib,
1817 lpTypeDesc->u.hreftype);
1829 MSFT_DoFuncs(TLBContext* pcx,
1834 TLBFuncDesc** pptfd)
1837 * member information is stored in a data structure at offset
1838 * indicated by the memoffset field of the typeinfo structure
1839 * There are several distinctive parts.
1840 * The first part starts with a field that holds the total length
1841 * of this (first) part excluding this field. Then follow the records,
1842 * for each member there is one record.
1844 * The first entry is always the length of the record (including this
1846 * The rest of the record depends on the type of the member. If there is
1847 * a field indicating the member type (function, variable, interface, etc)
1848 * I have not found it yet. At this time we depend on the information
1849 * in the type info and the usual order how things are stored.
1851 * Second follows an array sized nrMEM*sizeof(INT) with a member id
1854 * Third is an equal sized array with file offsets to the name entry
1857 * The fourth and last (?) part is an array with offsets to the records
1858 * in the first part of this file segment.
1861 int infolen, nameoffset, reclength, nrattributes, i;
1862 int recoffset = offset + sizeof(INT);
1864 char *recbuf = HeapAlloc(GetProcessHeap(), 0, 0xffff);
1865 MSFT_FuncRecord * pFuncRec=(MSFT_FuncRecord *) recbuf;
1866 TLBFuncDesc *ptfd_prev = NULL;
1868 TRACE_(typelib)("\n");
1870 MSFT_ReadLEDWords(&infolen, sizeof(INT), pcx, offset);
1872 for ( i = 0; i < cFuncs ; i++ )
1874 *pptfd = TLB_Alloc(sizeof(TLBFuncDesc));
1876 /* name, eventually add to a hash table */
1877 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
1878 offset + infolen + (cFuncs + cVars + i + 1) * sizeof(INT));
1880 /* nameoffset is sometimes -1 on the second half of a propget/propput
1881 * pair of functions */
1882 if ((nameoffset == -1) && (i > 0))
1883 (*pptfd)->Name = SysAllocString(ptfd_prev->Name);
1885 (*pptfd)->Name = MSFT_ReadName(pcx, nameoffset);
1887 /* read the function information record */
1888 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
1890 reclength &= 0xffff;
1892 MSFT_ReadLEDWords(pFuncRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
1894 /* do the attributes */
1895 nrattributes = (reclength - pFuncRec->nrargs * 3 * sizeof(int) - 0x18)
1898 if ( nrattributes > 0 )
1900 (*pptfd)->helpcontext = pFuncRec->OptAttr[0] ;
1902 if ( nrattributes > 1 )
1904 (*pptfd)->HelpString = MSFT_ReadString(pcx,
1905 pFuncRec->OptAttr[1]) ;
1907 if ( nrattributes > 2 )
1909 if ( pFuncRec->FKCCIC & 0x2000 )
1911 if (!IS_INTRESOURCE(pFuncRec->OptAttr[2]))
1912 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec->OptAttr[2]);
1913 (*pptfd)->Entry = (BSTR)(DWORD_PTR)LOWORD(pFuncRec->OptAttr[2]);
1917 (*pptfd)->Entry = MSFT_ReadString(pcx,
1918 pFuncRec->OptAttr[2]);
1920 if( nrattributes > 5 )
1922 (*pptfd)->HelpStringContext = pFuncRec->OptAttr[5] ;
1924 if ( nrattributes > 6 && pFuncRec->FKCCIC & 0x80 )
1927 pFuncRec->OptAttr[6],
1928 &(*pptfd)->pCustData);
1934 (*pptfd)->Entry = (BSTR)-1;
1939 /* fill the FuncDesc Structure */
1940 MSFT_ReadLEDWords( & (*pptfd)->funcdesc.memid, sizeof(INT), pcx,
1941 offset + infolen + ( i + 1) * sizeof(INT));
1943 (*pptfd)->funcdesc.funckind = (pFuncRec->FKCCIC) & 0x7;
1944 (*pptfd)->funcdesc.invkind = (pFuncRec->FKCCIC) >> 3 & 0xF;
1945 (*pptfd)->funcdesc.callconv = (pFuncRec->FKCCIC) >> 8 & 0xF;
1946 (*pptfd)->funcdesc.cParams = pFuncRec->nrargs ;
1947 (*pptfd)->funcdesc.cParamsOpt = pFuncRec->nroargs ;
1948 (*pptfd)->funcdesc.oVft = pFuncRec->VtableOffset;
1949 (*pptfd)->funcdesc.wFuncFlags = LOWORD(pFuncRec->Flags) ;
1953 &(*pptfd)->funcdesc.elemdescFunc.tdesc,
1955 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptfd)->funcdesc.elemdescFunc.tdesc);
1957 /* do the parameters/arguments */
1958 if(pFuncRec->nrargs)
1961 MSFT_ParameterInfo paraminfo;
1963 (*pptfd)->funcdesc.lprgelemdescParam =
1964 TLB_Alloc(pFuncRec->nrargs * sizeof(ELEMDESC));
1966 (*pptfd)->pParamDesc =
1967 TLB_Alloc(pFuncRec->nrargs * sizeof(TLBParDesc));
1969 MSFT_ReadLEDWords(¶minfo, sizeof(paraminfo), pcx,
1970 recoffset + reclength - pFuncRec->nrargs * sizeof(MSFT_ParameterInfo));
1972 for ( j = 0 ; j < pFuncRec->nrargs ; j++ )
1974 ELEMDESC *elemdesc = &(*pptfd)->funcdesc.lprgelemdescParam[j];
1981 elemdesc->u.paramdesc.wParamFlags = paraminfo.Flags;
1984 if (paraminfo.oName == -1)
1985 /* this occurs for [propput] or [propget] methods, so
1986 * we should just set the name of the parameter to the
1987 * name of the method. */
1988 (*pptfd)->pParamDesc[j].Name = SysAllocString((*pptfd)->Name);
1990 (*pptfd)->pParamDesc[j].Name =
1991 MSFT_ReadName( pcx, paraminfo.oName );
1992 TRACE_(typelib)("param[%d] = %s\n", j, debugstr_w((*pptfd)->pParamDesc[j].Name));
1994 MSFT_ResolveReferencedTypes(pcx, pTI, &elemdesc->tdesc);
1997 if ( (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT) &&
1998 (pFuncRec->FKCCIC & 0x1000) )
2000 INT* pInt = (INT *)((char *)pFuncRec +
2002 (pFuncRec->nrargs * 4 + 1) * sizeof(INT) );
2004 PARAMDESC* pParamDesc = &elemdesc->u.paramdesc;
2006 pParamDesc->pparamdescex = TLB_Alloc(sizeof(PARAMDESCEX));
2007 pParamDesc->pparamdescex->cBytes = sizeof(PARAMDESCEX);
2009 MSFT_ReadValue(&(pParamDesc->pparamdescex->varDefaultValue),
2013 elemdesc->u.paramdesc.pparamdescex = NULL;
2015 if ( nrattributes > 7 + j && pFuncRec->FKCCIC & 0x80 )
2018 pFuncRec->OptAttr[7+j],
2019 &(*pptfd)->pParamDesc[j].pCustData);
2022 /* SEEK value = jump to offset,
2023 * from there jump to the end of record,
2024 * go back by (j-1) arguments
2026 MSFT_ReadLEDWords( ¶minfo ,
2027 sizeof(MSFT_ParameterInfo), pcx,
2028 recoffset + reclength - ((pFuncRec->nrargs - j - 1)
2029 * sizeof(MSFT_ParameterInfo)));
2033 /* scode is not used: archaic win16 stuff FIXME: right? */
2034 (*pptfd)->funcdesc.cScodes = 0 ;
2035 (*pptfd)->funcdesc.lprgscode = NULL ;
2038 pptfd = & ((*pptfd)->next);
2039 recoffset += reclength;
2041 HeapFree(GetProcessHeap(), 0, recbuf);
2044 static void MSFT_DoVars(TLBContext *pcx, ITypeInfoImpl *pTI, int cFuncs,
2045 int cVars, int offset, TLBVarDesc ** pptvd)
2047 int infolen, nameoffset, reclength;
2049 MSFT_VarRecord * pVarRec=(MSFT_VarRecord *) recbuf;
2053 TRACE_(typelib)("\n");
2055 MSFT_ReadLEDWords(&infolen,sizeof(INT), pcx, offset);
2056 MSFT_ReadLEDWords(&recoffset,sizeof(INT), pcx, offset + infolen +
2057 ((cFuncs+cVars)*2+cFuncs + 1)*sizeof(INT));
2058 recoffset += offset+sizeof(INT);
2059 for(i=0;i<cVars;i++){
2060 *pptvd=TLB_Alloc(sizeof(TLBVarDesc));
2061 /* name, eventually add to a hash table */
2062 MSFT_ReadLEDWords(&nameoffset, sizeof(INT), pcx,
2063 offset + infolen + (2*cFuncs + cVars + i + 1) * sizeof(INT));
2064 (*pptvd)->Name=MSFT_ReadName(pcx, nameoffset);
2065 /* read the variable information record */
2066 MSFT_ReadLEDWords(&reclength, sizeof(INT), pcx, recoffset);
2068 MSFT_ReadLEDWords(pVarRec, reclength - sizeof(INT), pcx, DO_NOT_SEEK);
2070 if(reclength >(6*sizeof(INT)) )
2071 (*pptvd)->HelpContext=pVarRec->HelpContext;
2072 if(reclength >(7*sizeof(INT)) )
2073 (*pptvd)->HelpString = MSFT_ReadString(pcx, pVarRec->oHelpString) ;
2074 if(reclength >(8*sizeof(INT)) )
2075 if(reclength >(9*sizeof(INT)) )
2076 (*pptvd)->HelpStringContext=pVarRec->HelpStringContext;
2077 /* fill the VarDesc Structure */
2078 MSFT_ReadLEDWords(&(*pptvd)->vardesc.memid, sizeof(INT), pcx,
2079 offset + infolen + (cFuncs + i + 1) * sizeof(INT));
2080 (*pptvd)->vardesc.varkind = pVarRec->VarKind;
2081 (*pptvd)->vardesc.wVarFlags = pVarRec->Flags;
2082 MSFT_GetTdesc(pcx, pVarRec->DataType,
2083 &(*pptvd)->vardesc.elemdescVar.tdesc, pTI);
2084 /* (*pptvd)->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2085 if(pVarRec->VarKind == VAR_CONST ){
2086 (*pptvd)->vardesc.u.lpvarValue=TLB_Alloc(sizeof(VARIANT));
2087 MSFT_ReadValue((*pptvd)->vardesc.u.lpvarValue,
2088 pVarRec->OffsValue, pcx);
2090 (*pptvd)->vardesc.u.oInst=pVarRec->OffsValue;
2091 MSFT_ResolveReferencedTypes(pcx, pTI, &(*pptvd)->vardesc.elemdescVar.tdesc);
2092 pptvd=&((*pptvd)->next);
2093 recoffset += reclength;
2096 /* fill in data for a hreftype (offset). When the referenced type is contained
2097 * in the typelib, it's just an (file) offset in the type info base dir.
2098 * If comes from import, it's an offset+1 in the ImpInfo table
2100 static void MSFT_DoRefType(TLBContext *pcx, ITypeLibImpl *pTL,
2105 TRACE_(typelib)("TLB context %p, TLB offset %x\n", pcx, offset);
2107 LIST_FOR_EACH_ENTRY(ref, &pTL->ref_list, TLBRefType, entry)
2109 if(ref->reference == offset) return;
2112 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
2113 list_add_tail(&pTL->ref_list, &ref->entry);
2115 if(!MSFT_HREFTYPE_INTHISFILE( offset)) {
2116 /* external typelib */
2117 MSFT_ImpInfo impinfo;
2118 TLBImpLib *pImpLib=(pcx->pLibInfo->pImpLibs);
2120 TRACE_(typelib)("offset %x, masked offset %x\n", offset, offset + (offset & 0xfffffffc));
2122 MSFT_ReadLEDWords(&impinfo, sizeof(impinfo), pcx,
2123 pcx->pTblDir->pImpInfo.offset + (offset & 0xfffffffc));
2124 while (pImpLib){ /* search the known offsets of all import libraries */
2125 if(pImpLib->offset==impinfo.oImpFile) break;
2126 pImpLib=pImpLib->next;
2129 ref->reference = offset;
2130 ref->pImpTLInfo = pImpLib;
2131 if(impinfo.flags & MSFT_IMPINFO_OFFSET_IS_GUID) {
2132 MSFT_ReadGuid(&ref->guid, impinfo.oGuid, pcx);
2133 TRACE("importing by guid %s\n", debugstr_guid(&ref->guid));
2134 ref->index = TLB_REF_USE_GUID;
2136 ref->index = impinfo.oGuid;
2138 ERR("Cannot find a reference\n");
2139 ref->reference = -1;
2140 ref->pImpTLInfo = TLB_REF_NOT_FOUND;
2143 /* in this typelib */
2144 ref->index = MSFT_HREFTYPE_INDEX(offset);
2145 ref->reference = offset;
2146 ref->pImpTLInfo = TLB_REF_INTERNAL;
2150 /* process Implemented Interfaces of a com class */
2151 static void MSFT_DoImplTypes(TLBContext *pcx, ITypeInfoImpl *pTI, int count,
2155 MSFT_RefRecord refrec;
2156 TLBImplType **ppImpl = &pTI->impltypelist;
2158 TRACE_(typelib)("\n");
2160 for(i=0;i<count;i++){
2161 if(offset<0) break; /* paranoia */
2162 *ppImpl=TLB_Alloc(sizeof(**ppImpl));
2163 MSFT_ReadLEDWords(&refrec,sizeof(refrec),pcx,offset+pcx->pTblDir->pRefTab.offset);
2164 MSFT_DoRefType(pcx, pTI->pTypeLib, refrec.reftype);
2165 (*ppImpl)->hRef = refrec.reftype;
2166 (*ppImpl)->implflags=refrec.flags;
2167 (*ppImpl)->ctCustData=
2168 MSFT_CustData(pcx, refrec.oCustData, &(*ppImpl)->pCustData);
2169 offset=refrec.onext;
2170 ppImpl=&((*ppImpl)->next);
2174 * process a typeinfo record
2176 static ITypeInfoImpl * MSFT_DoTypeInfo(
2179 ITypeLibImpl * pLibInfo)
2181 MSFT_TypeInfoBase tiBase;
2182 ITypeInfoImpl *ptiRet;
2184 TRACE_(typelib)("count=%u\n", count);
2186 ptiRet = (ITypeInfoImpl*) ITypeInfo_Constructor();
2187 MSFT_ReadLEDWords(&tiBase, sizeof(tiBase) ,pcx ,
2188 pcx->pTblDir->pTypeInfoTab.offset+count*sizeof(tiBase));
2190 /* this is where we are coming from */
2191 ptiRet->pTypeLib = pLibInfo;
2192 ptiRet->index=count;
2193 /* fill in the typeattr fields */
2195 MSFT_ReadGuid(&ptiRet->TypeAttr.guid, tiBase.posguid, pcx);
2196 ptiRet->TypeAttr.lcid=pLibInfo->LibAttr.lcid; /* FIXME: correct? */
2197 ptiRet->TypeAttr.lpstrSchema=NULL; /* reserved */
2198 ptiRet->TypeAttr.cbSizeInstance=tiBase.size;
2199 ptiRet->TypeAttr.typekind=tiBase.typekind & 0xF;
2200 ptiRet->TypeAttr.cFuncs=LOWORD(tiBase.cElement);
2201 ptiRet->TypeAttr.cVars=HIWORD(tiBase.cElement);
2202 ptiRet->TypeAttr.cbAlignment=(tiBase.typekind >> 11 )& 0x1F; /* there are more flags there */
2203 ptiRet->TypeAttr.wTypeFlags=tiBase.flags;
2204 ptiRet->TypeAttr.wMajorVerNum=LOWORD(tiBase.version);
2205 ptiRet->TypeAttr.wMinorVerNum=HIWORD(tiBase.version);
2206 ptiRet->TypeAttr.cImplTypes=tiBase.cImplTypes;
2207 ptiRet->TypeAttr.cbSizeVft=tiBase.cbSizeVft; /* FIXME: this is only the non inherited part */
2208 if(ptiRet->TypeAttr.typekind == TKIND_ALIAS)
2209 MSFT_GetTdesc(pcx, tiBase.datatype1,
2210 &ptiRet->TypeAttr.tdescAlias, ptiRet);
2213 /* IDLDESC idldescType; *//* never saw this one != zero */
2215 /* name, eventually add to a hash table */
2216 ptiRet->Name=MSFT_ReadName(pcx, tiBase.NameOffset);
2217 ptiRet->hreftype = MSFT_ReadHreftype(pcx, tiBase.NameOffset);
2218 TRACE_(typelib)("reading %s\n", debugstr_w(ptiRet->Name));
2220 ptiRet->DocString=MSFT_ReadString(pcx, tiBase.docstringoffs);
2221 ptiRet->dwHelpStringContext=tiBase.helpstringcontext;
2222 ptiRet->dwHelpContext=tiBase.helpcontext;
2224 if (ptiRet->TypeAttr.typekind == TKIND_MODULE)
2225 ptiRet->DllName = MSFT_ReadString(pcx, tiBase.datatype1);
2227 /* note: InfoType's Help file and HelpStringDll come from the containing
2228 * library. Further HelpString and Docstring appear to be the same thing :(
2231 if(ptiRet->TypeAttr.cFuncs >0 )
2232 MSFT_DoFuncs(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2233 ptiRet->TypeAttr.cVars,
2234 tiBase.memoffset, & ptiRet->funclist);
2236 if(ptiRet->TypeAttr.cVars >0 )
2237 MSFT_DoVars(pcx, ptiRet, ptiRet->TypeAttr.cFuncs,
2238 ptiRet->TypeAttr.cVars,
2239 tiBase.memoffset, & ptiRet->varlist);
2240 if(ptiRet->TypeAttr.cImplTypes >0 ) {
2241 switch(ptiRet->TypeAttr.typekind)
2244 MSFT_DoImplTypes(pcx, ptiRet, ptiRet->TypeAttr.cImplTypes ,
2247 case TKIND_DISPATCH:
2248 /* This is not -1 when the interface is a non-base dual interface or
2249 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2250 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2254 if (tiBase.datatype1 != -1)
2256 ptiRet->impltypelist = TLB_Alloc(sizeof(TLBImplType));
2257 ptiRet->impltypelist->hRef = tiBase.datatype1;
2258 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2262 ptiRet->impltypelist=TLB_Alloc(sizeof(TLBImplType));
2263 MSFT_DoRefType(pcx, pLibInfo, tiBase.datatype1);
2264 ptiRet->impltypelist->hRef = tiBase.datatype1;
2269 MSFT_CustData(pcx, tiBase.oCustData, &ptiRet->pCustData);
2271 TRACE_(typelib)("%s guid: %s kind:%s\n",
2272 debugstr_w(ptiRet->Name),
2273 debugstr_guid(&ptiRet->TypeAttr.guid),
2274 typekind_desc[ptiRet->TypeAttr.typekind]);
2275 if (TRACE_ON(typelib))
2276 dump_TypeInfo(ptiRet);
2281 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2282 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2283 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2286 static ITypeLibImpl *tlb_cache_first;
2287 static CRITICAL_SECTION cache_section;
2288 static CRITICAL_SECTION_DEBUG cache_section_debug =
2290 0, 0, &cache_section,
2291 { &cache_section_debug.ProcessLocksList, &cache_section_debug.ProcessLocksList },
2292 0, 0, { (DWORD_PTR)(__FILE__ ": typelib loader cache") }
2294 static CRITICAL_SECTION cache_section = { &cache_section_debug, -1, 0, 0, 0, 0 };
2297 typedef struct TLB_PEFile
2299 const IUnknownVtbl *lpvtbl;
2302 HRSRC typelib_resource;
2303 HGLOBAL typelib_global;
2304 LPVOID typelib_base;
2307 static HRESULT WINAPI TLB_PEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2309 if (IsEqualIID(riid, &IID_IUnknown))
2312 IUnknown_AddRef(iface);
2316 return E_NOINTERFACE;
2319 static ULONG WINAPI TLB_PEFile_AddRef(IUnknown *iface)
2321 TLB_PEFile *This = (TLB_PEFile *)iface;
2322 return InterlockedIncrement(&This->refs);
2325 static ULONG WINAPI TLB_PEFile_Release(IUnknown *iface)
2327 TLB_PEFile *This = (TLB_PEFile *)iface;
2328 ULONG refs = InterlockedDecrement(&This->refs);
2331 if (This->typelib_global)
2332 FreeResource(This->typelib_global);
2334 FreeLibrary(This->dll);
2335 HeapFree(GetProcessHeap(), 0, This);
2340 static const IUnknownVtbl TLB_PEFile_Vtable =
2342 TLB_PEFile_QueryInterface,
2347 static HRESULT TLB_PEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2351 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2353 return E_OUTOFMEMORY;
2355 This->lpvtbl = &TLB_PEFile_Vtable;
2358 This->typelib_resource = NULL;
2359 This->typelib_global = NULL;
2360 This->typelib_base = NULL;
2362 This->dll = LoadLibraryExW(path, 0, DONT_RESOLVE_DLL_REFERENCES |
2363 LOAD_LIBRARY_AS_DATAFILE | LOAD_WITH_ALTERED_SEARCH_PATH);
2367 static const WCHAR TYPELIBW[] = {'T','Y','P','E','L','I','B',0};
2368 This->typelib_resource = FindResourceW(This->dll, MAKEINTRESOURCEW(index), TYPELIBW);
2369 if (This->typelib_resource)
2371 This->typelib_global = LoadResource(This->dll, This->typelib_resource);
2372 if (This->typelib_global)
2374 This->typelib_base = LockResource(This->typelib_global);
2376 if (This->typelib_base)
2378 *pdwTLBLength = SizeofResource(This->dll, This->typelib_resource);
2379 *ppBase = This->typelib_base;
2380 *ppFile = (IUnknown *)&This->lpvtbl;
2387 TLB_PEFile_Release((IUnknown *)&This->lpvtbl);
2388 return TYPE_E_CANTLOADLIBRARY;
2391 typedef struct TLB_NEFile
2393 const IUnknownVtbl *lpvtbl;
2395 LPVOID typelib_base;
2398 static HRESULT WINAPI TLB_NEFile_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2400 if (IsEqualIID(riid, &IID_IUnknown))
2403 IUnknown_AddRef(iface);
2407 return E_NOINTERFACE;
2410 static ULONG WINAPI TLB_NEFile_AddRef(IUnknown *iface)
2412 TLB_NEFile *This = (TLB_NEFile *)iface;
2413 return InterlockedIncrement(&This->refs);
2416 static ULONG WINAPI TLB_NEFile_Release(IUnknown *iface)
2418 TLB_NEFile *This = (TLB_NEFile *)iface;
2419 ULONG refs = InterlockedDecrement(&This->refs);
2422 HeapFree(GetProcessHeap(), 0, This->typelib_base);
2423 HeapFree(GetProcessHeap(), 0, This);
2428 static const IUnknownVtbl TLB_NEFile_Vtable =
2430 TLB_NEFile_QueryInterface,
2435 /***********************************************************************
2436 * read_xx_header [internal]
2438 static int read_xx_header( HFILE lzfd )
2440 IMAGE_DOS_HEADER mzh;
2443 LZSeek( lzfd, 0, SEEK_SET );
2444 if ( sizeof(mzh) != LZRead( lzfd, (LPSTR)&mzh, sizeof(mzh) ) )
2446 if ( mzh.e_magic != IMAGE_DOS_SIGNATURE )
2449 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2450 if ( 2 != LZRead( lzfd, magic, 2 ) )
2453 LZSeek( lzfd, mzh.e_lfanew, SEEK_SET );
2455 if ( magic[0] == 'N' && magic[1] == 'E' )
2456 return IMAGE_OS2_SIGNATURE;
2457 if ( magic[0] == 'P' && magic[1] == 'E' )
2458 return IMAGE_NT_SIGNATURE;
2461 WARN("Can't handle %s files.\n", magic );
2466 /***********************************************************************
2467 * find_ne_resource [internal]
2469 static BOOL find_ne_resource( HFILE lzfd, LPCSTR typeid, LPCSTR resid,
2470 DWORD *resLen, DWORD *resOff )
2472 IMAGE_OS2_HEADER nehd;
2473 NE_TYPEINFO *typeInfo;
2474 NE_NAMEINFO *nameInfo;
2480 /* Read in NE header */
2481 nehdoffset = LZSeek( lzfd, 0, SEEK_CUR );
2482 if ( sizeof(nehd) != LZRead( lzfd, (LPSTR)&nehd, sizeof(nehd) ) ) return 0;
2484 resTabSize = nehd.ne_restab - nehd.ne_rsrctab;
2487 TRACE("No resources in NE dll\n" );
2491 /* Read in resource table */
2492 resTab = HeapAlloc( GetProcessHeap(), 0, resTabSize );
2493 if ( !resTab ) return FALSE;
2495 LZSeek( lzfd, nehd.ne_rsrctab + nehdoffset, SEEK_SET );
2496 if ( resTabSize != LZRead( lzfd, (char*)resTab, resTabSize ) )
2498 HeapFree( GetProcessHeap(), 0, resTab );
2503 typeInfo = (NE_TYPEINFO *)(resTab + 2);
2505 if (!IS_INTRESOURCE(typeid)) /* named type */
2507 BYTE len = strlen( typeid );
2508 while (typeInfo->type_id)
2510 if (!(typeInfo->type_id & 0x8000))
2512 BYTE *p = resTab + typeInfo->type_id;
2513 if ((*p == len) && !strncasecmp( (char*)p+1, typeid, len )) goto found_type;
2515 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2516 typeInfo->count * sizeof(NE_NAMEINFO));
2519 else /* numeric type id */
2521 WORD id = LOWORD(typeid) | 0x8000;
2522 while (typeInfo->type_id)
2524 if (typeInfo->type_id == id) goto found_type;
2525 typeInfo = (NE_TYPEINFO *)((char *)(typeInfo + 1) +
2526 typeInfo->count * sizeof(NE_NAMEINFO));
2529 TRACE("No typeid entry found for %p\n", typeid );
2530 HeapFree( GetProcessHeap(), 0, resTab );
2534 nameInfo = (NE_NAMEINFO *)(typeInfo + 1);
2536 if (!IS_INTRESOURCE(resid)) /* named resource */
2538 BYTE len = strlen( resid );
2539 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2541 BYTE *p = resTab + nameInfo->id;
2542 if (nameInfo->id & 0x8000) continue;
2543 if ((*p == len) && !strncasecmp( (char*)p+1, resid, len )) goto found_name;
2546 else /* numeric resource id */
2548 WORD id = LOWORD(resid) | 0x8000;
2549 for (count = typeInfo->count; count > 0; count--, nameInfo++)
2550 if (nameInfo->id == id) goto found_name;
2552 TRACE("No resid entry found for %p\n", typeid );
2553 HeapFree( GetProcessHeap(), 0, resTab );
2557 /* Return resource data */
2558 if ( resLen ) *resLen = nameInfo->length << *(WORD *)resTab;
2559 if ( resOff ) *resOff = nameInfo->offset << *(WORD *)resTab;
2561 HeapFree( GetProcessHeap(), 0, resTab );
2565 static HRESULT TLB_NEFile_Open(LPCWSTR path, INT index, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile){
2569 HRESULT hr = TYPE_E_CANTLOADLIBRARY;
2570 TLB_NEFile *This = NULL;
2572 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2573 if (!This) return E_OUTOFMEMORY;
2575 This->lpvtbl = &TLB_NEFile_Vtable;
2577 This->typelib_base = NULL;
2579 lzfd = LZOpenFileW( (LPWSTR)path, &ofs, OF_READ );
2580 if ( lzfd >= 0 && read_xx_header( lzfd ) == IMAGE_OS2_SIGNATURE )
2582 DWORD reslen, offset;
2583 if( find_ne_resource( lzfd, "TYPELIB", MAKEINTRESOURCEA(index), &reslen, &offset ) )
2585 This->typelib_base = HeapAlloc(GetProcessHeap(), 0, reslen);
2586 if( !This->typelib_base )
2590 LZSeek( lzfd, offset, SEEK_SET );
2591 reslen = LZRead( lzfd, This->typelib_base, reslen );
2593 *ppBase = This->typelib_base;
2594 *pdwTLBLength = reslen;
2595 *ppFile = (IUnknown *)&This->lpvtbl;
2601 if( lzfd >= 0) LZClose( lzfd );
2602 TLB_NEFile_Release((IUnknown *)&This->lpvtbl);
2606 typedef struct TLB_Mapping
2608 const IUnknownVtbl *lpvtbl;
2612 LPVOID typelib_base;
2615 static HRESULT WINAPI TLB_Mapping_QueryInterface(IUnknown *iface, REFIID riid, void **ppv)
2617 if (IsEqualIID(riid, &IID_IUnknown))
2620 IUnknown_AddRef(iface);
2624 return E_NOINTERFACE;
2627 static ULONG WINAPI TLB_Mapping_AddRef(IUnknown *iface)
2629 TLB_Mapping *This = (TLB_Mapping *)iface;
2630 return InterlockedIncrement(&This->refs);
2633 static ULONG WINAPI TLB_Mapping_Release(IUnknown *iface)
2635 TLB_Mapping *This = (TLB_Mapping *)iface;
2636 ULONG refs = InterlockedDecrement(&This->refs);
2639 if (This->typelib_base)
2640 UnmapViewOfFile(This->typelib_base);
2642 CloseHandle(This->mapping);
2643 if (This->file != INVALID_HANDLE_VALUE)
2644 CloseHandle(This->file);
2645 HeapFree(GetProcessHeap(), 0, This);
2650 static const IUnknownVtbl TLB_Mapping_Vtable =
2652 TLB_Mapping_QueryInterface,
2657 static HRESULT TLB_Mapping_Open(LPCWSTR path, LPVOID *ppBase, DWORD *pdwTLBLength, IUnknown **ppFile)
2661 This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
2663 return E_OUTOFMEMORY;
2665 This->lpvtbl = &TLB_Mapping_Vtable;
2667 This->file = INVALID_HANDLE_VALUE;
2668 This->mapping = NULL;
2669 This->typelib_base = NULL;
2671 This->file = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, 0);
2672 if (INVALID_HANDLE_VALUE != This->file)
2674 This->mapping = CreateFileMappingW(This->file, NULL, PAGE_READONLY | SEC_COMMIT, 0, 0, NULL);
2677 This->typelib_base = MapViewOfFile(This->mapping, FILE_MAP_READ, 0, 0, 0);
2678 if(This->typelib_base)
2680 /* retrieve file size */
2681 *pdwTLBLength = GetFileSize(This->file, NULL);
2682 *ppBase = This->typelib_base;
2683 *ppFile = (IUnknown *)&This->lpvtbl;
2689 IUnknown_Release((IUnknown *)&This->lpvtbl);
2690 return TYPE_E_CANTLOADLIBRARY;
2693 /****************************************************************************
2696 * find the type of the typelib file and map the typelib resource into
2699 #define MSFT_SIGNATURE 0x5446534D /* "MSFT" */
2700 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2701 static HRESULT TLB_ReadTypeLib(LPCWSTR pszFileName, LPWSTR pszPath, UINT cchPath, ITypeLib2 **ppTypeLib)
2703 ITypeLibImpl *entry;
2706 LPWSTR index_str, file = (LPWSTR)pszFileName;
2707 LPVOID pBase = NULL;
2708 DWORD dwTLBLength = 0;
2709 IUnknown *pFile = NULL;
2713 index_str = strrchrW(pszFileName, '\\');
2714 if(index_str && *++index_str != '\0')
2717 LONG idx = strtolW(index_str, &end_ptr, 10);
2718 if(*end_ptr == '\0')
2720 int str_len = index_str - pszFileName - 1;
2722 file = HeapAlloc(GetProcessHeap(), 0, (str_len + 1) * sizeof(WCHAR));
2723 memcpy(file, pszFileName, str_len * sizeof(WCHAR));
2728 if(!SearchPathW(NULL, file, NULL, cchPath, pszPath, NULL))
2730 if(strchrW(file, '\\'))
2732 lstrcpyW(pszPath, file);
2736 int len = GetSystemDirectoryW(pszPath, cchPath);
2737 pszPath[len] = '\\';
2738 memcpy(pszPath + len + 1, file, (strlenW(file) + 1) * sizeof(WCHAR));
2742 if(file != pszFileName) HeapFree(GetProcessHeap(), 0, file);
2744 TRACE_(typelib)("File %s index %d\n", debugstr_w(pszPath), index);
2746 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2747 EnterCriticalSection(&cache_section);
2748 for (entry = tlb_cache_first; entry != NULL; entry = entry->next)
2750 if (!strcmpiW(entry->path, pszPath) && entry->index == index)
2752 TRACE("cache hit\n");
2753 *ppTypeLib = (ITypeLib2*)entry;
2754 ITypeLib_AddRef(*ppTypeLib);
2755 LeaveCriticalSection(&cache_section);
2759 LeaveCriticalSection(&cache_section);
2761 /* now actually load and parse the typelib */
2763 ret = TLB_PEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2764 if (ret == TYPE_E_CANTLOADLIBRARY)
2765 ret = TLB_NEFile_Open(pszPath, index, &pBase, &dwTLBLength, &pFile);
2766 if (ret == TYPE_E_CANTLOADLIBRARY)
2767 ret = TLB_Mapping_Open(pszPath, &pBase, &dwTLBLength, &pFile);
2770 if (dwTLBLength >= 4)
2772 DWORD dwSignature = FromLEDWord(*((DWORD*) pBase));
2773 if (dwSignature == MSFT_SIGNATURE)
2774 *ppTypeLib = ITypeLib2_Constructor_MSFT(pBase, dwTLBLength);
2775 else if (dwSignature == SLTG_SIGNATURE)
2776 *ppTypeLib = ITypeLib2_Constructor_SLTG(pBase, dwTLBLength);
2779 FIXME("Header type magic 0x%08x not supported.\n",dwSignature);
2780 ret = TYPE_E_CANTLOADLIBRARY;
2784 ret = TYPE_E_CANTLOADLIBRARY;
2785 IUnknown_Release(pFile);
2789 ITypeLibImpl *impl = (ITypeLibImpl*)*ppTypeLib;
2791 TRACE("adding to cache\n");
2792 impl->path = HeapAlloc(GetProcessHeap(), 0, (strlenW(pszPath)+1) * sizeof(WCHAR));
2793 lstrcpyW(impl->path, pszPath);
2794 /* We should really canonicalise the path here. */
2795 impl->index = index;
2797 /* FIXME: check if it has added already in the meantime */
2798 EnterCriticalSection(&cache_section);
2799 if ((impl->next = tlb_cache_first) != NULL) impl->next->prev = impl;
2801 tlb_cache_first = impl;
2802 LeaveCriticalSection(&cache_section);
2805 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName), GetLastError());
2810 /*================== ITypeLib(2) Methods ===================================*/
2812 static ITypeLibImpl* TypeLibImpl_Constructor(void)
2814 ITypeLibImpl* pTypeLibImpl;
2816 pTypeLibImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeLibImpl));
2817 if (!pTypeLibImpl) return NULL;
2819 pTypeLibImpl->lpVtbl = &tlbvt;
2820 pTypeLibImpl->lpVtblTypeComp = &tlbtcvt;
2821 pTypeLibImpl->ref = 1;
2823 list_init(&pTypeLibImpl->ref_list);
2824 pTypeLibImpl->dispatch_href = -1;
2826 return pTypeLibImpl;
2829 /****************************************************************************
2830 * ITypeLib2_Constructor_MSFT
2832 * loading an MSFT typelib from an in-memory image
2834 static ITypeLib2* ITypeLib2_Constructor_MSFT(LPVOID pLib, DWORD dwTLBLength)
2838 MSFT_Header tlbHeader;
2839 MSFT_SegDir tlbSegDir;
2840 ITypeLibImpl * pTypeLibImpl;
2842 TRACE("%p, TLB length = %d\n", pLib, dwTLBLength);
2844 pTypeLibImpl = TypeLibImpl_Constructor();
2845 if (!pTypeLibImpl) return NULL;
2847 /* get pointer to beginning of typelib data */
2851 cx.pLibInfo = pTypeLibImpl;
2852 cx.length = dwTLBLength;
2855 MSFT_ReadLEDWords((void*)&tlbHeader, sizeof(tlbHeader), &cx, 0);
2856 TRACE_(typelib)("header:\n");
2857 TRACE_(typelib)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader.magic1,tlbHeader.magic2 );
2858 if (tlbHeader.magic1 != MSFT_SIGNATURE) {
2859 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader.magic1);
2862 TRACE_(typelib)("\tdispatchpos = 0x%x\n", tlbHeader.dispatchpos);
2864 /* there is a small amount of information here until the next important
2866 * the segment directory . Try to calculate the amount of data */
2867 lPSegDir = sizeof(tlbHeader) + (tlbHeader.nrtypeinfos)*4 + ((tlbHeader.varflags & HELPDLLFLAG)? 4 :0);
2869 /* now read the segment directory */
2870 TRACE("read segment directory (at %d)\n",lPSegDir);
2871 MSFT_ReadLEDWords(&tlbSegDir, sizeof(tlbSegDir), &cx, lPSegDir);
2872 cx.pTblDir = &tlbSegDir;
2874 /* just check two entries */
2875 if ( tlbSegDir.pTypeInfoTab.res0c != 0x0F || tlbSegDir.pImpInfo.res0c != 0x0F)
2877 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir);
2878 HeapFree(GetProcessHeap(),0,pTypeLibImpl);
2882 /* now fill our internal data */
2883 /* TLIBATTR fields */
2884 MSFT_ReadGuid(&pTypeLibImpl->LibAttr.guid, tlbHeader.posguid, &cx);
2886 pTypeLibImpl->LibAttr.lcid = tlbHeader.lcid2;
2887 pTypeLibImpl->LibAttr.syskind = tlbHeader.varflags & 0x0f; /* check the mask */
2888 pTypeLibImpl->LibAttr.wMajorVerNum = LOWORD(tlbHeader.version);
2889 pTypeLibImpl->LibAttr.wMinorVerNum = HIWORD(tlbHeader.version);
2890 pTypeLibImpl->LibAttr.wLibFlags = (WORD) tlbHeader.flags & 0xffff;/* check mask */
2892 pTypeLibImpl->lcid = tlbHeader.lcid;
2894 /* name, eventually add to a hash table */
2895 pTypeLibImpl->Name = MSFT_ReadName(&cx, tlbHeader.NameOffset);
2898 pTypeLibImpl->DocString = MSFT_ReadString(&cx, tlbHeader.helpstring);
2899 pTypeLibImpl->HelpFile = MSFT_ReadString(&cx, tlbHeader.helpfile);
2901 if( tlbHeader.varflags & HELPDLLFLAG)
2904 MSFT_ReadLEDWords(&offset, sizeof(offset), &cx, sizeof(tlbHeader));
2905 pTypeLibImpl->HelpStringDll = MSFT_ReadString(&cx, offset);
2908 pTypeLibImpl->dwHelpContext = tlbHeader.helpstringcontext;
2911 if(tlbHeader.CustomDataOffset >= 0)
2913 pTypeLibImpl->ctCustData = MSFT_CustData(&cx, tlbHeader.CustomDataOffset, &pTypeLibImpl->pCustData);
2916 /* fill in type descriptions */
2917 if(tlbSegDir.pTypdescTab.length > 0)
2919 int i, j, cTD = tlbSegDir.pTypdescTab.length / (2*sizeof(INT));
2921 pTypeLibImpl->ctTypeDesc = cTD;
2922 pTypeLibImpl->pTypeDesc = TLB_Alloc( cTD * sizeof(TYPEDESC));
2923 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pTypdescTab.offset);
2926 /* FIXME: add several sanity checks here */
2927 pTypeLibImpl->pTypeDesc[i].vt = td[0] & VT_TYPEMASK;
2928 if(td[0] == VT_PTR || td[0] == VT_SAFEARRAY)
2930 /* FIXME: check safearray */
2932 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & stndTypeDesc[td[2]];
2934 pTypeLibImpl->pTypeDesc[i].u.lptdesc= & pTypeLibImpl->pTypeDesc[td[2]/8];
2936 else if(td[0] == VT_CARRAY)
2938 /* array descr table here */
2939 pTypeLibImpl->pTypeDesc[i].u.lpadesc = (void *)(INT_PTR)td[2]; /* temp store offset in*/
2941 else if(td[0] == VT_USERDEFINED)
2943 pTypeLibImpl->pTypeDesc[i].u.hreftype = MAKELONG(td[2],td[3]);
2945 if(++i<cTD) MSFT_ReadLEWords(td, sizeof(td), &cx, DO_NOT_SEEK);
2948 /* second time around to fill the array subscript info */
2951 if(pTypeLibImpl->pTypeDesc[i].vt != VT_CARRAY) continue;
2952 if(tlbSegDir.pArrayDescriptions.offset>0)
2954 MSFT_ReadLEWords(td, sizeof(td), &cx, tlbSegDir.pArrayDescriptions.offset + (INT_PTR)pTypeLibImpl->pTypeDesc[i].u.lpadesc);
2955 pTypeLibImpl->pTypeDesc[i].u.lpadesc = TLB_Alloc(sizeof(ARRAYDESC)+sizeof(SAFEARRAYBOUND)*(td[3]-1));
2958 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem.vt = td[0] & VT_TYPEMASK;
2960 pTypeLibImpl->pTypeDesc[i].u.lpadesc->tdescElem = cx.pLibInfo->pTypeDesc[td[0]/(2*sizeof(INT))];
2962 pTypeLibImpl->pTypeDesc[i].u.lpadesc->cDims = td[2];
2964 for(j = 0; j<td[2]; j++)
2966 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].cElements,
2967 sizeof(INT), &cx, DO_NOT_SEEK);
2968 MSFT_ReadLEDWords(& pTypeLibImpl->pTypeDesc[i].u.lpadesc->rgbounds[j].lLbound,
2969 sizeof(INT), &cx, DO_NOT_SEEK);
2974 pTypeLibImpl->pTypeDesc[i].u.lpadesc = NULL;
2975 ERR("didn't find array description data\n");
2980 /* imported type libs */
2981 if(tlbSegDir.pImpFiles.offset>0)
2983 TLBImpLib **ppImpLib = &(pTypeLibImpl->pImpLibs);
2984 int oGuid, offset = tlbSegDir.pImpFiles.offset;
2987 while(offset < tlbSegDir.pImpFiles.offset +tlbSegDir.pImpFiles.length)
2991 *ppImpLib = TLB_Alloc(sizeof(TLBImpLib));
2992 (*ppImpLib)->offset = offset - tlbSegDir.pImpFiles.offset;
2993 MSFT_ReadLEDWords(&oGuid, sizeof(INT), &cx, offset);
2995 MSFT_ReadLEDWords(&(*ppImpLib)->lcid, sizeof(LCID), &cx, DO_NOT_SEEK);
2996 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMajor, sizeof(WORD), &cx, DO_NOT_SEEK);
2997 MSFT_ReadLEWords(&(*ppImpLib)->wVersionMinor, sizeof(WORD), &cx, DO_NOT_SEEK);
2998 MSFT_ReadLEWords(& size, sizeof(UINT16), &cx, DO_NOT_SEEK);
3001 name = TLB_Alloc(size+1);
3002 MSFT_Read(name, size, &cx, DO_NOT_SEEK);
3003 (*ppImpLib)->name = TLB_MultiByteToBSTR(name);
3006 MSFT_ReadGuid(&(*ppImpLib)->guid, oGuid, &cx);
3007 offset = (offset + sizeof(INT) + sizeof(DWORD) + sizeof(LCID) + sizeof(UINT16) + size + 3) & ~3;
3009 ppImpLib = &(*ppImpLib)->next;
3013 pTypeLibImpl->dispatch_href = tlbHeader.dispatchpos;
3014 if(pTypeLibImpl->dispatch_href != -1)
3015 MSFT_DoRefType(&cx, pTypeLibImpl, pTypeLibImpl->dispatch_href);
3018 if(tlbHeader.nrtypeinfos >= 0 )
3020 /*pTypeLibImpl->TypeInfoCount=tlbHeader.nrtypeinfos; */
3021 ITypeInfoImpl **ppTI = &(pTypeLibImpl->pTypeInfo);
3024 for(i = 0; i < tlbHeader.nrtypeinfos; i++)
3026 *ppTI = MSFT_DoTypeInfo(&cx, i, pTypeLibImpl);
3028 ppTI = &((*ppTI)->next);
3029 (pTypeLibImpl->TypeInfoCount)++;
3033 TRACE("(%p)\n", pTypeLibImpl);
3034 return (ITypeLib2*) pTypeLibImpl;
3038 static BOOL TLB_GUIDFromString(const char *str, GUID *guid)
3044 if(sscanf(str, "%x-%hx-%hx-%hx", &guid->Data1, &guid->Data2, &guid->Data3, &s) != 4) {
3045 FIXME("Can't parse guid %s\n", debugstr_guid(guid));
3049 guid->Data4[0] = s >> 8;
3050 guid->Data4[1] = s & 0xff;
3053 for(i = 0; i < 6; i++) {
3054 memcpy(b, str + 24 + 2 * i, 2);
3055 guid->Data4[i + 2] = strtol(b, NULL, 16);
3060 static WORD SLTG_ReadString(const char *ptr, BSTR *pBstr)
3066 bytelen = *(const WORD*)ptr;
3067 if(bytelen == 0xffff) return 2;
3068 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, NULL, 0);
3069 *pBstr = SysAllocStringLen(NULL, len);
3071 len = MultiByteToWideChar(CP_ACP, 0, ptr + 2, bytelen, *pBstr, len);
3075 static WORD SLTG_ReadStringA(const char *ptr, char **str)
3080 bytelen = *(const WORD*)ptr;
3081 if(bytelen == 0xffff) return 2;
3082 *str = HeapAlloc(GetProcessHeap(), 0, bytelen + 1);
3083 memcpy(*str, ptr + 2, bytelen);
3084 (*str)[bytelen] = '\0';
3088 static DWORD SLTG_ReadLibBlk(LPVOID pLibBlk, ITypeLibImpl *pTypeLibImpl)
3090 char *ptr = pLibBlk;
3093 if((w = *(WORD*)ptr) != SLTG_LIBBLK_MAGIC) {
3094 FIXME("libblk magic = %04x\n", w);
3099 if((w = *(WORD*)ptr) != 0xffff) {
3100 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w);
3105 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->DocString);
3107 ptr += SLTG_ReadString(ptr, &pTypeLibImpl->HelpFile);
3109 pTypeLibImpl->dwHelpContext = *(DWORD*)ptr;
3112 pTypeLibImpl->LibAttr.syskind = *(WORD*)ptr;
3115 if(SUBLANGID(*(WORD*)ptr) == SUBLANG_NEUTRAL)
3116 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD*)ptr),0),0);
3118 pTypeLibImpl->lcid = pTypeLibImpl->LibAttr.lcid = 0;
3121 ptr += 4; /* skip res12 */
3123 pTypeLibImpl->LibAttr.wLibFlags = *(WORD*)ptr;
3126 pTypeLibImpl->LibAttr.wMajorVerNum = *(WORD*)ptr;
3129 pTypeLibImpl->LibAttr.wMinorVerNum = *(WORD*)ptr;
3132 memcpy(&pTypeLibImpl->LibAttr.guid, ptr, sizeof(GUID));
3133 ptr += sizeof(GUID);
3135 return ptr - (char*)pLibBlk;
3138 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3143 } sltg_ref_lookup_t;
3145 static HRESULT sltg_get_typelib_ref(const sltg_ref_lookup_t *table, DWORD typeinfo_ref,
3146 HREFTYPE *typelib_ref)
3148 if(table && typeinfo_ref < table->num)
3150 *typelib_ref = table->refs[typeinfo_ref];
3154 ERR_(typelib)("Unable to find reference\n");
3159 static WORD *SLTG_DoType(WORD *pType, char *pBlk, TYPEDESC *pTD, const sltg_ref_lookup_t *ref_lookup)
3164 if((*pType & 0xe00) == 0xe00) {
3166 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3168 pTD = pTD->u.lptdesc;
3170 switch(*pType & 0x3f) {
3173 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3175 pTD = pTD->u.lptdesc;
3178 case VT_USERDEFINED:
3179 pTD->vt = VT_USERDEFINED;
3180 sltg_get_typelib_ref(ref_lookup, *(++pType) / 4, &pTD->u.hreftype);
3186 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3189 SAFEARRAY *pSA = (SAFEARRAY *)(pBlk + *(++pType));
3191 pTD->vt = VT_CARRAY;
3192 pTD->u.lpadesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3194 (pSA->cDims - 1) * sizeof(SAFEARRAYBOUND));
3195 pTD->u.lpadesc->cDims = pSA->cDims;
3196 memcpy(pTD->u.lpadesc->rgbounds, pSA->rgsabound,
3197 pSA->cDims * sizeof(SAFEARRAYBOUND));
3199 pTD = &pTD->u.lpadesc->tdescElem;
3205 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3209 pTD->vt = VT_SAFEARRAY;
3210 pTD->u.lptdesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3212 pTD = pTD->u.lptdesc;
3216 pTD->vt = *pType & 0x3f;
3225 static WORD *SLTG_DoElem(WORD *pType, char *pBlk,
3226 ELEMDESC *pElem, const sltg_ref_lookup_t *ref_lookup)
3228 /* Handle [in/out] first */
3229 if((*pType & 0xc000) == 0xc000)
3230 pElem->u.paramdesc.wParamFlags = PARAMFLAG_NONE;
3231 else if(*pType & 0x8000)
3232 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN | PARAMFLAG_FOUT;
3233 else if(*pType & 0x4000)
3234 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FOUT;
3236 pElem->u.paramdesc.wParamFlags = PARAMFLAG_FIN;
3239 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FLCID;
3242 pElem->u.paramdesc.wParamFlags |= PARAMFLAG_FRETVAL;
3244 return SLTG_DoType(pType, pBlk, &pElem->tdesc, ref_lookup);
3248 static sltg_ref_lookup_t *SLTG_DoRefs(SLTG_RefInfo *pRef, ITypeLibImpl *pTL,
3253 TLBRefType *ref_type;
3254 sltg_ref_lookup_t *table;
3255 HREFTYPE typelib_ref;
3257 if(pRef->magic != SLTG_REF_MAGIC) {
3258 FIXME("Ref magic = %x\n", pRef->magic);
3261 name = ( (char*)pRef->names + pRef->number);
3263 table = HeapAlloc(GetProcessHeap(), 0, sizeof(*table) + ((pRef->number >> 3) - 1) * sizeof(table->refs[0]));
3264 table->num = pRef->number >> 3;
3266 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3268 /* We don't want the first href to be 0 */
3269 typelib_ref = (list_count(&pTL->ref_list) + 1) << 2;
3271 for(ref = 0; ref < pRef->number >> 3; ref++) {
3273 unsigned int lib_offs, type_num;
3275 ref_type = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref_type));
3277 name += SLTG_ReadStringA(name, &refname);
3278 if(sscanf(refname, "*\\R%x*#%x", &lib_offs, &type_num) != 2)
3279 FIXME_(typelib)("Can't sscanf ref\n");
3280 if(lib_offs != 0xffff) {
3281 TLBImpLib **import = &pTL->pImpLibs;
3284 if((*import)->offset == lib_offs)
3286 import = &(*import)->next;
3289 char fname[MAX_PATH+1];
3292 *import = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3294 (*import)->offset = lib_offs;
3295 TLB_GUIDFromString( pNameTable + lib_offs + 4,
3297 if(sscanf(pNameTable + lib_offs + 40, "}#%hd.%hd#%x#%s",
3298 &(*import)->wVersionMajor,
3299 &(*import)->wVersionMinor,
3300 &(*import)->lcid, fname) != 4) {
3301 FIXME_(typelib)("can't sscanf ref %s\n",
3302 pNameTable + lib_offs + 40);
3304 len = strlen(fname);
3305 if(fname[len-1] != '#')
3306 FIXME("fname = %s\n", fname);
3307 fname[len-1] = '\0';
3308 (*import)->name = TLB_MultiByteToBSTR(fname);
3310 ref_type->pImpTLInfo = *import;
3312 /* Store a reference to IDispatch */
3313 if(pTL->dispatch_href == -1 && IsEqualGUID(&(*import)->guid, &IID_StdOle) && type_num == 4)
3314 pTL->dispatch_href = typelib_ref;
3316 } else { /* internal ref */
3317 ref_type->pImpTLInfo = TLB_REF_INTERNAL;
3319 ref_type->reference = typelib_ref;
3320 ref_type->index = type_num;
3322 HeapFree(GetProcessHeap(), 0, refname);
3323 list_add_tail(&pTL->ref_list, &ref_type->entry);
3325 table->refs[ref] = typelib_ref;
3328 if((BYTE)*name != SLTG_REF_MAGIC)
3329 FIXME_(typelib)("End of ref block magic = %x\n", *name);
3330 dump_TLBRefType(pTL);
3334 static char *SLTG_DoImpls(char *pBlk, ITypeInfoImpl *pTI,
3335 BOOL OneOnly, const sltg_ref_lookup_t *ref_lookup)
3337 SLTG_ImplInfo *info;
3338 TLBImplType **ppImplType = &pTI->impltypelist;
3339 /* I don't really get this structure, usually it's 0x16 bytes
3340 long, but iuser.tlb contains some that are 0x18 bytes long.
3341 That's ok because we can use the next ptr to jump to the next
3342 one. But how do we know the length of the last one? The WORD
3343 at offs 0x8 might be the clue. For now I'm just assuming that
3344 the last one is the regular 0x16 bytes. */
3346 info = (SLTG_ImplInfo*)pBlk;
3348 *ppImplType = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3349 sizeof(**ppImplType));
3350 sltg_get_typelib_ref(ref_lookup, info->ref, &(*ppImplType)->hRef);
3351 (*ppImplType)->implflags = info->impltypeflags;
3352 pTI->TypeAttr.cImplTypes++;
3353 ppImplType = &(*ppImplType)->next;
3355 if(info->next == 0xffff)
3358 FIXME_(typelib)("Interface inheriting more than one interface\n");
3359 info = (SLTG_ImplInfo*)(pBlk + info->next);
3361 info++; /* see comment at top of function */
3365 static void SLTG_DoVars(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI, unsigned short cVars,
3366 const char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3368 TLBVarDesc **ppVarDesc = &pTI->varlist;
3369 BSTR bstrPrevName = NULL;
3370 SLTG_Variable *pItem;
3374 for(pItem = (SLTG_Variable *)pFirstItem, i = 0; i < cVars;
3375 pItem = (SLTG_Variable *)(pBlk + pItem->next), i++) {
3377 *ppVarDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3378 sizeof(**ppVarDesc));
3379 (*ppVarDesc)->vardesc.memid = pItem->memid;
3381 if (pItem->magic != SLTG_VAR_MAGIC &&
3382 pItem->magic != SLTG_VAR_WITH_FLAGS_MAGIC) {
3383 FIXME_(typelib)("var magic = %02x\n", pItem->magic);
3387 if (pItem->name == 0xfffe)
3388 (*ppVarDesc)->Name = SysAllocString(bstrPrevName);
3390 (*ppVarDesc)->Name = TLB_MultiByteToBSTR(pItem->name + pNameTable);
3392 TRACE_(typelib)("name: %s\n", debugstr_w((*ppVarDesc)->Name));
3393 TRACE_(typelib)("byte_offs = 0x%x\n", pItem->byte_offs);
3394 TRACE_(typelib)("memid = 0x%x\n", pItem->memid);
3396 if(pItem->flags & 0x02)
3397 pType = &pItem->type;
3399 pType = (WORD*)(pBlk + pItem->type);
3401 if (pItem->flags & ~0xda)
3402 FIXME_(typelib)("unhandled flags = %02x\n", pItem->flags & ~0xda);
3404 SLTG_DoElem(pType, pBlk,
3405 &(*ppVarDesc)->vardesc.elemdescVar, ref_lookup);
3407 if (TRACE_ON(typelib)) {
3409 dump_TypeDesc(&(*ppVarDesc)->vardesc.elemdescVar.tdesc, buf);
3410 TRACE_(typelib)("elemdescVar: %s\n", buf);
3413 if (pItem->flags & 0x40) {
3414 TRACE_(typelib)("VAR_DISPATCH\n");
3415 (*ppVarDesc)->vardesc.varkind = VAR_DISPATCH;
3417 else if (pItem->flags & 0x10) {
3418 TRACE_(typelib)("VAR_CONST\n");
3419 (*ppVarDesc)->vardesc.varkind = VAR_CONST;
3420 (*ppVarDesc)->vardesc.u.lpvarValue = HeapAlloc(GetProcessHeap(), 0,
3422 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_INT;
3423 if (pItem->flags & 0x08)
3424 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) = pItem->byte_offs;
3426 switch ((*ppVarDesc)->vardesc.elemdescVar.tdesc.vt)
3432 WORD len = *(WORD *)(pBlk + pItem->byte_offs);
3434 TRACE_(typelib)("len = %u\n", len);
3435 if (len == 0xffff) {
3438 INT alloc_len = MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, NULL, 0);
3439 str = SysAllocStringLen(NULL, alloc_len);
3440 MultiByteToWideChar(CP_ACP, 0, pBlk + pItem->byte_offs + 2, len, str, alloc_len);
3442 V_VT((*ppVarDesc)->vardesc.u.lpvarValue) = VT_BSTR;
3443 V_BSTR((*ppVarDesc)->vardesc.u.lpvarValue) = str;
3452 V_INT((*ppVarDesc)->vardesc.u.lpvarValue) =
3453 *(INT*)(pBlk + pItem->byte_offs);
3456 FIXME_(typelib)("VAR_CONST unimplemented for type %d\n", (*ppVarDesc)->vardesc.elemdescVar.tdesc.vt);
3461 TRACE_(typelib)("VAR_PERINSTANCE\n");
3462 (*ppVarDesc)->vardesc.u.oInst = pItem->byte_offs;
3463 (*ppVarDesc)->vardesc.varkind = VAR_PERINSTANCE;
3466 if (pItem->magic == SLTG_VAR_WITH_FLAGS_MAGIC)
3467 (*ppVarDesc)->vardesc.wVarFlags = pItem->varflags;
3469 if (pItem->flags & 0x80)
3470 (*ppVarDesc)->vardesc.wVarFlags |= VARFLAG_FREADONLY;
3472 bstrPrevName = (*ppVarDesc)->Name;
3473 ppVarDesc = &((*ppVarDesc)->next);
3475 pTI->TypeAttr.cVars = cVars;
3478 static void SLTG_DoFuncs(char *pBlk, char *pFirstItem, ITypeInfoImpl *pTI,
3479 unsigned short cFuncs, char *pNameTable, const sltg_ref_lookup_t *ref_lookup)
3481 SLTG_Function *pFunc;
3483 TLBFuncDesc **ppFuncDesc = &pTI->funclist;
3485 for(pFunc = (SLTG_Function*)pFirstItem, i = 0; i < cFuncs;
3486 pFunc = (SLTG_Function*)(pBlk + pFunc->next), i++) {
3491 *ppFuncDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3492 sizeof(**ppFuncDesc));
3494 switch (pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT) {
3495 case SLTG_FUNCTION_MAGIC:
3496 (*ppFuncDesc)->funcdesc.funckind = FUNC_PUREVIRTUAL;
3498 case SLTG_DISPATCH_FUNCTION_MAGIC:
3499 (*ppFuncDesc)->funcdesc.funckind = FUNC_DISPATCH;
3501 case SLTG_STATIC_FUNCTION_MAGIC:
3502 (*ppFuncDesc)->funcdesc.funckind = FUNC_STATIC;
3505 FIXME("unimplemented func magic = %02x\n", pFunc->magic & ~SLTG_FUNCTION_FLAGS_PRESENT);
3506 HeapFree(GetProcessHeap(), 0, *ppFuncDesc);
3510 (*ppFuncDesc)->Name = TLB_MultiByteToBSTR(pFunc->name + pNameTable);
3512 (*ppFuncDesc)->funcdesc.memid = pFunc->dispid;
3513 (*ppFuncDesc)->funcdesc.invkind = pFunc->inv >> 4;
3514 (*ppFuncDesc)->funcdesc.callconv = pFunc->nacc & 0x7;
3515 (*ppFuncDesc)->funcdesc.cParams = pFunc->nacc >> 3;
3516 (*ppFuncDesc)->funcdesc.cParamsOpt = (pFunc->retnextopt & 0x7e) >> 1;
3517 (*ppFuncDesc)->funcdesc.oVft = pFunc->vtblpos;
3519 if(pFunc->magic & SLTG_FUNCTION_FLAGS_PRESENT)
3520 (*ppFuncDesc)->funcdesc.wFuncFlags = pFunc->funcflags;
3522 if(pFunc->retnextopt & 0x80)
3523 pType = &pFunc->rettype;
3525 pType = (WORD*)(pBlk + pFunc->rettype);
3527 SLTG_DoElem(pType, pBlk, &(*ppFuncDesc)->funcdesc.elemdescFunc, ref_lookup);
3529 (*ppFuncDesc)->funcdesc.lprgelemdescParam =
3530 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3531 (*ppFuncDesc)->funcdesc.cParams * sizeof(ELEMDESC));
3532 (*ppFuncDesc)->pParamDesc =
3533 HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3534 (*ppFuncDesc)->funcdesc.cParams * sizeof(TLBParDesc));
3536 pArg = (WORD*)(pBlk + pFunc->arg_off);
3538 for(param = 0; param < (*ppFuncDesc)->funcdesc.cParams; param++) {
3539 char *paramName = pNameTable + *pArg;
3541 /* If arg type follows then paramName points to the 2nd
3542 letter of the name, else the next WORD is an offset to
3543 the arg type and paramName points to the first letter.
3544 So let's take one char off paramName and see if we're
3545 pointing at an alpha-numeric char. However if *pArg is
3546 0xffff or 0xfffe then the param has no name, the former
3547 meaning that the next WORD is the type, the latter
3548 meaning that the next WORD is an offset to the type. */
3553 else if(*pArg == 0xfffe) {
3557 else if(paramName[-1] && !isalnum(paramName[-1]))
3562 if(HaveOffs) { /* the next word is an offset to type */
3563 pType = (WORD*)(pBlk + *pArg);
3564 SLTG_DoElem(pType, pBlk,
3565 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3570 pArg = SLTG_DoElem(pArg, pBlk,
3571 &(*ppFuncDesc)->funcdesc.lprgelemdescParam[param], ref_lookup);
3574 /* Are we an optional param ? */
3575 if((*ppFuncDesc)->funcdesc.cParams - param <=
3576 (*ppFuncDesc)->funcdesc.cParamsOpt)
3577 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].u.paramdesc.wParamFlags |= PARAMFLAG_FOPT;
3580 (*ppFuncDesc)->pParamDesc[param].Name =
3581 TLB_MultiByteToBSTR(paramName);
3583 (*ppFuncDesc)->pParamDesc[param].Name =
3584 SysAllocString((*ppFuncDesc)->Name);
3588 ppFuncDesc = &((*ppFuncDesc)->next);
3589 if(pFunc->next == 0xffff) break;
3591 pTI->TypeAttr.cFuncs = cFuncs;
3594 static void SLTG_ProcessCoClass(char *pBlk, ITypeInfoImpl *pTI,
3595 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3596 SLTG_TypeInfoTail *pTITail)
3599 sltg_ref_lookup_t *ref_lookup = NULL;
3601 if(pTIHeader->href_table != 0xffffffff) {
3602 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3608 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3609 SLTG_DoImpls(pFirstItem, pTI, FALSE, ref_lookup);
3611 HeapFree(GetProcessHeap(), 0, ref_lookup);
3615 static void SLTG_ProcessInterface(char *pBlk, ITypeInfoImpl *pTI,
3616 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3617 const SLTG_TypeInfoTail *pTITail)
3620 sltg_ref_lookup_t *ref_lookup = NULL;
3622 if(pTIHeader->href_table != 0xffffffff) {
3623 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3629 if(*(WORD*)pFirstItem == SLTG_IMPL_MAGIC) {
3630 SLTG_DoImpls(pFirstItem, pTI, TRUE, ref_lookup);
3633 if (pTITail->funcs_off != 0xffff)
3634 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3636 HeapFree(GetProcessHeap(), 0, ref_lookup);
3638 if (TRACE_ON(typelib))
3639 dump_TLBFuncDesc(pTI->funclist);
3642 static void SLTG_ProcessRecord(char *pBlk, ITypeInfoImpl *pTI,
3643 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3644 const SLTG_TypeInfoTail *pTITail)
3646 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3649 static void SLTG_ProcessAlias(char *pBlk, ITypeInfoImpl *pTI,
3650 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3651 const SLTG_TypeInfoTail *pTITail)
3654 sltg_ref_lookup_t *ref_lookup = NULL;
3656 if (pTITail->simple_alias) {
3657 /* if simple alias, no more processing required */
3658 pTI->TypeAttr.tdescAlias.vt = pTITail->tdescalias_vt;
3662 if(pTIHeader->href_table != 0xffffffff) {
3663 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3667 /* otherwise it is an offset to a type */
3668 pType = (WORD *)(pBlk + pTITail->tdescalias_vt);
3670 SLTG_DoType(pType, pBlk, &pTI->TypeAttr.tdescAlias, ref_lookup);
3672 HeapFree(GetProcessHeap(), 0, ref_lookup);
3675 static void SLTG_ProcessDispatch(char *pBlk, ITypeInfoImpl *pTI,
3676 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3677 const SLTG_TypeInfoTail *pTITail)
3679 sltg_ref_lookup_t *ref_lookup = NULL;
3680 if (pTIHeader->href_table != 0xffffffff)
3681 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3684 if (pTITail->vars_off != 0xffff)
3685 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3687 if (pTITail->funcs_off != 0xffff)
3688 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3690 if (pTITail->impls_off != 0xffff)
3691 SLTG_DoImpls(pBlk + pTITail->impls_off, pTI, FALSE, ref_lookup);
3693 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3694 * of dispinterface functions including the IDispatch ones, so
3695 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3696 pTI->TypeAttr.cbSizeVft = pTI->TypeAttr.cFuncs * sizeof(void *);
3698 HeapFree(GetProcessHeap(), 0, ref_lookup);
3699 if (TRACE_ON(typelib))
3700 dump_TLBFuncDesc(pTI->funclist);
3703 static void SLTG_ProcessEnum(char *pBlk, ITypeInfoImpl *pTI,
3704 const char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3705 const SLTG_TypeInfoTail *pTITail)
3707 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, NULL);
3710 static void SLTG_ProcessModule(char *pBlk, ITypeInfoImpl *pTI,
3711 char *pNameTable, SLTG_TypeInfoHeader *pTIHeader,
3712 const SLTG_TypeInfoTail *pTITail)
3714 sltg_ref_lookup_t *ref_lookup = NULL;
3715 if (pTIHeader->href_table != 0xffffffff)
3716 ref_lookup = SLTG_DoRefs((SLTG_RefInfo*)((char *)pTIHeader + pTIHeader->href_table), pTI->pTypeLib,
3719 if (pTITail->vars_off != 0xffff)
3720 SLTG_DoVars(pBlk, pBlk + pTITail->vars_off, pTI, pTITail->cVars, pNameTable, ref_lookup);
3722 if (pTITail->funcs_off != 0xffff)
3723 SLTG_DoFuncs(pBlk, pBlk + pTITail->funcs_off, pTI, pTITail->cFuncs, pNameTable, ref_lookup);
3724 HeapFree(GetProcessHeap(), 0, ref_lookup);
3725 if (TRACE_ON(typelib))
3729 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3730 managable copy of it into this */
3743 } SLTG_InternalOtherTypeInfo;
3745 /****************************************************************************
3746 * ITypeLib2_Constructor_SLTG
3748 * loading a SLTG typelib from an in-memory image
3750 static ITypeLib2* ITypeLib2_Constructor_SLTG(LPVOID pLib, DWORD dwTLBLength)
3752 ITypeLibImpl *pTypeLibImpl;
3753 SLTG_Header *pHeader;
3754 SLTG_BlkEntry *pBlkEntry;
3758 LPVOID pBlk, pFirstBlk;
3759 SLTG_LibBlk *pLibBlk;
3760 SLTG_InternalOtherTypeInfo *pOtherTypeInfoBlks;
3761 char *pAfterOTIBlks = NULL;
3762 char *pNameTable, *ptr;
3765 ITypeInfoImpl **ppTypeInfoImpl;
3767 TRACE_(typelib)("%p, TLB length = %d\n", pLib, dwTLBLength);
3770 pTypeLibImpl = TypeLibImpl_Constructor();
3771 if (!pTypeLibImpl) return NULL;
3775 TRACE_(typelib)("header:\n");
3776 TRACE_(typelib)("\tmagic=0x%08x, file blocks = %d\n", pHeader->SLTG_magic,
3777 pHeader->nrOfFileBlks );
3778 if (pHeader->SLTG_magic != SLTG_SIGNATURE) {
3779 FIXME_(typelib)("Header type magic 0x%08x not supported.\n",
3780 pHeader->SLTG_magic);
3784 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3785 pTypeLibImpl->TypeInfoCount = pHeader->nrOfFileBlks - 2;
3787 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3788 pBlkEntry = (SLTG_BlkEntry*)(pHeader + 1);
3790 /* Next we have a magic block */
3791 pMagic = (SLTG_Magic*)(pBlkEntry + pHeader->nrOfFileBlks - 1);
3793 /* Let's see if we're still in sync */
3794 if(memcmp(pMagic->CompObj_magic, SLTG_COMPOBJ_MAGIC,
3795 sizeof(SLTG_COMPOBJ_MAGIC))) {
3796 FIXME_(typelib)("CompObj magic = %s\n", pMagic->CompObj_magic);
3799 if(memcmp(pMagic->dir_magic, SLTG_DIR_MAGIC,
3800 sizeof(SLTG_DIR_MAGIC))) {
3801 FIXME_(typelib)("dir magic = %s\n", pMagic->dir_magic);
3805 pIndex = (SLTG_Index*)(pMagic+1);
3807 pPad9 = (SLTG_Pad9*)(pIndex + pTypeLibImpl->TypeInfoCount);
3809 pFirstBlk = pPad9 + 1;
3811 /* We'll set up a ptr to the main library block, which is the last one. */
3813 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3814 pBlkEntry[order].next != 0;
3815 order = pBlkEntry[order].next - 1, i++) {
3816 pBlk = (char*)pBlk + pBlkEntry[order].len;
3820 len = SLTG_ReadLibBlk(pLibBlk, pTypeLibImpl);
3822 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3827 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3829 pOtherTypeInfoBlks = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
3830 sizeof(*pOtherTypeInfoBlks) *
3831 pTypeLibImpl->TypeInfoCount);
3834 ptr = (char*)pLibBlk + len;
3836 for(i = 0; i < pTypeLibImpl->TypeInfoCount; i++) {
3840 pOtherTypeInfoBlks[i].small_no = *(WORD*)ptr;
3842 w = *(WORD*)(ptr + 2);
3845 pOtherTypeInfoBlks[i].index_name = HeapAlloc(GetProcessHeap(),0,
3847 memcpy(pOtherTypeInfoBlks[i].index_name, ptr + 4, w);
3848 pOtherTypeInfoBlks[i].index_name[w] = '\0';
3850 w = *(WORD*)(ptr + 4 + len);
3852 TRACE_(typelib)("\twith %s\n", debugstr_an(ptr + 6 + len, w));
3854 pOtherTypeInfoBlks[i].other_name = HeapAlloc(GetProcessHeap(),0,
3856 memcpy(pOtherTypeInfoBlks[i].other_name, ptr + 6 + len, w);
3857 pOtherTypeInfoBlks[i].other_name[w] = '\0';
3859 pOtherTypeInfoBlks[i].res1a = *(WORD*)(ptr + len + 6);
3860 pOtherTypeInfoBlks[i].name_offs = *(WORD*)(ptr + len + 8);
3861 extra = pOtherTypeInfoBlks[i].more_bytes = *(WORD*)(ptr + 10 + len);
3863 pOtherTypeInfoBlks[i].extra = HeapAlloc(GetProcessHeap(),0,
3865 memcpy(pOtherTypeInfoBlks[i].extra, ptr + 12, extra);
3868 pOtherTypeInfoBlks[i].res20 = *(WORD*)(ptr + 12 + len);
3869 pOtherTypeInfoBlks[i].helpcontext = *(DWORD*)(ptr + 14 + len);
3870 pOtherTypeInfoBlks[i].res26 = *(WORD*)(ptr + 18 + len);
3871 memcpy(&pOtherTypeInfoBlks[i].uuid, ptr + 20 + len, sizeof(GUID));
3872 len += sizeof(SLTG_OtherTypeInfo);
3876 pAfterOTIBlks = ptr;
3878 /* Skip this WORD and get the next DWORD */
3879 len = *(DWORD*)(pAfterOTIBlks + 2);
3881 /* Now add this to pLibBLk look at what we're pointing at and
3882 possibly add 0x20, then add 0x216, sprinkle a bit a magic
3883 dust and we should be pointing at the beginning of the name
3886 pNameTable = (char*)pLibBlk + len;
3888 switch(*(WORD*)pNameTable) {
3895 FIXME_(typelib)("pNameTable jump = %x\n", *(WORD*)pNameTable);
3899 pNameTable += 0x216;
3903 TRACE_(typelib)("Library name is %s\n", pNameTable + pLibBlk->name);
3905 pTypeLibImpl->Name = TLB_MultiByteToBSTR(pNameTable + pLibBlk->name);
3908 /* Hopefully we now have enough ptrs set up to actually read in
3909 some TypeInfos. It's not clear which order to do them in, so
3910 I'll just follow the links along the BlkEntry chain and read
3911 them in the order in which they are in the file */
3913 ppTypeInfoImpl = &(pTypeLibImpl->pTypeInfo);
3915 for(pBlk = pFirstBlk, order = pHeader->first_blk - 1, i = 0;
3916 pBlkEntry[order].next != 0;
3917 order = pBlkEntry[order].next - 1, i++) {
3919 SLTG_TypeInfoHeader *pTIHeader;
3920 SLTG_TypeInfoTail *pTITail;
3921 SLTG_MemberHeader *pMemHeader;
3923 if(strcmp(pBlkEntry[order].index_string + (char*)pMagic,
3924 pOtherTypeInfoBlks[i].index_name)) {
3925 FIXME_(typelib)("Index strings don't match\n");
3930 if(pTIHeader->magic != SLTG_TIHEADER_MAGIC) {
3931 FIXME_(typelib)("TypeInfoHeader magic = %04x\n", pTIHeader->magic);
3934 TRACE_(typelib)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
3935 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
3936 pTIHeader->res06, pTIHeader->res0e, pTIHeader->res16, pTIHeader->res1e);
3938 *ppTypeInfoImpl = (ITypeInfoImpl*)ITypeInfo_Constructor();
3939 (*ppTypeInfoImpl)->pTypeLib = pTypeLibImpl;
3940 (*ppTypeInfoImpl)->index = i;
3941 (*ppTypeInfoImpl)->Name = TLB_MultiByteToBSTR(
3942 pOtherTypeInfoBlks[i].name_offs +
3944 (*ppTypeInfoImpl)->dwHelpContext = pOtherTypeInfoBlks[i].helpcontext;
3945 (*ppTypeInfoImpl)->TypeAttr.guid = pOtherTypeInfoBlks[i].uuid;
3946 (*ppTypeInfoImpl)->TypeAttr.typekind = pTIHeader->typekind;
3947 (*ppTypeInfoImpl)->TypeAttr.wMajorVerNum = pTIHeader->major_version;
3948 (*ppTypeInfoImpl)->TypeAttr.wMinorVerNum = pTIHeader->minor_version;
3949 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags =
3950 (pTIHeader->typeflags1 >> 3) | (pTIHeader->typeflags2 << 5);
3952 if((*ppTypeInfoImpl)->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
3953 (*ppTypeInfoImpl)->TypeAttr.typekind = TKIND_DISPATCH;
3955 if((pTIHeader->typeflags1 & 7) != 2)
3956 FIXME_(typelib)("typeflags1 = %02x\n", pTIHeader->typeflags1);
3957 if(pTIHeader->typeflags3 != 2)
3958 FIXME_(typelib)("typeflags3 = %02x\n", pTIHeader->typeflags3);
3960 TRACE_(typelib)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
3961 debugstr_w((*ppTypeInfoImpl)->Name),
3962 typekind_desc[pTIHeader->typekind],
3963 debugstr_guid(&(*ppTypeInfoImpl)->TypeAttr.guid),
3964 (*ppTypeInfoImpl)->TypeAttr.wTypeFlags);
3966 pMemHeader = (SLTG_MemberHeader*)((char *)pBlk + pTIHeader->elem_table);
3968 pTITail = (SLTG_TypeInfoTail*)((char *)(pMemHeader + 1) + pMemHeader->cbExtra);
3970 (*ppTypeInfoImpl)->TypeAttr.cbAlignment = pTITail->cbAlignment;
3971 (*ppTypeInfoImpl)->TypeAttr.cbSizeInstance = pTITail->cbSizeInstance;
3972 (*ppTypeInfoImpl)->TypeAttr.cbSizeVft = pTITail->cbSizeVft;
3974 switch(pTIHeader->typekind) {
3976 SLTG_ProcessEnum((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3977 pTIHeader, pTITail);
3981 SLTG_ProcessRecord((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3982 pTIHeader, pTITail);
3985 case TKIND_INTERFACE:
3986 SLTG_ProcessInterface((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3987 pTIHeader, pTITail);
3991 SLTG_ProcessCoClass((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3992 pTIHeader, pTITail);
3996 SLTG_ProcessAlias((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
3997 pTIHeader, pTITail);
4000 case TKIND_DISPATCH:
4001 SLTG_ProcessDispatch((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4002 pTIHeader, pTITail);
4006 SLTG_ProcessModule((char *)(pMemHeader + 1), *ppTypeInfoImpl, pNameTable,
4007 pTIHeader, pTITail);
4011 FIXME("Not processing typekind %d\n", pTIHeader->typekind);
4016 /* could get cFuncs, cVars and cImplTypes from here
4017 but we've already set those */
4018 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4033 ppTypeInfoImpl = &((*ppTypeInfoImpl)->next);
4034 pBlk = (char*)pBlk + pBlkEntry[order].len;
4037 if(i != pTypeLibImpl->TypeInfoCount) {
4038 FIXME("Somehow processed %d TypeInfos\n", i);
4042 HeapFree(GetProcessHeap(), 0, pOtherTypeInfoBlks);
4043 return (ITypeLib2*)pTypeLibImpl;
4046 /* ITypeLib::QueryInterface
4048 static HRESULT WINAPI ITypeLib2_fnQueryInterface(
4053 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4055 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4058 if(IsEqualIID(riid, &IID_IUnknown) ||
4059 IsEqualIID(riid,&IID_ITypeLib)||
4060 IsEqualIID(riid,&IID_ITypeLib2))
4067 ITypeLib2_AddRef(iface);
4068 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4071 TRACE("-- Interface: E_NOINTERFACE\n");
4072 return E_NOINTERFACE;
4077 static ULONG WINAPI ITypeLib2_fnAddRef( ITypeLib2 *iface)
4079 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4080 ULONG ref = InterlockedIncrement(&This->ref);
4082 TRACE("(%p)->ref was %u\n",This, ref - 1);
4087 /* ITypeLib::Release
4089 static ULONG WINAPI ITypeLib2_fnRelease( ITypeLib2 *iface)
4091 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4092 ULONG ref = InterlockedDecrement(&This->ref);
4094 TRACE("(%p)->(%u)\n",This, ref);
4098 TLBImpLib *pImpLib, *pImpLibNext;
4099 TLBCustData *pCustData, *pCustDataNext;
4100 TLBRefType *ref_type;
4103 ITypeInfoImpl *pTI, *pTINext;
4105 /* remove cache entry */
4108 TRACE("removing from cache list\n");
4109 EnterCriticalSection(&cache_section);
4110 if (This->next) This->next->prev = This->prev;
4111 if (This->prev) This->prev->next = This->next;
4112 else tlb_cache_first = This->next;
4113 LeaveCriticalSection(&cache_section);
4114 HeapFree(GetProcessHeap(), 0, This->path);
4116 TRACE(" destroying ITypeLib(%p)\n",This);
4118 SysFreeString(This->Name);
4121 SysFreeString(This->DocString);
4122 This->DocString = NULL;
4124 SysFreeString(This->HelpFile);
4125 This->HelpFile = NULL;
4127 SysFreeString(This->HelpStringDll);
4128 This->HelpStringDll = NULL;
4130 for (pCustData = This->pCustData; pCustData; pCustData = pCustDataNext)
4132 VariantClear(&pCustData->data);
4134 pCustDataNext = pCustData->next;
4135 TLB_Free(pCustData);
4138 for (i = 0; i < This->ctTypeDesc; i++)
4139 if (This->pTypeDesc[i].vt == VT_CARRAY)
4140 TLB_Free(This->pTypeDesc[i].u.lpadesc);
4142 TLB_Free(This->pTypeDesc);
4144 for (pImpLib = This->pImpLibs; pImpLib; pImpLib = pImpLibNext)
4146 if (pImpLib->pImpTypeLib)
4147 ITypeLib_Release((ITypeLib *)pImpLib->pImpTypeLib);
4148 SysFreeString(pImpLib->name);
4150 pImpLibNext = pImpLib->next;
4154 LIST_FOR_EACH_ENTRY_SAFE(ref_type, cursor2, &This->ref_list, TLBRefType, entry)
4156 list_remove(&ref_type->entry);
4160 for (pTI = This->pTypeInfo; pTI; pTI = pTINext)
4162 pTINext = pTI->next;
4163 ITypeInfo_fnDestroy(pTI);
4165 HeapFree(GetProcessHeap(),0,This);
4172 /* ITypeLib::GetTypeInfoCount
4174 * Returns the number of type descriptions in the type library
4176 static UINT WINAPI ITypeLib2_fnGetTypeInfoCount( ITypeLib2 *iface)
4178 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4179 TRACE("(%p)->count is %d\n",This, This->TypeInfoCount);
4180 return This->TypeInfoCount;
4183 /* ITypeLib::GetTypeInfo
4185 * retrieves the specified type description in the library.
4187 static HRESULT WINAPI ITypeLib2_fnGetTypeInfo(
4190 ITypeInfo **ppTInfo)
4194 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4195 ITypeInfoImpl *pTypeInfo = This->pTypeInfo;
4197 TRACE("(%p)->(index=%d)\n", This, index);
4199 if (!ppTInfo) return E_INVALIDARG;
4201 /* search element n in list */
4202 for(i=0; i < index; i++)
4204 pTypeInfo = pTypeInfo->next;
4207 TRACE("-- element not found\n");
4208 return TYPE_E_ELEMENTNOTFOUND;
4212 *ppTInfo = (ITypeInfo *) pTypeInfo;
4214 ITypeInfo_AddRef(*ppTInfo);
4215 TRACE("-- found (%p)\n",*ppTInfo);
4220 /* ITypeLibs::GetTypeInfoType
4222 * Retrieves the type of a type description.
4224 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoType(
4229 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4231 ITypeInfoImpl *pTInfo = This->pTypeInfo;
4233 if (ITypeLib2_fnGetTypeInfoCount(iface) < index + 1)
4234 return TYPE_E_ELEMENTNOTFOUND;
4236 TRACE("(%p) index %d\n", This, index);
4238 if(!pTKind) return E_INVALIDARG;
4240 /* search element n in list */
4241 for(i=0; i < index; i++)
4245 TRACE("-- element not found\n");
4246 return TYPE_E_ELEMENTNOTFOUND;
4248 pTInfo = pTInfo->next;
4251 *pTKind = pTInfo->TypeAttr.typekind;
4252 TRACE("-- found Type (%d)\n", *pTKind);
4256 /* ITypeLib::GetTypeInfoOfGuid
4258 * Retrieves the type description that corresponds to the specified GUID.
4261 static HRESULT WINAPI ITypeLib2_fnGetTypeInfoOfGuid(
4264 ITypeInfo **ppTInfo)
4266 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4267 ITypeInfoImpl *pTypeInfo = This->pTypeInfo; /* head of list */
4269 TRACE("(%p)\n\tguid:\t%s)\n",This,debugstr_guid(guid));
4273 WARN("-- element not found\n");
4274 return TYPE_E_ELEMENTNOTFOUND;
4277 /* search linked list for guid */
4278 while( !IsEqualIID(guid,&pTypeInfo->TypeAttr.guid) )
4280 pTypeInfo = pTypeInfo->next;
4284 /* end of list reached */
4285 WARN("-- element not found\n");
4286 return TYPE_E_ELEMENTNOTFOUND;
4290 TRACE("-- found (%p, %s)\n",
4292 debugstr_w(pTypeInfo->Name));
4294 *ppTInfo = (ITypeInfo*)pTypeInfo;
4295 ITypeInfo_AddRef(*ppTInfo);
4299 /* ITypeLib::GetLibAttr
4301 * Retrieves the structure that contains the library's attributes.
4304 static HRESULT WINAPI ITypeLib2_fnGetLibAttr(
4306 LPTLIBATTR *ppTLibAttr)
4308 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4309 TRACE("(%p)\n",This);
4310 *ppTLibAttr = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppTLibAttr));
4311 **ppTLibAttr = This->LibAttr;
4315 /* ITypeLib::GetTypeComp
4317 * Enables a client compiler to bind to a library's types, variables,
4318 * constants, and global functions.
4321 static HRESULT WINAPI ITypeLib2_fnGetTypeComp(
4323 ITypeComp **ppTComp)
4325 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4327 TRACE("(%p)->(%p)\n",This,ppTComp);
4328 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
4329 ITypeComp_AddRef(*ppTComp);
4334 /* ITypeLib::GetDocumentation
4336 * Retrieves the library's documentation string, the complete Help file name
4337 * and path, and the context identifier for the library Help topic in the Help
4340 * On a successful return all non-null BSTR pointers will have been set,
4343 static HRESULT WINAPI ITypeLib2_fnGetDocumentation(
4347 BSTR *pBstrDocString,
4348 DWORD *pdwHelpContext,
4349 BSTR *pBstrHelpFile)
4351 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4353 HRESULT result = E_INVALIDARG;
4358 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4360 pBstrName, pBstrDocString,
4361 pdwHelpContext, pBstrHelpFile);
4365 /* documentation for the typelib */
4370 if(!(*pBstrName = SysAllocString(This->Name)))
4378 if (This->DocString)
4380 if(!(*pBstrDocString = SysAllocString(This->DocString)))
4383 else if (This->Name)
4385 if(!(*pBstrDocString = SysAllocString(This->Name)))
4389 *pBstrDocString = NULL;
4393 *pdwHelpContext = This->dwHelpContext;
4399 if(!(*pBstrHelpFile = SysAllocString(This->HelpFile)))
4403 *pBstrHelpFile = NULL;
4410 /* for a typeinfo */
4411 result = ITypeLib2_fnGetTypeInfo(iface, index, &pTInfo);
4413 if(SUCCEEDED(result))
4415 result = ITypeInfo_GetDocumentation(pTInfo,
4419 pdwHelpContext, pBstrHelpFile);
4421 ITypeInfo_Release(pTInfo);
4426 if (pBstrDocString) SysFreeString (*pBstrDocString);
4428 if (pBstrName) SysFreeString (*pBstrName);
4430 return STG_E_INSUFFICIENTMEMORY;
4435 * Indicates whether a passed-in string contains the name of a type or member
4436 * described in the library.
4439 static HRESULT WINAPI ITypeLib2_fnIsName(
4445 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4446 ITypeInfoImpl *pTInfo;
4447 TLBFuncDesc *pFInfo;
4450 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4452 TRACE("(%p)->(%s,%08x,%p)\n", This, debugstr_w(szNameBuf), lHashVal,
4456 for(pTInfo=This->pTypeInfo;pTInfo;pTInfo=pTInfo->next){
4457 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4458 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4459 if(!memcmp(szNameBuf,pFInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4460 for(i=0;i<pFInfo->funcdesc.cParams;i++)
4461 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name, nNameBufLen))
4462 goto ITypeLib2_fnIsName_exit;
4464 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4465 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnIsName_exit;
4470 ITypeLib2_fnIsName_exit:
4471 TRACE("(%p)slow! search for %s: %s found!\n", This,
4472 debugstr_w(szNameBuf), *pfName?"NOT":"");
4477 /* ITypeLib::FindName
4479 * Finds occurrences of a type description in a type library. This may be used
4480 * to quickly verify that a name exists in a type library.
4483 static HRESULT WINAPI ITypeLib2_fnFindName(
4487 ITypeInfo **ppTInfo,
4491 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4492 ITypeInfoImpl *pTInfo;
4493 TLBFuncDesc *pFInfo;
4496 UINT nNameBufLen = (lstrlenW(szNameBuf)+1)*sizeof(WCHAR);
4498 for(pTInfo=This->pTypeInfo;pTInfo && j<*pcFound; pTInfo=pTInfo->next){
4499 if(!memcmp(szNameBuf,pTInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4500 for(pFInfo=pTInfo->funclist;pFInfo;pFInfo=pFInfo->next) {
4501 if(!memcmp(szNameBuf,pFInfo->Name,nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4502 for(i=0;i<pFInfo->funcdesc.cParams;i++) {
4503 if(!memcmp(szNameBuf,pFInfo->pParamDesc[i].Name,nNameBufLen))
4504 goto ITypeLib2_fnFindName_exit;
4507 for(pVInfo=pTInfo->varlist;pVInfo;pVInfo=pVInfo->next)
4508 if(!memcmp(szNameBuf,pVInfo->Name, nNameBufLen)) goto ITypeLib2_fnFindName_exit;
4510 ITypeLib2_fnFindName_exit:
4511 ITypeInfo_AddRef((ITypeInfo*)pTInfo);
4512 ppTInfo[j]=(LPTYPEINFO)pTInfo;
4515 TRACE("(%p)slow! search for %d with %s: found %d TypeInfo's!\n",
4516 This, *pcFound, debugstr_w(szNameBuf), j);
4523 /* ITypeLib::ReleaseTLibAttr
4525 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4528 static VOID WINAPI ITypeLib2_fnReleaseTLibAttr(
4530 TLIBATTR *pTLibAttr)
4532 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4533 TRACE("freeing (%p)\n",This);
4534 HeapFree(GetProcessHeap(),0,pTLibAttr);
4538 /* ITypeLib2::GetCustData
4540 * gets the custom data
4542 static HRESULT WINAPI ITypeLib2_fnGetCustData(
4547 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4548 TLBCustData *pCData;
4550 for(pCData=This->pCustData; pCData; pCData = pCData->next)
4552 if( IsEqualIID(guid, &pCData->guid)) break;
4555 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
4559 VariantInit( pVarVal);
4560 VariantCopy( pVarVal, &pCData->data);
4563 return E_INVALIDARG; /* FIXME: correct? */
4566 /* ITypeLib2::GetLibStatistics
4568 * Returns statistics about a type library that are required for efficient
4569 * sizing of hash tables.
4572 static HRESULT WINAPI ITypeLib2_fnGetLibStatistics(
4574 ULONG *pcUniqueNames,
4575 ULONG *pcchUniqueNames)
4577 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4579 FIXME("(%p): stub!\n", This);
4581 if(pcUniqueNames) *pcUniqueNames=1;
4582 if(pcchUniqueNames) *pcchUniqueNames=1;
4586 /* ITypeLib2::GetDocumentation2
4588 * Retrieves the library's documentation string, the complete Help file name
4589 * and path, the localization context to use, and the context ID for the
4590 * library Help topic in the Help file.
4593 static HRESULT WINAPI ITypeLib2_fnGetDocumentation2(
4597 BSTR *pbstrHelpString,
4598 DWORD *pdwHelpStringContext,
4599 BSTR *pbstrHelpStringDll)
4601 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4605 FIXME("(%p) index %d lcid %d half implemented stub!\n", This, index, lcid);
4607 /* the help string should be obtained from the helpstringdll,
4608 * using the _DLLGetDocumentation function, based on the supplied
4609 * lcid. Nice to do sometime...
4613 /* documentation for the typelib */
4615 *pbstrHelpString=SysAllocString(This->DocString);
4616 if(pdwHelpStringContext)
4617 *pdwHelpStringContext=This->dwHelpContext;
4618 if(pbstrHelpStringDll)
4619 *pbstrHelpStringDll=SysAllocString(This->HelpStringDll);
4625 /* for a typeinfo */
4626 result=ITypeLib2_GetTypeInfo(iface, index, &pTInfo);
4628 if(SUCCEEDED(result))
4630 ITypeInfo2 * pTInfo2;
4631 result = ITypeInfo_QueryInterface(pTInfo,
4633 (LPVOID*) &pTInfo2);
4635 if(SUCCEEDED(result))
4637 result = ITypeInfo2_GetDocumentation2(pTInfo2,
4641 pdwHelpStringContext,
4642 pbstrHelpStringDll);
4644 ITypeInfo2_Release(pTInfo2);
4647 ITypeInfo_Release(pTInfo);
4653 /* ITypeLib2::GetAllCustData
4655 * Gets all custom data items for the library.
4658 static HRESULT WINAPI ITypeLib2_fnGetAllCustData(
4660 CUSTDATA *pCustData)
4662 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4663 TLBCustData *pCData;
4665 TRACE("(%p) returning %d items\n", This, This->ctCustData);
4666 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
4667 if(pCustData->prgCustData ){
4668 pCustData->cCustData=This->ctCustData;
4669 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
4670 pCustData->prgCustData[i].guid=pCData->guid;
4671 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
4674 ERR(" OUT OF MEMORY!\n");
4675 return E_OUTOFMEMORY;
4680 static const ITypeLib2Vtbl tlbvt = {
4681 ITypeLib2_fnQueryInterface,
4683 ITypeLib2_fnRelease,
4684 ITypeLib2_fnGetTypeInfoCount,
4685 ITypeLib2_fnGetTypeInfo,
4686 ITypeLib2_fnGetTypeInfoType,
4687 ITypeLib2_fnGetTypeInfoOfGuid,
4688 ITypeLib2_fnGetLibAttr,
4689 ITypeLib2_fnGetTypeComp,
4690 ITypeLib2_fnGetDocumentation,
4692 ITypeLib2_fnFindName,
4693 ITypeLib2_fnReleaseTLibAttr,
4695 ITypeLib2_fnGetCustData,
4696 ITypeLib2_fnGetLibStatistics,
4697 ITypeLib2_fnGetDocumentation2,
4698 ITypeLib2_fnGetAllCustData
4702 static HRESULT WINAPI ITypeLibComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
4704 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4706 return ITypeLib2_QueryInterface((ITypeLib *)This, riid, ppv);
4709 static ULONG WINAPI ITypeLibComp_fnAddRef(ITypeComp * iface)
4711 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4713 return ITypeLib2_AddRef((ITypeLib2 *)This);
4716 static ULONG WINAPI ITypeLibComp_fnRelease(ITypeComp * iface)
4718 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4720 return ITypeLib2_Release((ITypeLib2 *)This);
4723 static HRESULT WINAPI ITypeLibComp_fnBind(
4728 ITypeInfo ** ppTInfo,
4729 DESCKIND * pDescKind,
4732 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4733 ITypeInfoImpl *pTypeInfo;
4736 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4738 *pDescKind = DESCKIND_NONE;
4739 pBindPtr->lptcomp = NULL;
4742 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4744 TRACE("testing %s\n", debugstr_w(pTypeInfo->Name));
4746 /* FIXME: check wFlags here? */
4747 /* FIXME: we should use a hash table to look this info up using lHash
4748 * instead of an O(n) search */
4749 if ((pTypeInfo->TypeAttr.typekind == TKIND_ENUM) ||
4750 (pTypeInfo->TypeAttr.typekind == TKIND_MODULE))
4752 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4754 *pDescKind = DESCKIND_TYPECOMP;
4755 pBindPtr->lptcomp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4756 ITypeComp_AddRef(pBindPtr->lptcomp);
4757 TRACE("module or enum: %s\n", debugstr_w(szName));
4762 if ((pTypeInfo->TypeAttr.typekind == TKIND_MODULE) ||
4763 (pTypeInfo->TypeAttr.typekind == TKIND_ENUM))
4765 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4768 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
4769 if (SUCCEEDED(hr) && (*pDescKind != DESCKIND_NONE))
4771 TRACE("found in module or in enum: %s\n", debugstr_w(szName));
4774 else if (hr == TYPE_E_TYPEMISMATCH)
4778 if ((pTypeInfo->TypeAttr.typekind == TKIND_COCLASS) &&
4779 (pTypeInfo->TypeAttr.wTypeFlags & TYPEFLAG_FAPPOBJECT))
4781 ITypeComp *pSubTypeComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4783 ITypeInfo *subtypeinfo;
4785 DESCKIND subdesckind;
4787 hr = ITypeComp_Bind(pSubTypeComp, szName, lHash, wFlags,
4788 &subtypeinfo, &subdesckind, &subbindptr);
4789 if (SUCCEEDED(hr) && (subdesckind != DESCKIND_NONE))
4791 TYPEDESC tdesc_appobject;
4792 const VARDESC vardesc_appobject =
4795 NULL, /* lpstrSchema */
4810 VAR_STATIC /* varkind */
4813 tdesc_appobject.u.hreftype = pTypeInfo->hreftype;
4814 tdesc_appobject.vt = VT_USERDEFINED;
4816 TRACE("found in implicit app object: %s\n", debugstr_w(szName));
4818 /* cleanup things filled in by Bind call so we can put our
4819 * application object data in there instead */
4820 switch (subdesckind)
4822 case DESCKIND_FUNCDESC:
4823 ITypeInfo_ReleaseFuncDesc(subtypeinfo, subbindptr.lpfuncdesc);
4825 case DESCKIND_VARDESC:
4826 ITypeInfo_ReleaseVarDesc(subtypeinfo, subbindptr.lpvardesc);
4831 if (subtypeinfo) ITypeInfo_Release(subtypeinfo);
4833 if (pTypeInfo->hreftype == -1)
4834 FIXME("no hreftype for interface %p\n", pTypeInfo);
4836 hr = TLB_AllocAndInitVarDesc(&vardesc_appobject, &pBindPtr->lpvardesc);
4840 *pDescKind = DESCKIND_IMPLICITAPPOBJ;
4841 *ppTInfo = (ITypeInfo *)pTypeInfo;
4842 ITypeInfo_AddRef(*ppTInfo);
4845 else if (hr == TYPE_E_TYPEMISMATCH)
4852 TRACE("type mismatch %s\n", debugstr_w(szName));
4853 return TYPE_E_TYPEMISMATCH;
4857 TRACE("name not found %s\n", debugstr_w(szName));
4862 static HRESULT WINAPI ITypeLibComp_fnBindType(
4866 ITypeInfo ** ppTInfo,
4867 ITypeComp ** ppTComp)
4869 ITypeLibImpl *This = impl_from_ITypeComp(iface);
4870 ITypeInfoImpl *pTypeInfo;
4872 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
4874 for (pTypeInfo = This->pTypeInfo; pTypeInfo; pTypeInfo = pTypeInfo->next)
4876 /* FIXME: should use lHash to do the search */
4877 if (pTypeInfo->Name && !strcmpW(pTypeInfo->Name, szName))
4879 TRACE("returning %p\n", pTypeInfo);
4880 *ppTInfo = (ITypeInfo *)&pTypeInfo->lpVtbl;
4881 ITypeInfo_AddRef(*ppTInfo);
4882 *ppTComp = (ITypeComp *)&pTypeInfo->lpVtblTypeComp;
4883 ITypeComp_AddRef(*ppTComp);
4888 TRACE("not found\n");
4894 static const ITypeCompVtbl tlbtcvt =
4897 ITypeLibComp_fnQueryInterface,
4898 ITypeLibComp_fnAddRef,
4899 ITypeLibComp_fnRelease,
4901 ITypeLibComp_fnBind,
4902 ITypeLibComp_fnBindType
4905 /*================== ITypeInfo(2) Methods ===================================*/
4906 static ITypeInfo2 * ITypeInfo_Constructor(void)
4908 ITypeInfoImpl * pTypeInfoImpl;
4910 pTypeInfoImpl = HeapAlloc(GetProcessHeap(),HEAP_ZERO_MEMORY,sizeof(ITypeInfoImpl));
4913 pTypeInfoImpl->lpVtbl = &tinfvt;
4914 pTypeInfoImpl->lpVtblTypeComp = &tcompvt;
4915 pTypeInfoImpl->ref = 0;
4916 pTypeInfoImpl->hreftype = -1;
4917 pTypeInfoImpl->TypeAttr.memidConstructor = MEMBERID_NIL;
4918 pTypeInfoImpl->TypeAttr.memidDestructor = MEMBERID_NIL;
4920 TRACE("(%p)\n", pTypeInfoImpl);
4921 return (ITypeInfo2*) pTypeInfoImpl;
4924 /* ITypeInfo::QueryInterface
4926 static HRESULT WINAPI ITypeInfo_fnQueryInterface(
4931 ITypeLibImpl *This = (ITypeLibImpl *)iface;
4933 TRACE("(%p)->(IID: %s)\n",This,debugstr_guid(riid));
4936 if(IsEqualIID(riid, &IID_IUnknown) ||
4937 IsEqualIID(riid,&IID_ITypeInfo)||
4938 IsEqualIID(riid,&IID_ITypeInfo2))
4942 ITypeInfo_AddRef(iface);
4943 TRACE("-- Interface: (%p)->(%p)\n",ppvObject,*ppvObject);
4946 TRACE("-- Interface: E_NOINTERFACE\n");
4947 return E_NOINTERFACE;
4950 /* ITypeInfo::AddRef
4952 static ULONG WINAPI ITypeInfo_fnAddRef( ITypeInfo2 *iface)
4954 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
4955 ULONG ref = InterlockedIncrement(&This->ref);
4957 TRACE("(%p)->ref is %u\n",This, ref);
4959 if (ref == 1 /* incremented from 0 */)
4960 ITypeLib2_AddRef((ITypeLib2*)This->pTypeLib);
4965 static void ITypeInfo_fnDestroy(ITypeInfoImpl *This)
4967 TLBFuncDesc *pFInfo, *pFInfoNext;
4968 TLBVarDesc *pVInfo, *pVInfoNext;
4969 TLBImplType *pImpl, *pImplNext;
4971 TRACE("destroying ITypeInfo(%p)\n",This);
4973 SysFreeString(This->Name);
4976 SysFreeString(This->DocString);
4977 This->DocString = NULL;
4979 SysFreeString(This->DllName);
4980 This->DllName = NULL;
4982 for (pFInfo = This->funclist; pFInfo; pFInfo = pFInfoNext)
4985 for(i = 0;i < pFInfo->funcdesc.cParams; i++)
4987 ELEMDESC *elemdesc = &pFInfo->funcdesc.lprgelemdescParam[i];
4988 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
4990 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
4991 TLB_Free(elemdesc->u.paramdesc.pparamdescex);
4993 SysFreeString(pFInfo->pParamDesc[i].Name);
4995 TLB_Free(pFInfo->funcdesc.lprgelemdescParam);
4996 TLB_Free(pFInfo->pParamDesc);
4997 TLB_FreeCustData(pFInfo->pCustData);
4998 if (!IS_INTRESOURCE(pFInfo->Entry) && pFInfo->Entry != (BSTR)-1)
4999 SysFreeString(pFInfo->Entry);
5000 SysFreeString(pFInfo->HelpString);
5001 SysFreeString(pFInfo->Name);
5003 pFInfoNext = pFInfo->next;
5006 for (pVInfo = This->varlist; pVInfo; pVInfo = pVInfoNext)
5008 if (pVInfo->vardesc.varkind == VAR_CONST)
5010 VariantClear(pVInfo->vardesc.u.lpvarValue);
5011 TLB_Free(pVInfo->vardesc.u.lpvarValue);
5013 TLB_FreeCustData(pVInfo->pCustData);
5014 SysFreeString(pVInfo->Name);
5015 pVInfoNext = pVInfo->next;
5018 for (pImpl = This->impltypelist; pImpl; pImpl = pImplNext)
5020 TLB_FreeCustData(pImpl->pCustData);
5021 pImplNext = pImpl->next;
5024 TLB_FreeCustData(This->pCustData);
5026 HeapFree(GetProcessHeap(), 0, This);
5029 /* ITypeInfo::Release
5031 static ULONG WINAPI ITypeInfo_fnRelease(ITypeInfo2 *iface)
5033 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5034 ULONG ref = InterlockedDecrement(&This->ref);
5036 TRACE("(%p)->(%u)\n",This, ref);
5040 BOOL not_attached_to_typelib = This->not_attached_to_typelib;
5041 ITypeLib2_Release((ITypeLib2*)This->pTypeLib);
5042 if (not_attached_to_typelib)
5043 HeapFree(GetProcessHeap(), 0, This);
5044 /* otherwise This will be freed when typelib is freed */
5050 /* ITypeInfo::GetTypeAttr
5052 * Retrieves a TYPEATTR structure that contains the attributes of the type
5056 static HRESULT WINAPI ITypeInfo_fnGetTypeAttr( ITypeInfo2 *iface,
5057 LPTYPEATTR *ppTypeAttr)
5059 const ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5062 TRACE("(%p)\n",This);
5064 size = sizeof(**ppTypeAttr);
5065 if (This->TypeAttr.typekind == TKIND_ALIAS)
5066 size += TLB_SizeTypeDesc(&This->TypeAttr.tdescAlias, FALSE);
5068 *ppTypeAttr = HeapAlloc(GetProcessHeap(), 0, size);
5070 return E_OUTOFMEMORY;
5072 **ppTypeAttr = This->TypeAttr;
5074 if (This->TypeAttr.typekind == TKIND_ALIAS)
5075 TLB_CopyTypeDesc(&(*ppTypeAttr)->tdescAlias,
5076 &This->TypeAttr.tdescAlias, *ppTypeAttr + 1);
5078 if((*ppTypeAttr)->typekind == TKIND_DISPATCH) {
5079 /* This should include all the inherited funcs */
5080 (*ppTypeAttr)->cFuncs = (*ppTypeAttr)->cbSizeVft / sizeof(void *);
5081 (*ppTypeAttr)->cbSizeVft = 7 * sizeof(void *); /* This is always the size of IDispatch's vtbl */
5082 (*ppTypeAttr)->wTypeFlags &= ~TYPEFLAG_FOLEAUTOMATION;
5087 /* ITypeInfo::GetTypeComp
5089 * Retrieves the ITypeComp interface for the type description, which enables a
5090 * client compiler to bind to the type description's members.
5093 static HRESULT WINAPI ITypeInfo_fnGetTypeComp( ITypeInfo2 *iface,
5094 ITypeComp * *ppTComp)
5096 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5098 TRACE("(%p)->(%p)\n", This, ppTComp);
5100 *ppTComp = (ITypeComp *)&This->lpVtblTypeComp;
5101 ITypeComp_AddRef(*ppTComp);
5105 static SIZE_T TLB_SizeElemDesc( const ELEMDESC *elemdesc )
5107 SIZE_T size = TLB_SizeTypeDesc(&elemdesc->tdesc, FALSE);
5108 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5109 size += sizeof(*elemdesc->u.paramdesc.pparamdescex);
5113 static HRESULT TLB_CopyElemDesc( const ELEMDESC *src, ELEMDESC *dest, char **buffer )
5116 *buffer = TLB_CopyTypeDesc(&dest->tdesc, &src->tdesc, *buffer);
5117 if (src->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5119 const PARAMDESCEX *pparamdescex_src = src->u.paramdesc.pparamdescex;
5120 PARAMDESCEX *pparamdescex_dest = dest->u.paramdesc.pparamdescex = (PARAMDESCEX *)*buffer;
5121 *buffer += sizeof(PARAMDESCEX);
5122 *pparamdescex_dest = *pparamdescex_src;
5123 VariantInit(&pparamdescex_dest->varDefaultValue);
5124 return VariantCopy(&pparamdescex_dest->varDefaultValue,
5125 (VARIANTARG *)&pparamdescex_src->varDefaultValue);
5128 dest->u.paramdesc.pparamdescex = NULL;
5132 static void TLB_FreeElemDesc( ELEMDESC *elemdesc )
5134 if (elemdesc->u.paramdesc.wParamFlags & PARAMFLAG_FHASDEFAULT)
5135 VariantClear(&elemdesc->u.paramdesc.pparamdescex->varDefaultValue);
5138 static HRESULT TLB_AllocAndInitFuncDesc( const FUNCDESC *src, FUNCDESC **dest_ptr, BOOL dispinterface )
5142 SIZE_T size = sizeof(*src);
5146 size += sizeof(*src->lprgscode) * src->cScodes;
5147 size += TLB_SizeElemDesc(&src->elemdescFunc);
5148 for (i = 0; i < src->cParams; i++)
5150 size += sizeof(ELEMDESC);
5151 size += TLB_SizeElemDesc(&src->lprgelemdescParam[i]);
5154 dest = (FUNCDESC *)SysAllocStringByteLen(NULL, size);
5155 if (!dest) return E_OUTOFMEMORY;
5158 if (dispinterface) /* overwrite funckind */
5159 dest->funckind = FUNC_DISPATCH;
5160 buffer = (char *)(dest + 1);
5162 dest->lprgscode = (SCODE *)buffer;
5163 memcpy(dest->lprgscode, src->lprgscode, sizeof(*src->lprgscode) * src->cScodes);
5164 buffer += sizeof(*src->lprgscode) * src->cScodes;
5166 hr = TLB_CopyElemDesc(&src->elemdescFunc, &dest->elemdescFunc, &buffer);
5169 SysFreeString((BSTR)dest);
5173 dest->lprgelemdescParam = (ELEMDESC *)buffer;
5174 buffer += sizeof(ELEMDESC) * src->cParams;
5175 for (i = 0; i < src->cParams; i++)
5177 hr = TLB_CopyElemDesc(&src->lprgelemdescParam[i], &dest->lprgelemdescParam[i], &buffer);
5183 /* undo the above actions */
5184 for (i = i - 1; i >= 0; i--)
5185 TLB_FreeElemDesc(&dest->lprgelemdescParam[i]);
5186 TLB_FreeElemDesc(&dest->elemdescFunc);
5187 SysFreeString((BSTR)dest);
5191 /* special treatment for dispinterfaces: this makes functions appear
5192 * to return their [retval] value when it is really returning an
5194 if (dispinterface && dest->elemdescFunc.tdesc.vt == VT_HRESULT)
5196 if (dest->cParams &&
5197 (dest->lprgelemdescParam[dest->cParams - 1].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL))
5199 ELEMDESC *elemdesc = &dest->lprgelemdescParam[dest->cParams - 1];
5200 if (elemdesc->tdesc.vt != VT_PTR)
5202 ERR("elemdesc should have started with VT_PTR instead of:\n");
5204 dump_ELEMDESC(elemdesc);
5205 return E_UNEXPECTED;
5208 /* copy last parameter to the return value. we are using a flat
5209 * buffer so there is no danger of leaking memory in
5211 dest->elemdescFunc.tdesc = *elemdesc->tdesc.u.lptdesc;
5213 /* remove the last parameter */
5217 /* otherwise this function is made to appear to have no return
5219 dest->elemdescFunc.tdesc.vt = VT_VOID;
5227 HRESULT ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo *iface, UINT index, const FUNCDESC **ppFuncDesc )
5229 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5230 const TLBFuncDesc *pFDesc;
5233 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++, pFDesc=pFDesc->next)
5238 *ppFuncDesc = &pFDesc->funcdesc;
5242 return TYPE_E_ELEMENTNOTFOUND;
5245 /* internal function to make the inherited interfaces' methods appear
5246 * part of the interface */
5247 static HRESULT ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo *iface,
5248 UINT index, const FUNCDESC **ppFuncDesc, UINT *funcs, UINT *hrefoffset)
5250 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5252 UINT implemented_funcs = 0;
5257 *hrefoffset = DISPATCH_HREF_OFFSET;
5259 if(This->impltypelist)
5261 ITypeInfo *pSubTypeInfo;
5264 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
5268 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo,
5271 &sub_funcs, hrefoffset);
5272 implemented_funcs += sub_funcs;
5273 ITypeInfo_Release(pSubTypeInfo);
5276 *hrefoffset += DISPATCH_HREF_OFFSET;
5280 *funcs = implemented_funcs + This->TypeAttr.cFuncs;
5284 if (index < implemented_funcs)
5285 return E_INVALIDARG;
5286 return ITypeInfoImpl_GetInternalFuncDesc(iface, index - implemented_funcs,
5290 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc, UINT hrefoffset)
5292 TYPEDESC *pTypeDesc = &pElemDesc->tdesc;
5295 switch (pTypeDesc->vt)
5297 case VT_USERDEFINED:
5298 pTypeDesc->u.hreftype += hrefoffset;
5302 pTypeDesc = pTypeDesc->u.lptdesc;
5305 pTypeDesc = &pTypeDesc->u.lpadesc->tdescElem;
5313 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc, UINT hrefoffset)
5316 for (i = 0; i < pFuncDesc->cParams; i++)
5317 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->lprgelemdescParam[i], hrefoffset);
5318 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc->elemdescFunc, hrefoffset);
5321 /* ITypeInfo::GetFuncDesc
5323 * Retrieves the FUNCDESC structure that contains information about a
5324 * specified function.
5327 static HRESULT WINAPI ITypeInfo_fnGetFuncDesc( ITypeInfo2 *iface, UINT index,
5328 LPFUNCDESC *ppFuncDesc)
5330 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5331 const FUNCDESC *internal_funcdesc;
5333 UINT hrefoffset = 0;
5335 TRACE("(%p) index %d\n", This, index);
5337 if (This->TypeAttr.typekind == TKIND_DISPATCH)
5338 hr = ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo *)iface, index,
5339 &internal_funcdesc, NULL,
5342 hr = ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo *)iface, index,
5343 &internal_funcdesc);
5346 WARN("description for function %d not found\n", index);
5350 hr = TLB_AllocAndInitFuncDesc(
5353 This->TypeAttr.typekind == TKIND_DISPATCH);
5355 if ((This->TypeAttr.typekind == TKIND_DISPATCH) && hrefoffset)
5356 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc, hrefoffset);
5358 TRACE("-- 0x%08x\n", hr);
5362 static HRESULT TLB_AllocAndInitVarDesc( const VARDESC *src, VARDESC **dest_ptr )
5366 SIZE_T size = sizeof(*src);
5369 if (src->lpstrSchema) size += (strlenW(src->lpstrSchema) + 1) * sizeof(WCHAR);
5370 if (src->varkind == VAR_CONST)
5371 size += sizeof(VARIANT);
5372 size += TLB_SizeElemDesc(&src->elemdescVar);
5374 dest = (VARDESC *)SysAllocStringByteLen(NULL, size);
5375 if (!dest) return E_OUTOFMEMORY;
5378 buffer = (char *)(dest + 1);
5379 if (src->lpstrSchema)
5382 dest->lpstrSchema = (LPOLESTR)buffer;
5383 len = strlenW(src->lpstrSchema);
5384 memcpy(dest->lpstrSchema, src->lpstrSchema, (len + 1) * sizeof(WCHAR));
5385 buffer += (len + 1) * sizeof(WCHAR);
5388 if (src->varkind == VAR_CONST)
5392 dest->u.lpvarValue = (VARIANT *)buffer;
5393 *dest->u.lpvarValue = *src->u.lpvarValue;
5394 buffer += sizeof(VARIANT);
5395 VariantInit(dest->u.lpvarValue);
5396 hr = VariantCopy(dest->u.lpvarValue, src->u.lpvarValue);
5399 SysFreeString((BSTR)dest);
5403 hr = TLB_CopyElemDesc(&src->elemdescVar, &dest->elemdescVar, &buffer);
5406 if (src->varkind == VAR_CONST)
5407 VariantClear(dest->u.lpvarValue);
5408 SysFreeString((BSTR)dest);
5415 /* ITypeInfo::GetVarDesc
5417 * Retrieves a VARDESC structure that describes the specified variable.
5420 static HRESULT WINAPI ITypeInfo_fnGetVarDesc( ITypeInfo2 *iface, UINT index,
5421 LPVARDESC *ppVarDesc)
5423 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5425 const TLBVarDesc *pVDesc;
5427 TRACE("(%p) index %d\n", This, index);
5429 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next)
5433 return TLB_AllocAndInitVarDesc(&pVDesc->vardesc, ppVarDesc);
5435 return E_INVALIDARG;
5438 /* ITypeInfo_GetNames
5440 * Retrieves the variable with the specified member ID (or the name of the
5441 * property or method and its parameters) that correspond to the specified
5444 static HRESULT WINAPI ITypeInfo_fnGetNames( ITypeInfo2 *iface, MEMBERID memid,
5445 BSTR *rgBstrNames, UINT cMaxNames, UINT *pcNames)
5447 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5448 const TLBFuncDesc *pFDesc;
5449 const TLBVarDesc *pVDesc;
5451 TRACE("(%p) memid=0x%08x Maxname=%d\n", This, memid, cMaxNames);
5452 for(pFDesc=This->funclist; pFDesc && pFDesc->funcdesc.memid != memid; pFDesc=pFDesc->next);
5455 /* function found, now return function and parameter names */
5456 for(i=0; i<cMaxNames && i <= pFDesc->funcdesc.cParams; i++)
5459 *rgBstrNames=SysAllocString(pFDesc->Name);
5461 rgBstrNames[i]=SysAllocString(pFDesc->pParamDesc[i-1].Name);
5467 for(pVDesc=This->varlist; pVDesc && pVDesc->vardesc.memid != memid; pVDesc=pVDesc->next);
5470 *rgBstrNames=SysAllocString(pVDesc->Name);
5475 if(This->impltypelist &&
5476 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
5477 /* recursive search */
5480 result=ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
5482 if(SUCCEEDED(result))
5484 result=ITypeInfo_GetNames(pTInfo, memid, rgBstrNames, cMaxNames, pcNames);
5485 ITypeInfo_Release(pTInfo);
5488 WARN("Could not search inherited interface!\n");
5492 WARN("no names found\n");
5495 return TYPE_E_ELEMENTNOTFOUND;
5502 /* ITypeInfo::GetRefTypeOfImplType
5504 * If a type description describes a COM class, it retrieves the type
5505 * description of the implemented interface types. For an interface,
5506 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5510 static HRESULT WINAPI ITypeInfo_fnGetRefTypeOfImplType(
5515 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5518 const TLBImplType *pImpl = This->impltypelist;
5520 TRACE("(%p) index %d\n", This, index);
5521 if (TRACE_ON(ole)) dump_TypeInfo(This);
5525 /* only valid on dual interfaces;
5526 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5528 if( This->TypeAttr.typekind != TKIND_DISPATCH) return E_INVALIDARG;
5530 if (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL)
5536 hr = TYPE_E_ELEMENTNOTFOUND;
5539 else if(index == 0 && This->TypeAttr.typekind == TKIND_DISPATCH)
5541 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5542 *pRefType = This->pTypeLib->dispatch_href;
5546 /* get element n from linked list */
5547 for(i=0; pImpl && i<index; i++)
5549 pImpl = pImpl->next;
5553 *pRefType = pImpl->hRef;
5555 hr = TYPE_E_ELEMENTNOTFOUND;
5561 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType );
5563 TRACE("FAILURE -- hresult = 0x%08x\n", hr);
5569 /* ITypeInfo::GetImplTypeFlags
5571 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5572 * or base interface in a type description.
5574 static HRESULT WINAPI ITypeInfo_fnGetImplTypeFlags( ITypeInfo2 *iface,
5575 UINT index, INT *pImplTypeFlags)
5577 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5581 TRACE("(%p) index %d\n", This, index);
5582 for(i=0, pImpl=This->impltypelist; i<index && pImpl;
5583 i++, pImpl=pImpl->next)
5585 if(i==index && pImpl){
5586 *pImplTypeFlags=pImpl->implflags;
5591 if(This->TypeAttr.typekind==TKIND_DISPATCH && !index)
5594 WARN("ImplType %d not found\n", index);
5595 return TYPE_E_ELEMENTNOTFOUND;
5599 * Maps between member names and member IDs, and parameter names and
5602 static HRESULT WINAPI ITypeInfo_fnGetIDsOfNames( ITypeInfo2 *iface,
5603 LPOLESTR *rgszNames, UINT cNames, MEMBERID *pMemId)
5605 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
5606 const TLBFuncDesc *pFDesc;
5607 const TLBVarDesc *pVDesc;
5611 TRACE("(%p) Name %s cNames %d\n", This, debugstr_w(*rgszNames),
5614 /* init out parameters in case of failure */
5615 for (i = 0; i < cNames; i++)
5616 pMemId[i] = MEMBERID_NIL;
5618 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next) {
5620 if(!lstrcmpiW(*rgszNames, pFDesc->Name)) {
5621 if(cNames) *pMemId=pFDesc->funcdesc.memid;
5622 for(i=1; i < cNames; i++){
5623 for(j=0; j<pFDesc->funcdesc.cParams; j++)
5624 if(!lstrcmpiW(rgszNames[i],pFDesc->pParamDesc[j].Name))
5626 if( j<pFDesc->funcdesc.cParams)
5629 ret=DISP_E_UNKNOWNNAME;
5631 TRACE("-- 0x%08x\n", ret);
5635 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next) {
5636 if(!lstrcmpiW(*rgszNames, pVDesc->Name)) {
5637 if(cNames) *pMemId=pVDesc->vardesc.memid;
5641 /* not found, see if it can be found in an inherited interface */
5642 if(This->impltypelist) {
5643 /* recursive search */
5645 ret=ITypeInfo_GetRefTypeInfo(iface,
5646 This->impltypelist->hRef, &pTInfo);
5648 ret=ITypeInfo_GetIDsOfNames(pTInfo, rgszNames, cNames, pMemId );
5649 ITypeInfo_Release(pTInfo);
5652 WARN("Could not search inherited interface!\n");
5654 WARN("no names found\n");
5655 return DISP_E_UNKNOWNNAME;
5661 extern DWORD CDECL call_method( void *func, int nb_args, const DWORD *args );
5662 __ASM_GLOBAL_FUNC( call_method,
5664 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5665 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5666 "movl %esp,%ebp\n\t"
5667 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5669 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5671 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5672 "movl 12(%ebp),%edx\n\t"
5675 "subl %edx,%esp\n\t"
5676 "andl $~15,%esp\n\t"
5677 "movl 12(%ebp),%ecx\n\t"
5678 "movl 16(%ebp),%esi\n\t"
5679 "movl %esp,%edi\n\t"
5682 "1:\tcall *8(%ebp)\n\t"
5683 "leal -8(%ebp),%esp\n\t"
5685 __ASM_CFI(".cfi_same_value %edi\n\t")
5687 __ASM_CFI(".cfi_same_value %esi\n\t")
5689 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5690 __ASM_CFI(".cfi_same_value %ebp\n\t")
5693 /* ITypeInfo::Invoke
5695 * Invokes a method, or accesses a property of an object, that implements the
5696 * interface described by the type description.
5699 _invoke(FARPROC func,CALLCONV callconv, int nrargs, DWORD *args) {
5702 if (TRACE_ON(ole)) {
5704 TRACE("Calling %p(",func);
5705 for (i=0;i<min(nrargs,30);i++) TRACE("%08x,",args[i]);
5706 if (nrargs > 30) TRACE("...");
5713 res = call_method( func, nrargs, args );
5716 FIXME("unsupported calling convention %d\n",callconv);
5720 TRACE("returns %08x\n",res);
5724 /* The size of the argument on the stack in DWORD units (in all x86 call
5725 * convetions the arguments on the stack are DWORD-aligned)
5727 static int _dispargsize(VARTYPE vt)
5732 return 8/sizeof(DWORD);
5734 return sizeof(double)/sizeof(DWORD);
5736 return (sizeof(DECIMAL)+3)/sizeof(DWORD);
5738 return sizeof(CY)/sizeof(DWORD);
5740 return sizeof(DATE)/sizeof(DWORD);
5742 return (sizeof(VARIANT)+3)/sizeof(DWORD);
5744 FIXME("VT_RECORD not implemented\n");
5750 #endif /* __i386__ */
5752 static HRESULT userdefined_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5755 ITypeInfo *tinfo2 = NULL;
5756 TYPEATTR *tattr = NULL;
5758 hr = ITypeInfo_GetRefTypeInfo(tinfo, tdesc->u.hreftype, &tinfo2);
5761 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5763 tdesc->u.hreftype, hr);
5766 hr = ITypeInfo_GetTypeAttr(tinfo2, &tattr);
5769 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr);
5770 ITypeInfo_Release(tinfo2);
5774 switch (tattr->typekind)
5781 tdesc = &tattr->tdescAlias;
5782 hr = typedescvt_to_variantvt(tinfo2, &tattr->tdescAlias, vt);
5785 case TKIND_INTERFACE:
5786 if (tattr->wTypeFlags & TYPEFLAG_FDISPATCHABLE)
5792 case TKIND_DISPATCH:
5801 FIXME("TKIND_RECORD unhandled.\n");
5806 FIXME("TKIND_UNION unhandled.\n");
5811 FIXME("TKIND %d unhandled.\n",tattr->typekind);
5815 ITypeInfo_ReleaseTypeAttr(tinfo2, tattr);
5816 ITypeInfo_Release(tinfo2);
5820 static HRESULT typedescvt_to_variantvt(ITypeInfo *tinfo, const TYPEDESC *tdesc, VARTYPE *vt)
5824 /* enforce only one level of pointer indirection */
5825 if (!(*vt & VT_BYREF) && !(*vt & VT_ARRAY) && (tdesc->vt == VT_PTR))
5827 tdesc = tdesc->u.lptdesc;
5829 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5830 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5831 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5832 if ((tdesc->vt == VT_USERDEFINED) ||
5833 ((tdesc->vt == VT_PTR) && (tdesc->u.lptdesc->vt == VT_USERDEFINED)))
5835 VARTYPE vt_userdefined = 0;
5836 const TYPEDESC *tdesc_userdefined = tdesc;
5837 if (tdesc->vt == VT_PTR)
5839 vt_userdefined = VT_BYREF;
5840 tdesc_userdefined = tdesc->u.lptdesc;
5842 hr = userdefined_to_variantvt(tinfo, tdesc_userdefined, &vt_userdefined);
5844 (((vt_userdefined & VT_TYPEMASK) == VT_UNKNOWN) ||
5845 ((vt_userdefined & VT_TYPEMASK) == VT_DISPATCH)))
5847 *vt |= vt_userdefined;
5859 case VT_USERDEFINED:
5860 hr = userdefined_to_variantvt(tinfo, tdesc, vt);
5867 ERR("cannot convert type %d into variant VT\n", tdesc->vt);
5868 hr = DISP_E_BADVARTYPE;
5872 hr = typedescvt_to_variantvt(tinfo, tdesc->u.lptdesc, vt);
5887 /***********************************************************************
5888 * DispCallFunc (OLEAUT32.@)
5890 * Invokes a function of the specified calling convention, passing the
5891 * specified arguments and returns the result.
5894 * pvInstance [I] Optional pointer to the instance whose function to invoke.
5895 * oVft [I] The offset in the vtable. See notes.
5896 * cc [I] Calling convention of the function to call.
5897 * vtReturn [I] The return type of the function.
5898 * cActuals [I] Number of parameters.
5899 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
5900 * prgpvarg [I] The arguments to pass.
5901 * pvargResult [O] The return value of the function. Can be NULL.
5905 * Failure: HRESULT code.
5908 * The HRESULT return value of this function is not affected by the return
5909 * value of the user supplied function, which is returned in pvargResult.
5911 * If pvInstance is NULL then a non-object function is to be called and oVft
5912 * is the address of the function to call.
5914 * The cc parameter can be one of the following values:
5927 void* pvInstance, ULONG_PTR oVft, CALLCONV cc, VARTYPE vtReturn, UINT cActuals,
5928 VARTYPE* prgvt, VARIANTARG** prgpvarg, VARIANT* pvargResult)
5931 int argsize, argspos;
5936 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
5937 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg,
5938 pvargResult, V_VT(pvargResult));
5942 argsize++; /* for This pointer */
5944 for (i=0;i<cActuals;i++)
5946 TRACE("arg %u: type %d, size %d\n",i,prgvt[i],_dispargsize(prgvt[i]));
5947 dump_Variant(prgpvarg[i]);
5948 argsize += _dispargsize(prgvt[i]);
5950 args = HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
5955 args[0] = (DWORD)pvInstance; /* the This pointer is always the first parameter */
5959 for (i=0;i<cActuals;i++)
5961 VARIANT *arg = prgpvarg[i];
5962 TRACE("Storing arg %u (%d as %d)\n",i,V_VT(arg),prgvt[i]);
5963 if (prgvt[i] == VT_VARIANT)
5964 memcpy(&args[argspos], arg, _dispargsize(prgvt[i]) * sizeof(DWORD));
5966 memcpy(&args[argspos], &V_NONE(arg), _dispargsize(prgvt[i]) * sizeof(DWORD));
5967 argspos += _dispargsize(prgvt[i]);
5972 FARPROC *vtable = *(FARPROC**)pvInstance;
5973 hres = _invoke(vtable[oVft/sizeof(void *)], cc, argsize, args);
5976 /* if we aren't invoking an object then the function pointer is stored
5978 hres = _invoke((FARPROC)oVft, cc, argsize, args);
5980 if (pvargResult && (vtReturn != VT_EMPTY))
5982 TRACE("Method returned 0x%08x\n",hres);
5983 V_VT(pvargResult) = vtReturn;
5984 V_UI4(pvargResult) = hres;
5986 HeapFree(GetProcessHeap(),0,args);
5989 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
5990 pvInstance, oVft, cc, vtReturn, cActuals, prgvt, prgpvarg, pvargResult, V_VT(pvargResult));
5995 #define INVBUF_ELEMENT_SIZE \
5996 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
5997 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
5998 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
5999 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6000 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6001 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6002 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6003 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6005 static HRESULT WINAPI ITypeInfo_fnInvoke(
6010 DISPPARAMS *pDispParams,
6011 VARIANT *pVarResult,
6012 EXCEPINFO *pExcepInfo,
6015 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6017 unsigned int var_index;
6020 const TLBFuncDesc *pFuncInfo;
6022 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6023 This,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr
6028 ERR("NULL pDispParams not allowed\n");
6029 return E_INVALIDARG;
6032 dump_DispParms(pDispParams);
6034 if (pDispParams->cNamedArgs > pDispParams->cArgs)
6036 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6037 pDispParams->cNamedArgs, pDispParams->cArgs);
6038 return E_INVALIDARG;
6041 /* we do this instead of using GetFuncDesc since it will return a fake
6042 * FUNCDESC for dispinterfaces and we want the real function description */
6043 for (pFuncInfo = This->funclist; pFuncInfo; pFuncInfo=pFuncInfo->next)
6044 if ((memid == pFuncInfo->funcdesc.memid) &&
6045 (wFlags & pFuncInfo->funcdesc.invkind))
6049 const FUNCDESC *func_desc = &pFuncInfo->funcdesc;
6053 TRACE("invoking:\n");
6054 dump_TLBFuncDescOne(pFuncInfo);
6057 switch (func_desc->funckind) {
6058 case FUNC_PUREVIRTUAL:
6059 case FUNC_VIRTUAL: {
6060 void *buffer = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, INVBUF_ELEMENT_SIZE * func_desc->cParams);
6062 VARIANT retval; /* pointer for storing byref retvals in */
6063 VARIANTARG **prgpvarg = INVBUF_GET_ARG_PTR_ARRAY(buffer, func_desc->cParams);
6064 VARIANTARG *rgvarg = INVBUF_GET_ARG_ARRAY(buffer, func_desc->cParams);
6065 VARTYPE *rgvt = INVBUF_GET_ARG_TYPE_ARRAY(buffer, func_desc->cParams);
6066 UINT cNamedArgs = pDispParams->cNamedArgs;
6067 DISPID *rgdispidNamedArgs = pDispParams->rgdispidNamedArgs;
6068 UINT vargs_converted=0;
6072 if (func_desc->invkind & (INVOKE_PROPERTYPUT|INVOKE_PROPERTYPUTREF))
6074 if (!cNamedArgs || (rgdispidNamedArgs[0] != DISPID_PROPERTYPUT))
6076 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6077 hres = DISP_E_PARAMNOTFOUND;
6082 if (func_desc->cParamsOpt < 0 && cNamedArgs)
6084 ERR("functions with the vararg attribute do not support named arguments\n");
6085 hres = DISP_E_NONAMEDARGS;
6089 for (i = 0; i < func_desc->cParams; i++)
6091 TYPEDESC *tdesc = &func_desc->lprgelemdescParam[i].tdesc;
6092 hres = typedescvt_to_variantvt((ITypeInfo *)iface, tdesc, &rgvt[i]);
6097 TRACE("changing args\n");
6098 for (i = 0; i < func_desc->cParams; i++)
6100 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6101 VARIANTARG *src_arg;
6103 if (wParamFlags & PARAMFLAG_FLCID)
6106 arg = prgpvarg[i] = &rgvarg[i];
6108 V_I4(arg) = This->pTypeLib->lcid;
6117 for (j = 0; j < cNamedArgs; j++)
6118 if (rgdispidNamedArgs[j] == i || (i == func_desc->cParams-1 && rgdispidNamedArgs[j] == DISPID_PROPERTYPUT))
6120 src_arg = &pDispParams->rgvarg[j];
6125 if (!src_arg && vargs_converted + cNamedArgs < pDispParams->cArgs)
6127 src_arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6131 if (wParamFlags & PARAMFLAG_FRETVAL)
6133 /* under most conditions the caller is not allowed to
6134 * pass in a dispparam arg in the index of what would be
6135 * the retval parameter. however, there is an exception
6136 * where the extra parameter is used in an extra
6137 * IDispatch::Invoke below */
6138 if ((i < pDispParams->cArgs) &&
6139 ((func_desc->cParams != 1) || !pVarResult ||
6140 !(func_desc->invkind & INVOKE_PROPERTYGET)))
6142 hres = DISP_E_BADPARAMCOUNT;
6146 /* note: this check is placed so that if the caller passes
6147 * in a VARIANTARG for the retval we just ignore it, like
6149 if (i == func_desc->cParams - 1)
6152 arg = prgpvarg[i] = &rgvarg[i];
6153 memset(arg, 0, sizeof(*arg));
6154 V_VT(arg) = rgvt[i];
6155 memset(&retval, 0, sizeof(retval));
6156 V_BYREF(arg) = &retval;
6160 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i, func_desc->cParams);
6161 hres = E_UNEXPECTED;
6167 dump_Variant(src_arg);
6169 if (rgvt[i] == VT_VARIANT)
6170 hres = VariantCopy(&rgvarg[i], src_arg);
6171 else if (rgvt[i] == (VT_VARIANT | VT_BYREF))
6173 if (rgvt[i] == V_VT(src_arg))
6174 V_VARIANTREF(&rgvarg[i]) = V_VARIANTREF(src_arg);
6177 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6178 if (wParamFlags & PARAMFLAG_FIN)
6179 hres = VariantCopy(&missing_arg[i], src_arg);
6180 V_VARIANTREF(&rgvarg[i]) = &missing_arg[i];
6182 V_VT(&rgvarg[i]) = rgvt[i];
6184 else if (rgvt[i] == (VT_VARIANT | VT_ARRAY) && func_desc->cParamsOpt < 0 && i == func_desc->cParams-1)
6187 SAFEARRAYBOUND bound;
6191 bound.cElements = pDispParams->cArgs-i;
6192 if (!(a = SafeArrayCreate(VT_VARIANT, 1, &bound)))
6194 ERR("SafeArrayCreate failed\n");
6197 hres = SafeArrayAccessData(a, (LPVOID)&v);
6200 ERR("SafeArrayAccessData failed with %x\n", hres);
6203 for (j = 0; j < bound.cElements; j++)
6204 VariantCopy(&v[j], &pDispParams->rgvarg[pDispParams->cArgs - 1 - i - j]);
6205 hres = SafeArrayUnaccessData(a);
6208 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6211 V_ARRAY(&rgvarg[i]) = a;
6212 V_VT(&rgvarg[i]) = rgvt[i];
6214 else if ((rgvt[i] & VT_BYREF) && !V_ISBYREF(src_arg))
6216 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6217 if (wParamFlags & PARAMFLAG_FIN)
6218 hres = VariantChangeType(&missing_arg[i], src_arg, 0, rgvt[i] & ~VT_BYREF);
6220 V_VT(&missing_arg[i]) = rgvt[i] & ~VT_BYREF;
6221 V_BYREF(&rgvarg[i]) = &V_NONE(&missing_arg[i]);
6222 V_VT(&rgvarg[i]) = rgvt[i];
6224 else if ((rgvt[i] & VT_BYREF) && (rgvt[i] == V_VT(src_arg)))
6226 V_BYREF(&rgvarg[i]) = V_BYREF(src_arg);
6227 V_VT(&rgvarg[i]) = rgvt[i];
6231 /* FIXME: this doesn't work for VT_BYREF arguments if
6232 * they are not the same type as in the paramdesc */
6233 V_VT(&rgvarg[i]) = V_VT(src_arg);
6234 hres = VariantChangeType(&rgvarg[i], src_arg, 0, rgvt[i]);
6235 V_VT(&rgvarg[i]) = rgvt[i];
6240 ERR("failed to convert param %d to %s%s from %s%s\n", i,
6241 debugstr_vt(rgvt[i]), debugstr_vf(rgvt[i]),
6242 debugstr_VT(src_arg), debugstr_VF(src_arg));
6245 prgpvarg[i] = &rgvarg[i];
6247 else if (wParamFlags & PARAMFLAG_FOPT)
6250 arg = prgpvarg[i] = &rgvarg[i];
6251 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6253 hres = VariantCopy(arg, &func_desc->lprgelemdescParam[i].u.paramdesc.pparamdescex->varDefaultValue);
6259 VARIANTARG *missing_arg;
6260 /* if the function wants a pointer to a variant then
6261 * set that up, otherwise just pass the VT_ERROR in
6262 * the argument by value */
6263 if (rgvt[i] & VT_BYREF)
6265 missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams) + i;
6266 V_VT(arg) = VT_VARIANT | VT_BYREF;
6267 V_VARIANTREF(arg) = missing_arg;
6271 V_VT(missing_arg) = VT_ERROR;
6272 V_ERROR(missing_arg) = DISP_E_PARAMNOTFOUND;
6277 hres = DISP_E_BADPARAMCOUNT;
6281 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6283 /* VT_VOID is a special case for return types, so it is not
6284 * handled in the general function */
6285 if (func_desc->elemdescFunc.tdesc.vt == VT_VOID)
6286 V_VT(&varresult) = VT_EMPTY;
6289 V_VT(&varresult) = 0;
6290 hres = typedescvt_to_variantvt((ITypeInfo *)iface, &func_desc->elemdescFunc.tdesc, &V_VT(&varresult));
6291 if (FAILED(hres)) goto func_fail; /* FIXME: we don't free changed types here */
6294 hres = DispCallFunc(pIUnk, func_desc->oVft, func_desc->callconv,
6295 V_VT(&varresult), func_desc->cParams, rgvt,
6296 prgpvarg, &varresult);
6298 vargs_converted = 0;
6300 for (i = 0; i < func_desc->cParams; i++)
6302 USHORT wParamFlags = func_desc->lprgelemdescParam[i].u.paramdesc.wParamFlags;
6303 VARIANTARG *missing_arg = INVBUF_GET_MISSING_ARG_ARRAY(buffer, func_desc->cParams);
6305 if (wParamFlags & PARAMFLAG_FLCID)
6307 else if (wParamFlags & PARAMFLAG_FRETVAL)
6311 TRACE("[retval] value: ");
6312 dump_Variant(prgpvarg[i]);
6317 VariantInit(pVarResult);
6318 /* deref return value */
6319 hres = VariantCopyInd(pVarResult, prgpvarg[i]);
6322 VARIANT_ClearInd(prgpvarg[i]);
6324 else if (vargs_converted < pDispParams->cArgs)
6326 VARIANTARG *arg = &pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted];
6327 if (wParamFlags & PARAMFLAG_FOUT)
6329 if ((rgvt[i] & VT_BYREF) && !(V_VT(arg) & VT_BYREF))
6331 hres = VariantChangeType(arg, &rgvarg[i], 0, V_VT(arg));
6335 ERR("failed to convert param %d to vt %d\n", i,
6336 V_VT(&pDispParams->rgvarg[pDispParams->cArgs - 1 - vargs_converted]));
6341 else if (V_VT(prgpvarg[i]) == (VT_VARIANT | VT_ARRAY) &&
6342 func_desc->cParamsOpt < 0 &&
6343 i == func_desc->cParams-1)
6345 SAFEARRAY *a = V_ARRAY(prgpvarg[i]);
6348 hres = SafeArrayGetUBound(a, 1, &ubound);
6351 ERR("SafeArrayGetUBound failed with %x\n", hres);
6354 hres = SafeArrayAccessData(a, (LPVOID)&v);
6357 ERR("SafeArrayAccessData failed with %x\n", hres);
6360 for (j = 0; j <= ubound; j++)
6361 VariantClear(&v[j]);
6362 hres = SafeArrayUnaccessData(a);
6365 ERR("SafeArrayUnaccessData failed with %x\n", hres);
6369 VariantClear(&rgvarg[i]);
6372 else if (wParamFlags & PARAMFLAG_FOPT)
6374 if (wParamFlags & PARAMFLAG_FHASDEFAULT)
6375 VariantClear(&rgvarg[i]);
6378 VariantClear(&missing_arg[i]);
6381 if ((V_VT(&varresult) == VT_ERROR) && FAILED(V_ERROR(&varresult)))
6383 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult));
6384 hres = DISP_E_EXCEPTION;
6387 IErrorInfo *pErrorInfo;
6388 pExcepInfo->scode = V_ERROR(&varresult);
6389 if (GetErrorInfo(0, &pErrorInfo) == S_OK)
6391 IErrorInfo_GetDescription(pErrorInfo, &pExcepInfo->bstrDescription);
6392 IErrorInfo_GetHelpFile(pErrorInfo, &pExcepInfo->bstrHelpFile);
6393 IErrorInfo_GetSource(pErrorInfo, &pExcepInfo->bstrSource);
6394 IErrorInfo_GetHelpContext(pErrorInfo, &pExcepInfo->dwHelpContext);
6396 IErrorInfo_Release(pErrorInfo);
6400 if (V_VT(&varresult) != VT_ERROR)
6402 TRACE("varresult value: ");
6403 dump_Variant(&varresult);
6407 VariantClear(pVarResult);
6408 *pVarResult = varresult;
6411 VariantClear(&varresult);
6414 if (SUCCEEDED(hres) && pVarResult && (func_desc->cParams == 1) &&
6415 (func_desc->invkind & INVOKE_PROPERTYGET) &&
6416 (func_desc->lprgelemdescParam[0].u.paramdesc.wParamFlags & PARAMFLAG_FRETVAL) &&
6417 (pDispParams->cArgs != 0))
6419 if (V_VT(pVarResult) == VT_DISPATCH)
6421 IDispatch *pDispatch = V_DISPATCH(pVarResult);
6422 /* Note: not VariantClear; we still need the dispatch
6423 * pointer to be valid */
6424 VariantInit(pVarResult);
6425 hres = IDispatch_Invoke(pDispatch, DISPID_VALUE, &IID_NULL,
6426 GetSystemDefaultLCID(), INVOKE_PROPERTYGET,
6427 pDispParams, pVarResult, pExcepInfo, pArgErr);
6428 IDispatch_Release(pDispatch);
6432 VariantClear(pVarResult);
6433 hres = DISP_E_NOTACOLLECTION;
6438 HeapFree(GetProcessHeap(), 0, buffer);
6441 case FUNC_DISPATCH: {
6444 hres = IUnknown_QueryInterface((LPUNKNOWN)pIUnk,&IID_IDispatch,(LPVOID*)&disp);
6445 if (SUCCEEDED(hres)) {
6446 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6447 hres = IDispatch_Invoke(
6448 disp,memid,&IID_NULL,LOCALE_USER_DEFAULT,wFlags,pDispParams,
6449 pVarResult,pExcepInfo,pArgErr
6452 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres);
6453 IDispatch_Release(disp);
6455 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6459 FIXME("Unknown function invocation type %d\n", func_desc->funckind);
6464 TRACE("-- 0x%08x\n", hres);
6467 } else if(SUCCEEDED(hres = ITypeInfo2_GetVarIndexOfMemId(iface, memid, &var_index))) {
6470 hres = ITypeInfo2_GetVarDesc(iface, var_index, &var_desc);
6471 if(FAILED(hres)) return hres;
6473 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6474 dump_VARDESC(var_desc);
6475 ITypeInfo2_ReleaseVarDesc(iface, var_desc);
6479 /* not found, look for it in inherited interfaces */
6480 ITypeInfo2_GetTypeKind(iface, &type_kind);
6481 if(type_kind == TKIND_INTERFACE || type_kind == TKIND_DISPATCH) {
6482 if(This->impltypelist) {
6483 /* recursive search */
6485 hres = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pTInfo);
6486 if(SUCCEEDED(hres)){
6487 hres = ITypeInfo_Invoke(pTInfo,pIUnk,memid,wFlags,pDispParams,pVarResult,pExcepInfo,pArgErr);
6488 ITypeInfo_Release(pTInfo);
6491 WARN("Could not search inherited interface!\n");
6494 ERR("did not find member id %d, flags 0x%x!\n", memid, wFlags);
6495 return DISP_E_MEMBERNOTFOUND;
6498 /* ITypeInfo::GetDocumentation
6500 * Retrieves the documentation string, the complete Help file name and path,
6501 * and the context ID for the Help topic for a specified type description.
6503 * (Can be tested by the Visual Basic Editor in Word for instance.)
6505 static HRESULT WINAPI ITypeInfo_fnGetDocumentation( ITypeInfo2 *iface,
6506 MEMBERID memid, BSTR *pBstrName, BSTR *pBstrDocString,
6507 DWORD *pdwHelpContext, BSTR *pBstrHelpFile)
6509 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6510 const TLBFuncDesc *pFDesc;
6511 const TLBVarDesc *pVDesc;
6512 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6513 " HelpContext(%p) HelpFile(%p)\n",
6514 This, memid, pBstrName, pBstrDocString, pdwHelpContext, pBstrHelpFile);
6515 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
6517 *pBstrName=SysAllocString(This->Name);
6519 *pBstrDocString=SysAllocString(This->DocString);
6521 *pdwHelpContext=This->dwHelpContext;
6523 *pBstrHelpFile=SysAllocString(This->DocString);/* FIXME */
6525 }else {/* for a member */
6526 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6527 if(pFDesc->funcdesc.memid==memid){
6529 *pBstrName = SysAllocString(pFDesc->Name);
6531 *pBstrDocString=SysAllocString(pFDesc->HelpString);
6533 *pdwHelpContext=pFDesc->helpcontext;
6536 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
6537 if(pVDesc->vardesc.memid==memid){
6539 *pBstrName = SysAllocString(pVDesc->Name);
6541 *pBstrDocString=SysAllocString(pVDesc->HelpString);
6543 *pdwHelpContext=pVDesc->HelpContext;
6548 if(This->impltypelist &&
6549 (This->TypeAttr.typekind==TKIND_INTERFACE || This->TypeAttr.typekind==TKIND_DISPATCH)) {
6550 /* recursive search */
6553 result = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef,
6555 if(SUCCEEDED(result)) {
6556 result = ITypeInfo_GetDocumentation(pTInfo, memid, pBstrName,
6557 pBstrDocString, pdwHelpContext, pBstrHelpFile);
6558 ITypeInfo_Release(pTInfo);
6561 WARN("Could not search inherited interface!\n");
6564 WARN("member %d not found\n", memid);
6565 return TYPE_E_ELEMENTNOTFOUND;
6568 /* ITypeInfo::GetDllEntry
6570 * Retrieves a description or specification of an entry point for a function
6573 static HRESULT WINAPI ITypeInfo_fnGetDllEntry( ITypeInfo2 *iface, MEMBERID memid,
6574 INVOKEKIND invKind, BSTR *pBstrDllName, BSTR *pBstrName,
6577 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6578 const TLBFuncDesc *pFDesc;
6580 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This, memid, invKind, pBstrDllName, pBstrName, pwOrdinal);
6582 if (pBstrDllName) *pBstrDllName = NULL;
6583 if (pBstrName) *pBstrName = NULL;
6584 if (pwOrdinal) *pwOrdinal = 0;
6586 if (This->TypeAttr.typekind != TKIND_MODULE)
6587 return TYPE_E_BADMODULEKIND;
6589 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
6590 if(pFDesc->funcdesc.memid==memid){
6591 dump_TypeInfo(This);
6593 dump_TLBFuncDescOne(pFDesc);
6596 *pBstrDllName = SysAllocString(This->DllName);
6598 if (!IS_INTRESOURCE(pFDesc->Entry) && (pFDesc->Entry != (void*)-1)) {
6600 *pBstrName = SysAllocString(pFDesc->Entry);
6608 *pwOrdinal = LOWORD(pFDesc->Entry);
6611 return TYPE_E_ELEMENTNOTFOUND;
6614 /* internal function to make the inherited interfaces' methods appear
6615 * part of the interface */
6616 static HRESULT ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo *iface,
6617 HREFTYPE *hRefType, ITypeInfo **ppTInfo)
6619 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6622 TRACE("%p, 0x%x\n", iface, *hRefType);
6624 if (This->impltypelist && (*hRefType & DISPATCH_HREF_MASK))
6626 ITypeInfo *pSubTypeInfo;
6628 hr = ITypeInfo_GetRefTypeInfo(iface, This->impltypelist->hRef, &pSubTypeInfo);
6632 hr = ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo,
6634 ITypeInfo_Release(pSubTypeInfo);
6638 *hRefType -= DISPATCH_HREF_OFFSET;
6640 if (!(*hRefType & DISPATCH_HREF_MASK))
6641 return ITypeInfo_GetRefTypeInfo(iface, *hRefType, ppTInfo);
6646 /* ITypeInfo::GetRefTypeInfo
6648 * If a type description references other type descriptions, it retrieves
6649 * the referenced type descriptions.
6651 static HRESULT WINAPI ITypeInfo_fnGetRefTypeInfo(
6654 ITypeInfo **ppTInfo)
6656 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6657 HRESULT result = E_FAIL;
6659 if ((This->hreftype != -1) && (This->hreftype == hRefType))
6661 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
6662 ITypeInfo_AddRef(*ppTInfo);
6665 else if (hRefType == -1 &&
6666 (This->TypeAttr.typekind == TKIND_DISPATCH) &&
6667 (This->TypeAttr.wTypeFlags & TYPEFLAG_FDUAL))
6669 /* when we meet a DUAL dispinterface, we must create the interface
6672 ITypeInfoImpl* pTypeInfoImpl = (ITypeInfoImpl*) ITypeInfo_Constructor();
6675 /* the interface version contains the same information as the dispinterface
6676 * copy the contents of the structs.
6678 *pTypeInfoImpl = *This;
6679 pTypeInfoImpl->ref = 0;
6681 /* change the type to interface */
6682 pTypeInfoImpl->TypeAttr.typekind = TKIND_INTERFACE;
6684 *ppTInfo = (ITypeInfo*) pTypeInfoImpl;
6686 /* the AddRef implicitly adds a reference to the parent typelib, which
6687 * stops the copied data from being destroyed until the new typeinfo's
6688 * refcount goes to zero, but we need to signal to the new instance to
6689 * not free its data structures when it is destroyed */
6690 pTypeInfoImpl->not_attached_to_typelib = TRUE;
6692 ITypeInfo_AddRef(*ppTInfo);
6696 } else if ((hRefType != -1) && (hRefType & DISPATCH_HREF_MASK) &&
6697 (This->TypeAttr.typekind == TKIND_DISPATCH))
6699 HREFTYPE href_dispatch = hRefType;
6700 result = ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo *)iface, &href_dispatch, ppTInfo);
6702 TLBRefType *ref_type;
6703 LIST_FOR_EACH_ENTRY(ref_type, &This->pTypeLib->ref_list, TLBRefType, entry)
6705 if(ref_type->reference == hRefType)
6708 if(&ref_type->entry == &This->pTypeLib->ref_list)
6710 FIXME("Can't find pRefType for ref %x\n", hRefType);
6713 if(hRefType != -1) {
6714 ITypeLib *pTLib = NULL;
6716 if(ref_type->pImpTLInfo == TLB_REF_INTERNAL) {
6718 result = ITypeInfo_GetContainingTypeLib(iface, &pTLib, &Index);
6720 if(ref_type->pImpTLInfo->pImpTypeLib) {
6721 TRACE("typeinfo in imported typelib that is already loaded\n");
6722 pTLib = (ITypeLib*)ref_type->pImpTLInfo->pImpTypeLib;
6723 ITypeLib2_AddRef(pTLib);
6726 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6727 result = LoadRegTypeLib( &ref_type->pImpTLInfo->guid,
6728 ref_type->pImpTLInfo->wVersionMajor,
6729 ref_type->pImpTLInfo->wVersionMinor,
6730 ref_type->pImpTLInfo->lcid,
6733 if(FAILED(result)) {
6734 BSTR libnam=SysAllocString(ref_type->pImpTLInfo->name);
6735 result=LoadTypeLib(libnam, &pTLib);
6736 SysFreeString(libnam);
6738 if(SUCCEEDED(result)) {
6739 ref_type->pImpTLInfo->pImpTypeLib = (ITypeLibImpl*)pTLib;
6740 ITypeLib2_AddRef(pTLib);
6744 if(SUCCEEDED(result)) {
6745 if(ref_type->index == TLB_REF_USE_GUID)
6746 result = ITypeLib2_GetTypeInfoOfGuid(pTLib,
6750 result = ITypeLib2_GetTypeInfo(pTLib, ref_type->index,
6754 ITypeLib2_Release(pTLib);
6759 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This, hRefType,
6760 SUCCEEDED(result)? "SUCCESS":"FAILURE", *ppTInfo);
6764 /* ITypeInfo::AddressOfMember
6766 * Retrieves the addresses of static functions or variables, such as those
6769 static HRESULT WINAPI ITypeInfo_fnAddressOfMember( ITypeInfo2 *iface,
6770 MEMBERID memid, INVOKEKIND invKind, PVOID *ppv)
6772 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6778 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This, memid, invKind, ppv);
6780 hr = ITypeInfo_GetDllEntry(iface, memid, invKind, &dll, &entry, &ordinal);
6784 module = LoadLibraryW(dll);
6787 ERR("couldn't load %s\n", debugstr_w(dll));
6789 SysFreeString(entry);
6790 return STG_E_FILENOTFOUND;
6792 /* FIXME: store library somewhere where we can free it */
6797 INT len = WideCharToMultiByte(CP_ACP, 0, entry, -1, NULL, 0, NULL, NULL);
6798 entryA = HeapAlloc(GetProcessHeap(), 0, len);
6799 WideCharToMultiByte(CP_ACP, 0, entry, -1, entryA, len, NULL, NULL);
6801 *ppv = GetProcAddress(module, entryA);
6803 ERR("function not found %s\n", debugstr_a(entryA));
6805 HeapFree(GetProcessHeap(), 0, entryA);
6809 *ppv = GetProcAddress(module, MAKEINTRESOURCEA(ordinal));
6811 ERR("function not found %d\n", ordinal);
6815 SysFreeString(entry);
6818 return TYPE_E_DLLFUNCTIONNOTFOUND;
6823 /* ITypeInfo::CreateInstance
6825 * Creates a new instance of a type that describes a component object class
6828 static HRESULT WINAPI ITypeInfo_fnCreateInstance( ITypeInfo2 *iface,
6829 IUnknown *pOuterUnk, REFIID riid, VOID **ppvObj)
6831 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6835 TRACE("(%p)->(%p, %s, %p)\n", This, pOuterUnk, debugstr_guid(riid), ppvObj);
6841 WARN("Not able to aggregate\n");
6842 return CLASS_E_NOAGGREGATION;
6845 hr = ITypeInfo_GetTypeAttr(iface, &pTA);
6846 if(FAILED(hr)) return hr;
6848 if(pTA->typekind != TKIND_COCLASS)
6850 WARN("CreateInstance on typeinfo of type %x\n", pTA->typekind);
6856 if(pTA->wTypeFlags & TYPEFLAG_FAPPOBJECT)
6859 hr = GetActiveObject(&pTA->guid, NULL, &pUnk);
6860 TRACE("GetActiveObject rets %08x\n", hr);
6863 hr = IUnknown_QueryInterface(pUnk, riid, ppvObj);
6864 IUnknown_Release(pUnk);
6869 hr = CoCreateInstance(&pTA->guid, NULL,
6870 CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
6874 ITypeInfo_ReleaseTypeAttr(iface, pTA);
6878 /* ITypeInfo::GetMops
6880 * Retrieves marshalling information.
6882 static HRESULT WINAPI ITypeInfo_fnGetMops( ITypeInfo2 *iface, MEMBERID memid,
6885 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6886 FIXME("(%p %d) stub!\n", This, memid);
6891 /* ITypeInfo::GetContainingTypeLib
6893 * Retrieves the containing type library and the index of the type description
6894 * within that type library.
6896 static HRESULT WINAPI ITypeInfo_fnGetContainingTypeLib( ITypeInfo2 *iface,
6897 ITypeLib * *ppTLib, UINT *pIndex)
6899 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6901 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
6903 *pIndex=This->index;
6904 TRACE("returning pIndex=%d\n", *pIndex);
6908 *ppTLib=(LPTYPELIB )(This->pTypeLib);
6909 ITypeLib2_AddRef(*ppTLib);
6910 TRACE("returning ppTLib=%p\n", *ppTLib);
6916 /* ITypeInfo::ReleaseTypeAttr
6918 * Releases a TYPEATTR previously returned by GetTypeAttr.
6921 static void WINAPI ITypeInfo_fnReleaseTypeAttr( ITypeInfo2 *iface,
6922 TYPEATTR* pTypeAttr)
6924 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6925 TRACE("(%p)->(%p)\n", This, pTypeAttr);
6926 HeapFree(GetProcessHeap(), 0, pTypeAttr);
6929 /* ITypeInfo::ReleaseFuncDesc
6931 * Releases a FUNCDESC previously returned by GetFuncDesc. *
6933 static void WINAPI ITypeInfo_fnReleaseFuncDesc(
6935 FUNCDESC *pFuncDesc)
6937 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6940 TRACE("(%p)->(%p)\n", This, pFuncDesc);
6942 for (i = 0; i < pFuncDesc->cParams; i++)
6943 TLB_FreeElemDesc(&pFuncDesc->lprgelemdescParam[i]);
6944 TLB_FreeElemDesc(&pFuncDesc->elemdescFunc);
6946 SysFreeString((BSTR)pFuncDesc);
6949 /* ITypeInfo::ReleaseVarDesc
6951 * Releases a VARDESC previously returned by GetVarDesc.
6953 static void WINAPI ITypeInfo_fnReleaseVarDesc( ITypeInfo2 *iface,
6956 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6957 TRACE("(%p)->(%p)\n", This, pVarDesc);
6959 TLB_FreeElemDesc(&pVarDesc->elemdescVar);
6960 if (pVarDesc->varkind == VAR_CONST)
6961 VariantClear(pVarDesc->u.lpvarValue);
6962 SysFreeString((BSTR)pVarDesc);
6965 /* ITypeInfo2::GetTypeKind
6967 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
6970 static HRESULT WINAPI ITypeInfo2_fnGetTypeKind( ITypeInfo2 * iface,
6971 TYPEKIND *pTypeKind)
6973 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6974 *pTypeKind=This->TypeAttr.typekind;
6975 TRACE("(%p) type 0x%0x\n", This,*pTypeKind);
6979 /* ITypeInfo2::GetTypeFlags
6981 * Returns the type flags without any allocations. This returns a DWORD type
6982 * flag, which expands the type flags without growing the TYPEATTR (type
6986 static HRESULT WINAPI ITypeInfo2_fnGetTypeFlags( ITypeInfo2 *iface, ULONG *pTypeFlags)
6988 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
6989 *pTypeFlags=This->TypeAttr.wTypeFlags;
6990 TRACE("(%p) flags 0x%x\n", This,*pTypeFlags);
6994 /* ITypeInfo2::GetFuncIndexOfMemId
6995 * Binds to a specific member based on a known DISPID, where the member name
6996 * is not known (for example, when binding to a default member).
6999 static HRESULT WINAPI ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2 * iface,
7000 MEMBERID memid, INVOKEKIND invKind, UINT *pFuncIndex)
7002 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7003 const TLBFuncDesc *pFuncInfo;
7007 for(i = 0, pFuncInfo = This->funclist; pFuncInfo; i++, pFuncInfo=pFuncInfo->next)
7008 if(memid == pFuncInfo->funcdesc.memid && (invKind & pFuncInfo->funcdesc.invkind))
7014 result = TYPE_E_ELEMENTNOTFOUND;
7016 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This,
7017 memid, invKind, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7021 /* TypeInfo2::GetVarIndexOfMemId
7023 * Binds to a specific member based on a known DISPID, where the member name
7024 * is not known (for example, when binding to a default member).
7027 static HRESULT WINAPI ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2 * iface,
7028 MEMBERID memid, UINT *pVarIndex)
7030 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7031 TLBVarDesc *pVarInfo;
7034 for(i=0, pVarInfo=This->varlist; pVarInfo &&
7035 memid != pVarInfo->vardesc.memid; i++, pVarInfo=pVarInfo->next)
7041 result = TYPE_E_ELEMENTNOTFOUND;
7043 TRACE("(%p) memid 0x%08x -> %s\n", This,
7044 memid, SUCCEEDED(result) ? "SUCCESS" : "FAILED");
7048 /* ITypeInfo2::GetCustData
7050 * Gets the custom data
7052 static HRESULT WINAPI ITypeInfo2_fnGetCustData(
7057 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7058 TLBCustData *pCData;
7060 for(pCData=This->pCustData; pCData; pCData = pCData->next)
7061 if( IsEqualIID(guid, &pCData->guid)) break;
7063 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7065 VariantInit( pVarVal);
7067 VariantCopy( pVarVal, &pCData->data);
7069 VariantClear( pVarVal );
7073 /* ITypeInfo2::GetFuncCustData
7075 * Gets the custom data
7077 static HRESULT WINAPI ITypeInfo2_fnGetFuncCustData(
7083 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7084 TLBCustData *pCData=NULL;
7085 TLBFuncDesc * pFDesc;
7087 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7088 pFDesc=pFDesc->next);
7091 for(pCData=pFDesc->pCustData; pCData; pCData = pCData->next)
7092 if( IsEqualIID(guid, &pCData->guid)) break;
7094 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7097 VariantInit( pVarVal);
7098 VariantCopy( pVarVal, &pCData->data);
7101 return E_INVALIDARG; /* FIXME: correct? */
7104 /* ITypeInfo2::GetParamCustData
7106 * Gets the custom data
7108 static HRESULT WINAPI ITypeInfo2_fnGetParamCustData(
7115 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7116 TLBCustData *pCData=NULL;
7117 TLBFuncDesc * pFDesc;
7120 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,pFDesc=pFDesc->next);
7122 if(pFDesc && indexParam<pFDesc->funcdesc.cParams)
7123 for(pCData=pFDesc->pParamDesc[indexParam].pCustData; pCData;
7124 pCData = pCData->next)
7125 if( IsEqualIID(guid, &pCData->guid)) break;
7127 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7131 VariantInit( pVarVal);
7132 VariantCopy( pVarVal, &pCData->data);
7135 return E_INVALIDARG; /* FIXME: correct? */
7138 /* ITypeInfo2::GetVarCustData
7140 * Gets the custom data
7142 static HRESULT WINAPI ITypeInfo2_fnGetVarCustData(
7148 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7149 TLBCustData *pCData=NULL;
7150 TLBVarDesc * pVDesc;
7153 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++, pVDesc=pVDesc->next);
7157 for(pCData=pVDesc->pCustData; pCData; pCData = pCData->next)
7159 if( IsEqualIID(guid, &pCData->guid)) break;
7163 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7167 VariantInit( pVarVal);
7168 VariantCopy( pVarVal, &pCData->data);
7171 return E_INVALIDARG; /* FIXME: correct? */
7174 /* ITypeInfo2::GetImplCustData
7176 * Gets the custom data
7178 static HRESULT WINAPI ITypeInfo2_fnGetImplTypeCustData(
7184 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7185 TLBCustData *pCData=NULL;
7186 TLBImplType * pRDesc;
7189 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++, pRDesc=pRDesc->next);
7193 for(pCData=pRDesc->pCustData; pCData; pCData = pCData->next)
7195 if( IsEqualIID(guid, &pCData->guid)) break;
7199 TRACE("(%p) guid %s %s found!x)\n", This, debugstr_guid(guid), pCData? "" : "NOT");
7203 VariantInit( pVarVal);
7204 VariantCopy( pVarVal, &pCData->data);
7207 return E_INVALIDARG; /* FIXME: correct? */
7210 /* ITypeInfo2::GetDocumentation2
7212 * Retrieves the documentation string, the complete Help file name and path,
7213 * the localization context to use, and the context ID for the library Help
7214 * topic in the Help file.
7217 static HRESULT WINAPI ITypeInfo2_fnGetDocumentation2(
7221 BSTR *pbstrHelpString,
7222 DWORD *pdwHelpStringContext,
7223 BSTR *pbstrHelpStringDll)
7225 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7226 const TLBFuncDesc *pFDesc;
7227 const TLBVarDesc *pVDesc;
7228 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7229 "HelpStringContext(%p) HelpStringDll(%p)\n",
7230 This, memid, lcid, pbstrHelpString, pdwHelpStringContext,
7231 pbstrHelpStringDll );
7232 /* the help string should be obtained from the helpstringdll,
7233 * using the _DLLGetDocumentation function, based on the supplied
7234 * lcid. Nice to do sometime...
7236 if(memid==MEMBERID_NIL){ /* documentation for the typeinfo */
7238 *pbstrHelpString=SysAllocString(This->Name);
7239 if(pdwHelpStringContext)
7240 *pdwHelpStringContext=This->dwHelpStringContext;
7241 if(pbstrHelpStringDll)
7242 *pbstrHelpStringDll=
7243 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7245 }else {/* for a member */
7246 for(pFDesc=This->funclist; pFDesc; pFDesc=pFDesc->next)
7247 if(pFDesc->funcdesc.memid==memid){
7249 *pbstrHelpString=SysAllocString(pFDesc->HelpString);
7250 if(pdwHelpStringContext)
7251 *pdwHelpStringContext=pFDesc->HelpStringContext;
7252 if(pbstrHelpStringDll)
7253 *pbstrHelpStringDll=
7254 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7257 for(pVDesc=This->varlist; pVDesc; pVDesc=pVDesc->next)
7258 if(pVDesc->vardesc.memid==memid){
7260 *pbstrHelpString=SysAllocString(pVDesc->HelpString);
7261 if(pdwHelpStringContext)
7262 *pdwHelpStringContext=pVDesc->HelpStringContext;
7263 if(pbstrHelpStringDll)
7264 *pbstrHelpStringDll=
7265 SysAllocString(This->pTypeLib->HelpStringDll);/* FIXME */
7269 return TYPE_E_ELEMENTNOTFOUND;
7272 /* ITypeInfo2::GetAllCustData
7274 * Gets all custom data items for the Type info.
7277 static HRESULT WINAPI ITypeInfo2_fnGetAllCustData(
7279 CUSTDATA *pCustData)
7281 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7282 TLBCustData *pCData;
7285 TRACE("(%p) returning %d items\n", This, This->ctCustData);
7287 pCustData->prgCustData = TLB_Alloc(This->ctCustData * sizeof(CUSTDATAITEM));
7288 if(pCustData->prgCustData ){
7289 pCustData->cCustData=This->ctCustData;
7290 for(i=0, pCData=This->pCustData; pCData; i++, pCData = pCData->next){
7291 pCustData->prgCustData[i].guid=pCData->guid;
7292 VariantCopy(& pCustData->prgCustData[i].varValue, & pCData->data);
7295 ERR(" OUT OF MEMORY!\n");
7296 return E_OUTOFMEMORY;
7301 /* ITypeInfo2::GetAllFuncCustData
7303 * Gets all custom data items for the specified Function
7306 static HRESULT WINAPI ITypeInfo2_fnGetAllFuncCustData(
7309 CUSTDATA *pCustData)
7311 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7312 TLBCustData *pCData;
7313 TLBFuncDesc * pFDesc;
7315 TRACE("(%p) index %d\n", This, index);
7316 for(i=0, pFDesc=This->funclist; i!=index && pFDesc; i++,
7317 pFDesc=pFDesc->next)
7320 pCustData->prgCustData =
7321 TLB_Alloc(pFDesc->ctCustData * sizeof(CUSTDATAITEM));
7322 if(pCustData->prgCustData ){
7323 pCustData->cCustData=pFDesc->ctCustData;
7324 for(i=0, pCData=pFDesc->pCustData; pCData; i++,
7325 pCData = pCData->next){
7326 pCustData->prgCustData[i].guid=pCData->guid;
7327 VariantCopy(& pCustData->prgCustData[i].varValue,
7331 ERR(" OUT OF MEMORY!\n");
7332 return E_OUTOFMEMORY;
7336 return TYPE_E_ELEMENTNOTFOUND;
7339 /* ITypeInfo2::GetAllParamCustData
7341 * Gets all custom data items for the Functions
7344 static HRESULT WINAPI ITypeInfo2_fnGetAllParamCustData( ITypeInfo2 * iface,
7345 UINT indexFunc, UINT indexParam, CUSTDATA *pCustData)
7347 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7348 TLBCustData *pCData=NULL;
7349 TLBFuncDesc * pFDesc;
7351 TRACE("(%p) index %d\n", This, indexFunc);
7352 for(i=0, pFDesc=This->funclist; i!=indexFunc && pFDesc; i++,
7353 pFDesc=pFDesc->next)
7355 if(pFDesc && indexParam<pFDesc->funcdesc.cParams){
7356 pCustData->prgCustData =
7357 TLB_Alloc(pFDesc->pParamDesc[indexParam].ctCustData *
7358 sizeof(CUSTDATAITEM));
7359 if(pCustData->prgCustData ){
7360 pCustData->cCustData=pFDesc->pParamDesc[indexParam].ctCustData;
7361 for(i=0, pCData=pFDesc->pParamDesc[indexParam].pCustData;
7362 pCData; i++, pCData = pCData->next){
7363 pCustData->prgCustData[i].guid=pCData->guid;
7364 VariantCopy(& pCustData->prgCustData[i].varValue,
7368 ERR(" OUT OF MEMORY!\n");
7369 return E_OUTOFMEMORY;
7373 return TYPE_E_ELEMENTNOTFOUND;
7376 /* ITypeInfo2::GetAllVarCustData
7378 * Gets all custom data items for the specified Variable
7381 static HRESULT WINAPI ITypeInfo2_fnGetAllVarCustData( ITypeInfo2 * iface,
7382 UINT index, CUSTDATA *pCustData)
7384 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7385 TLBCustData *pCData;
7386 TLBVarDesc * pVDesc;
7388 TRACE("(%p) index %d\n", This, index);
7389 for(i=0, pVDesc=This->varlist; i!=index && pVDesc; i++,
7390 pVDesc=pVDesc->next)
7393 pCustData->prgCustData =
7394 TLB_Alloc(pVDesc->ctCustData * sizeof(CUSTDATAITEM));
7395 if(pCustData->prgCustData ){
7396 pCustData->cCustData=pVDesc->ctCustData;
7397 for(i=0, pCData=pVDesc->pCustData; pCData; i++,
7398 pCData = pCData->next){
7399 pCustData->prgCustData[i].guid=pCData->guid;
7400 VariantCopy(& pCustData->prgCustData[i].varValue,
7404 ERR(" OUT OF MEMORY!\n");
7405 return E_OUTOFMEMORY;
7409 return TYPE_E_ELEMENTNOTFOUND;
7412 /* ITypeInfo2::GetAllImplCustData
7414 * Gets all custom data items for the specified implementation type
7417 static HRESULT WINAPI ITypeInfo2_fnGetAllImplTypeCustData(
7420 CUSTDATA *pCustData)
7422 ITypeInfoImpl *This = (ITypeInfoImpl *)iface;
7423 TLBCustData *pCData;
7424 TLBImplType * pRDesc;
7426 TRACE("(%p) index %d\n", This, index);
7427 for(i=0, pRDesc=This->impltypelist; i!=index && pRDesc; i++,
7428 pRDesc=pRDesc->next)
7431 pCustData->prgCustData =
7432 TLB_Alloc(pRDesc->ctCustData * sizeof(CUSTDATAITEM));
7433 if(pCustData->prgCustData ){
7434 pCustData->cCustData=pRDesc->ctCustData;
7435 for(i=0, pCData=pRDesc->pCustData; pCData; i++,
7436 pCData = pCData->next){
7437 pCustData->prgCustData[i].guid=pCData->guid;
7438 VariantCopy(& pCustData->prgCustData[i].varValue,
7442 ERR(" OUT OF MEMORY!\n");
7443 return E_OUTOFMEMORY;
7447 return TYPE_E_ELEMENTNOTFOUND;
7450 static const ITypeInfo2Vtbl tinfvt =
7453 ITypeInfo_fnQueryInterface,
7455 ITypeInfo_fnRelease,
7457 ITypeInfo_fnGetTypeAttr,
7458 ITypeInfo_fnGetTypeComp,
7459 ITypeInfo_fnGetFuncDesc,
7460 ITypeInfo_fnGetVarDesc,
7461 ITypeInfo_fnGetNames,
7462 ITypeInfo_fnGetRefTypeOfImplType,
7463 ITypeInfo_fnGetImplTypeFlags,
7464 ITypeInfo_fnGetIDsOfNames,
7466 ITypeInfo_fnGetDocumentation,
7467 ITypeInfo_fnGetDllEntry,
7468 ITypeInfo_fnGetRefTypeInfo,
7469 ITypeInfo_fnAddressOfMember,
7470 ITypeInfo_fnCreateInstance,
7471 ITypeInfo_fnGetMops,
7472 ITypeInfo_fnGetContainingTypeLib,
7473 ITypeInfo_fnReleaseTypeAttr,
7474 ITypeInfo_fnReleaseFuncDesc,
7475 ITypeInfo_fnReleaseVarDesc,
7477 ITypeInfo2_fnGetTypeKind,
7478 ITypeInfo2_fnGetTypeFlags,
7479 ITypeInfo2_fnGetFuncIndexOfMemId,
7480 ITypeInfo2_fnGetVarIndexOfMemId,
7481 ITypeInfo2_fnGetCustData,
7482 ITypeInfo2_fnGetFuncCustData,
7483 ITypeInfo2_fnGetParamCustData,
7484 ITypeInfo2_fnGetVarCustData,
7485 ITypeInfo2_fnGetImplTypeCustData,
7486 ITypeInfo2_fnGetDocumentation2,
7487 ITypeInfo2_fnGetAllCustData,
7488 ITypeInfo2_fnGetAllFuncCustData,
7489 ITypeInfo2_fnGetAllParamCustData,
7490 ITypeInfo2_fnGetAllVarCustData,
7491 ITypeInfo2_fnGetAllImplTypeCustData,
7494 /******************************************************************************
7495 * CreateDispTypeInfo [OLEAUT32.31]
7497 * Build type information for an object so it can be called through an
7498 * IDispatch interface.
7501 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7502 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7505 * This call allows an objects methods to be accessed through IDispatch, by
7506 * building an ITypeInfo object that IDispatch can use to call through.
7508 HRESULT WINAPI CreateDispTypeInfo(
7509 INTERFACEDATA *pidata, /* [I] Description of the interface to build type info for */
7510 LCID lcid, /* [I] Locale Id */
7511 ITypeInfo **pptinfo) /* [O] Destination for created ITypeInfo object */
7513 ITypeInfoImpl *pTIClass, *pTIIface;
7514 ITypeLibImpl *pTypeLibImpl;
7515 unsigned int param, func;
7516 TLBFuncDesc **ppFuncDesc;
7520 pTypeLibImpl = TypeLibImpl_Constructor();
7521 if (!pTypeLibImpl) return E_FAIL;
7523 pTIIface = (ITypeInfoImpl*)ITypeInfo_Constructor();
7524 pTIIface->pTypeLib = pTypeLibImpl;
7525 pTIIface->index = 0;
7526 pTIIface->Name = NULL;
7527 pTIIface->dwHelpContext = -1;
7528 memset(&pTIIface->TypeAttr.guid, 0, sizeof(GUID));
7529 pTIIface->TypeAttr.lcid = lcid;
7530 pTIIface->TypeAttr.typekind = TKIND_INTERFACE;
7531 pTIIface->TypeAttr.wMajorVerNum = 0;
7532 pTIIface->TypeAttr.wMinorVerNum = 0;
7533 pTIIface->TypeAttr.cbAlignment = 2;
7534 pTIIface->TypeAttr.cbSizeInstance = -1;
7535 pTIIface->TypeAttr.cbSizeVft = -1;
7536 pTIIface->TypeAttr.cFuncs = 0;
7537 pTIIface->TypeAttr.cImplTypes = 0;
7538 pTIIface->TypeAttr.cVars = 0;
7539 pTIIface->TypeAttr.wTypeFlags = 0;
7541 ppFuncDesc = &pTIIface->funclist;
7542 for(func = 0; func < pidata->cMembers; func++) {
7543 METHODDATA *md = pidata->pmethdata + func;
7544 *ppFuncDesc = HeapAlloc(GetProcessHeap(), 0, sizeof(**ppFuncDesc));
7545 (*ppFuncDesc)->Name = SysAllocString(md->szName);
7546 (*ppFuncDesc)->funcdesc.memid = md->dispid;
7547 (*ppFuncDesc)->funcdesc.lprgscode = NULL;
7548 (*ppFuncDesc)->funcdesc.funckind = FUNC_VIRTUAL;
7549 (*ppFuncDesc)->funcdesc.invkind = md->wFlags;
7550 (*ppFuncDesc)->funcdesc.callconv = md->cc;
7551 (*ppFuncDesc)->funcdesc.cParams = md->cArgs;
7552 (*ppFuncDesc)->funcdesc.cParamsOpt = 0;
7553 (*ppFuncDesc)->funcdesc.oVft = md->iMeth * sizeof(void *);
7554 (*ppFuncDesc)->funcdesc.cScodes = 0;
7555 (*ppFuncDesc)->funcdesc.wFuncFlags = 0;
7556 (*ppFuncDesc)->funcdesc.elemdescFunc.tdesc.vt = md->vtReturn;
7557 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.wParamFlags = PARAMFLAG_NONE;
7558 (*ppFuncDesc)->funcdesc.elemdescFunc.u.paramdesc.pparamdescex = NULL;
7559 (*ppFuncDesc)->funcdesc.lprgelemdescParam = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7560 md->cArgs * sizeof(ELEMDESC));
7561 (*ppFuncDesc)->pParamDesc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
7562 md->cArgs * sizeof(TLBParDesc));
7563 for(param = 0; param < md->cArgs; param++) {
7564 (*ppFuncDesc)->funcdesc.lprgelemdescParam[param].tdesc.vt = md->ppdata[param].vt;
7565 (*ppFuncDesc)->pParamDesc[param].Name = SysAllocString(md->ppdata[param].szName);
7567 (*ppFuncDesc)->helpcontext = 0;
7568 (*ppFuncDesc)->HelpStringContext = 0;
7569 (*ppFuncDesc)->HelpString = NULL;
7570 (*ppFuncDesc)->Entry = NULL;
7571 (*ppFuncDesc)->ctCustData = 0;
7572 (*ppFuncDesc)->pCustData = NULL;
7573 (*ppFuncDesc)->next = NULL;
7574 pTIIface->TypeAttr.cFuncs++;
7575 ppFuncDesc = &(*ppFuncDesc)->next;
7578 dump_TypeInfo(pTIIface);
7580 pTypeLibImpl->pTypeInfo = pTIIface;
7581 pTypeLibImpl->TypeInfoCount++;
7583 pTIClass = (ITypeInfoImpl*)ITypeInfo_Constructor();
7584 pTIClass->pTypeLib = pTypeLibImpl;
7585 pTIClass->index = 1;
7586 pTIClass->Name = NULL;
7587 pTIClass->dwHelpContext = -1;
7588 memset(&pTIClass->TypeAttr.guid, 0, sizeof(GUID));
7589 pTIClass->TypeAttr.lcid = lcid;
7590 pTIClass->TypeAttr.typekind = TKIND_COCLASS;
7591 pTIClass->TypeAttr.wMajorVerNum = 0;
7592 pTIClass->TypeAttr.wMinorVerNum = 0;
7593 pTIClass->TypeAttr.cbAlignment = 2;
7594 pTIClass->TypeAttr.cbSizeInstance = -1;
7595 pTIClass->TypeAttr.cbSizeVft = -1;
7596 pTIClass->TypeAttr.cFuncs = 0;
7597 pTIClass->TypeAttr.cImplTypes = 1;
7598 pTIClass->TypeAttr.cVars = 0;
7599 pTIClass->TypeAttr.wTypeFlags = 0;
7601 pTIClass->impltypelist = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pTIClass->impltypelist));
7602 pTIClass->impltypelist->hRef = 0;
7604 ref = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*ref));
7607 ref->pImpTLInfo = TLB_REF_INTERNAL;
7608 list_add_head(&pTypeLibImpl->ref_list, &ref->entry);
7610 dump_TypeInfo(pTIClass);
7612 pTIIface->next = pTIClass;
7613 pTypeLibImpl->TypeInfoCount++;
7615 *pptinfo = (ITypeInfo*)pTIClass;
7617 ITypeInfo_AddRef(*pptinfo);
7618 ITypeLib_Release((ITypeLib *)&pTypeLibImpl->lpVtbl);
7624 static HRESULT WINAPI ITypeComp_fnQueryInterface(ITypeComp * iface, REFIID riid, LPVOID * ppv)
7626 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7628 return ITypeInfo_QueryInterface((ITypeInfo *)This, riid, ppv);
7631 static ULONG WINAPI ITypeComp_fnAddRef(ITypeComp * iface)
7633 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7635 return ITypeInfo_AddRef((ITypeInfo *)This);
7638 static ULONG WINAPI ITypeComp_fnRelease(ITypeComp * iface)
7640 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7642 return ITypeInfo_Release((ITypeInfo *)This);
7645 static HRESULT WINAPI ITypeComp_fnBind(
7650 ITypeInfo ** ppTInfo,
7651 DESCKIND * pDescKind,
7654 ITypeInfoImpl *This = info_impl_from_ITypeComp(iface);
7655 const TLBFuncDesc *pFDesc;
7656 const TLBVarDesc *pVDesc;
7657 HRESULT hr = DISP_E_MEMBERNOTFOUND;
7659 TRACE("(%s, %x, 0x%x, %p, %p, %p)\n", debugstr_w(szName), lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7661 *pDescKind = DESCKIND_NONE;
7662 pBindPtr->lpfuncdesc = NULL;
7665 for(pFDesc = This->funclist; pFDesc; pFDesc = pFDesc->next)
7666 if (!strcmpiW(pFDesc->Name, szName)) {
7667 if (!wFlags || (pFDesc->funcdesc.invkind & wFlags))
7670 /* name found, but wrong flags */
7671 hr = TYPE_E_TYPEMISMATCH;
7676 HRESULT hr = TLB_AllocAndInitFuncDesc(
7678 &pBindPtr->lpfuncdesc,
7679 This->TypeAttr.typekind == TKIND_DISPATCH);
7682 *pDescKind = DESCKIND_FUNCDESC;
7683 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7684 ITypeInfo_AddRef(*ppTInfo);
7687 for(pVDesc = This->varlist; pVDesc; pVDesc = pVDesc->next) {
7688 if (!strcmpiW(pVDesc->Name, szName)) {
7689 HRESULT hr = TLB_AllocAndInitVarDesc(&pVDesc->vardesc, &pBindPtr->lpvardesc);
7692 *pDescKind = DESCKIND_VARDESC;
7693 *ppTInfo = (ITypeInfo *)&This->lpVtbl;
7694 ITypeInfo_AddRef(*ppTInfo);
7699 /* FIXME: search each inherited interface, not just the first */
7700 if (hr == DISP_E_MEMBERNOTFOUND && This->impltypelist) {
7701 /* recursive search */
7705 hr=ITypeInfo_GetRefTypeInfo((ITypeInfo *)&This->lpVtbl, This->impltypelist->hRef, &pTInfo);
7708 hr = ITypeInfo_GetTypeComp(pTInfo,&pTComp);
7709 ITypeInfo_Release(pTInfo);
7713 hr = ITypeComp_Bind(pTComp, szName, lHash, wFlags, ppTInfo, pDescKind, pBindPtr);
7714 ITypeComp_Release(pTComp);
7717 WARN("Could not search inherited interface!\n");
7719 WARN("did not find member with name %s, flags 0x%x!\n", debugstr_w(szName), wFlags);
7723 static HRESULT WINAPI ITypeComp_fnBindType(
7727 ITypeInfo ** ppTInfo,
7728 ITypeComp ** ppTComp)
7730 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName), lHash, ppTInfo, ppTComp);
7732 /* strange behaviour (does nothing) but like the
7735 if (!ppTInfo || !ppTComp)
7744 static const ITypeCompVtbl tcompvt =
7747 ITypeComp_fnQueryInterface,
7749 ITypeComp_fnRelease,
7752 ITypeComp_fnBindType