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
)
371 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
);
375 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
);
378 /******************************************************************************
379 * CreateTypeLib [OLEAUT32.160] creates a typelib
385 HRESULT WINAPI
CreateTypeLib(
386 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
388 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
392 /******************************************************************************
393 * LoadTypeLib [OLEAUT32.161]
395 * Loads a type library
398 * szFile [I] Name of file to load from.
399 * pptLib [O] Pointer that receives ITypeLib object on success.
406 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
408 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
410 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
411 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
414 /******************************************************************************
415 * LoadTypeLibEx [OLEAUT32.183]
417 * Loads and optionally registers a type library
423 HRESULT WINAPI
LoadTypeLibEx(
424 LPCOLESTR szFile
, /* [in] Name of file to load from */
425 REGKIND regkind
, /* [in] Specify kind of registration */
426 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
428 WCHAR szPath
[MAX_PATH
+1];
431 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
435 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
440 case REGKIND_DEFAULT
:
441 /* don't register typelibs supplied with full path. Experimentation confirms the following */
442 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
443 (szFile
[0] && (szFile
[1] == ':'))) break;
444 /* else fall-through */
446 case REGKIND_REGISTER
:
447 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
449 ITypeLib_Release(*pptLib
);
457 TRACE(" returns %08x\n",res
);
461 /******************************************************************************
462 * LoadRegTypeLib [OLEAUT32.162]
464 * Loads a registered type library.
467 * rguid [I] GUID of the registered type library.
468 * wVerMajor [I] major version.
469 * wVerMinor [I] minor version.
470 * lcid [I] locale ID.
471 * ppTLib [O] pointer that receives an ITypeLib object on success.
475 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
478 HRESULT WINAPI
LoadRegTypeLib(
490 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
494 res
= LoadTypeLib(bstr
, ppTLib
);
498 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
504 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
505 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
506 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
507 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
508 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
509 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
511 /******************************************************************************
512 * RegisterTypeLib [OLEAUT32.163]
513 * Adds information about a type library to the System Registry
515 * Docs: ITypeLib FAR * ptlib
516 * Docs: OLECHAR FAR* szFullPath
517 * Docs: OLECHAR FAR* szHelpDir
523 HRESULT WINAPI
RegisterTypeLib(
524 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
525 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
526 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
529 static const WCHAR PSOA
[] = {'{','0','0','0','2','0','4','2','4','-',
530 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
531 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
541 if (ptlib
== NULL
|| szFullPath
== NULL
)
544 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
548 if (attr
->syskind
!= SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
550 if (attr
->syskind
!= SYS_WIN32
&& attr
->syskind
!= SYS_WIN16
) return TYPE_E_BADMODULEKIND
;
553 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
556 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
557 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
561 /* Set the human-readable name of the typelib */
562 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
566 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
567 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
573 /* Make up the name of the typelib path subkey */
574 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
576 /* Create the typelib path subkey */
577 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
578 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
580 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
581 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
589 /* Create the flags subkey */
590 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
591 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
593 /* FIXME: is %u correct? */
594 static const WCHAR formatW
[] = {'%','u',0};
596 sprintfW(buf
, formatW
, attr
->wLibFlags
);
597 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
598 (BYTE
*)buf
, (strlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
606 /* create the helpdir subkey */
607 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
608 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
610 BOOL freeHelpDir
= FALSE
;
613 /* if we created a new key, and helpDir was null, set the helpdir
614 to the directory which contains the typelib. However,
615 if we just opened an existing key, we leave the helpdir alone */
616 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
617 szHelpDir
= SysAllocString(szFullPath
);
618 pIndexStr
= strrchrW(szHelpDir
, '\\');
625 /* if we have an szHelpDir, set it! */
626 if (szHelpDir
!= NULL
) {
627 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
628 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
634 if (freeHelpDir
) SysFreeString(szHelpDir
);
646 /* register OLE Automation-compatible interfaces for this typelib */
647 types
= ITypeLib_GetTypeInfoCount(ptlib
);
648 for (tidx
=0; tidx
<types
; tidx
++) {
649 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
650 LPOLESTR name
= NULL
;
651 ITypeInfo
*tinfo
= NULL
;
653 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
656 case TKIND_INTERFACE
:
657 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
658 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
662 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
663 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
667 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
672 TYPEATTR
*tattr
= NULL
;
673 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
676 TRACE_(typelib
)("guid=%s, flags=%04x (",
677 debugstr_guid(&tattr
->guid
),
680 if (TRACE_ON(typelib
)) {
681 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
701 /* Register all dispinterfaces (which includes dual interfaces) and
702 oleautomation interfaces */
703 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
704 kind
== TKIND_DISPATCH
)
706 /* register interface<->typelib coupling */
707 get_interface_key( &tattr
->guid
, keyName
);
708 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
709 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
712 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
713 (BYTE
*)name
, (strlenW(name
)+1) * sizeof(OLECHAR
));
715 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
716 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
717 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
718 (const BYTE
*)PSOA
, sizeof PSOA
);
722 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
723 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
724 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
725 (const BYTE
*)PSOA
, sizeof PSOA
);
729 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
730 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
733 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
734 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
736 StringFromGUID2(&attr
->guid
, buffer
, 40);
737 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
738 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
739 sprintfW(buffer
, fmtver
, attr
->wMajorVerNum
, attr
->wMinorVerNum
);
740 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
741 (BYTE
*)buffer
, (strlenW(buffer
)+1) * sizeof(WCHAR
));
749 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
752 ITypeInfo_Release(tinfo
);
759 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
765 /******************************************************************************
766 * UnRegisterTypeLib [OLEAUT32.186]
767 * Removes information about a type library from the System Registry
774 HRESULT WINAPI
UnRegisterTypeLib(
775 REFGUID libid
, /* [in] Guid of the library */
776 WORD wVerMajor
, /* [in] major version */
777 WORD wVerMinor
, /* [in] minor version */
778 LCID lcid
, /* [in] locale id */
781 BSTR tlibPath
= NULL
;
784 WCHAR subKeyName
[50];
787 BOOL deleteOtherStuff
;
790 TYPEATTR
* typeAttr
= NULL
;
792 ITypeInfo
* typeInfo
= NULL
;
793 ITypeLib
* typeLib
= NULL
;
796 TRACE("(IID: %s)\n",debugstr_guid(libid
));
798 /* Create the path to the key */
799 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
801 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
803 TRACE("Unsupported syskind %i\n", syskind
);
804 result
= E_INVALIDARG
;
808 /* get the path to the typelib on disk */
809 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
) != S_OK
) {
810 result
= E_INVALIDARG
;
814 /* Try and open the key to the type library. */
815 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
816 result
= E_INVALIDARG
;
820 /* Try and load the type library */
821 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
822 result
= TYPE_E_INVALIDSTATE
;
826 /* remove any types registered with this typelib */
827 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
828 for (i
=0; i
<numTypes
; i
++) {
829 /* get the kind of type */
830 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
834 /* skip non-interfaces, and get type info for the type */
835 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
838 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
841 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
845 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
846 kind
== TKIND_DISPATCH
)
848 /* the path to the type */
849 get_interface_key( &typeAttr
->guid
, subKeyName
);
851 /* Delete its bits */
852 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
, &subKey
) != ERROR_SUCCESS
)
855 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
856 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
857 RegDeleteKeyW(subKey
, TypeLibW
);
860 RegDeleteKeyW(HKEY_CLASSES_ROOT
, subKeyName
);
864 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
866 if (typeInfo
) ITypeInfo_Release(typeInfo
);
870 /* Now, delete the type library path subkey */
871 get_lcid_subkey( lcid
, syskind
, subKeyName
);
872 RegDeleteKeyW(key
, subKeyName
);
873 *strrchrW( subKeyName
, '\\' ) = 0; /* remove last path component */
874 RegDeleteKeyW(key
, subKeyName
);
876 /* check if there is anything besides the FLAGS/HELPDIR keys.
877 If there is, we don't delete them */
878 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
879 deleteOtherStuff
= TRUE
;
881 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
882 tmpLength
= sizeof(subKeyName
)/sizeof(WCHAR
);
884 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
885 if (!strcmpW(subKeyName
, FLAGSW
)) continue;
886 if (!strcmpW(subKeyName
, HELPDIRW
)) continue;
887 deleteOtherStuff
= FALSE
;
891 /* only delete the other parts of the key if we're absolutely sure */
892 if (deleteOtherStuff
) {
893 RegDeleteKeyW(key
, FLAGSW
);
894 RegDeleteKeyW(key
, HELPDIRW
);
898 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
899 *strrchrW( keyName
, '\\' ) = 0; /* remove last path component */
900 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
904 SysFreeString(tlibPath
);
905 if (typeLib
) ITypeLib_Release(typeLib
);
906 if (subKey
) RegCloseKey(subKey
);
907 if (key
) RegCloseKey(key
);
911 /******************************************************************************
912 * RegisterTypeLibForUser [OLEAUT32.442]
913 * Adds information about a type library to the user registry
915 * Docs: ITypeLib FAR * ptlib
916 * Docs: OLECHAR FAR* szFullPath
917 * Docs: OLECHAR FAR* szHelpDir
923 HRESULT WINAPI
RegisterTypeLibForUser(
924 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
925 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
926 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
929 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
930 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
931 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
934 /******************************************************************************
935 * UnRegisterTypeLibForUser [OLEAUT32.443]
936 * Removes information about a type library from the user registry
942 HRESULT WINAPI
UnRegisterTypeLibForUser(
943 REFGUID libid
, /* [in] GUID of the library */
944 WORD wVerMajor
, /* [in] major version */
945 WORD wVerMinor
, /* [in] minor version */
946 LCID lcid
, /* [in] locale id */
949 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
950 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
951 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
954 /*======================= ITypeLib implementation =======================*/
956 typedef struct tagTLBCustData
963 /* data structure for import typelibs */
964 typedef struct tagTLBImpLib
966 int offset
; /* offset in the file (MSFT)
967 offset in nametable (SLTG)
968 just used to identify library while reading
970 GUID guid
; /* libid */
971 BSTR name
; /* name */
973 LCID lcid
; /* lcid of imported typelib */
975 WORD wVersionMajor
; /* major version number */
976 WORD wVersionMinor
; /* minor version number */
978 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
979 NULL if not yet loaded */
983 /* internal ITypeLib data */
984 typedef struct tagITypeLibImpl
986 ITypeLib2 ITypeLib2_iface
;
987 ITypeComp ITypeComp_iface
;
989 TLIBATTR LibAttr
; /* guid,lcid,syskind,version,flags */
992 /* strings can be stored in tlb as multibyte strings BUT they are *always*
993 * exported to the application as a UNICODE string.
1000 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1001 struct tagITypeInfoImpl
**typeinfos
;
1002 struct list custdata_list
;
1003 struct list implib_list
;
1004 int ctTypeDesc
; /* number of items in type desc array */
1005 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1006 library. Only used while reading MSFT
1008 struct list ref_list
; /* list of ref types in this typelib */
1009 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1012 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1018 static const ITypeLib2Vtbl tlbvt
;
1019 static const ITypeCompVtbl tlbtcvt
;
1021 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1023 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1026 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1028 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1031 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1033 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1036 /* ITypeLib methods */
1037 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1038 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1040 /*======================= ITypeInfo implementation =======================*/
1042 /* data for referenced types */
1043 typedef struct tagTLBRefType
1045 INT index
; /* Type index for internal ref or for external ref
1046 it the format is SLTG. -2 indicates to
1049 GUID guid
; /* guid of the referenced type */
1050 /* if index == TLB_REF_USE_GUID */
1052 HREFTYPE reference
; /* The href of this ref */
1053 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1054 TLB_REF_INTERNAL for internal refs
1055 TLB_REF_NOT_FOUND for broken refs */
1060 #define TLB_REF_USE_GUID -2
1062 #define TLB_REF_INTERNAL (void*)-2
1063 #define TLB_REF_NOT_FOUND (void*)-1
1065 /* internal Parameter data */
1066 typedef struct tagTLBParDesc
1069 struct list custdata_list
;
1072 /* internal Function data */
1073 typedef struct tagTLBFuncDesc
1075 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1076 BSTR Name
; /* the name of this function */
1077 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1079 int HelpStringContext
;
1081 BSTR Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1082 struct list custdata_list
;
1085 /* internal Variable data */
1086 typedef struct tagTLBVarDesc
1088 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1089 BSTR Name
; /* the name of this variable */
1091 int HelpStringContext
;
1093 struct list custdata_list
;
1096 /* internal implemented interface data */
1097 typedef struct tagTLBImplType
1099 HREFTYPE hRef
; /* hRef of interface */
1100 int implflags
; /* IMPLFLAG_*s */
1101 struct list custdata_list
;
1104 /* internal TypeInfo data */
1105 typedef struct tagITypeInfoImpl
1107 ITypeInfo2 ITypeInfo2_iface
;
1108 ITypeComp ITypeComp_iface
;
1110 BOOL not_attached_to_typelib
;
1111 TYPEATTR TypeAttr
; /* _lots_ of type information. */
1112 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1113 int index
; /* index in this typelib; */
1114 HREFTYPE hreftype
; /* hreftype for app object binding */
1115 /* type libs seem to store the doc strings in ascii
1116 * so why should we do it in unicode?
1121 DWORD dwHelpContext
;
1122 DWORD dwHelpStringContext
;
1125 TLBFuncDesc
*funcdescs
;
1128 TLBVarDesc
*vardescs
;
1130 /* Implemented Interfaces */
1131 TLBImplType
*impltypes
;
1133 struct list custdata_list
;
1136 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1138 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1141 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1143 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1146 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1148 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1151 static const ITypeInfo2Vtbl tinfvt
;
1152 static const ITypeCompVtbl tcompvt
;
1154 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1155 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1157 typedef struct tagTLBContext
1159 unsigned int oStart
; /* start of TLB in file */
1160 unsigned int pos
; /* current pos */
1161 unsigned int length
; /* total length */
1162 void *mapping
; /* memory mapping */
1163 MSFT_SegDir
* pTblDir
;
1164 ITypeLibImpl
* pLibInfo
;
1168 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
, int offset
);
1173 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1174 if (pTD
->vt
& VT_RESERVED
)
1175 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1176 if (pTD
->vt
& VT_BYREF
)
1177 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1178 if (pTD
->vt
& VT_ARRAY
)
1179 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1180 if (pTD
->vt
& VT_VECTOR
)
1181 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1182 switch(pTD
->vt
& VT_TYPEMASK
) {
1183 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1184 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1185 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1186 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1187 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1188 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1189 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1190 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1191 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1192 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1193 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1194 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1195 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1196 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1197 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1198 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1199 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1200 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1201 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1202 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1203 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1204 pTD
->u
.hreftype
); break;
1205 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1206 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1207 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1208 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1210 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1211 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1213 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1214 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1215 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1218 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1222 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1224 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1225 dump_TypeDesc(&edesc
->tdesc
,buf
);
1226 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1227 MESSAGE("\t\tu.paramdesc.wParamFlags");
1228 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1229 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1230 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1231 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1232 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1233 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1234 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1235 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1236 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1238 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1240 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1241 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1242 MESSAGE("Param %d:\n",i
);
1243 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1245 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1246 switch (funcdesc
->funckind
) {
1247 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1248 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1249 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1250 case FUNC_STATIC
: MESSAGE("static");break;
1251 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1252 default: MESSAGE("unknown");break;
1254 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1255 switch (funcdesc
->invkind
) {
1256 case INVOKE_FUNC
: MESSAGE("func");break;
1257 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1258 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1259 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1261 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1262 switch (funcdesc
->callconv
) {
1263 case CC_CDECL
: MESSAGE("cdecl");break;
1264 case CC_PASCAL
: MESSAGE("pascal");break;
1265 case CC_STDCALL
: MESSAGE("stdcall");break;
1266 case CC_SYSCALL
: MESSAGE("syscall");break;
1269 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1270 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1271 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1273 MESSAGE("\telemdescFunc (return value type):\n");
1274 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1277 static const char * const typekind_desc
[] =
1290 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1293 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1294 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1295 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1298 dump_FUNCDESC(&(pfd
->funcdesc
));
1300 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1301 MESSAGE("\tentry: %s\n", (pfd
->Entry
== (void *)-1) ? "invalid" : debugstr_w(pfd
->Entry
));
1303 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1307 dump_TLBFuncDescOne(pfd
);
1312 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1316 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1322 static void dump_TLBImpLib(const TLBImpLib
*import
)
1324 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1325 debugstr_w(import
->name
));
1326 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1327 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1330 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1334 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1336 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1337 if(ref
->index
== -1)
1338 TRACE_(typelib
)("%s\n", debugstr_guid(&(ref
->guid
)));
1340 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1342 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1344 TRACE_(typelib
)("in lib\n");
1345 dump_TLBImpLib(ref
->pImpTLInfo
);
1350 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1355 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1356 impl
->hRef
, impl
->implflags
);
1362 static void dump_Variant(const VARIANT
* pvar
)
1366 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1370 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1371 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1373 TRACE(",%p", V_BYREF(pvar
));
1375 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1377 TRACE(",%p", V_ARRAY(pvar
));
1379 else switch (V_TYPE(pvar
))
1381 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1382 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1383 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1384 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1386 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1388 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1389 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1390 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1391 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1392 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1393 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1394 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1395 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1396 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1397 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1398 V_CY(pvar
).s
.Lo
); break;
1400 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1401 TRACE(",<invalid>");
1403 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1404 st
.wHour
, st
.wMinute
, st
.wSecond
);
1408 case VT_USERDEFINED
:
1410 case VT_NULL
: break;
1411 default: TRACE(",?"); break;
1417 static void dump_DispParms(const DISPPARAMS
* pdp
)
1421 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1423 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1425 TRACE("named args:\n");
1426 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1427 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1430 if (pdp
->cArgs
&& pdp
->rgvarg
)
1433 for (index
= 0; index
< pdp
->cArgs
; index
++)
1434 dump_Variant( &pdp
->rgvarg
[index
] );
1438 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1440 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1441 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1442 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1443 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1444 TRACE("fct:%u var:%u impl:%u\n",
1445 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1446 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1447 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1448 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1450 dump_TLBFuncDesc(pty
->funcdescs
, pty
->TypeAttr
.cFuncs
);
1451 dump_TLBVarDesc(pty
->vardescs
, pty
->TypeAttr
.cVars
);
1452 dump_TLBImplType(pty
->impltypes
, pty
->TypeAttr
.cImplTypes
);
1455 static void dump_VARDESC(const VARDESC
*v
)
1457 MESSAGE("memid %d\n",v
->memid
);
1458 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1459 MESSAGE("oInst %d\n",v
->u
.oInst
);
1460 dump_ELEMDESC(&(v
->elemdescVar
));
1461 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1462 MESSAGE("varkind %d\n",v
->varkind
);
1465 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1467 /* VT_LPWSTR is largest type that, may appear in type description */
1468 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1469 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1470 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1471 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1472 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1473 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1474 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1475 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1478 static void TLB_abort(void)
1483 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1485 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1486 if (!ret
) ERR("cannot allocate memory\n");
1490 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1492 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1493 if (!ret
) ERR("cannot allocate memory\n");
1497 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1499 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1502 void heap_free(void *ptr
)
1504 HeapFree(GetProcessHeap(), 0, ptr
);
1507 /* returns the size required for a deep copy of a typedesc into a
1509 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1513 if (alloc_initial_space
)
1514 size
+= sizeof(TYPEDESC
);
1520 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1523 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1524 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1530 /* deep copy a typedesc into a flat buffer */
1531 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1536 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1545 dest
->u
.lptdesc
= buffer
;
1546 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1549 dest
->u
.lpadesc
= buffer
;
1550 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1551 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1552 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1558 /* free custom data allocated by MSFT_CustData */
1559 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1561 TLBCustData
*cd
, *cdn
;
1562 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1564 list_remove(&cd
->entry
);
1565 VariantClear(&cd
->data
);
1570 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1575 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1576 ret
= SysAllocStringLen(NULL
, len
- 1);
1577 if (!ret
) return ret
;
1578 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1582 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1583 UINT n
, MEMBERID memid
)
1586 if(funcdescs
->funcdesc
.memid
== memid
)
1594 static inline TLBFuncDesc
*TLB_get_funcdesc_by_name(TLBFuncDesc
*funcdescs
,
1595 UINT n
, const OLECHAR
*name
)
1598 if(!lstrcmpiW(funcdescs
->Name
, name
))
1606 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1607 UINT n
, MEMBERID memid
)
1610 if(vardescs
->vardesc
.memid
== memid
)
1618 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1619 UINT n
, const OLECHAR
*name
)
1622 if(!lstrcmpiW(vardescs
->Name
, name
))
1630 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1632 TLBCustData
*cust_data
;
1633 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1634 if(IsEqualIID(&cust_data
->guid
, guid
))
1639 static TLBVarDesc
*TLBVarDesc_Constructor(UINT n
)
1643 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1648 list_init(&ret
[n
-1].custdata_list
);
1655 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1659 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1664 list_init(&ret
[n
-1].custdata_list
);
1671 static TLBFuncDesc
*TLBFuncDesc_Constructor(UINT n
)
1675 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1680 list_init(&ret
[n
-1].custdata_list
);
1687 static TLBImplType
*TLBImplType_Constructor(UINT n
)
1691 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1696 list_init(&ret
[n
-1].custdata_list
);
1703 /**********************************************************************
1705 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1707 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
1712 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
1714 if (where
!= DO_NOT_SEEK
)
1716 where
+= pcx
->oStart
;
1717 if (where
> pcx
->length
)
1720 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
1728 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
1730 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1731 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1733 MSFT_Seek(pcx
, where
);
1734 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1735 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1740 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1745 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1746 FromLEDWords(buffer
, ret
);
1751 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1756 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1757 FromLEWords(buffer
, ret
);
1762 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1764 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1765 memset(pGuid
,0, sizeof(GUID
));
1768 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1769 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1770 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1771 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1772 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1775 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1777 MSFT_NameIntro niName
;
1781 ERR_(typelib
)("bad offset %d\n", offset
);
1785 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1786 pcx
->pTblDir
->pNametab
.offset
+offset
);
1788 return niName
.hreftype
;
1791 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1794 MSFT_NameIntro niName
;
1796 BSTR bstrName
= NULL
;
1800 ERR_(typelib
)("bad offset %d\n", offset
);
1803 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1804 pcx
->pTblDir
->pNametab
.offset
+offset
);
1805 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1806 name
= heap_alloc_zero((niName
.namelen
& 0xff) +1);
1807 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1808 name
[niName
.namelen
& 0xff]='\0';
1810 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1813 /* no invalid characters in string */
1816 bstrName
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1818 /* don't check for invalid character since this has been done previously */
1819 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, bstrName
, lengthInChars
);
1823 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1827 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1834 if(offset
<0) return NULL
;
1835 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1836 if(length
<= 0) return 0;
1837 string
= heap_alloc_zero(length
+1);
1838 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1839 string
[length
]='\0';
1841 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1842 string
, -1, NULL
, 0);
1844 /* no invalid characters in string */
1847 bstr
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1849 /* don't check for invalid character since this has been done previously */
1850 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, bstr
, lengthInChars
);
1854 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1858 * read a value and fill a VARIANT structure
1860 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1864 TRACE_(typelib
)("\n");
1866 if(offset
<0) { /* data are packed in here */
1867 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1868 V_I4(pVar
) = offset
& 0x3ffffff;
1871 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1872 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1873 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1874 switch (V_VT(pVar
)){
1875 case VT_EMPTY
: /* FIXME: is this right? */
1876 case VT_NULL
: /* FIXME: is this right? */
1877 case VT_I2
: /* this should not happen */
1888 case VT_VOID
: /* FIXME: is this right? */
1896 case VT_DECIMAL
: /* FIXME: is this right? */
1899 /* pointer types with known behaviour */
1902 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1905 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
1908 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
1910 nullPos
= MSFT_Tell(pcx
);
1911 size
= nullPos
- origPos
;
1912 MSFT_Seek(pcx
, origPos
);
1914 ptr
= heap_alloc_zero(size
);/* allocate temp buffer */
1915 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1916 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1917 /* FIXME: do we need a AtoW conversion here? */
1918 V_UNION(pVar
, bstrVal
[size
])='\0';
1919 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1923 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1930 case VT_USERDEFINED
:
1936 case VT_STREAMED_OBJECT
:
1937 case VT_STORED_OBJECT
:
1938 case VT_BLOB_OBJECT
:
1943 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1947 if(size
>0) /* (big|small) endian correct? */
1948 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1952 * create a linked list with custom data
1954 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
1960 TRACE_(typelib
)("\n");
1962 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
1966 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
1967 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1968 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1969 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1970 list_add_head(custdata_list
, &pNew
->entry
);
1971 offset
= entry
.next
;
1976 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1980 pTd
->vt
=type
& VT_TYPEMASK
;
1982 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1984 if(pTd
->vt
== VT_USERDEFINED
)
1985 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
1987 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1990 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
1992 /* resolve referenced type if any */
1995 switch (lpTypeDesc
->vt
)
1998 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
2002 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
2005 case VT_USERDEFINED
:
2006 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
2007 lpTypeDesc
->u
.hreftype
);
2019 MSFT_DoFuncs(TLBContext
* pcx
,
2024 TLBFuncDesc
** pptfd
)
2027 * member information is stored in a data structure at offset
2028 * indicated by the memoffset field of the typeinfo structure
2029 * There are several distinctive parts.
2030 * The first part starts with a field that holds the total length
2031 * of this (first) part excluding this field. Then follow the records,
2032 * for each member there is one record.
2034 * The first entry is always the length of the record (including this
2036 * The rest of the record depends on the type of the member. If there is
2037 * a field indicating the member type (function, variable, interface, etc)
2038 * I have not found it yet. At this time we depend on the information
2039 * in the type info and the usual order how things are stored.
2041 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2044 * Third is an equal sized array with file offsets to the name entry
2047 * The fourth and last (?) part is an array with offsets to the records
2048 * in the first part of this file segment.
2051 int infolen
, nameoffset
, reclength
, i
;
2052 int recoffset
= offset
+ sizeof(INT
);
2054 char *recbuf
= heap_alloc(0xffff);
2055 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2056 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2058 TRACE_(typelib
)("\n");
2060 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2062 *pptfd
= TLBFuncDesc_Constructor(cFuncs
);
2064 for ( i
= 0; i
< cFuncs
; i
++ )
2068 /* name, eventually add to a hash table */
2069 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2070 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2072 /* nameoffset is sometimes -1 on the second half of a propget/propput
2073 * pair of functions */
2074 if ((nameoffset
== -1) && (i
> 0))
2075 ptfd
->Name
= SysAllocString(ptfd_prev
->Name
);
2077 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2079 /* read the function information record */
2080 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2082 reclength
&= 0xffff;
2084 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2086 /* size without argument data */
2087 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2089 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2090 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2092 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2093 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2095 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2097 if (pFuncRec
->FKCCIC
& 0x2000 )
2099 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2100 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2101 ptfd
->Entry
= (BSTR
)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2104 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2107 ptfd
->Entry
= (BSTR
)-1;
2109 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2110 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2112 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2113 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2115 /* fill the FuncDesc Structure */
2116 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2117 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2119 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2120 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2121 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2122 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2123 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2124 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2125 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2129 &ptfd
->funcdesc
.elemdescFunc
.tdesc
,
2131 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2133 /* do the parameters/arguments */
2134 if(pFuncRec
->nrargs
)
2137 MSFT_ParameterInfo paraminfo
;
2139 ptfd
->funcdesc
.lprgelemdescParam
=
2140 heap_alloc_zero(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
2142 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2144 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2145 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2147 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2149 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2156 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2159 if (paraminfo
.oName
== -1)
2160 /* this occurs for [propput] or [propget] methods, so
2161 * we should just set the name of the parameter to the
2162 * name of the method. */
2163 ptfd
->pParamDesc
[j
].Name
= SysAllocString(ptfd
->Name
);
2165 ptfd
->pParamDesc
[j
].Name
=
2166 MSFT_ReadName( pcx
, paraminfo
.oName
);
2167 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(ptfd
->pParamDesc
[j
].Name
));
2169 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
2172 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2173 (pFuncRec
->FKCCIC
& 0x1000) )
2175 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2177 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2179 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2181 pParamDesc
->pparamdescex
= heap_alloc_zero(sizeof(PARAMDESCEX
));
2182 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2184 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2188 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2191 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2192 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2193 pFuncRec
->FKCCIC
& 0x80 )
2196 pFuncRec
->oArgCustData
[j
],
2197 &ptfd
->pParamDesc
[j
].custdata_list
);
2200 /* SEEK value = jump to offset,
2201 * from there jump to the end of record,
2202 * go back by (j-1) arguments
2204 MSFT_ReadLEDWords( ¶minfo
,
2205 sizeof(MSFT_ParameterInfo
), pcx
,
2206 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2207 * sizeof(MSFT_ParameterInfo
)));
2211 /* scode is not used: archaic win16 stuff FIXME: right? */
2212 ptfd
->funcdesc
.cScodes
= 0 ;
2213 ptfd
->funcdesc
.lprgscode
= NULL
;
2217 recoffset
+= reclength
;
2222 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2223 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2225 int infolen
, nameoffset
, reclength
;
2227 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2232 TRACE_(typelib
)("\n");
2234 ptvd
= *pptvd
= TLBVarDesc_Constructor(cVars
);
2235 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2236 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2237 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2238 recoffset
+= offset
+sizeof(INT
);
2239 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2240 /* name, eventually add to a hash table */
2241 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2242 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2243 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2244 /* read the variable information record */
2245 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2247 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2250 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2251 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2253 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2254 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2256 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2257 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2259 /* fill the VarDesc Structure */
2260 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2261 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2262 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2263 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2264 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2265 &ptvd
->vardesc
.elemdescVar
.tdesc
, pTI
);
2266 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2267 if(pVarRec
->VarKind
== VAR_CONST
){
2268 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2269 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2270 pVarRec
->OffsValue
, pcx
);
2272 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2273 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptvd
->vardesc
.elemdescVar
.tdesc
);
2274 recoffset
+= reclength
;
2278 /* fill in data for a hreftype (offset). When the referenced type is contained
2279 * in the typelib, it's just an (file) offset in the type info base dir.
2280 * If comes from import, it's an offset+1 in the ImpInfo table
2282 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2287 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2289 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2291 if(ref
->reference
== offset
) return;
2294 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2295 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2297 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2298 /* external typelib */
2299 MSFT_ImpInfo impinfo
;
2302 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2304 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2305 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2307 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2308 if(pImpLib
->offset
==impinfo
.oImpFile
)
2311 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2312 ref
->reference
= offset
;
2313 ref
->pImpTLInfo
= pImpLib
;
2314 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2315 MSFT_ReadGuid(&ref
->guid
, impinfo
.oGuid
, pcx
);
2316 TRACE("importing by guid %s\n", debugstr_guid(&ref
->guid
));
2317 ref
->index
= TLB_REF_USE_GUID
;
2319 ref
->index
= impinfo
.oGuid
;
2321 ERR("Cannot find a reference\n");
2322 ref
->reference
= -1;
2323 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2326 /* in this typelib */
2327 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2328 ref
->reference
= offset
;
2329 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2333 /* process Implemented Interfaces of a com class */
2334 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2338 MSFT_RefRecord refrec
;
2341 TRACE_(typelib
)("\n");
2343 pTI
->impltypes
= TLBImplType_Constructor(count
);
2344 pImpl
= pTI
->impltypes
;
2345 for(i
=0;i
<count
;i
++){
2346 if(offset
<0) break; /* paranoia */
2347 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2348 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2349 pImpl
->hRef
= refrec
.reftype
;
2350 pImpl
->implflags
=refrec
.flags
;
2351 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2352 offset
=refrec
.onext
;
2357 * process a typeinfo record
2359 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2362 ITypeLibImpl
* pLibInfo
)
2364 MSFT_TypeInfoBase tiBase
;
2365 ITypeInfoImpl
*ptiRet
;
2367 TRACE_(typelib
)("count=%u\n", count
);
2369 ptiRet
= ITypeInfoImpl_Constructor();
2370 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2371 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2373 /* this is where we are coming from */
2374 ptiRet
->pTypeLib
= pLibInfo
;
2375 ptiRet
->index
=count
;
2376 /* fill in the typeattr fields */
2378 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2379 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2380 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2381 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2382 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2383 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2384 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2385 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2386 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2387 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2388 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2389 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2390 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2391 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2392 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2393 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2396 /* IDLDESC idldescType; *//* never saw this one != zero */
2398 /* name, eventually add to a hash table */
2399 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2400 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2401 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2403 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2404 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2405 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2407 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2408 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2410 /* note: InfoType's Help file and HelpStringDll come from the containing
2411 * library. Further HelpString and Docstring appear to be the same thing :(
2414 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2415 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2416 ptiRet
->TypeAttr
.cVars
,
2417 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2419 if(ptiRet
->TypeAttr
.cVars
>0 )
2420 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2421 ptiRet
->TypeAttr
.cVars
,
2422 tiBase
.memoffset
, &ptiRet
->vardescs
);
2423 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2424 switch(ptiRet
->TypeAttr
.typekind
)
2427 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2430 case TKIND_DISPATCH
:
2431 /* This is not -1 when the interface is a non-base dual interface or
2432 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2433 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2437 if (tiBase
.datatype1
!= -1)
2439 ptiRet
->impltypes
= TLBImplType_Constructor(1);
2440 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2441 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2445 ptiRet
->impltypes
= TLBImplType_Constructor(1);
2446 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2447 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2451 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->custdata_list
);
2453 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2454 debugstr_w(ptiRet
->Name
),
2455 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2456 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2457 if (TRACE_ON(typelib
))
2458 dump_TypeInfo(ptiRet
);
2463 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2464 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2465 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2468 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2469 static CRITICAL_SECTION cache_section
;
2470 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2472 0, 0, &cache_section
,
2473 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2474 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2476 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2479 typedef struct TLB_PEFile
2481 IUnknown IUnknown_iface
;
2484 HRSRC typelib_resource
;
2485 HGLOBAL typelib_global
;
2486 LPVOID typelib_base
;
2489 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2491 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2494 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2496 if (IsEqualIID(riid
, &IID_IUnknown
))
2499 IUnknown_AddRef(iface
);
2503 return E_NOINTERFACE
;
2506 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2508 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2509 return InterlockedIncrement(&This
->refs
);
2512 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2514 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2515 ULONG refs
= InterlockedDecrement(&This
->refs
);
2518 if (This
->typelib_global
)
2519 FreeResource(This
->typelib_global
);
2521 FreeLibrary(This
->dll
);
2527 static const IUnknownVtbl TLB_PEFile_Vtable
=
2529 TLB_PEFile_QueryInterface
,
2534 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2537 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2539 This
= heap_alloc(sizeof(TLB_PEFile
));
2541 return E_OUTOFMEMORY
;
2543 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2546 This
->typelib_resource
= NULL
;
2547 This
->typelib_global
= NULL
;
2548 This
->typelib_base
= NULL
;
2550 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2551 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2555 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2556 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2557 if (This
->typelib_resource
)
2559 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2560 if (This
->typelib_global
)
2562 This
->typelib_base
= LockResource(This
->typelib_global
);
2564 if (This
->typelib_base
)
2566 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2567 *ppBase
= This
->typelib_base
;
2568 *ppFile
= &This
->IUnknown_iface
;
2574 TRACE("No TYPELIB resource found\n");
2578 TLB_PEFile_Release(&This
->IUnknown_iface
);
2582 typedef struct TLB_NEFile
2584 IUnknown IUnknown_iface
;
2586 LPVOID typelib_base
;
2589 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2591 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2594 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2596 if (IsEqualIID(riid
, &IID_IUnknown
))
2599 IUnknown_AddRef(iface
);
2603 return E_NOINTERFACE
;
2606 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2608 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2609 return InterlockedIncrement(&This
->refs
);
2612 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2614 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2615 ULONG refs
= InterlockedDecrement(&This
->refs
);
2618 heap_free(This
->typelib_base
);
2624 static const IUnknownVtbl TLB_NEFile_Vtable
=
2626 TLB_NEFile_QueryInterface
,
2631 /***********************************************************************
2632 * read_xx_header [internal]
2634 static int read_xx_header( HFILE lzfd
)
2636 IMAGE_DOS_HEADER mzh
;
2639 LZSeek( lzfd
, 0, SEEK_SET
);
2640 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2642 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2645 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2646 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2649 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2651 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2652 return IMAGE_OS2_SIGNATURE
;
2653 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2654 return IMAGE_NT_SIGNATURE
;
2657 WARN("Can't handle %s files.\n", magic
);
2662 /***********************************************************************
2663 * find_ne_resource [internal]
2665 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2666 DWORD
*resLen
, DWORD
*resOff
)
2668 IMAGE_OS2_HEADER nehd
;
2669 NE_TYPEINFO
*typeInfo
;
2670 NE_NAMEINFO
*nameInfo
;
2676 /* Read in NE header */
2677 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2678 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2680 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2683 TRACE("No resources in NE dll\n" );
2687 /* Read in resource table */
2688 resTab
= heap_alloc( resTabSize
);
2689 if ( !resTab
) return FALSE
;
2691 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2692 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2694 heap_free( resTab
);
2699 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2701 if (!IS_INTRESOURCE(typeid)) /* named type */
2703 BYTE len
= strlen( typeid );
2704 while (typeInfo
->type_id
)
2706 if (!(typeInfo
->type_id
& 0x8000))
2708 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2709 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2711 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2712 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2715 else /* numeric type id */
2717 WORD id
= LOWORD(typeid) | 0x8000;
2718 while (typeInfo
->type_id
)
2720 if (typeInfo
->type_id
== id
) goto found_type
;
2721 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2722 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2725 TRACE("No typeid entry found for %p\n", typeid );
2726 heap_free( resTab
);
2730 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
2732 if (!IS_INTRESOURCE(resid
)) /* named resource */
2734 BYTE len
= strlen( resid
);
2735 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2737 BYTE
*p
= resTab
+ nameInfo
->id
;
2738 if (nameInfo
->id
& 0x8000) continue;
2739 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
2742 else /* numeric resource id */
2744 WORD id
= LOWORD(resid
) | 0x8000;
2745 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2746 if (nameInfo
->id
== id
) goto found_name
;
2748 TRACE("No resid entry found for %p\n", typeid );
2749 heap_free( resTab
);
2753 /* Return resource data */
2754 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
2755 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
2757 heap_free( resTab
);
2761 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
2765 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2768 This
= heap_alloc(sizeof(TLB_NEFile
));
2769 if (!This
) return E_OUTOFMEMORY
;
2771 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
2773 This
->typelib_base
= NULL
;
2775 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
2776 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
2778 DWORD reslen
, offset
;
2779 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
2781 This
->typelib_base
= heap_alloc(reslen
);
2782 if( !This
->typelib_base
)
2786 LZSeek( lzfd
, offset
, SEEK_SET
);
2787 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
2789 *ppBase
= This
->typelib_base
;
2790 *pdwTLBLength
= reslen
;
2791 *ppFile
= &This
->IUnknown_iface
;
2797 if( lzfd
>= 0) LZClose( lzfd
);
2798 TLB_NEFile_Release(&This
->IUnknown_iface
);
2802 typedef struct TLB_Mapping
2804 IUnknown IUnknown_iface
;
2808 LPVOID typelib_base
;
2811 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
2813 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
2816 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2818 if (IsEqualIID(riid
, &IID_IUnknown
))
2821 IUnknown_AddRef(iface
);
2825 return E_NOINTERFACE
;
2828 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
2830 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
2831 return InterlockedIncrement(&This
->refs
);
2834 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
2836 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
2837 ULONG refs
= InterlockedDecrement(&This
->refs
);
2840 if (This
->typelib_base
)
2841 UnmapViewOfFile(This
->typelib_base
);
2843 CloseHandle(This
->mapping
);
2844 if (This
->file
!= INVALID_HANDLE_VALUE
)
2845 CloseHandle(This
->file
);
2851 static const IUnknownVtbl TLB_Mapping_Vtable
=
2853 TLB_Mapping_QueryInterface
,
2858 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2862 This
= heap_alloc(sizeof(TLB_Mapping
));
2864 return E_OUTOFMEMORY
;
2866 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
2868 This
->file
= INVALID_HANDLE_VALUE
;
2869 This
->mapping
= NULL
;
2870 This
->typelib_base
= NULL
;
2872 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
2873 if (INVALID_HANDLE_VALUE
!= This
->file
)
2875 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2878 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
2879 if(This
->typelib_base
)
2881 /* retrieve file size */
2882 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
2883 *ppBase
= This
->typelib_base
;
2884 *ppFile
= &This
->IUnknown_iface
;
2890 IUnknown_Release(&This
->IUnknown_iface
);
2891 return TYPE_E_CANTLOADLIBRARY
;
2894 /****************************************************************************
2897 * find the type of the typelib file and map the typelib resource into
2901 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2902 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2904 ITypeLibImpl
*entry
;
2907 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
2908 LPVOID pBase
= NULL
;
2909 DWORD dwTLBLength
= 0;
2910 IUnknown
*pFile
= NULL
;
2914 index_str
= strrchrW(pszFileName
, '\\');
2915 if(index_str
&& *++index_str
!= '\0')
2918 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
2919 if(*end_ptr
== '\0')
2921 int str_len
= index_str
- pszFileName
- 1;
2923 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
2924 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
2929 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
2931 if(strchrW(file
, '\\'))
2933 lstrcpyW(pszPath
, file
);
2937 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
2938 pszPath
[len
] = '\\';
2939 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
2943 if(file
!= pszFileName
) heap_free(file
);
2945 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2947 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2948 EnterCriticalSection(&cache_section
);
2949 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
2951 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2953 TRACE("cache hit\n");
2954 *ppTypeLib
= &entry
->ITypeLib2_iface
;
2955 ITypeLib2_AddRef(*ppTypeLib
);
2956 LeaveCriticalSection(&cache_section
);
2960 LeaveCriticalSection(&cache_section
);
2962 /* now actually load and parse the typelib */
2964 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2965 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2966 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2967 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2968 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
2971 if (dwTLBLength
>= 4)
2973 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2974 if (dwSignature
== MSFT_SIGNATURE
)
2975 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2976 else if (dwSignature
== SLTG_SIGNATURE
)
2977 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2980 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
2981 ret
= TYPE_E_CANTLOADLIBRARY
;
2985 ret
= TYPE_E_CANTLOADLIBRARY
;
2986 IUnknown_Release(pFile
);
2990 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
2992 TRACE("adding to cache\n");
2993 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
2994 lstrcpyW(impl
->path
, pszPath
);
2995 /* We should really canonicalise the path here. */
2996 impl
->index
= index
;
2998 /* FIXME: check if it has added already in the meantime */
2999 EnterCriticalSection(&cache_section
);
3000 list_add_head(&tlb_cache
, &impl
->entry
);
3001 LeaveCriticalSection(&cache_section
);
3007 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3009 ret
= TYPE_E_CANTLOADLIBRARY
;
3016 /*================== ITypeLib(2) Methods ===================================*/
3018 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3020 ITypeLibImpl
* pTypeLibImpl
;
3022 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3023 if (!pTypeLibImpl
) return NULL
;
3025 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3026 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3027 pTypeLibImpl
->ref
= 1;
3029 list_init(&pTypeLibImpl
->implib_list
);
3030 list_init(&pTypeLibImpl
->custdata_list
);
3031 list_init(&pTypeLibImpl
->ref_list
);
3032 pTypeLibImpl
->dispatch_href
= -1;
3034 return pTypeLibImpl
;
3037 /****************************************************************************
3038 * ITypeLib2_Constructor_MSFT
3040 * loading an MSFT typelib from an in-memory image
3042 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3046 MSFT_Header tlbHeader
;
3047 MSFT_SegDir tlbSegDir
;
3048 ITypeLibImpl
* pTypeLibImpl
;
3050 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3052 pTypeLibImpl
= TypeLibImpl_Constructor();
3053 if (!pTypeLibImpl
) return NULL
;
3055 /* get pointer to beginning of typelib data */
3059 cx
.pLibInfo
= pTypeLibImpl
;
3060 cx
.length
= dwTLBLength
;
3063 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3064 TRACE_(typelib
)("header:\n");
3065 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3066 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3067 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3070 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3072 /* there is a small amount of information here until the next important
3074 * the segment directory . Try to calculate the amount of data */
3075 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3077 /* now read the segment directory */
3078 TRACE("read segment directory (at %d)\n",lPSegDir
);
3079 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3080 cx
.pTblDir
= &tlbSegDir
;
3082 /* just check two entries */
3083 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3085 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3086 heap_free(pTypeLibImpl
);
3090 /* now fill our internal data */
3091 /* TLIBATTR fields */
3092 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
3094 pTypeLibImpl
->LibAttr
.lcid
= tlbHeader
.lcid2
;
3095 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3096 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
3097 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
3098 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
3100 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3102 /* name, eventually add to a hash table */
3103 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3106 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3107 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3109 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3112 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3113 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3116 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3119 if(tlbHeader
.CustomDataOffset
>= 0)
3121 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3124 /* fill in type descriptions */
3125 if(tlbSegDir
.pTypdescTab
.length
> 0)
3127 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3129 pTypeLibImpl
->ctTypeDesc
= cTD
;
3130 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3131 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3134 /* FIXME: add several sanity checks here */
3135 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3136 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3138 /* FIXME: check safearray */
3140 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3142 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3144 else if(td
[0] == VT_CARRAY
)
3146 /* array descr table here */
3147 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3149 else if(td
[0] == VT_USERDEFINED
)
3151 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3153 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3156 /* second time around to fill the array subscript info */
3159 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3160 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3162 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3163 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3166 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3168 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3170 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3172 for(j
= 0; j
<td
[2]; j
++)
3174 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3175 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3176 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3177 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3182 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3183 ERR("didn't find array description data\n");
3188 /* imported type libs */
3189 if(tlbSegDir
.pImpFiles
.offset
>0)
3192 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3195 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3199 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3200 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3201 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3203 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3204 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3205 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3206 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3209 name
= heap_alloc_zero(size
+1);
3210 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3211 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3214 MSFT_ReadGuid(&pImpLib
->guid
, oGuid
, &cx
);
3215 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3217 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3221 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3222 if(pTypeLibImpl
->dispatch_href
!= -1)
3223 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
3226 if(tlbHeader
.nrtypeinfos
>= 0 )
3228 ITypeInfoImpl
**ppTI
;
3231 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3233 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3235 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3238 (pTypeLibImpl
->TypeInfoCount
)++;
3242 TRACE("(%p)\n", pTypeLibImpl
);
3243 return &pTypeLibImpl
->ITypeLib2_iface
;
3247 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3253 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3254 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3258 guid
->Data4
[0] = s
>> 8;
3259 guid
->Data4
[1] = s
& 0xff;
3262 for(i
= 0; i
< 6; i
++) {
3263 memcpy(b
, str
+ 24 + 2 * i
, 2);
3264 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3269 static WORD
SLTG_ReadString(const char *ptr
, BSTR
*pBstr
)
3275 bytelen
= *(const WORD
*)ptr
;
3276 if(bytelen
== 0xffff) return 2;
3277 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3278 *pBstr
= SysAllocStringLen(NULL
, len
);
3280 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, *pBstr
, len
);
3284 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3289 bytelen
= *(const WORD
*)ptr
;
3290 if(bytelen
== 0xffff) return 2;
3291 *str
= heap_alloc(bytelen
+ 1);
3292 memcpy(*str
, ptr
+ 2, bytelen
);
3293 (*str
)[bytelen
] = '\0';
3297 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3299 char *ptr
= pLibBlk
;
3302 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3303 FIXME("libblk magic = %04x\n", w
);
3308 if((w
= *(WORD
*)ptr
) != 0xffff) {
3309 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3314 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
3316 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
3318 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3321 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
3324 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3325 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3327 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= 0;
3330 ptr
+= 4; /* skip res12 */
3332 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
3335 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
3338 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
3341 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
3342 ptr
+= sizeof(GUID
);
3344 return ptr
- (char*)pLibBlk
;
3347 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3352 } sltg_ref_lookup_t
;
3354 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3355 HREFTYPE
*typelib_ref
)
3357 if(table
&& typeinfo_ref
< table
->num
)
3359 *typelib_ref
= table
->refs
[typeinfo_ref
];
3363 ERR_(typelib
)("Unable to find reference\n");
3368 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3373 if((*pType
& 0xe00) == 0xe00) {
3375 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3376 pTD
= pTD
->u
.lptdesc
;
3378 switch(*pType
& 0x3f) {
3381 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3382 pTD
= pTD
->u
.lptdesc
;
3385 case VT_USERDEFINED
:
3386 pTD
->vt
= VT_USERDEFINED
;
3387 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3393 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3396 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3398 pTD
->vt
= VT_CARRAY
;
3399 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3400 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3401 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3402 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3404 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3410 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3414 pTD
->vt
= VT_SAFEARRAY
;
3415 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3416 pTD
= pTD
->u
.lptdesc
;
3420 pTD
->vt
= *pType
& 0x3f;
3429 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3430 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3432 /* Handle [in/out] first */
3433 if((*pType
& 0xc000) == 0xc000)
3434 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3435 else if(*pType
& 0x8000)
3436 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3437 else if(*pType
& 0x4000)
3438 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3440 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3443 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3446 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3448 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3452 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3457 TLBRefType
*ref_type
;
3458 sltg_ref_lookup_t
*table
;
3459 HREFTYPE typelib_ref
;
3461 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3462 FIXME("Ref magic = %x\n", pRef
->magic
);
3465 name
= ( (char*)pRef
->names
+ pRef
->number
);
3467 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3468 table
->num
= pRef
->number
>> 3;
3470 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3472 /* We don't want the first href to be 0 */
3473 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3475 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3477 unsigned int lib_offs
, type_num
;
3479 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3481 name
+= SLTG_ReadStringA(name
, &refname
);
3482 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3483 FIXME_(typelib
)("Can't sscanf ref\n");
3484 if(lib_offs
!= 0xffff) {
3487 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3488 if(import
->offset
== lib_offs
)
3491 if(&import
->entry
== &pTL
->implib_list
) {
3492 char fname
[MAX_PATH
+1];
3495 import
= heap_alloc_zero(sizeof(*import
));
3496 import
->offset
= lib_offs
;
3497 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
3499 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3500 &import
->wVersionMajor
,
3501 &import
->wVersionMinor
,
3502 &import
->lcid
, fname
) != 4) {
3503 FIXME_(typelib
)("can't sscanf ref %s\n",
3504 pNameTable
+ lib_offs
+ 40);
3506 len
= strlen(fname
);
3507 if(fname
[len
-1] != '#')
3508 FIXME("fname = %s\n", fname
);
3509 fname
[len
-1] = '\0';
3510 import
->name
= TLB_MultiByteToBSTR(fname
);
3511 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3513 ref_type
->pImpTLInfo
= import
;
3515 /* Store a reference to IDispatch */
3516 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
, &IID_StdOle
) && type_num
== 4)
3517 pTL
->dispatch_href
= typelib_ref
;
3519 } else { /* internal ref */
3520 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3522 ref_type
->reference
= typelib_ref
;
3523 ref_type
->index
= type_num
;
3526 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3528 table
->refs
[ref
] = typelib_ref
;
3531 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3532 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3533 dump_TLBRefType(pTL
);
3537 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3538 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3540 SLTG_ImplInfo
*info
;
3541 TLBImplType
*pImplType
;
3542 /* I don't really get this structure, usually it's 0x16 bytes
3543 long, but iuser.tlb contains some that are 0x18 bytes long.
3544 That's ok because we can use the next ptr to jump to the next
3545 one. But how do we know the length of the last one? The WORD
3546 at offs 0x8 might be the clue. For now I'm just assuming that
3547 the last one is the regular 0x16 bytes. */
3549 info
= (SLTG_ImplInfo
*)pBlk
;
3551 pTI
->TypeAttr
.cImplTypes
++;
3552 if(info
->next
== 0xffff)
3554 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3557 info
= (SLTG_ImplInfo
*)pBlk
;
3558 pTI
->impltypes
= TLBImplType_Constructor(pTI
->TypeAttr
.cImplTypes
);
3559 pImplType
= pTI
->impltypes
;
3561 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3562 pImplType
->implflags
= info
->impltypeflags
;
3565 if(info
->next
== 0xffff)
3568 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3569 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3571 info
++; /* see comment at top of function */
3575 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3576 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3578 TLBVarDesc
*pVarDesc
;
3579 BSTR bstrPrevName
= NULL
;
3580 SLTG_Variable
*pItem
;
3584 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Constructor(cVars
);
3586 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3587 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
3589 pVarDesc
->vardesc
.memid
= pItem
->memid
;
3591 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3592 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3593 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3597 if (pItem
->name
== 0xfffe)
3598 pVarDesc
->Name
= SysAllocString(bstrPrevName
);
3600 pVarDesc
->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3602 TRACE_(typelib
)("name: %s\n", debugstr_w(pVarDesc
->Name
));
3603 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3604 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3606 if(pItem
->flags
& 0x02)
3607 pType
= &pItem
->type
;
3609 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3611 if (pItem
->flags
& ~0xda)
3612 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3614 SLTG_DoElem(pType
, pBlk
,
3615 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
3617 if (TRACE_ON(typelib
)) {
3619 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
3620 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3623 if (pItem
->flags
& 0x40) {
3624 TRACE_(typelib
)("VAR_DISPATCH\n");
3625 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
3627 else if (pItem
->flags
& 0x10) {
3628 TRACE_(typelib
)("VAR_CONST\n");
3629 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
3630 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
3631 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
3632 if (pItem
->flags
& 0x08)
3633 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3635 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
3641 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3643 TRACE_(typelib
)("len = %u\n", len
);
3644 if (len
== 0xffff) {
3647 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3648 str
= SysAllocStringLen(NULL
, alloc_len
);
3649 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3651 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3652 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
3661 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
3662 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3665 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
3670 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3671 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
3672 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
3675 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3676 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
3678 if (pItem
->flags
& 0x80)
3679 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3681 bstrPrevName
= pVarDesc
->Name
;
3683 pTI
->TypeAttr
.cVars
= cVars
;
3686 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3687 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3689 SLTG_Function
*pFunc
;
3691 TLBFuncDesc
*pFuncDesc
;
3693 pTI
->funcdescs
= TLBFuncDesc_Constructor(cFuncs
);
3695 pFuncDesc
= pTI
->funcdescs
;
3696 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
3697 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
3702 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
3703 case SLTG_FUNCTION_MAGIC
:
3704 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
3706 case SLTG_DISPATCH_FUNCTION_MAGIC
:
3707 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
3709 case SLTG_STATIC_FUNCTION_MAGIC
:
3710 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
3713 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
3716 pFuncDesc
->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
3718 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
3719 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
3720 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
3721 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
3722 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
3723 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
3725 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
3726 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
3728 if(pFunc
->retnextopt
& 0x80)
3729 pType
= &pFunc
->rettype
;
3731 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
3733 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
3735 pFuncDesc
->funcdesc
.lprgelemdescParam
=
3736 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
3737 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
3739 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3741 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
3742 char *paramName
= pNameTable
+ *pArg
;
3744 /* If arg type follows then paramName points to the 2nd
3745 letter of the name, else the next WORD is an offset to
3746 the arg type and paramName points to the first letter.
3747 So let's take one char off paramName and see if we're
3748 pointing at an alpha-numeric char. However if *pArg is
3749 0xffff or 0xfffe then the param has no name, the former
3750 meaning that the next WORD is the type, the latter
3751 meaning that the next WORD is an offset to the type. */
3756 else if(*pArg
== 0xfffe) {
3760 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3765 if(HaveOffs
) { /* the next word is an offset to type */
3766 pType
= (WORD
*)(pBlk
+ *pArg
);
3767 SLTG_DoElem(pType
, pBlk
,
3768 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3773 pArg
= SLTG_DoElem(pArg
, pBlk
,
3774 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3777 /* Are we an optional param ? */
3778 if(pFuncDesc
->funcdesc
.cParams
- param
<=
3779 pFuncDesc
->funcdesc
.cParamsOpt
)
3780 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3783 pFuncDesc
->pParamDesc
[param
].Name
=
3784 TLB_MultiByteToBSTR(paramName
);
3786 pFuncDesc
->pParamDesc
[param
].Name
=
3787 SysAllocString(pFuncDesc
->Name
);
3791 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3794 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3795 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3796 SLTG_TypeInfoTail
*pTITail
)
3799 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3801 if(pTIHeader
->href_table
!= 0xffffffff) {
3802 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3808 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3809 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
3811 heap_free(ref_lookup
);
3815 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3816 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3817 const SLTG_TypeInfoTail
*pTITail
)
3820 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3822 if(pTIHeader
->href_table
!= 0xffffffff) {
3823 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3829 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3830 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
3833 if (pTITail
->funcs_off
!= 0xffff)
3834 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3836 heap_free(ref_lookup
);
3838 if (TRACE_ON(typelib
))
3839 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->TypeAttr
.cFuncs
);
3842 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3843 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3844 const SLTG_TypeInfoTail
*pTITail
)
3846 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3849 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3850 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3851 const SLTG_TypeInfoTail
*pTITail
)
3854 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3856 if (pTITail
->simple_alias
) {
3857 /* if simple alias, no more processing required */
3858 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3862 if(pTIHeader
->href_table
!= 0xffffffff) {
3863 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3867 /* otherwise it is an offset to a type */
3868 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3870 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
, ref_lookup
);
3872 heap_free(ref_lookup
);
3875 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3876 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3877 const SLTG_TypeInfoTail
*pTITail
)
3879 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3880 if (pTIHeader
->href_table
!= 0xffffffff)
3881 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3884 if (pTITail
->vars_off
!= 0xffff)
3885 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3887 if (pTITail
->funcs_off
!= 0xffff)
3888 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3890 if (pTITail
->impls_off
!= 0xffff)
3891 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
3893 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3894 * of dispinterface functions including the IDispatch ones, so
3895 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3896 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3898 heap_free(ref_lookup
);
3899 if (TRACE_ON(typelib
))
3900 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->TypeAttr
.cFuncs
);
3903 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3904 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3905 const SLTG_TypeInfoTail
*pTITail
)
3907 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3910 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
3911 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3912 const SLTG_TypeInfoTail
*pTITail
)
3914 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3915 if (pTIHeader
->href_table
!= 0xffffffff)
3916 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3919 if (pTITail
->vars_off
!= 0xffff)
3920 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3922 if (pTITail
->funcs_off
!= 0xffff)
3923 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3924 heap_free(ref_lookup
);
3925 if (TRACE_ON(typelib
))
3929 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3930 manageable copy of it into this */
3943 } SLTG_InternalOtherTypeInfo
;
3945 /****************************************************************************
3946 * ITypeLib2_Constructor_SLTG
3948 * loading a SLTG typelib from an in-memory image
3950 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3952 ITypeLibImpl
*pTypeLibImpl
;
3953 SLTG_Header
*pHeader
;
3954 SLTG_BlkEntry
*pBlkEntry
;
3958 LPVOID pBlk
, pFirstBlk
;
3959 SLTG_LibBlk
*pLibBlk
;
3960 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3961 char *pAfterOTIBlks
= NULL
;
3962 char *pNameTable
, *ptr
;
3965 ITypeInfoImpl
**ppTypeInfoImpl
;
3967 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3970 pTypeLibImpl
= TypeLibImpl_Constructor();
3971 if (!pTypeLibImpl
) return NULL
;
3975 TRACE_(typelib
)("header:\n");
3976 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
3977 pHeader
->nrOfFileBlks
);
3978 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3979 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
3980 pHeader
->SLTG_magic
);
3984 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3985 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3987 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3988 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3990 /* Next we have a magic block */
3991 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3993 /* Let's see if we're still in sync */
3994 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3995 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3996 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3999 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4000 sizeof(SLTG_DIR_MAGIC
))) {
4001 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4005 pIndex
= (SLTG_Index
*)(pMagic
+1);
4007 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4009 pFirstBlk
= pPad9
+ 1;
4011 /* We'll set up a ptr to the main library block, which is the last one. */
4013 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4014 pBlkEntry
[order
].next
!= 0;
4015 order
= pBlkEntry
[order
].next
- 1, i
++) {
4016 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4020 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4022 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4027 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4029 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4032 ptr
= (char*)pLibBlk
+ len
;
4034 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4038 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4040 w
= *(WORD
*)(ptr
+ 2);
4043 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4044 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4045 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4047 w
= *(WORD
*)(ptr
+ 4 + len
);
4049 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4051 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4052 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4053 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4055 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4056 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4057 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4059 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4060 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4063 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4064 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4065 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4066 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4067 len
+= sizeof(SLTG_OtherTypeInfo
);
4071 pAfterOTIBlks
= ptr
;
4073 /* Skip this WORD and get the next DWORD */
4074 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4076 /* Now add this to pLibBLk look at what we're pointing at and
4077 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4078 dust and we should be pointing at the beginning of the name
4081 pNameTable
= (char*)pLibBlk
+ len
;
4083 switch(*(WORD
*)pNameTable
) {
4090 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4094 pNameTable
+= 0x216;
4098 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4100 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
4103 /* Hopefully we now have enough ptrs set up to actually read in
4104 some TypeInfos. It's not clear which order to do them in, so
4105 I'll just follow the links along the BlkEntry chain and read
4106 them in the order in which they are in the file */
4108 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4109 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4111 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4112 pBlkEntry
[order
].next
!= 0;
4113 order
= pBlkEntry
[order
].next
- 1, i
++) {
4115 SLTG_TypeInfoHeader
*pTIHeader
;
4116 SLTG_TypeInfoTail
*pTITail
;
4117 SLTG_MemberHeader
*pMemHeader
;
4119 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4120 FIXME_(typelib
)("Index strings don't match\n");
4121 heap_free(pOtherTypeInfoBlks
);
4126 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4127 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4128 heap_free(pOtherTypeInfoBlks
);
4131 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4132 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4133 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4135 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4136 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4137 (*ppTypeInfoImpl
)->index
= i
;
4138 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
4139 pOtherTypeInfoBlks
[i
].name_offs
+
4141 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4142 (*ppTypeInfoImpl
)->TypeAttr
.guid
= pOtherTypeInfoBlks
[i
].uuid
;
4143 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
4144 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
4145 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
4146 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
4147 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4149 if((*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4150 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= TKIND_DISPATCH
;
4152 if((pTIHeader
->typeflags1
& 7) != 2)
4153 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4154 if(pTIHeader
->typeflags3
!= 2)
4155 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4157 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4158 debugstr_w((*ppTypeInfoImpl
)->Name
),
4159 typekind_desc
[pTIHeader
->typekind
],
4160 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
4161 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
4163 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4165 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4167 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
4168 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4169 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
4171 switch(pTIHeader
->typekind
) {
4173 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4174 pTIHeader
, pTITail
);
4178 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4179 pTIHeader
, pTITail
);
4182 case TKIND_INTERFACE
:
4183 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4184 pTIHeader
, pTITail
);
4188 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4189 pTIHeader
, pTITail
);
4193 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4194 pTIHeader
, pTITail
);
4197 case TKIND_DISPATCH
:
4198 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4199 pTIHeader
, pTITail
);
4203 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4204 pTIHeader
, pTITail
);
4208 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4213 /* could get cFuncs, cVars and cImplTypes from here
4214 but we've already set those */
4215 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4231 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4234 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4235 FIXME("Somehow processed %d TypeInfos\n", i
);
4236 heap_free(pOtherTypeInfoBlks
);
4240 heap_free(pOtherTypeInfoBlks
);
4241 return &pTypeLibImpl
->ITypeLib2_iface
;
4244 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4246 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4248 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4250 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4251 IsEqualIID(riid
,&IID_ITypeLib
)||
4252 IsEqualIID(riid
,&IID_ITypeLib2
))
4254 *ppv
= &This
->ITypeLib2_iface
;
4259 TRACE("-- Interface: E_NOINTERFACE\n");
4260 return E_NOINTERFACE
;
4263 IUnknown_AddRef((IUnknown
*)*ppv
);
4267 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4269 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4270 ULONG ref
= InterlockedIncrement(&This
->ref
);
4272 TRACE("(%p) ref=%u\n", This
, ref
);
4277 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4279 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4280 ULONG ref
= InterlockedDecrement(&This
->ref
);
4282 TRACE("(%p) ref=%u\n",This
, ref
);
4286 TLBImpLib
*pImpLib
, *pImpLibNext
;
4287 TLBRefType
*ref_type
;
4291 /* remove cache entry */
4294 TRACE("removing from cache list\n");
4295 EnterCriticalSection(&cache_section
);
4296 if(This
->entry
.next
)
4297 list_remove(&This
->entry
);
4298 LeaveCriticalSection(&cache_section
);
4299 heap_free(This
->path
);
4301 TRACE(" destroying ITypeLib(%p)\n",This
);
4303 SysFreeString(This
->Name
);
4306 SysFreeString(This
->DocString
);
4307 This
->DocString
= NULL
;
4309 SysFreeString(This
->HelpFile
);
4310 This
->HelpFile
= NULL
;
4312 SysFreeString(This
->HelpStringDll
);
4313 This
->HelpStringDll
= NULL
;
4315 TLB_FreeCustData(&This
->custdata_list
);
4317 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4318 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4319 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4321 heap_free(This
->pTypeDesc
);
4323 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4325 if (pImpLib
->pImpTypeLib
)
4326 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4327 SysFreeString(pImpLib
->name
);
4329 list_remove(&pImpLib
->entry
);
4333 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4335 list_remove(&ref_type
->entry
);
4336 heap_free(ref_type
);
4339 for (i
= 0; i
< This
->TypeInfoCount
; ++i
)
4340 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4341 heap_free(This
->typeinfos
);
4349 /* ITypeLib::GetTypeInfoCount
4351 * Returns the number of type descriptions in the type library
4353 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4355 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4356 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4357 return This
->TypeInfoCount
;
4360 /* ITypeLib::GetTypeInfo
4362 * retrieves the specified type description in the library.
4364 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4367 ITypeInfo
**ppTInfo
)
4369 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4371 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4374 return E_INVALIDARG
;
4376 if(index
>= This
->TypeInfoCount
)
4377 return TYPE_E_ELEMENTNOTFOUND
;
4379 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[index
];
4380 ITypeInfo_AddRef(*ppTInfo
);
4386 /* ITypeLibs::GetTypeInfoType
4388 * Retrieves the type of a type description.
4390 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4395 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4397 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4400 return E_INVALIDARG
;
4402 if(index
>= This
->TypeInfoCount
)
4403 return TYPE_E_ELEMENTNOTFOUND
;
4405 *pTKind
= This
->typeinfos
[index
]->TypeAttr
.typekind
;
4410 /* ITypeLib::GetTypeInfoOfGuid
4412 * Retrieves the type description that corresponds to the specified GUID.
4415 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4418 ITypeInfo
**ppTInfo
)
4420 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4423 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4425 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4426 if(IsEqualIID(&This
->typeinfos
[i
]->TypeAttr
.guid
, guid
)){
4427 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[i
];
4428 ITypeInfo_AddRef(*ppTInfo
);
4433 return TYPE_E_ELEMENTNOTFOUND
;
4436 /* ITypeLib::GetLibAttr
4438 * Retrieves the structure that contains the library's attributes.
4441 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4445 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4447 TRACE("(%p, %p)\n", This
, attr
);
4449 if (!attr
) return E_INVALIDARG
;
4451 *attr
= heap_alloc(sizeof(**attr
));
4452 if (!*attr
) return E_OUTOFMEMORY
;
4454 **attr
= This
->LibAttr
;
4458 /* ITypeLib::GetTypeComp
4460 * Enables a client compiler to bind to a library's types, variables,
4461 * constants, and global functions.
4464 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4466 ITypeComp
**ppTComp
)
4468 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4470 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4471 *ppTComp
= &This
->ITypeComp_iface
;
4472 ITypeComp_AddRef(*ppTComp
);
4477 /* ITypeLib::GetDocumentation
4479 * Retrieves the library's documentation string, the complete Help file name
4480 * and path, and the context identifier for the library Help topic in the Help
4483 * On a successful return all non-null BSTR pointers will have been set,
4486 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4490 BSTR
*pBstrDocString
,
4491 DWORD
*pdwHelpContext
,
4492 BSTR
*pBstrHelpFile
)
4494 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4495 HRESULT result
= E_INVALIDARG
;
4498 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4500 pBstrName
, pBstrDocString
,
4501 pdwHelpContext
, pBstrHelpFile
);
4505 /* documentation for the typelib */
4510 if(!(*pBstrName
= SysAllocString(This
->Name
)))
4518 if (This
->DocString
)
4520 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
4523 else if (This
->Name
)
4525 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
4529 *pBstrDocString
= NULL
;
4533 *pdwHelpContext
= This
->dwHelpContext
;
4539 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
4543 *pBstrHelpFile
= NULL
;
4550 /* for a typeinfo */
4551 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4553 if(SUCCEEDED(result
))
4555 result
= ITypeInfo_GetDocumentation(pTInfo
,
4559 pdwHelpContext
, pBstrHelpFile
);
4561 ITypeInfo_Release(pTInfo
);
4566 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4568 if (pBstrName
) SysFreeString (*pBstrName
);
4570 return STG_E_INSUFFICIENTMEMORY
;
4575 * Indicates whether a passed-in string contains the name of a type or member
4576 * described in the library.
4579 static HRESULT WINAPI
ITypeLib2_fnIsName(
4585 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4587 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
4589 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4593 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
4594 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4595 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4596 for(fdc
= 0; fdc
< pTInfo
->TypeAttr
.cFuncs
; ++fdc
) {
4597 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
4600 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4601 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++)
4602 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
4603 goto ITypeLib2_fnIsName_exit
;
4605 for(vrc
= 0; vrc
< pTInfo
->TypeAttr
.cVars
; ++vrc
){
4606 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
4607 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4613 ITypeLib2_fnIsName_exit
:
4614 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4615 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4620 /* ITypeLib::FindName
4622 * Finds occurrences of a type description in a type library. This may be used
4623 * to quickly verify that a name exists in a type library.
4626 static HRESULT WINAPI
ITypeLib2_fnFindName(
4630 ITypeInfo
**ppTInfo
,
4634 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4639 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
4641 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
4642 return E_INVALIDARG
;
4644 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
4645 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
4646 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4650 if(!memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4651 for(fdc
= 0; fdc
< pTInfo
->TypeAttr
.cFuncs
; ++fdc
) {
4652 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
4655 if(!memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4656 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
4657 if(!memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
4658 goto ITypeLib2_fnFindName_exit
;
4662 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->TypeAttr
.cVars
, name
);
4664 goto ITypeLib2_fnFindName_exit
;
4667 ITypeLib2_fnFindName_exit
:
4668 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4669 ppTInfo
[count
]=(LPTYPEINFO
)pTInfo
;
4672 TRACE("found %d typeinfos\n", count
);
4679 /* ITypeLib::ReleaseTLibAttr
4681 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4684 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4686 TLIBATTR
*pTLibAttr
)
4688 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4689 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
4690 heap_free(pTLibAttr
);
4693 /* ITypeLib2::GetCustData
4695 * gets the custom data
4697 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
4702 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4703 TLBCustData
*pCData
;
4705 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
4707 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
4709 return TYPE_E_ELEMENTNOTFOUND
;
4711 VariantInit(pVarVal
);
4712 VariantCopy(pVarVal
, &pCData
->data
);
4717 /* ITypeLib2::GetLibStatistics
4719 * Returns statistics about a type library that are required for efficient
4720 * sizing of hash tables.
4723 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4725 ULONG
*pcUniqueNames
,
4726 ULONG
*pcchUniqueNames
)
4728 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4730 FIXME("(%p): stub!\n", This
);
4732 if(pcUniqueNames
) *pcUniqueNames
=1;
4733 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4737 /* ITypeLib2::GetDocumentation2
4739 * Retrieves the library's documentation string, the complete Help file name
4740 * and path, the localization context to use, and the context ID for the
4741 * library Help topic in the Help file.
4744 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4748 BSTR
*pbstrHelpString
,
4749 DWORD
*pdwHelpStringContext
,
4750 BSTR
*pbstrHelpStringDll
)
4752 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4756 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4758 /* the help string should be obtained from the helpstringdll,
4759 * using the _DLLGetDocumentation function, based on the supplied
4760 * lcid. Nice to do sometime...
4764 /* documentation for the typelib */
4766 *pbstrHelpString
=SysAllocString(This
->DocString
);
4767 if(pdwHelpStringContext
)
4768 *pdwHelpStringContext
=This
->dwHelpContext
;
4769 if(pbstrHelpStringDll
)
4770 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
4776 /* for a typeinfo */
4777 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
4779 if(SUCCEEDED(result
))
4781 ITypeInfo2
* pTInfo2
;
4782 result
= ITypeInfo_QueryInterface(pTInfo
,
4784 (LPVOID
*) &pTInfo2
);
4786 if(SUCCEEDED(result
))
4788 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4792 pdwHelpStringContext
,
4793 pbstrHelpStringDll
);
4795 ITypeInfo2_Release(pTInfo2
);
4798 ITypeInfo_Release(pTInfo
);
4804 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
4806 TLBCustData
*pCData
;
4810 ct
= list_count(custdata_list
);
4812 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
4813 if(!pCustData
->prgCustData
)
4814 return E_OUTOFMEMORY
;
4816 pCustData
->cCustData
= ct
;
4818 cdi
= pCustData
->prgCustData
;
4819 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
4820 cdi
->guid
= pCData
->guid
;
4821 VariantCopy(&cdi
->varValue
, &pCData
->data
);
4829 /* ITypeLib2::GetAllCustData
4831 * Gets all custom data items for the library.
4834 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4836 CUSTDATA
*pCustData
)
4838 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4839 TRACE("(%p)->(%p)\n", This
, pCustData
);
4840 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
4843 static const ITypeLib2Vtbl tlbvt
= {
4844 ITypeLib2_fnQueryInterface
,
4846 ITypeLib2_fnRelease
,
4847 ITypeLib2_fnGetTypeInfoCount
,
4848 ITypeLib2_fnGetTypeInfo
,
4849 ITypeLib2_fnGetTypeInfoType
,
4850 ITypeLib2_fnGetTypeInfoOfGuid
,
4851 ITypeLib2_fnGetLibAttr
,
4852 ITypeLib2_fnGetTypeComp
,
4853 ITypeLib2_fnGetDocumentation
,
4855 ITypeLib2_fnFindName
,
4856 ITypeLib2_fnReleaseTLibAttr
,
4858 ITypeLib2_fnGetCustData
,
4859 ITypeLib2_fnGetLibStatistics
,
4860 ITypeLib2_fnGetDocumentation2
,
4861 ITypeLib2_fnGetAllCustData
4865 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4867 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4869 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
4872 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4874 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4876 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
4879 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4881 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4883 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
4886 static HRESULT WINAPI
ITypeLibComp_fnBind(
4891 ITypeInfo
** ppTInfo
,
4892 DESCKIND
* pDescKind
,
4895 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4896 int typemismatch
=0, i
;
4898 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4900 *pDescKind
= DESCKIND_NONE
;
4901 pBindPtr
->lptcomp
= NULL
;
4904 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4905 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
4906 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4908 /* FIXME: check wFlags here? */
4909 /* FIXME: we should use a hash table to look this info up using lHash
4910 * instead of an O(n) search */
4911 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4912 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4914 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4916 *pDescKind
= DESCKIND_TYPECOMP
;
4917 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
4918 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4919 TRACE("module or enum: %s\n", debugstr_w(szName
));
4924 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4925 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4927 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
4930 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4931 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4933 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4936 else if (hr
== TYPE_E_TYPEMISMATCH
)
4940 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4941 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4943 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
4945 ITypeInfo
*subtypeinfo
;
4947 DESCKIND subdesckind
;
4949 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4950 &subtypeinfo
, &subdesckind
, &subbindptr
);
4951 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4953 TYPEDESC tdesc_appobject
;
4954 const VARDESC vardesc_appobject
=
4957 NULL
, /* lpstrSchema */
4972 VAR_STATIC
/* varkind */
4975 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
4976 tdesc_appobject
.vt
= VT_USERDEFINED
;
4978 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
4980 /* cleanup things filled in by Bind call so we can put our
4981 * application object data in there instead */
4982 switch (subdesckind
)
4984 case DESCKIND_FUNCDESC
:
4985 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
4987 case DESCKIND_VARDESC
:
4988 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
4993 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
4995 if (pTypeInfo
->hreftype
== -1)
4996 FIXME("no hreftype for interface %p\n", pTypeInfo
);
4998 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5002 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5003 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
5004 ITypeInfo_AddRef(*ppTInfo
);
5007 else if (hr
== TYPE_E_TYPEMISMATCH
)
5014 TRACE("type mismatch %s\n", debugstr_w(szName
));
5015 return TYPE_E_TYPEMISMATCH
;
5019 TRACE("name not found %s\n", debugstr_w(szName
));
5024 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5028 ITypeInfo
** ppTInfo
,
5029 ITypeComp
** ppTComp
)
5031 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5034 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5036 if(!szName
|| !ppTInfo
|| !ppTComp
)
5037 return E_INVALIDARG
;
5039 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
5041 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5042 /* FIXME: should use lHash to do the search */
5043 if (pTypeInfo
->Name
&& !strcmpiW(pTypeInfo
->Name
, szName
))
5045 TRACE("returning %p\n", pTypeInfo
);
5046 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5047 ITypeInfo_AddRef(*ppTInfo
);
5048 *ppTComp
= &pTypeInfo
->ITypeComp_iface
;
5049 ITypeComp_AddRef(*ppTComp
);
5054 TRACE("not found\n");
5060 static const ITypeCompVtbl tlbtcvt
=
5063 ITypeLibComp_fnQueryInterface
,
5064 ITypeLibComp_fnAddRef
,
5065 ITypeLibComp_fnRelease
,
5067 ITypeLibComp_fnBind
,
5068 ITypeLibComp_fnBindType
5071 /*================== ITypeInfo(2) Methods ===================================*/
5072 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5074 ITypeInfoImpl
*pTypeInfoImpl
;
5076 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5079 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5080 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5081 pTypeInfoImpl
->ref
= 0;
5082 pTypeInfoImpl
->hreftype
= -1;
5083 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
5084 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
5085 list_init(&pTypeInfoImpl
->custdata_list
);
5087 TRACE("(%p)\n", pTypeInfoImpl
);
5088 return pTypeInfoImpl
;
5091 /* ITypeInfo::QueryInterface
5093 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5098 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5100 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5103 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5104 IsEqualIID(riid
,&IID_ITypeInfo
)||
5105 IsEqualIID(riid
,&IID_ITypeInfo2
))
5109 ITypeInfo2_AddRef(iface
);
5110 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5113 TRACE("-- Interface: E_NOINTERFACE\n");
5114 return E_NOINTERFACE
;
5117 /* ITypeInfo::AddRef
5119 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5121 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5122 ULONG ref
= InterlockedIncrement(&This
->ref
);
5124 TRACE("(%p)->ref is %u\n",This
, ref
);
5126 if (ref
== 1 /* incremented from 0 */)
5127 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5132 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5136 TRACE("destroying ITypeInfo(%p)\n",This
);
5138 SysFreeString(This
->Name
);
5141 SysFreeString(This
->DocString
);
5142 This
->DocString
= NULL
;
5144 SysFreeString(This
->DllName
);
5145 This
->DllName
= NULL
;
5147 for (i
= 0; i
< This
->TypeAttr
.cFuncs
; ++i
)
5150 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5151 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5153 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5154 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5156 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5157 heap_free(elemdesc
->u
.paramdesc
.pparamdescex
);
5159 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5160 SysFreeString(pFInfo
->pParamDesc
[j
].Name
);
5162 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5163 heap_free(pFInfo
->pParamDesc
);
5164 TLB_FreeCustData(&pFInfo
->custdata_list
);
5165 if (!IS_INTRESOURCE(pFInfo
->Entry
) && pFInfo
->Entry
!= (BSTR
)-1)
5166 SysFreeString(pFInfo
->Entry
);
5167 SysFreeString(pFInfo
->HelpString
);
5168 SysFreeString(pFInfo
->Name
);
5170 heap_free(This
->funcdescs
);
5172 for(i
= 0; i
< This
->TypeAttr
.cVars
; ++i
)
5174 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5175 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
5177 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5178 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5180 TLB_FreeCustData(&pVInfo
->custdata_list
);
5181 SysFreeString(pVInfo
->Name
);
5182 SysFreeString(pVInfo
->HelpString
);
5184 heap_free(This
->vardescs
);
5186 if(This
->impltypes
){
5187 for (i
= 0; i
< This
->TypeAttr
.cImplTypes
; ++i
){
5188 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5189 TLB_FreeCustData(&pImpl
->custdata_list
);
5191 heap_free(This
->impltypes
);
5194 TLB_FreeCustData(&This
->custdata_list
);
5199 /* ITypeInfo::Release
5201 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5203 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5204 ULONG ref
= InterlockedDecrement(&This
->ref
);
5206 TRACE("(%p)->(%u)\n",This
, ref
);
5210 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5211 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5212 if (not_attached_to_typelib
)
5214 /* otherwise This will be freed when typelib is freed */
5220 /* ITypeInfo::GetTypeAttr
5222 * Retrieves a TYPEATTR structure that contains the attributes of the type
5226 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5227 LPTYPEATTR
*ppTypeAttr
)
5229 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5232 TRACE("(%p)\n",This
);
5234 size
= sizeof(**ppTypeAttr
);
5235 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5236 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
5238 *ppTypeAttr
= heap_alloc(size
);
5240 return E_OUTOFMEMORY
;
5242 **ppTypeAttr
= This
->TypeAttr
;
5244 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5245 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5246 &This
->TypeAttr
.tdescAlias
, *ppTypeAttr
+ 1);
5248 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5249 /* This should include all the inherited funcs */
5250 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ sizeof(void *);
5251 /* This is always the size of IDispatch's vtbl */
5252 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5253 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5258 /* ITypeInfo::GetTypeComp
5260 * Retrieves the ITypeComp interface for the type description, which enables a
5261 * client compiler to bind to the type description's members.
5264 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5265 ITypeComp
* *ppTComp
)
5267 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5269 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5271 *ppTComp
= &This
->ITypeComp_iface
;
5272 ITypeComp_AddRef(*ppTComp
);
5276 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5278 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5279 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5280 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5284 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5287 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5288 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5290 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5291 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5292 *buffer
+= sizeof(PARAMDESCEX
);
5293 *pparamdescex_dest
= *pparamdescex_src
;
5294 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5295 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5296 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5299 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5303 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5305 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5306 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5309 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5313 SIZE_T size
= sizeof(*src
);
5317 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5318 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5319 for (i
= 0; i
< src
->cParams
; i
++)
5321 size
+= sizeof(ELEMDESC
);
5322 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5325 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5326 if (!dest
) return E_OUTOFMEMORY
;
5329 if (dispinterface
) /* overwrite funckind */
5330 dest
->funckind
= FUNC_DISPATCH
;
5331 buffer
= (char *)(dest
+ 1);
5333 if (dest
->cScodes
) {
5334 dest
->lprgscode
= (SCODE
*)buffer
;
5335 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5336 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5338 dest
->lprgscode
= NULL
;
5340 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5343 SysFreeString((BSTR
)dest
);
5347 if (dest
->cParams
) {
5348 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5349 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5350 for (i
= 0; i
< src
->cParams
; i
++)
5352 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5358 /* undo the above actions */
5359 for (i
= i
- 1; i
>= 0; i
--)
5360 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5361 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5362 SysFreeString((BSTR
)dest
);
5366 dest
->lprgelemdescParam
= NULL
;
5368 /* special treatment for dispinterfaces: this makes functions appear
5369 * to return their [retval] value when it is really returning an
5371 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5373 if (dest
->cParams
&&
5374 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5376 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5377 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5379 ERR("elemdesc should have started with VT_PTR instead of:\n");
5381 dump_ELEMDESC(elemdesc
);
5382 return E_UNEXPECTED
;
5385 /* copy last parameter to the return value. we are using a flat
5386 * buffer so there is no danger of leaking memory in
5388 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5390 /* remove the last parameter */
5394 /* otherwise this function is made to appear to have no return
5396 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5404 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5406 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5408 if (index
>= This
->TypeAttr
.cFuncs
)
5409 return TYPE_E_ELEMENTNOTFOUND
;
5411 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5415 /* internal function to make the inherited interfaces' methods appear
5416 * part of the interface */
5417 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5418 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5420 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5422 UINT implemented_funcs
= 0;
5427 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5431 ITypeInfo
*pSubTypeInfo
;
5434 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5438 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5441 &sub_funcs
, hrefoffset
);
5442 implemented_funcs
+= sub_funcs
;
5443 ITypeInfo_Release(pSubTypeInfo
);
5446 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5450 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
5454 if (index
< implemented_funcs
)
5455 return E_INVALIDARG
;
5456 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5460 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5462 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5465 switch (pTypeDesc
->vt
)
5467 case VT_USERDEFINED
:
5468 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5472 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5475 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5483 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5486 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5487 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5488 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5491 /* ITypeInfo::GetFuncDesc
5493 * Retrieves the FUNCDESC structure that contains information about a
5494 * specified function.
5497 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5498 LPFUNCDESC
*ppFuncDesc
)
5500 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5501 const FUNCDESC
*internal_funcdesc
;
5503 UINT hrefoffset
= 0;
5505 TRACE("(%p) index %d\n", This
, index
);
5508 return E_INVALIDARG
;
5510 if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5511 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5512 &internal_funcdesc
, NULL
,
5515 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5516 &internal_funcdesc
);
5519 WARN("description for function %d not found\n", index
);
5523 hr
= TLB_AllocAndInitFuncDesc(
5526 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
5528 if ((This
->TypeAttr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5529 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5531 TRACE("-- 0x%08x\n", hr
);
5535 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5539 SIZE_T size
= sizeof(*src
);
5542 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5543 if (src
->varkind
== VAR_CONST
)
5544 size
+= sizeof(VARIANT
);
5545 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5547 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5548 if (!dest
) return E_OUTOFMEMORY
;
5551 buffer
= (char *)(dest
+ 1);
5552 if (src
->lpstrSchema
)
5555 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5556 len
= strlenW(src
->lpstrSchema
);
5557 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5558 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5561 if (src
->varkind
== VAR_CONST
)
5565 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5566 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5567 buffer
+= sizeof(VARIANT
);
5568 VariantInit(dest
->u
.lpvarValue
);
5569 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5572 SysFreeString((BSTR
)dest
);
5576 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5579 if (src
->varkind
== VAR_CONST
)
5580 VariantClear(dest
->u
.lpvarValue
);
5581 SysFreeString((BSTR
)dest
);
5588 /* ITypeInfo::GetVarDesc
5590 * Retrieves a VARDESC structure that describes the specified variable.
5593 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5594 LPVARDESC
*ppVarDesc
)
5596 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5597 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
5599 TRACE("(%p) index %d\n", This
, index
);
5601 if(index
>= This
->TypeAttr
.cVars
)
5602 return TYPE_E_ELEMENTNOTFOUND
;
5604 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5607 /* ITypeInfo_GetNames
5609 * Retrieves the variable with the specified member ID (or the name of the
5610 * property or method and its parameters) that correspond to the specified
5613 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5614 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5616 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5617 const TLBFuncDesc
*pFDesc
;
5618 const TLBVarDesc
*pVDesc
;
5620 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5621 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
5624 /* function found, now return function and parameter names */
5625 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
5628 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
5630 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
5636 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
5639 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
5644 if(This
->impltypes
&&
5645 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
5646 /* recursive search */
5649 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
5650 if(SUCCEEDED(result
))
5652 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5653 ITypeInfo_Release(pTInfo
);
5656 WARN("Could not search inherited interface!\n");
5660 WARN("no names found\n");
5663 return TYPE_E_ELEMENTNOTFOUND
;
5670 /* ITypeInfo::GetRefTypeOfImplType
5672 * If a type description describes a COM class, it retrieves the type
5673 * description of the implemented interface types. For an interface,
5674 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5678 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
5683 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5686 TRACE("(%p) index %d\n", This
, index
);
5687 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
5691 /* only valid on dual interfaces;
5692 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5694 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
5696 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
5702 hr
= TYPE_E_ELEMENTNOTFOUND
;
5705 else if(index
== 0 && This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5707 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5708 *pRefType
= This
->pTypeLib
->dispatch_href
;
5712 if(index
>= This
->TypeAttr
.cImplTypes
)
5713 hr
= TYPE_E_ELEMENTNOTFOUND
;
5715 *pRefType
= This
->impltypes
[index
].hRef
;
5721 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
5723 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
5729 /* ITypeInfo::GetImplTypeFlags
5731 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5732 * or base interface in a type description.
5734 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
5735 UINT index
, INT
*pImplTypeFlags
)
5737 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5739 TRACE("(%p) index %d\n", This
, index
);
5742 return E_INVALIDARG
;
5744 if(This
->TypeAttr
.typekind
== TKIND_DISPATCH
&& index
== 0){
5745 *pImplTypeFlags
= 0;
5749 if(index
>= This
->TypeAttr
.cImplTypes
)
5750 return TYPE_E_ELEMENTNOTFOUND
;
5752 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
5758 * Maps between member names and member IDs, and parameter names and
5761 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
5762 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
5764 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5765 const TLBVarDesc
*pVDesc
;
5769 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
5772 /* init out parameters in case of failure */
5773 for (i
= 0; i
< cNames
; i
++)
5774 pMemId
[i
] = MEMBERID_NIL
;
5776 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
) {
5778 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
5779 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
5780 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
5781 for(i
=1; i
< cNames
; i
++){
5782 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
5783 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
5785 if( j
<pFDesc
->funcdesc
.cParams
)
5788 ret
=DISP_E_UNKNOWNNAME
;
5790 TRACE("-- 0x%08x\n", ret
);
5794 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->TypeAttr
.cVars
, *rgszNames
);
5797 *pMemId
= pVDesc
->vardesc
.memid
;
5800 /* not found, see if it can be found in an inherited interface */
5801 if(This
->impltypes
) {
5802 /* recursive search */
5804 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
5806 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
5807 ITypeInfo_Release(pTInfo
);
5810 WARN("Could not search inherited interface!\n");
5812 WARN("no names found\n");
5813 return DISP_E_UNKNOWNNAME
;
5819 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
5820 __ASM_GLOBAL_FUNC( call_method
,
5822 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5823 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5824 "movl %esp,%ebp\n\t"
5825 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5827 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5829 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5830 "movl 12(%ebp),%edx\n\t"
5831 "movl %esp,%edi\n\t"
5834 "subl %edx,%edi\n\t"
5835 "andl $~15,%edi\n\t"
5836 "movl %edi,%esp\n\t"
5837 "movl 12(%ebp),%ecx\n\t"
5838 "movl 16(%ebp),%esi\n\t"
5841 "1:\tcall *8(%ebp)\n\t"
5842 "subl %esp,%edi\n\t"
5843 "movl 20(%ebp),%ecx\n\t"
5844 "movl %edi,(%ecx)\n\t"
5845 "leal -8(%ebp),%esp\n\t"
5847 __ASM_CFI(".cfi_same_value %edi\n\t")
5849 __ASM_CFI(".cfi_same_value %esi\n\t")
5851 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5852 __ASM_CFI(".cfi_same_value %ebp\n\t")
5855 /* same function but returning floating point */
5856 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
5858 /* ITypeInfo::Invoke
5860 * Invokes a method, or accesses a property of an object, that implements the
5861 * interface described by the type description.
5864 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
5868 if (TRACE_ON(ole
)) {
5870 TRACE("Calling %p(",func
);
5871 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
5872 if (nrargs
> 30) TRACE("...");
5879 res
= call_method( func
, nrargs
, args
, &stack_offset
);
5882 FIXME("unsupported calling convention %d\n",callconv
);
5886 TRACE("returns %08x\n",res
);
5890 #elif defined(__x86_64__)
5892 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
5893 __ASM_GLOBAL_FUNC( call_method
,
5895 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5896 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5897 "movq %rsp,%rbp\n\t"
5898 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5900 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5902 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5903 "movq %rcx,%rax\n\t"
5906 "cmovgq %rdx,%rcx\n\t"
5907 "leaq 0(,%rcx,8),%rdx\n\t"
5908 "subq %rdx,%rsp\n\t"
5909 "andq $~15,%rsp\n\t"
5910 "movq %rsp,%rdi\n\t"
5913 "movq 0(%rsp),%rcx\n\t"
5914 "movq 8(%rsp),%rdx\n\t"
5915 "movq 16(%rsp),%r8\n\t"
5916 "movq 24(%rsp),%r9\n\t"
5917 "movq %rcx,%xmm0\n\t"
5918 "movq %rdx,%xmm1\n\t"
5919 "movq %r8,%xmm2\n\t"
5920 "movq %r9,%xmm3\n\t"
5922 "leaq -16(%rbp),%rsp\n\t"
5924 __ASM_CFI(".cfi_same_value %rdi\n\t")
5926 __ASM_CFI(".cfi_same_value %rsi\n\t")
5927 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5929 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5930 __ASM_CFI(".cfi_same_value %rbp\n\t")
5933 /* same function but returning floating point */
5934 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
5936 #endif /* __x86_64__ */
5938 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5941 ITypeInfo
*tinfo2
= NULL
;
5942 TYPEATTR
*tattr
= NULL
;
5944 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
5947 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5949 tdesc
->u
.hreftype
, hr
);
5952 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
5955 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
5956 ITypeInfo_Release(tinfo2
);
5960 switch (tattr
->typekind
)
5967 tdesc
= &tattr
->tdescAlias
;
5968 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
5971 case TKIND_INTERFACE
:
5972 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
5978 case TKIND_DISPATCH
:
5987 FIXME("TKIND_RECORD unhandled.\n");
5992 FIXME("TKIND_UNION unhandled.\n");
5997 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6001 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6002 ITypeInfo_Release(tinfo2
);
6006 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6010 /* enforce only one level of pointer indirection */
6011 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6013 tdesc
= tdesc
->u
.lptdesc
;
6015 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6016 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6017 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6018 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6019 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6021 VARTYPE vt_userdefined
= 0;
6022 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6023 if (tdesc
->vt
== VT_PTR
)
6025 vt_userdefined
= VT_BYREF
;
6026 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6028 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6030 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6031 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6033 *vt
|= vt_userdefined
;
6045 case VT_USERDEFINED
:
6046 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6053 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6054 hr
= DISP_E_BADVARTYPE
;
6058 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6073 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6079 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6083 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6085 ITypeInfo_Release(tinfo2
);
6089 switch(tattr
->typekind
) {
6091 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6094 case TKIND_INTERFACE
:
6095 case TKIND_DISPATCH
:
6096 *guid
= tattr
->guid
;
6100 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6101 hres
= E_UNEXPECTED
;
6104 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6105 ITypeInfo_Release(tinfo2
);
6109 /***********************************************************************
6110 * DispCallFunc (OLEAUT32.@)
6112 * Invokes a function of the specified calling convention, passing the
6113 * specified arguments and returns the result.
6116 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6117 * oVft [I] The offset in the vtable. See notes.
6118 * cc [I] Calling convention of the function to call.
6119 * vtReturn [I] The return type of the function.
6120 * cActuals [I] Number of parameters.
6121 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6122 * prgpvarg [I] The arguments to pass.
6123 * pvargResult [O] The return value of the function. Can be NULL.
6127 * Failure: HRESULT code.
6130 * The HRESULT return value of this function is not affected by the return
6131 * value of the user supplied function, which is returned in pvargResult.
6133 * If pvInstance is NULL then a non-object function is to be called and oVft
6134 * is the address of the function to call.
6136 * The cc parameter can be one of the following values:
6149 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6150 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6153 int argspos
, stack_offset
;
6158 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6159 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6160 pvargResult
, V_VT(pvargResult
));
6162 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6164 FIXME("unsupported calling convention %d\n",cc
);
6165 return E_INVALIDARG
;
6168 /* maximum size for an argument is sizeof(VARIANT) */
6169 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6171 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6175 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6176 func
= vtable
[oVft
/sizeof(void *)];
6177 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6179 else func
= (void *)oVft
;
6181 for (i
= 0; i
< cActuals
; i
++)
6183 VARIANT
*arg
= prgpvarg
[i
];
6194 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6195 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6199 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6200 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6202 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6203 args
[argspos
++] = V_BOOL(arg
);
6206 args
[argspos
++] = V_UI4(arg
);
6209 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6216 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6219 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6223 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6227 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6228 call_method( func
, argspos
, args
, &stack_offset
);
6233 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6236 WARN("invalid return type %u\n", vtReturn
);
6238 return E_INVALIDARG
;
6240 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6244 if (stack_offset
&& cc
== CC_STDCALL
)
6246 WARN( "stack pointer off by %d\n", stack_offset
);
6247 return DISP_E_BADCALLEE
;
6249 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6250 TRACE("retval: "); dump_Variant(pvargResult
);
6253 #elif defined(__x86_64__)
6259 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6260 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6261 pvargResult
, V_VT(pvargResult
));
6263 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6265 FIXME("unsupported calling convention %d\n",cc
);
6266 return E_INVALIDARG
;
6269 /* maximum size for an argument is sizeof(DWORD_PTR) */
6270 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6272 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6276 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6277 func
= vtable
[oVft
/sizeof(void *)];
6278 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6280 else func
= (void *)oVft
;
6282 for (i
= 0; i
< cActuals
; i
++)
6284 VARIANT
*arg
= prgpvarg
[i
];
6290 args
[argspos
++] = (ULONG_PTR
)arg
;
6292 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6293 args
[argspos
++] = V_BOOL(arg
);
6296 args
[argspos
++] = V_UI8(arg
);
6299 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6306 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6310 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6314 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6315 call_method( func
, argspos
, args
);
6318 WARN("invalid return type %u\n", vtReturn
);
6320 return E_INVALIDARG
;
6322 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6326 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6327 TRACE("retval: "); dump_Variant(pvargResult
);
6331 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6332 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6337 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6339 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6342 #define INVBUF_ELEMENT_SIZE \
6343 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6344 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6345 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6346 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6347 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6348 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6349 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6350 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6352 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6357 DISPPARAMS
*pDispParams
,
6358 VARIANT
*pVarResult
,
6359 EXCEPINFO
*pExcepInfo
,
6362 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6364 unsigned int var_index
;
6367 const TLBFuncDesc
*pFuncInfo
;
6370 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6371 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6374 if( This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6375 return DISP_E_MEMBERNOTFOUND
;
6379 ERR("NULL pDispParams not allowed\n");
6380 return E_INVALIDARG
;
6383 dump_DispParms(pDispParams
);
6385 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6387 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6388 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6389 return E_INVALIDARG
;
6392 /* we do this instead of using GetFuncDesc since it will return a fake
6393 * FUNCDESC for dispinterfaces and we want the real function description */
6394 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
6395 pFuncInfo
= &This
->funcdescs
[fdc
];
6396 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6397 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6398 !func_restricted( &pFuncInfo
->funcdesc
))
6402 if (fdc
< This
->TypeAttr
.cFuncs
) {
6403 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6407 TRACE("invoking:\n");
6408 dump_TLBFuncDescOne(pFuncInfo
);
6411 switch (func_desc
->funckind
) {
6412 case FUNC_PUREVIRTUAL
:
6413 case FUNC_VIRTUAL
: {
6414 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6416 VARIANT retval
; /* pointer for storing byref retvals in */
6417 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6418 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6419 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6420 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6421 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6422 UINT vargs_converted
=0;
6426 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6428 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6430 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6431 hres
= DISP_E_PARAMNOTFOUND
;
6436 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6438 ERR("functions with the vararg attribute do not support named arguments\n");
6439 hres
= DISP_E_NONAMEDARGS
;
6443 for (i
= 0; i
< func_desc
->cParams
; i
++)
6445 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6446 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6451 TRACE("changing args\n");
6452 for (i
= 0; i
< func_desc
->cParams
; i
++)
6454 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6455 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6456 VARIANTARG
*src_arg
;
6458 if (wParamFlags
& PARAMFLAG_FLCID
)
6461 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6463 V_I4(arg
) = This
->pTypeLib
->lcid
;
6472 for (j
= 0; j
< cNamedArgs
; j
++)
6473 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6475 src_arg
= &pDispParams
->rgvarg
[j
];
6480 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6482 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6486 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6488 /* under most conditions the caller is not allowed to
6489 * pass in a dispparam arg in the index of what would be
6490 * the retval parameter. however, there is an exception
6491 * where the extra parameter is used in an extra
6492 * IDispatch::Invoke below */
6493 if ((i
< pDispParams
->cArgs
) &&
6494 ((func_desc
->cParams
!= 1) || !pVarResult
||
6495 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6497 hres
= DISP_E_BADPARAMCOUNT
;
6501 /* note: this check is placed so that if the caller passes
6502 * in a VARIANTARG for the retval we just ignore it, like
6504 if (i
== func_desc
->cParams
- 1)
6507 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6508 memset(arg
, 0, sizeof(*arg
));
6509 V_VT(arg
) = rgvt
[i
];
6510 memset(&retval
, 0, sizeof(retval
));
6511 V_BYREF(arg
) = &retval
;
6515 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6516 hres
= E_UNEXPECTED
;
6522 dump_Variant(src_arg
);
6524 if(rgvt
[i
]!=V_VT(src_arg
))
6526 if (rgvt
[i
] == VT_VARIANT
)
6527 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6528 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6530 if (rgvt
[i
] == V_VT(src_arg
))
6531 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6534 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6535 if (wParamFlags
& PARAMFLAG_FIN
)
6536 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6537 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6539 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6541 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6544 SAFEARRAYBOUND bound
;
6548 bound
.cElements
= pDispParams
->cArgs
-i
;
6549 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6551 ERR("SafeArrayCreate failed\n");
6554 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6557 ERR("SafeArrayAccessData failed with %x\n", hres
);
6558 SafeArrayDestroy(a
);
6561 for (j
= 0; j
< bound
.cElements
; j
++)
6562 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6563 hres
= SafeArrayUnaccessData(a
);
6566 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6567 SafeArrayDestroy(a
);
6570 V_ARRAY(&rgvarg
[i
]) = a
;
6571 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6573 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6575 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6576 if (wParamFlags
& PARAMFLAG_FIN
)
6577 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6579 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
6580 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6581 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6583 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6585 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6586 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6590 /* FIXME: this doesn't work for VT_BYREF arguments if
6591 * they are not the same type as in the paramdesc */
6592 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6593 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6594 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6599 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6600 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6601 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6604 prgpvarg
[i
] = &rgvarg
[i
];
6608 prgpvarg
[i
] = src_arg
;
6611 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
6612 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
6613 && V_UNKNOWN(prgpvarg
[i
])) {
6614 IUnknown
*userdefined_iface
;
6617 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
6621 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
6623 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
6627 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
6628 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
6631 else if (wParamFlags
& PARAMFLAG_FOPT
)
6634 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6635 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6637 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6643 VARIANTARG
*missing_arg
;
6644 /* if the function wants a pointer to a variant then
6645 * set that up, otherwise just pass the VT_ERROR in
6646 * the argument by value */
6647 if (rgvt
[i
] & VT_BYREF
)
6649 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6650 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6651 V_VARIANTREF(arg
) = missing_arg
;
6655 V_VT(missing_arg
) = VT_ERROR
;
6656 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
6661 hres
= DISP_E_BADPARAMCOUNT
;
6665 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6667 /* VT_VOID is a special case for return types, so it is not
6668 * handled in the general function */
6669 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
6670 V_VT(&varresult
) = VT_EMPTY
;
6673 V_VT(&varresult
) = 0;
6674 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
6675 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6678 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
6679 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
6680 prgpvarg
, &varresult
);
6682 vargs_converted
= 0;
6684 for (i
= 0; i
< func_desc
->cParams
; i
++)
6686 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6687 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6689 if (wParamFlags
& PARAMFLAG_FLCID
)
6691 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
6695 TRACE("[retval] value: ");
6696 dump_Variant(prgpvarg
[i
]);
6701 VariantInit(pVarResult
);
6702 /* deref return value */
6703 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
6706 VARIANT_ClearInd(prgpvarg
[i
]);
6708 else if (vargs_converted
< pDispParams
->cArgs
)
6710 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6711 if (wParamFlags
& PARAMFLAG_FOUT
)
6713 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
6715 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
6719 ERR("failed to convert param %d to vt %d\n", i
,
6720 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
6725 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
6726 func_desc
->cParamsOpt
< 0 &&
6727 i
== func_desc
->cParams
-1)
6729 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
6732 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
6735 ERR("SafeArrayGetUBound failed with %x\n", hres
);
6738 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6741 ERR("SafeArrayAccessData failed with %x\n", hres
);
6744 for (j
= 0; j
<= ubound
; j
++)
6745 VariantClear(&v
[j
]);
6746 hres
= SafeArrayUnaccessData(a
);
6749 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6753 VariantClear(&rgvarg
[i
]);
6756 else if (wParamFlags
& PARAMFLAG_FOPT
)
6758 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6759 VariantClear(&rgvarg
[i
]);
6762 VariantClear(&missing_arg
[i
]);
6765 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
6767 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
6768 hres
= DISP_E_EXCEPTION
;
6771 IErrorInfo
*pErrorInfo
;
6772 pExcepInfo
->scode
= V_ERROR(&varresult
);
6773 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
6775 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
6776 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
6777 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
6778 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
6780 IErrorInfo_Release(pErrorInfo
);
6784 if (V_VT(&varresult
) != VT_ERROR
)
6786 TRACE("varresult value: ");
6787 dump_Variant(&varresult
);
6791 VariantClear(pVarResult
);
6792 *pVarResult
= varresult
;
6795 VariantClear(&varresult
);
6798 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
6799 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
6800 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
6801 (pDispParams
->cArgs
!= 0))
6803 if (V_VT(pVarResult
) == VT_DISPATCH
)
6805 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
6806 /* Note: not VariantClear; we still need the dispatch
6807 * pointer to be valid */
6808 VariantInit(pVarResult
);
6809 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
6810 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
6811 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
6812 IDispatch_Release(pDispatch
);
6816 VariantClear(pVarResult
);
6817 hres
= DISP_E_NOTACOLLECTION
;
6825 case FUNC_DISPATCH
: {
6828 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
6829 if (SUCCEEDED(hres
)) {
6830 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6831 hres
= IDispatch_Invoke(
6832 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
6833 pVarResult
,pExcepInfo
,pArgErr
6836 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
6837 IDispatch_Release(disp
);
6839 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6843 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
6848 TRACE("-- 0x%08x\n", hres
);
6851 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
6854 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
6855 if(FAILED(hres
)) return hres
;
6857 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6858 dump_VARDESC(var_desc
);
6859 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
6863 /* not found, look for it in inherited interfaces */
6864 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
6865 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
6866 if(This
->impltypes
) {
6867 /* recursive search */
6869 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6870 if(SUCCEEDED(hres
)){
6871 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
6872 ITypeInfo_Release(pTInfo
);
6875 WARN("Could not search inherited interface!\n");
6878 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
6879 return DISP_E_MEMBERNOTFOUND
;
6882 /* ITypeInfo::GetDocumentation
6884 * Retrieves the documentation string, the complete Help file name and path,
6885 * and the context ID for the Help topic for a specified type description.
6887 * (Can be tested by the Visual Basic Editor in Word for instance.)
6889 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
6890 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
6891 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
6893 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6894 const TLBFuncDesc
*pFDesc
;
6895 const TLBVarDesc
*pVDesc
;
6896 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6897 " HelpContext(%p) HelpFile(%p)\n",
6898 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6899 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6901 *pBstrName
=SysAllocString(This
->Name
);
6903 *pBstrDocString
=SysAllocString(This
->DocString
);
6905 *pdwHelpContext
=This
->dwHelpContext
;
6907 *pBstrHelpFile
=SysAllocString(This
->pTypeLib
->HelpFile
);
6909 }else {/* for a member */
6910 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
6913 *pBstrName
= SysAllocString(pFDesc
->Name
);
6915 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
6917 *pdwHelpContext
=pFDesc
->helpcontext
;
6920 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
6923 *pBstrName
= SysAllocString(pVDesc
->Name
);
6925 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
6927 *pdwHelpContext
=pVDesc
->HelpContext
;
6929 *pBstrHelpFile
= SysAllocString(This
->pTypeLib
->HelpFile
);
6934 if(This
->impltypes
&&
6935 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
6936 /* recursive search */
6939 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6940 if(SUCCEEDED(result
)) {
6941 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
6942 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6943 ITypeInfo_Release(pTInfo
);
6946 WARN("Could not search inherited interface!\n");
6949 WARN("member %d not found\n", memid
);
6950 return TYPE_E_ELEMENTNOTFOUND
;
6953 /* ITypeInfo::GetDllEntry
6955 * Retrieves a description or specification of an entry point for a function
6958 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
6959 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
6962 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6963 const TLBFuncDesc
*pFDesc
;
6965 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
6967 if (pBstrDllName
) *pBstrDllName
= NULL
;
6968 if (pBstrName
) *pBstrName
= NULL
;
6969 if (pwOrdinal
) *pwOrdinal
= 0;
6971 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
6972 return TYPE_E_BADMODULEKIND
;
6974 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
6976 dump_TypeInfo(This
);
6978 dump_TLBFuncDescOne(pFDesc
);
6981 *pBstrDllName
= SysAllocString(This
->DllName
);
6983 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
6985 *pBstrName
= SysAllocString(pFDesc
->Entry
);
6993 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
6996 return TYPE_E_ELEMENTNOTFOUND
;
6999 /* internal function to make the inherited interfaces' methods appear
7000 * part of the interface */
7001 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7002 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7004 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7007 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7009 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7011 ITypeInfo
*pSubTypeInfo
;
7013 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7017 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7019 ITypeInfo_Release(pSubTypeInfo
);
7023 *hRefType
-= DISPATCH_HREF_OFFSET
;
7025 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7026 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7031 /* ITypeInfo::GetRefTypeInfo
7033 * If a type description references other type descriptions, it retrieves
7034 * the referenced type descriptions.
7036 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7039 ITypeInfo
**ppTInfo
)
7041 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7042 HRESULT result
= E_FAIL
;
7045 return E_INVALIDARG
;
7047 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
7049 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
7050 ITypeInfo_AddRef(*ppTInfo
);
7053 else if (hRefType
== -1 &&
7054 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
7055 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
7057 /* when we meet a DUAL dispinterface, we must create the interface
7060 ITypeInfoImpl
*pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7063 /* the interface version contains the same information as the dispinterface
7064 * copy the contents of the structs.
7066 *pTypeInfoImpl
= *This
;
7067 pTypeInfoImpl
->ref
= 0;
7069 /* change the type to interface */
7070 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7072 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
7074 /* the AddRef implicitly adds a reference to the parent typelib, which
7075 * stops the copied data from being destroyed until the new typeinfo's
7076 * refcount goes to zero, but we need to signal to the new instance to
7077 * not free its data structures when it is destroyed */
7078 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7080 ITypeInfo_AddRef(*ppTInfo
);
7084 } else if ((hRefType
!= -1) && (hRefType
& DISPATCH_HREF_MASK
) &&
7085 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
))
7087 HREFTYPE href_dispatch
= hRefType
;
7088 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7090 TLBRefType
*ref_type
;
7091 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7093 if(ref_type
->reference
== hRefType
)
7096 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7098 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7101 if(hRefType
!= -1) {
7102 ITypeLib
*pTLib
= NULL
;
7104 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7106 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7108 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7109 TRACE("typeinfo in imported typelib that is already loaded\n");
7110 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7111 ITypeLib_AddRef(pTLib
);
7114 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7115 result
= LoadRegTypeLib( &ref_type
->pImpTLInfo
->guid
,
7116 ref_type
->pImpTLInfo
->wVersionMajor
,
7117 ref_type
->pImpTLInfo
->wVersionMinor
,
7118 ref_type
->pImpTLInfo
->lcid
,
7121 if(FAILED(result
)) {
7122 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
7123 result
=LoadTypeLib(libnam
, &pTLib
);
7124 SysFreeString(libnam
);
7126 if(SUCCEEDED(result
)) {
7127 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7128 ITypeLib_AddRef(pTLib
);
7132 if(SUCCEEDED(result
)) {
7133 if(ref_type
->index
== TLB_REF_USE_GUID
)
7134 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, &ref_type
->guid
, ppTInfo
);
7136 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7139 ITypeLib_Release(pTLib
);
7144 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7145 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7149 /* ITypeInfo::AddressOfMember
7151 * Retrieves the addresses of static functions or variables, such as those
7154 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7155 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7157 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7163 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7165 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7169 module
= LoadLibraryW(dll
);
7172 ERR("couldn't load %s\n", debugstr_w(dll
));
7174 SysFreeString(entry
);
7175 return STG_E_FILENOTFOUND
;
7177 /* FIXME: store library somewhere where we can free it */
7182 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7183 entryA
= heap_alloc(len
);
7184 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7186 *ppv
= GetProcAddress(module
, entryA
);
7188 ERR("function not found %s\n", debugstr_a(entryA
));
7194 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7196 ERR("function not found %d\n", ordinal
);
7200 SysFreeString(entry
);
7203 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7208 /* ITypeInfo::CreateInstance
7210 * Creates a new instance of a type that describes a component object class
7213 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7214 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7216 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7220 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7226 WARN("Not able to aggregate\n");
7227 return CLASS_E_NOAGGREGATION
;
7230 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7231 if(FAILED(hr
)) return hr
;
7233 if(pTA
->typekind
!= TKIND_COCLASS
)
7235 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7241 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7244 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7245 TRACE("GetActiveObject rets %08x\n", hr
);
7248 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7249 IUnknown_Release(pUnk
);
7254 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7255 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7259 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7263 /* ITypeInfo::GetMops
7265 * Retrieves marshalling information.
7267 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7270 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7271 FIXME("(%p %d) stub!\n", This
, memid
);
7276 /* ITypeInfo::GetContainingTypeLib
7278 * Retrieves the containing type library and the index of the type description
7279 * within that type library.
7281 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7282 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7284 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7286 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7288 *pIndex
=This
->index
;
7289 TRACE("returning pIndex=%d\n", *pIndex
);
7293 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7294 ITypeLib_AddRef(*ppTLib
);
7295 TRACE("returning ppTLib=%p\n", *ppTLib
);
7301 /* ITypeInfo::ReleaseTypeAttr
7303 * Releases a TYPEATTR previously returned by GetTypeAttr.
7306 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7307 TYPEATTR
* pTypeAttr
)
7309 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7310 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7311 heap_free(pTypeAttr
);
7314 /* ITypeInfo::ReleaseFuncDesc
7316 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7318 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7320 FUNCDESC
*pFuncDesc
)
7322 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7325 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7327 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7328 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7329 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7331 SysFreeString((BSTR
)pFuncDesc
);
7334 /* ITypeInfo::ReleaseVarDesc
7336 * Releases a VARDESC previously returned by GetVarDesc.
7338 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7341 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7342 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7344 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
7345 if (pVarDesc
->varkind
== VAR_CONST
)
7346 VariantClear(pVarDesc
->u
.lpvarValue
);
7347 SysFreeString((BSTR
)pVarDesc
);
7350 /* ITypeInfo2::GetTypeKind
7352 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7355 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7356 TYPEKIND
*pTypeKind
)
7358 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7359 *pTypeKind
=This
->TypeAttr
.typekind
;
7360 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7364 /* ITypeInfo2::GetTypeFlags
7366 * Returns the type flags without any allocations. This returns a DWORD type
7367 * flag, which expands the type flags without growing the TYPEATTR (type
7371 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7373 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7374 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
7375 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7379 /* ITypeInfo2::GetFuncIndexOfMemId
7380 * Binds to a specific member based on a known DISPID, where the member name
7381 * is not known (for example, when binding to a default member).
7384 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7385 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7387 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7391 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
7392 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7393 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7396 if(fdc
< This
->TypeAttr
.cFuncs
) {
7400 result
= TYPE_E_ELEMENTNOTFOUND
;
7402 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7403 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7407 /* TypeInfo2::GetVarIndexOfMemId
7409 * Binds to a specific member based on a known DISPID, where the member name
7410 * is not known (for example, when binding to a default member).
7413 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7414 MEMBERID memid
, UINT
*pVarIndex
)
7416 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7417 TLBVarDesc
*pVarInfo
;
7419 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7421 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
7423 return TYPE_E_ELEMENTNOTFOUND
;
7425 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7430 /* ITypeInfo2::GetCustData
7432 * Gets the custom data
7434 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7439 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7440 TLBCustData
*pCData
;
7442 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7444 if(!guid
|| !pVarVal
)
7445 return E_INVALIDARG
;
7447 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
7449 VariantInit( pVarVal
);
7451 VariantCopy( pVarVal
, &pCData
->data
);
7453 VariantClear( pVarVal
);
7457 /* ITypeInfo2::GetFuncCustData
7459 * Gets the custom data
7461 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7467 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7468 TLBCustData
*pCData
;
7469 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7471 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7473 if(index
>= This
->TypeAttr
.cFuncs
)
7474 return TYPE_E_ELEMENTNOTFOUND
;
7476 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
7478 return TYPE_E_ELEMENTNOTFOUND
;
7480 VariantInit(pVarVal
);
7481 VariantCopy(pVarVal
, &pCData
->data
);
7486 /* ITypeInfo2::GetParamCustData
7488 * Gets the custom data
7490 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7497 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7498 TLBCustData
*pCData
;
7499 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7501 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
7502 debugstr_guid(guid
), pVarVal
);
7504 if(indexFunc
>= This
->TypeAttr
.cFuncs
)
7505 return TYPE_E_ELEMENTNOTFOUND
;
7507 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7508 return TYPE_E_ELEMENTNOTFOUND
;
7510 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
7512 return TYPE_E_ELEMENTNOTFOUND
;
7514 VariantInit(pVarVal
);
7515 VariantCopy(pVarVal
, &pCData
->data
);
7520 /* ITypeInfo2::GetVarCustData
7522 * Gets the custom data
7524 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7530 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7531 TLBCustData
*pCData
;
7532 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
7534 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7536 if(index
>= This
->TypeAttr
.cVars
)
7537 return TYPE_E_ELEMENTNOTFOUND
;
7539 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
7541 return TYPE_E_ELEMENTNOTFOUND
;
7543 VariantInit(pVarVal
);
7544 VariantCopy(pVarVal
, &pCData
->data
);
7549 /* ITypeInfo2::GetImplCustData
7551 * Gets the custom data
7553 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7559 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7560 TLBCustData
*pCData
;
7561 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7563 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7565 if(index
>= This
->TypeAttr
.cImplTypes
)
7566 return TYPE_E_ELEMENTNOTFOUND
;
7568 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
7570 return TYPE_E_ELEMENTNOTFOUND
;
7572 VariantInit(pVarVal
);
7573 VariantCopy(pVarVal
, &pCData
->data
);
7578 /* ITypeInfo2::GetDocumentation2
7580 * Retrieves the documentation string, the complete Help file name and path,
7581 * the localization context to use, and the context ID for the library Help
7582 * topic in the Help file.
7585 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7589 BSTR
*pbstrHelpString
,
7590 DWORD
*pdwHelpStringContext
,
7591 BSTR
*pbstrHelpStringDll
)
7593 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7594 const TLBFuncDesc
*pFDesc
;
7595 const TLBVarDesc
*pVDesc
;
7596 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7597 "HelpStringContext(%p) HelpStringDll(%p)\n",
7598 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7599 pbstrHelpStringDll
);
7600 /* the help string should be obtained from the helpstringdll,
7601 * using the _DLLGetDocumentation function, based on the supplied
7602 * lcid. Nice to do sometime...
7604 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7606 *pbstrHelpString
=SysAllocString(This
->Name
);
7607 if(pdwHelpStringContext
)
7608 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7609 if(pbstrHelpStringDll
)
7610 *pbstrHelpStringDll
=
7611 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7613 }else {/* for a member */
7614 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
7617 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
7618 if(pdwHelpStringContext
)
7619 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7620 if(pbstrHelpStringDll
)
7621 *pbstrHelpStringDll
=
7622 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7625 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
7628 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
7629 if(pdwHelpStringContext
)
7630 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7631 if(pbstrHelpStringDll
)
7632 *pbstrHelpStringDll
=
7633 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7637 return TYPE_E_ELEMENTNOTFOUND
;
7640 /* ITypeInfo2::GetAllCustData
7642 * Gets all custom data items for the Type info.
7645 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
7647 CUSTDATA
*pCustData
)
7649 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7651 TRACE("%p %p\n", This
, pCustData
);
7653 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
7656 /* ITypeInfo2::GetAllFuncCustData
7658 * Gets all custom data items for the specified Function
7661 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
7664 CUSTDATA
*pCustData
)
7666 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7667 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7669 TRACE("%p %u %p\n", This
, index
, pCustData
);
7671 if(index
>= This
->TypeAttr
.cFuncs
)
7672 return TYPE_E_ELEMENTNOTFOUND
;
7674 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
7677 /* ITypeInfo2::GetAllParamCustData
7679 * Gets all custom data items for the Functions
7682 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
7683 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
7685 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7686 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7688 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
7690 if(indexFunc
>= This
->TypeAttr
.cFuncs
)
7691 return TYPE_E_ELEMENTNOTFOUND
;
7693 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7694 return TYPE_E_ELEMENTNOTFOUND
;
7696 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
7699 /* ITypeInfo2::GetAllVarCustData
7701 * Gets all custom data items for the specified Variable
7704 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
7705 UINT index
, CUSTDATA
*pCustData
)
7707 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7708 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
7710 TRACE("%p %u %p\n", This
, index
, pCustData
);
7712 if(index
>= This
->TypeAttr
.cVars
)
7713 return TYPE_E_ELEMENTNOTFOUND
;
7715 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
7718 /* ITypeInfo2::GetAllImplCustData
7720 * Gets all custom data items for the specified implementation type
7723 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
7726 CUSTDATA
*pCustData
)
7728 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7729 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7731 TRACE("%p %u %p\n", This
, index
, pCustData
);
7733 if(index
>= This
->TypeAttr
.cImplTypes
)
7734 return TYPE_E_ELEMENTNOTFOUND
;
7736 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
7739 static const ITypeInfo2Vtbl tinfvt
=
7742 ITypeInfo_fnQueryInterface
,
7744 ITypeInfo_fnRelease
,
7746 ITypeInfo_fnGetTypeAttr
,
7747 ITypeInfo_fnGetTypeComp
,
7748 ITypeInfo_fnGetFuncDesc
,
7749 ITypeInfo_fnGetVarDesc
,
7750 ITypeInfo_fnGetNames
,
7751 ITypeInfo_fnGetRefTypeOfImplType
,
7752 ITypeInfo_fnGetImplTypeFlags
,
7753 ITypeInfo_fnGetIDsOfNames
,
7755 ITypeInfo_fnGetDocumentation
,
7756 ITypeInfo_fnGetDllEntry
,
7757 ITypeInfo_fnGetRefTypeInfo
,
7758 ITypeInfo_fnAddressOfMember
,
7759 ITypeInfo_fnCreateInstance
,
7760 ITypeInfo_fnGetMops
,
7761 ITypeInfo_fnGetContainingTypeLib
,
7762 ITypeInfo_fnReleaseTypeAttr
,
7763 ITypeInfo_fnReleaseFuncDesc
,
7764 ITypeInfo_fnReleaseVarDesc
,
7766 ITypeInfo2_fnGetTypeKind
,
7767 ITypeInfo2_fnGetTypeFlags
,
7768 ITypeInfo2_fnGetFuncIndexOfMemId
,
7769 ITypeInfo2_fnGetVarIndexOfMemId
,
7770 ITypeInfo2_fnGetCustData
,
7771 ITypeInfo2_fnGetFuncCustData
,
7772 ITypeInfo2_fnGetParamCustData
,
7773 ITypeInfo2_fnGetVarCustData
,
7774 ITypeInfo2_fnGetImplTypeCustData
,
7775 ITypeInfo2_fnGetDocumentation2
,
7776 ITypeInfo2_fnGetAllCustData
,
7777 ITypeInfo2_fnGetAllFuncCustData
,
7778 ITypeInfo2_fnGetAllParamCustData
,
7779 ITypeInfo2_fnGetAllVarCustData
,
7780 ITypeInfo2_fnGetAllImplTypeCustData
,
7783 /******************************************************************************
7784 * CreateDispTypeInfo [OLEAUT32.31]
7786 * Build type information for an object so it can be called through an
7787 * IDispatch interface.
7790 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7791 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7794 * This call allows an objects methods to be accessed through IDispatch, by
7795 * building an ITypeInfo object that IDispatch can use to call through.
7797 HRESULT WINAPI
CreateDispTypeInfo(
7798 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
7799 LCID lcid
, /* [I] Locale Id */
7800 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
7802 ITypeInfoImpl
*pTIClass
, *pTIIface
;
7803 ITypeLibImpl
*pTypeLibImpl
;
7804 unsigned int param
, func
;
7805 TLBFuncDesc
*pFuncDesc
;
7809 pTypeLibImpl
= TypeLibImpl_Constructor();
7810 if (!pTypeLibImpl
) return E_FAIL
;
7812 pTypeLibImpl
->TypeInfoCount
= 2;
7813 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
7815 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
7816 pTIIface
->pTypeLib
= pTypeLibImpl
;
7817 pTIIface
->index
= 0;
7818 pTIIface
->Name
= NULL
;
7819 pTIIface
->dwHelpContext
= -1;
7820 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
7821 pTIIface
->TypeAttr
.lcid
= lcid
;
7822 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7823 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
7824 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
7825 pTIIface
->TypeAttr
.cbAlignment
= 2;
7826 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
7827 pTIIface
->TypeAttr
.cbSizeVft
= -1;
7828 pTIIface
->TypeAttr
.cFuncs
= 0;
7829 pTIIface
->TypeAttr
.cImplTypes
= 0;
7830 pTIIface
->TypeAttr
.cVars
= 0;
7831 pTIIface
->TypeAttr
.wTypeFlags
= 0;
7833 pTIIface
->funcdescs
= TLBFuncDesc_Constructor(pidata
->cMembers
);
7834 pFuncDesc
= pTIIface
->funcdescs
;
7835 for(func
= 0; func
< pidata
->cMembers
; func
++) {
7836 METHODDATA
*md
= pidata
->pmethdata
+ func
;
7837 pFuncDesc
->Name
= SysAllocString(md
->szName
);
7838 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
7839 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
7840 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
7841 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
7842 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
7843 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
7844 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
7845 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
7846 pFuncDesc
->funcdesc
.cScodes
= 0;
7847 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
7848 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
7849 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
7850 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
7851 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7852 md
->cArgs
* sizeof(ELEMDESC
));
7853 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
7854 for(param
= 0; param
< md
->cArgs
; param
++) {
7855 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
7856 pFuncDesc
->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
7858 pFuncDesc
->helpcontext
= 0;
7859 pFuncDesc
->HelpStringContext
= 0;
7860 pFuncDesc
->HelpString
= NULL
;
7861 pFuncDesc
->Entry
= NULL
;
7862 list_init(&pFuncDesc
->custdata_list
);
7863 pTIIface
->TypeAttr
.cFuncs
++;
7867 dump_TypeInfo(pTIIface
);
7869 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
7870 pTIClass
->pTypeLib
= pTypeLibImpl
;
7871 pTIClass
->index
= 1;
7872 pTIClass
->Name
= NULL
;
7873 pTIClass
->dwHelpContext
= -1;
7874 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
7875 pTIClass
->TypeAttr
.lcid
= lcid
;
7876 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
7877 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
7878 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
7879 pTIClass
->TypeAttr
.cbAlignment
= 2;
7880 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
7881 pTIClass
->TypeAttr
.cbSizeVft
= -1;
7882 pTIClass
->TypeAttr
.cFuncs
= 0;
7883 pTIClass
->TypeAttr
.cImplTypes
= 1;
7884 pTIClass
->TypeAttr
.cVars
= 0;
7885 pTIClass
->TypeAttr
.wTypeFlags
= 0;
7887 pTIClass
->impltypes
= TLBImplType_Constructor(1);
7889 ref
= heap_alloc_zero(sizeof(*ref
));
7890 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
7891 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
7893 dump_TypeInfo(pTIClass
);
7895 *pptinfo
= (ITypeInfo
*)pTIClass
;
7897 ITypeInfo_AddRef(*pptinfo
);
7898 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
7904 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
7906 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7908 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
7911 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
7913 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7915 return ITypeInfo_AddRef((ITypeInfo
*)This
);
7918 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
7920 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7922 return ITypeInfo_Release((ITypeInfo
*)This
);
7925 static HRESULT WINAPI
ITypeComp_fnBind(
7930 ITypeInfo
** ppTInfo
,
7931 DESCKIND
* pDescKind
,
7934 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7935 const TLBFuncDesc
*pFDesc
;
7936 const TLBVarDesc
*pVDesc
;
7937 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
7940 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7942 *pDescKind
= DESCKIND_NONE
;
7943 pBindPtr
->lpfuncdesc
= NULL
;
7946 for(fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
7947 pFDesc
= &This
->funcdescs
[fdc
];
7948 if (!strcmpiW(pFDesc
->Name
, szName
)) {
7949 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
7952 /* name found, but wrong flags */
7953 hr
= TYPE_E_TYPEMISMATCH
;
7957 if (fdc
< This
->TypeAttr
.cFuncs
)
7959 HRESULT hr
= TLB_AllocAndInitFuncDesc(
7961 &pBindPtr
->lpfuncdesc
,
7962 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
7965 *pDescKind
= DESCKIND_FUNCDESC
;
7966 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
7967 ITypeInfo_AddRef(*ppTInfo
);
7970 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->TypeAttr
.cVars
, szName
);
7972 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
7975 *pDescKind
= DESCKIND_VARDESC
;
7976 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
7977 ITypeInfo_AddRef(*ppTInfo
);
7981 /* FIXME: search each inherited interface, not just the first */
7982 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
7983 /* recursive search */
7987 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7990 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
7991 ITypeInfo_Release(pTInfo
);
7995 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7996 ITypeComp_Release(pTComp
);
7999 WARN("Could not search inherited interface!\n");
8001 if (hr
== DISP_E_MEMBERNOTFOUND
)
8003 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8007 static HRESULT WINAPI
ITypeComp_fnBindType(
8011 ITypeInfo
** ppTInfo
,
8012 ITypeComp
** ppTComp
)
8014 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8016 /* strange behaviour (does nothing) but like the
8019 if (!ppTInfo
|| !ppTComp
)
8028 static const ITypeCompVtbl tcompvt
=
8031 ITypeComp_fnQueryInterface
,
8033 ITypeComp_fnRelease
,
8036 ITypeComp_fnBindType