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 const ITypeLib2Vtbl
*lpVtbl
;
987 const ITypeCompVtbl
*lpVtblTypeComp
;
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_ITypeComp( ITypeComp
*iface
)
1023 return (ITypeLibImpl
*)((char*)iface
- FIELD_OFFSET(ITypeLibImpl
, lpVtblTypeComp
));
1026 /* ITypeLib methods */
1027 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1028 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1030 /*======================= ITypeInfo implementation =======================*/
1032 /* data for referenced types */
1033 typedef struct tagTLBRefType
1035 INT index
; /* Type index for internal ref or for external ref
1036 it the format is SLTG. -2 indicates to
1039 GUID guid
; /* guid of the referenced type */
1040 /* if index == TLB_REF_USE_GUID */
1042 HREFTYPE reference
; /* The href of this ref */
1043 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1044 TLB_REF_INTERNAL for internal refs
1045 TLB_REF_NOT_FOUND for broken refs */
1050 #define TLB_REF_USE_GUID -2
1052 #define TLB_REF_INTERNAL (void*)-2
1053 #define TLB_REF_NOT_FOUND (void*)-1
1055 /* internal Parameter data */
1056 typedef struct tagTLBParDesc
1059 struct list custdata_list
;
1062 /* internal Function data */
1063 typedef struct tagTLBFuncDesc
1065 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1066 BSTR Name
; /* the name of this function */
1067 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1069 int HelpStringContext
;
1071 BSTR Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1072 struct list custdata_list
;
1075 /* internal Variable data */
1076 typedef struct tagTLBVarDesc
1078 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1079 BSTR Name
; /* the name of this variable */
1081 int HelpStringContext
;
1083 struct list custdata_list
;
1086 /* internal implemented interface data */
1087 typedef struct tagTLBImplType
1089 HREFTYPE hRef
; /* hRef of interface */
1090 int implflags
; /* IMPLFLAG_*s */
1091 struct list custdata_list
;
1094 /* internal TypeInfo data */
1095 typedef struct tagITypeInfoImpl
1097 const ITypeInfo2Vtbl
*lpVtbl
;
1098 const ITypeCompVtbl
*lpVtblTypeComp
;
1100 BOOL not_attached_to_typelib
;
1101 TYPEATTR TypeAttr
; /* _lots_ of type information. */
1102 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1103 int index
; /* index in this typelib; */
1104 HREFTYPE hreftype
; /* hreftype for app object binding */
1105 /* type libs seem to store the doc strings in ascii
1106 * so why should we do it in unicode?
1111 DWORD dwHelpContext
;
1112 DWORD dwHelpStringContext
;
1115 TLBFuncDesc
*funcdescs
;
1118 TLBVarDesc
*vardescs
;
1120 /* Implemented Interfaces */
1121 TLBImplType
*impltypes
;
1123 struct list custdata_list
;
1126 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1128 return (ITypeInfoImpl
*)((char*)iface
- FIELD_OFFSET(ITypeInfoImpl
, lpVtblTypeComp
));
1131 static const ITypeInfo2Vtbl tinfvt
;
1132 static const ITypeCompVtbl tcompvt
;
1134 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1135 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1137 typedef struct tagTLBContext
1139 unsigned int oStart
; /* start of TLB in file */
1140 unsigned int pos
; /* current pos */
1141 unsigned int length
; /* total length */
1142 void *mapping
; /* memory mapping */
1143 MSFT_SegDir
* pTblDir
;
1144 ITypeLibImpl
* pLibInfo
;
1148 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
, int offset
);
1153 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1154 if (pTD
->vt
& VT_RESERVED
)
1155 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1156 if (pTD
->vt
& VT_BYREF
)
1157 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1158 if (pTD
->vt
& VT_ARRAY
)
1159 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1160 if (pTD
->vt
& VT_VECTOR
)
1161 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1162 switch(pTD
->vt
& VT_TYPEMASK
) {
1163 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1164 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1165 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1166 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1167 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1168 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1169 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1170 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1171 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1172 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1173 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1174 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1175 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1176 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1177 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1178 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1179 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1180 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1181 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1182 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1183 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1184 pTD
->u
.hreftype
); break;
1185 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1186 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1187 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1188 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1190 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1191 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1193 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1194 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1195 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1198 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1202 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1204 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1205 dump_TypeDesc(&edesc
->tdesc
,buf
);
1206 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1207 MESSAGE("\t\tu.paramdesc.wParamFlags");
1208 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1209 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1210 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1211 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1212 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1213 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1214 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1215 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1216 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1218 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1220 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1221 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1222 MESSAGE("Param %d:\n",i
);
1223 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1225 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1226 switch (funcdesc
->funckind
) {
1227 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1228 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1229 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1230 case FUNC_STATIC
: MESSAGE("static");break;
1231 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1232 default: MESSAGE("unknown");break;
1234 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1235 switch (funcdesc
->invkind
) {
1236 case INVOKE_FUNC
: MESSAGE("func");break;
1237 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1238 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1239 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1241 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1242 switch (funcdesc
->callconv
) {
1243 case CC_CDECL
: MESSAGE("cdecl");break;
1244 case CC_PASCAL
: MESSAGE("pascal");break;
1245 case CC_STDCALL
: MESSAGE("stdcall");break;
1246 case CC_SYSCALL
: MESSAGE("syscall");break;
1249 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1250 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1251 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1253 MESSAGE("\telemdescFunc (return value type):\n");
1254 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1257 static const char * const typekind_desc
[] =
1270 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1273 MESSAGE("%s(%u)\n", debugstr_w(pfd
->Name
), pfd
->funcdesc
.cParams
);
1274 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1275 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(pfd
->pParamDesc
[i
].Name
));
1278 dump_FUNCDESC(&(pfd
->funcdesc
));
1280 MESSAGE("\thelpstring: %s\n", debugstr_w(pfd
->HelpString
));
1281 MESSAGE("\tentry: %s\n", (pfd
->Entry
== (void *)-1) ? "invalid" : debugstr_w(pfd
->Entry
));
1283 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1287 dump_TLBFuncDescOne(pfd
);
1292 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1296 TRACE_(typelib
)("%s\n", debugstr_w(pvd
->Name
));
1302 static void dump_TLBImpLib(const TLBImpLib
*import
)
1304 TRACE_(typelib
)("%s %s\n", debugstr_guid(&(import
->guid
)),
1305 debugstr_w(import
->name
));
1306 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1307 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1310 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1314 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1316 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1317 if(ref
->index
== -1)
1318 TRACE_(typelib
)("%s\n", debugstr_guid(&(ref
->guid
)));
1320 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1322 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1324 TRACE_(typelib
)("in lib\n");
1325 dump_TLBImpLib(ref
->pImpTLInfo
);
1330 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1335 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1336 impl
->hRef
, impl
->implflags
);
1342 static void dump_Variant(const VARIANT
* pvar
)
1346 TRACE("%p->{%s%s", pvar
, debugstr_VT(pvar
), debugstr_VF(pvar
));
1350 if (V_ISBYREF(pvar
) || V_TYPE(pvar
) == VT_UNKNOWN
||
1351 V_TYPE(pvar
) == VT_DISPATCH
|| V_TYPE(pvar
) == VT_RECORD
)
1353 TRACE(",%p", V_BYREF(pvar
));
1355 else if (V_ISARRAY(pvar
) || V_ISVECTOR(pvar
))
1357 TRACE(",%p", V_ARRAY(pvar
));
1359 else switch (V_TYPE(pvar
))
1361 case VT_I1
: TRACE(",%d", V_I1(pvar
)); break;
1362 case VT_UI1
: TRACE(",%d", V_UI1(pvar
)); break;
1363 case VT_I2
: TRACE(",%d", V_I2(pvar
)); break;
1364 case VT_UI2
: TRACE(",%d", V_UI2(pvar
)); break;
1366 case VT_I4
: TRACE(",%d", V_I4(pvar
)); break;
1368 case VT_UI4
: TRACE(",%d", V_UI4(pvar
)); break;
1369 case VT_I8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_I8(pvar
) >> 32),
1370 (ULONG
)(V_I8(pvar
) & 0xffffffff)); break;
1371 case VT_UI8
: TRACE(",0x%08x,0x%08x", (ULONG
)(V_UI8(pvar
) >> 32),
1372 (ULONG
)(V_UI8(pvar
) & 0xffffffff)); break;
1373 case VT_R4
: TRACE(",%3.3e", V_R4(pvar
)); break;
1374 case VT_R8
: TRACE(",%3.3e", V_R8(pvar
)); break;
1375 case VT_BOOL
: TRACE(",%s", V_BOOL(pvar
) ? "TRUE" : "FALSE"); break;
1376 case VT_BSTR
: TRACE(",%s", debugstr_w(V_BSTR(pvar
))); break;
1377 case VT_CY
: TRACE(",0x%08x,0x%08x", V_CY(pvar
).s
.Hi
,
1378 V_CY(pvar
).s
.Lo
); break;
1380 if(!VariantTimeToSystemTime(V_DATE(pvar
), &st
))
1381 TRACE(",<invalid>");
1383 TRACE(",%04d/%02d/%02d %02d:%02d:%02d", st
.wYear
, st
.wMonth
, st
.wDay
,
1384 st
.wHour
, st
.wMinute
, st
.wSecond
);
1388 case VT_USERDEFINED
:
1390 case VT_NULL
: break;
1391 default: TRACE(",?"); break;
1397 static void dump_DispParms(const DISPPARAMS
* pdp
)
1401 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1403 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1405 TRACE("named args:\n");
1406 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1407 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1410 if (pdp
->cArgs
&& pdp
->rgvarg
)
1413 for (index
= 0; index
< pdp
->cArgs
; index
++)
1414 dump_Variant( &pdp
->rgvarg
[index
] );
1418 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1420 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1421 TRACE("%s %s\n", debugstr_w(pty
->Name
), debugstr_w(pty
->DocString
));
1422 TRACE("attr:%s\n", debugstr_guid(&(pty
->TypeAttr
.guid
)));
1423 TRACE("kind:%s\n", typekind_desc
[pty
->TypeAttr
.typekind
]);
1424 TRACE("fct:%u var:%u impl:%u\n",
1425 pty
->TypeAttr
.cFuncs
, pty
->TypeAttr
.cVars
, pty
->TypeAttr
.cImplTypes
);
1426 TRACE("wTypeFlags: 0x%04x\n", pty
->TypeAttr
.wTypeFlags
);
1427 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1428 if (pty
->TypeAttr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(pty
->DllName
));
1430 dump_TLBFuncDesc(pty
->funcdescs
, pty
->TypeAttr
.cFuncs
);
1431 dump_TLBVarDesc(pty
->vardescs
, pty
->TypeAttr
.cVars
);
1432 dump_TLBImplType(pty
->impltypes
, pty
->TypeAttr
.cImplTypes
);
1435 static void dump_VARDESC(const VARDESC
*v
)
1437 MESSAGE("memid %d\n",v
->memid
);
1438 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1439 MESSAGE("oInst %d\n",v
->u
.oInst
);
1440 dump_ELEMDESC(&(v
->elemdescVar
));
1441 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1442 MESSAGE("varkind %d\n",v
->varkind
);
1445 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1447 /* VT_LPWSTR is largest type that, may appear in type description */
1448 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1449 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1450 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1451 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1452 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1453 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1454 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1455 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1458 static void TLB_abort(void)
1463 void* __WINE_ALLOC_SIZE(1) heap_alloc_zero(unsigned size
)
1465 void *ret
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, size
);
1466 if (!ret
) ERR("cannot allocate memory\n");
1470 void* __WINE_ALLOC_SIZE(1) heap_alloc(unsigned size
)
1472 void *ret
= HeapAlloc(GetProcessHeap(), 0, size
);
1473 if (!ret
) ERR("cannot allocate memory\n");
1477 void* __WINE_ALLOC_SIZE(2) heap_realloc(void *ptr
, unsigned size
)
1479 return HeapReAlloc(GetProcessHeap(), 0, ptr
, size
);
1482 void heap_free(void *ptr
)
1484 HeapFree(GetProcessHeap(), 0, ptr
);
1487 /* returns the size required for a deep copy of a typedesc into a
1489 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1493 if (alloc_initial_space
)
1494 size
+= sizeof(TYPEDESC
);
1500 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1503 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1504 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1510 /* deep copy a typedesc into a flat buffer */
1511 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1516 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1525 dest
->u
.lptdesc
= buffer
;
1526 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1529 dest
->u
.lpadesc
= buffer
;
1530 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1531 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1532 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1538 /* free custom data allocated by MSFT_CustData */
1539 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1541 TLBCustData
*cd
, *cdn
;
1542 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1544 list_remove(&cd
->entry
);
1545 VariantClear(&cd
->data
);
1550 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1555 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1556 ret
= SysAllocStringLen(NULL
, len
- 1);
1557 if (!ret
) return ret
;
1558 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1562 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1563 UINT n
, MEMBERID memid
)
1566 if(funcdescs
->funcdesc
.memid
== memid
)
1574 static inline TLBFuncDesc
*TLB_get_funcdesc_by_name(TLBFuncDesc
*funcdescs
,
1575 UINT n
, const OLECHAR
*name
)
1578 if(!lstrcmpiW(funcdescs
->Name
, name
))
1586 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1587 UINT n
, MEMBERID memid
)
1590 if(vardescs
->vardesc
.memid
== memid
)
1598 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1599 UINT n
, const OLECHAR
*name
)
1602 if(!lstrcmpiW(vardescs
->Name
, name
))
1610 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1612 TLBCustData
*cust_data
;
1613 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1614 if(IsEqualIID(&cust_data
->guid
, guid
))
1619 static TLBVarDesc
*TLBVarDesc_Constructor(UINT n
)
1623 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1628 list_init(&ret
[n
-1].custdata_list
);
1635 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1639 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1644 list_init(&ret
[n
-1].custdata_list
);
1651 static TLBFuncDesc
*TLBFuncDesc_Constructor(UINT n
)
1655 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1660 list_init(&ret
[n
-1].custdata_list
);
1667 static TLBImplType
*TLBImplType_Constructor(UINT n
)
1671 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1676 list_init(&ret
[n
-1].custdata_list
);
1683 /**********************************************************************
1685 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
1687 static inline unsigned int MSFT_Tell(const TLBContext
*pcx
)
1692 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
1694 if (where
!= DO_NOT_SEEK
)
1696 where
+= pcx
->oStart
;
1697 if (where
> pcx
->length
)
1700 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
1708 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
1710 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
1711 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
1713 MSFT_Seek(pcx
, where
);
1714 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
1715 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
1720 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1725 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1726 FromLEDWords(buffer
, ret
);
1731 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
1736 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
1737 FromLEWords(buffer
, ret
);
1742 static void MSFT_ReadGuid( GUID
*pGuid
, int offset
, TLBContext
*pcx
)
1744 if(offset
<0 || pcx
->pTblDir
->pGuidTab
.offset
<0){
1745 memset(pGuid
,0, sizeof(GUID
));
1748 MSFT_Read(pGuid
, sizeof(GUID
), pcx
, pcx
->pTblDir
->pGuidTab
.offset
+offset
);
1749 pGuid
->Data1
= FromLEDWord(pGuid
->Data1
);
1750 pGuid
->Data2
= FromLEWord(pGuid
->Data2
);
1751 pGuid
->Data3
= FromLEWord(pGuid
->Data3
);
1752 TRACE_(typelib
)("%s\n", debugstr_guid(pGuid
));
1755 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
1757 MSFT_NameIntro niName
;
1761 ERR_(typelib
)("bad offset %d\n", offset
);
1765 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1766 pcx
->pTblDir
->pNametab
.offset
+offset
);
1768 return niName
.hreftype
;
1771 static BSTR
MSFT_ReadName( TLBContext
*pcx
, int offset
)
1774 MSFT_NameIntro niName
;
1776 BSTR bstrName
= NULL
;
1780 ERR_(typelib
)("bad offset %d\n", offset
);
1783 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
1784 pcx
->pTblDir
->pNametab
.offset
+offset
);
1785 niName
.namelen
&= 0xFF; /* FIXME: correct ? */
1786 name
= heap_alloc_zero((niName
.namelen
& 0xff) +1);
1787 MSFT_Read(name
, (niName
.namelen
& 0xff), pcx
, DO_NOT_SEEK
);
1788 name
[niName
.namelen
& 0xff]='\0';
1790 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1793 /* no invalid characters in string */
1796 bstrName
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1798 /* don't check for invalid character since this has been done previously */
1799 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, name
, -1, bstrName
, lengthInChars
);
1803 TRACE_(typelib
)("%s %d\n", debugstr_w(bstrName
), lengthInChars
);
1807 static BSTR
MSFT_ReadString( TLBContext
*pcx
, int offset
)
1814 if(offset
<0) return NULL
;
1815 MSFT_ReadLEWords(&length
, sizeof(INT16
), pcx
, pcx
->pTblDir
->pStringtab
.offset
+offset
);
1816 if(length
<= 0) return 0;
1817 string
= heap_alloc_zero(length
+1);
1818 MSFT_Read(string
, length
, pcx
, DO_NOT_SEEK
);
1819 string
[length
]='\0';
1821 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
1822 string
, -1, NULL
, 0);
1824 /* no invalid characters in string */
1827 bstr
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
1829 /* don't check for invalid character since this has been done previously */
1830 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, bstr
, lengthInChars
);
1834 TRACE_(typelib
)("%s %d\n", debugstr_w(bstr
), lengthInChars
);
1838 * read a value and fill a VARIANT structure
1840 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
1844 TRACE_(typelib
)("\n");
1846 if(offset
<0) { /* data are packed in here */
1847 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
1848 V_I4(pVar
) = offset
& 0x3ffffff;
1851 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
1852 pcx
->pTblDir
->pCustData
.offset
+ offset
);
1853 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
1854 switch (V_VT(pVar
)){
1855 case VT_EMPTY
: /* FIXME: is this right? */
1856 case VT_NULL
: /* FIXME: is this right? */
1857 case VT_I2
: /* this should not happen */
1868 case VT_VOID
: /* FIXME: is this right? */
1876 case VT_DECIMAL
: /* FIXME: is this right? */
1879 /* pointer types with known behaviour */
1882 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
1885 DWORD origPos
= MSFT_Tell(pcx
), nullPos
;
1888 MSFT_Read(&next
, 1, pcx
, DO_NOT_SEEK
);
1890 nullPos
= MSFT_Tell(pcx
);
1891 size
= nullPos
- origPos
;
1892 MSFT_Seek(pcx
, origPos
);
1894 ptr
= heap_alloc_zero(size
);/* allocate temp buffer */
1895 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);/* read string (ANSI) */
1896 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
1897 /* FIXME: do we need a AtoW conversion here? */
1898 V_UNION(pVar
, bstrVal
[size
])='\0';
1899 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
1903 /* FIXME: this will not work AT ALL when the variant contains a pointer */
1910 case VT_USERDEFINED
:
1916 case VT_STREAMED_OBJECT
:
1917 case VT_STORED_OBJECT
:
1918 case VT_BLOB_OBJECT
:
1923 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
1927 if(size
>0) /* (big|small) endian correct? */
1928 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
1932 * create a linked list with custom data
1934 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
1940 TRACE_(typelib
)("\n");
1942 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
1946 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
1947 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1948 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1949 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1950 list_add_head(custdata_list
, &pNew
->entry
);
1951 offset
= entry
.next
;
1956 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1960 pTd
->vt
=type
& VT_TYPEMASK
;
1962 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1964 if(pTd
->vt
== VT_USERDEFINED
)
1965 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
1967 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1970 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
1972 /* resolve referenced type if any */
1975 switch (lpTypeDesc
->vt
)
1978 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
1982 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
1985 case VT_USERDEFINED
:
1986 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
1987 lpTypeDesc
->u
.hreftype
);
1999 MSFT_DoFuncs(TLBContext
* pcx
,
2004 TLBFuncDesc
** pptfd
)
2007 * member information is stored in a data structure at offset
2008 * indicated by the memoffset field of the typeinfo structure
2009 * There are several distinctive parts.
2010 * The first part starts with a field that holds the total length
2011 * of this (first) part excluding this field. Then follow the records,
2012 * for each member there is one record.
2014 * The first entry is always the length of the record (including this
2016 * The rest of the record depends on the type of the member. If there is
2017 * a field indicating the member type (function, variable, interface, etc)
2018 * I have not found it yet. At this time we depend on the information
2019 * in the type info and the usual order how things are stored.
2021 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2024 * Third is an equal sized array with file offsets to the name entry
2027 * The fourth and last (?) part is an array with offsets to the records
2028 * in the first part of this file segment.
2031 int infolen
, nameoffset
, reclength
, i
;
2032 int recoffset
= offset
+ sizeof(INT
);
2034 char *recbuf
= heap_alloc(0xffff);
2035 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2036 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2038 TRACE_(typelib
)("\n");
2040 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2042 *pptfd
= TLBFuncDesc_Constructor(cFuncs
);
2044 for ( i
= 0; i
< cFuncs
; i
++ )
2048 /* name, eventually add to a hash table */
2049 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2050 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2052 /* nameoffset is sometimes -1 on the second half of a propget/propput
2053 * pair of functions */
2054 if ((nameoffset
== -1) && (i
> 0))
2055 ptfd
->Name
= SysAllocString(ptfd_prev
->Name
);
2057 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2059 /* read the function information record */
2060 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2062 reclength
&= 0xffff;
2064 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2066 /* size without argument data */
2067 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2069 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2070 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2072 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2073 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2075 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2077 if (pFuncRec
->FKCCIC
& 0x2000 )
2079 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2080 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2081 ptfd
->Entry
= (BSTR
)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2084 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2087 ptfd
->Entry
= (BSTR
)-1;
2089 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2090 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2092 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2093 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2095 /* fill the FuncDesc Structure */
2096 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2097 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2099 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2100 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2101 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2102 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2103 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2104 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2105 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2109 &ptfd
->funcdesc
.elemdescFunc
.tdesc
,
2111 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2113 /* do the parameters/arguments */
2114 if(pFuncRec
->nrargs
)
2117 MSFT_ParameterInfo paraminfo
;
2119 ptfd
->funcdesc
.lprgelemdescParam
=
2120 heap_alloc_zero(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
2122 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2124 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2125 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2127 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2129 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2136 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2139 if (paraminfo
.oName
== -1)
2140 /* this occurs for [propput] or [propget] methods, so
2141 * we should just set the name of the parameter to the
2142 * name of the method. */
2143 ptfd
->pParamDesc
[j
].Name
= SysAllocString(ptfd
->Name
);
2145 ptfd
->pParamDesc
[j
].Name
=
2146 MSFT_ReadName( pcx
, paraminfo
.oName
);
2147 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(ptfd
->pParamDesc
[j
].Name
));
2149 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
2152 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2153 (pFuncRec
->FKCCIC
& 0x1000) )
2155 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2157 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2159 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2161 pParamDesc
->pparamdescex
= heap_alloc_zero(sizeof(PARAMDESCEX
));
2162 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2164 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2168 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2171 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2172 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2173 pFuncRec
->FKCCIC
& 0x80 )
2176 pFuncRec
->oArgCustData
[j
],
2177 &ptfd
->pParamDesc
[j
].custdata_list
);
2180 /* SEEK value = jump to offset,
2181 * from there jump to the end of record,
2182 * go back by (j-1) arguments
2184 MSFT_ReadLEDWords( ¶minfo
,
2185 sizeof(MSFT_ParameterInfo
), pcx
,
2186 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2187 * sizeof(MSFT_ParameterInfo
)));
2191 /* scode is not used: archaic win16 stuff FIXME: right? */
2192 ptfd
->funcdesc
.cScodes
= 0 ;
2193 ptfd
->funcdesc
.lprgscode
= NULL
;
2197 recoffset
+= reclength
;
2202 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2203 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2205 int infolen
, nameoffset
, reclength
;
2207 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2212 TRACE_(typelib
)("\n");
2214 ptvd
= *pptvd
= TLBVarDesc_Constructor(cVars
);
2215 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2216 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2217 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2218 recoffset
+= offset
+sizeof(INT
);
2219 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2220 /* name, eventually add to a hash table */
2221 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2222 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2223 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2224 /* read the variable information record */
2225 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2227 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2230 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2231 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2233 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2234 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2236 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2237 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2239 /* fill the VarDesc Structure */
2240 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2241 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2242 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2243 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2244 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2245 &ptvd
->vardesc
.elemdescVar
.tdesc
, pTI
);
2246 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2247 if(pVarRec
->VarKind
== VAR_CONST
){
2248 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2249 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2250 pVarRec
->OffsValue
, pcx
);
2252 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2253 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptvd
->vardesc
.elemdescVar
.tdesc
);
2254 recoffset
+= reclength
;
2258 /* fill in data for a hreftype (offset). When the referenced type is contained
2259 * in the typelib, it's just an (file) offset in the type info base dir.
2260 * If comes from import, it's an offset+1 in the ImpInfo table
2262 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2267 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2269 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2271 if(ref
->reference
== offset
) return;
2274 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2275 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2277 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2278 /* external typelib */
2279 MSFT_ImpInfo impinfo
;
2282 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2284 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2285 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2287 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2288 if(pImpLib
->offset
==impinfo
.oImpFile
)
2291 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2292 ref
->reference
= offset
;
2293 ref
->pImpTLInfo
= pImpLib
;
2294 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2295 MSFT_ReadGuid(&ref
->guid
, impinfo
.oGuid
, pcx
);
2296 TRACE("importing by guid %s\n", debugstr_guid(&ref
->guid
));
2297 ref
->index
= TLB_REF_USE_GUID
;
2299 ref
->index
= impinfo
.oGuid
;
2301 ERR("Cannot find a reference\n");
2302 ref
->reference
= -1;
2303 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2306 /* in this typelib */
2307 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2308 ref
->reference
= offset
;
2309 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2313 /* process Implemented Interfaces of a com class */
2314 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2318 MSFT_RefRecord refrec
;
2321 TRACE_(typelib
)("\n");
2323 pTI
->impltypes
= TLBImplType_Constructor(count
);
2324 pImpl
= pTI
->impltypes
;
2325 for(i
=0;i
<count
;i
++){
2326 if(offset
<0) break; /* paranoia */
2327 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2328 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2329 pImpl
->hRef
= refrec
.reftype
;
2330 pImpl
->implflags
=refrec
.flags
;
2331 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2332 offset
=refrec
.onext
;
2337 * process a typeinfo record
2339 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2342 ITypeLibImpl
* pLibInfo
)
2344 MSFT_TypeInfoBase tiBase
;
2345 ITypeInfoImpl
*ptiRet
;
2347 TRACE_(typelib
)("count=%u\n", count
);
2349 ptiRet
= ITypeInfoImpl_Constructor();
2350 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2351 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2353 /* this is where we are coming from */
2354 ptiRet
->pTypeLib
= pLibInfo
;
2355 ptiRet
->index
=count
;
2356 /* fill in the typeattr fields */
2358 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2359 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2360 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2361 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2362 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2363 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2364 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2365 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2366 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2367 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2368 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2369 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2370 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2371 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2372 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2373 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2376 /* IDLDESC idldescType; *//* never saw this one != zero */
2378 /* name, eventually add to a hash table */
2379 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2380 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2381 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2383 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2384 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2385 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2387 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2388 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2390 /* note: InfoType's Help file and HelpStringDll come from the containing
2391 * library. Further HelpString and Docstring appear to be the same thing :(
2394 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2395 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2396 ptiRet
->TypeAttr
.cVars
,
2397 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2399 if(ptiRet
->TypeAttr
.cVars
>0 )
2400 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2401 ptiRet
->TypeAttr
.cVars
,
2402 tiBase
.memoffset
, &ptiRet
->vardescs
);
2403 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2404 switch(ptiRet
->TypeAttr
.typekind
)
2407 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2410 case TKIND_DISPATCH
:
2411 /* This is not -1 when the interface is a non-base dual interface or
2412 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2413 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2417 if (tiBase
.datatype1
!= -1)
2419 ptiRet
->impltypes
= TLBImplType_Constructor(1);
2420 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2421 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2425 ptiRet
->impltypes
= TLBImplType_Constructor(1);
2426 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2427 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2431 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->custdata_list
);
2433 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2434 debugstr_w(ptiRet
->Name
),
2435 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2436 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2437 if (TRACE_ON(typelib
))
2438 dump_TypeInfo(ptiRet
);
2443 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2444 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2445 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2448 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2449 static CRITICAL_SECTION cache_section
;
2450 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2452 0, 0, &cache_section
,
2453 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2454 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2456 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2459 typedef struct TLB_PEFile
2461 const IUnknownVtbl
*lpvtbl
;
2464 HRSRC typelib_resource
;
2465 HGLOBAL typelib_global
;
2466 LPVOID typelib_base
;
2469 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2471 if (IsEqualIID(riid
, &IID_IUnknown
))
2474 IUnknown_AddRef(iface
);
2478 return E_NOINTERFACE
;
2481 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2483 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2484 return InterlockedIncrement(&This
->refs
);
2487 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2489 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2490 ULONG refs
= InterlockedDecrement(&This
->refs
);
2493 if (This
->typelib_global
)
2494 FreeResource(This
->typelib_global
);
2496 FreeLibrary(This
->dll
);
2502 static const IUnknownVtbl TLB_PEFile_Vtable
=
2504 TLB_PEFile_QueryInterface
,
2509 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2512 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2514 This
= heap_alloc(sizeof(TLB_PEFile
));
2516 return E_OUTOFMEMORY
;
2518 This
->lpvtbl
= &TLB_PEFile_Vtable
;
2521 This
->typelib_resource
= NULL
;
2522 This
->typelib_global
= NULL
;
2523 This
->typelib_base
= NULL
;
2525 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2526 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2530 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2531 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2532 if (This
->typelib_resource
)
2534 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2535 if (This
->typelib_global
)
2537 This
->typelib_base
= LockResource(This
->typelib_global
);
2539 if (This
->typelib_base
)
2541 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2542 *ppBase
= This
->typelib_base
;
2543 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2549 TRACE("No TYPELIB resource found\n");
2553 TLB_PEFile_Release((IUnknown
*)&This
->lpvtbl
);
2557 typedef struct TLB_NEFile
2559 const IUnknownVtbl
*lpvtbl
;
2561 LPVOID typelib_base
;
2564 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2566 if (IsEqualIID(riid
, &IID_IUnknown
))
2569 IUnknown_AddRef(iface
);
2573 return E_NOINTERFACE
;
2576 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2578 TLB_NEFile
*This
= (TLB_NEFile
*)iface
;
2579 return InterlockedIncrement(&This
->refs
);
2582 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2584 TLB_NEFile
*This
= (TLB_NEFile
*)iface
;
2585 ULONG refs
= InterlockedDecrement(&This
->refs
);
2588 heap_free(This
->typelib_base
);
2594 static const IUnknownVtbl TLB_NEFile_Vtable
=
2596 TLB_NEFile_QueryInterface
,
2601 /***********************************************************************
2602 * read_xx_header [internal]
2604 static int read_xx_header( HFILE lzfd
)
2606 IMAGE_DOS_HEADER mzh
;
2609 LZSeek( lzfd
, 0, SEEK_SET
);
2610 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2612 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2615 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2616 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2619 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2621 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2622 return IMAGE_OS2_SIGNATURE
;
2623 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2624 return IMAGE_NT_SIGNATURE
;
2627 WARN("Can't handle %s files.\n", magic
);
2632 /***********************************************************************
2633 * find_ne_resource [internal]
2635 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2636 DWORD
*resLen
, DWORD
*resOff
)
2638 IMAGE_OS2_HEADER nehd
;
2639 NE_TYPEINFO
*typeInfo
;
2640 NE_NAMEINFO
*nameInfo
;
2646 /* Read in NE header */
2647 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2648 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2650 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2653 TRACE("No resources in NE dll\n" );
2657 /* Read in resource table */
2658 resTab
= heap_alloc( resTabSize
);
2659 if ( !resTab
) return FALSE
;
2661 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2662 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2664 heap_free( resTab
);
2669 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2671 if (!IS_INTRESOURCE(typeid)) /* named type */
2673 BYTE len
= strlen( typeid );
2674 while (typeInfo
->type_id
)
2676 if (!(typeInfo
->type_id
& 0x8000))
2678 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2679 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2681 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2682 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2685 else /* numeric type id */
2687 WORD id
= LOWORD(typeid) | 0x8000;
2688 while (typeInfo
->type_id
)
2690 if (typeInfo
->type_id
== id
) goto found_type
;
2691 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2692 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2695 TRACE("No typeid entry found for %p\n", typeid );
2696 heap_free( resTab
);
2700 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
2702 if (!IS_INTRESOURCE(resid
)) /* named resource */
2704 BYTE len
= strlen( resid
);
2705 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2707 BYTE
*p
= resTab
+ nameInfo
->id
;
2708 if (nameInfo
->id
& 0x8000) continue;
2709 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
2712 else /* numeric resource id */
2714 WORD id
= LOWORD(resid
) | 0x8000;
2715 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2716 if (nameInfo
->id
== id
) goto found_name
;
2718 TRACE("No resid entry found for %p\n", typeid );
2719 heap_free( resTab
);
2723 /* Return resource data */
2724 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
2725 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
2727 heap_free( resTab
);
2731 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
2735 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2738 This
= heap_alloc(sizeof(TLB_NEFile
));
2739 if (!This
) return E_OUTOFMEMORY
;
2741 This
->lpvtbl
= &TLB_NEFile_Vtable
;
2743 This
->typelib_base
= NULL
;
2745 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
2746 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
2748 DWORD reslen
, offset
;
2749 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
2751 This
->typelib_base
= heap_alloc(reslen
);
2752 if( !This
->typelib_base
)
2756 LZSeek( lzfd
, offset
, SEEK_SET
);
2757 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
2759 *ppBase
= This
->typelib_base
;
2760 *pdwTLBLength
= reslen
;
2761 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2767 if( lzfd
>= 0) LZClose( lzfd
);
2768 TLB_NEFile_Release((IUnknown
*)&This
->lpvtbl
);
2772 typedef struct TLB_Mapping
2774 const IUnknownVtbl
*lpvtbl
;
2778 LPVOID typelib_base
;
2781 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2783 if (IsEqualIID(riid
, &IID_IUnknown
))
2786 IUnknown_AddRef(iface
);
2790 return E_NOINTERFACE
;
2793 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
2795 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2796 return InterlockedIncrement(&This
->refs
);
2799 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
2801 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2802 ULONG refs
= InterlockedDecrement(&This
->refs
);
2805 if (This
->typelib_base
)
2806 UnmapViewOfFile(This
->typelib_base
);
2808 CloseHandle(This
->mapping
);
2809 if (This
->file
!= INVALID_HANDLE_VALUE
)
2810 CloseHandle(This
->file
);
2816 static const IUnknownVtbl TLB_Mapping_Vtable
=
2818 TLB_Mapping_QueryInterface
,
2823 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2827 This
= heap_alloc(sizeof(TLB_Mapping
));
2829 return E_OUTOFMEMORY
;
2831 This
->lpvtbl
= &TLB_Mapping_Vtable
;
2833 This
->file
= INVALID_HANDLE_VALUE
;
2834 This
->mapping
= NULL
;
2835 This
->typelib_base
= NULL
;
2837 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
2838 if (INVALID_HANDLE_VALUE
!= This
->file
)
2840 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2843 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
2844 if(This
->typelib_base
)
2846 /* retrieve file size */
2847 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
2848 *ppBase
= This
->typelib_base
;
2849 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2855 IUnknown_Release((IUnknown
*)&This
->lpvtbl
);
2856 return TYPE_E_CANTLOADLIBRARY
;
2859 /****************************************************************************
2862 * find the type of the typelib file and map the typelib resource into
2866 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2867 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2869 ITypeLibImpl
*entry
;
2872 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
2873 LPVOID pBase
= NULL
;
2874 DWORD dwTLBLength
= 0;
2875 IUnknown
*pFile
= NULL
;
2879 index_str
= strrchrW(pszFileName
, '\\');
2880 if(index_str
&& *++index_str
!= '\0')
2883 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
2884 if(*end_ptr
== '\0')
2886 int str_len
= index_str
- pszFileName
- 1;
2888 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
2889 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
2894 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
2896 if(strchrW(file
, '\\'))
2898 lstrcpyW(pszPath
, file
);
2902 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
2903 pszPath
[len
] = '\\';
2904 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
2908 if(file
!= pszFileName
) heap_free(file
);
2910 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2912 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2913 EnterCriticalSection(&cache_section
);
2914 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
2916 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2918 TRACE("cache hit\n");
2919 *ppTypeLib
= (ITypeLib2
*)entry
;
2920 ITypeLib2_AddRef(*ppTypeLib
);
2921 LeaveCriticalSection(&cache_section
);
2925 LeaveCriticalSection(&cache_section
);
2927 /* now actually load and parse the typelib */
2929 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2930 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2931 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2932 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2933 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
2936 if (dwTLBLength
>= 4)
2938 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2939 if (dwSignature
== MSFT_SIGNATURE
)
2940 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2941 else if (dwSignature
== SLTG_SIGNATURE
)
2942 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2945 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
2946 ret
= TYPE_E_CANTLOADLIBRARY
;
2950 ret
= TYPE_E_CANTLOADLIBRARY
;
2951 IUnknown_Release(pFile
);
2955 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2957 TRACE("adding to cache\n");
2958 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
2959 lstrcpyW(impl
->path
, pszPath
);
2960 /* We should really canonicalise the path here. */
2961 impl
->index
= index
;
2963 /* FIXME: check if it has added already in the meantime */
2964 EnterCriticalSection(&cache_section
);
2965 list_add_head(&tlb_cache
, &impl
->entry
);
2966 LeaveCriticalSection(&cache_section
);
2972 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
2974 ret
= TYPE_E_CANTLOADLIBRARY
;
2981 /*================== ITypeLib(2) Methods ===================================*/
2983 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
2985 ITypeLibImpl
* pTypeLibImpl
;
2987 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
2988 if (!pTypeLibImpl
) return NULL
;
2990 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2991 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2992 pTypeLibImpl
->ref
= 1;
2994 list_init(&pTypeLibImpl
->implib_list
);
2995 list_init(&pTypeLibImpl
->custdata_list
);
2996 list_init(&pTypeLibImpl
->ref_list
);
2997 pTypeLibImpl
->dispatch_href
= -1;
2999 return pTypeLibImpl
;
3002 /****************************************************************************
3003 * ITypeLib2_Constructor_MSFT
3005 * loading an MSFT typelib from an in-memory image
3007 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3011 MSFT_Header tlbHeader
;
3012 MSFT_SegDir tlbSegDir
;
3013 ITypeLibImpl
* pTypeLibImpl
;
3015 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3017 pTypeLibImpl
= TypeLibImpl_Constructor();
3018 if (!pTypeLibImpl
) return NULL
;
3020 /* get pointer to beginning of typelib data */
3024 cx
.pLibInfo
= pTypeLibImpl
;
3025 cx
.length
= dwTLBLength
;
3028 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3029 TRACE_(typelib
)("header:\n");
3030 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3031 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3032 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3035 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3037 /* there is a small amount of information here until the next important
3039 * the segment directory . Try to calculate the amount of data */
3040 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3042 /* now read the segment directory */
3043 TRACE("read segment directory (at %d)\n",lPSegDir
);
3044 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3045 cx
.pTblDir
= &tlbSegDir
;
3047 /* just check two entries */
3048 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3050 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3051 heap_free(pTypeLibImpl
);
3055 /* now fill our internal data */
3056 /* TLIBATTR fields */
3057 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
3059 pTypeLibImpl
->LibAttr
.lcid
= tlbHeader
.lcid2
;
3060 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3061 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
3062 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
3063 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
3065 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3067 /* name, eventually add to a hash table */
3068 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3071 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3072 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3074 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3077 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3078 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3081 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3084 if(tlbHeader
.CustomDataOffset
>= 0)
3086 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3089 /* fill in type descriptions */
3090 if(tlbSegDir
.pTypdescTab
.length
> 0)
3092 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3094 pTypeLibImpl
->ctTypeDesc
= cTD
;
3095 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3096 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3099 /* FIXME: add several sanity checks here */
3100 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3101 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3103 /* FIXME: check safearray */
3105 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3107 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3109 else if(td
[0] == VT_CARRAY
)
3111 /* array descr table here */
3112 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3114 else if(td
[0] == VT_USERDEFINED
)
3116 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3118 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3121 /* second time around to fill the array subscript info */
3124 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3125 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3127 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3128 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3131 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3133 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3135 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3137 for(j
= 0; j
<td
[2]; j
++)
3139 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3140 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3141 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3142 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3147 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3148 ERR("didn't find array description data\n");
3153 /* imported type libs */
3154 if(tlbSegDir
.pImpFiles
.offset
>0)
3157 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3160 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3164 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3165 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3166 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3168 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3169 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3170 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3171 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3174 name
= heap_alloc_zero(size
+1);
3175 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3176 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3179 MSFT_ReadGuid(&pImpLib
->guid
, oGuid
, &cx
);
3180 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3182 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3186 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3187 if(pTypeLibImpl
->dispatch_href
!= -1)
3188 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
3191 if(tlbHeader
.nrtypeinfos
>= 0 )
3193 ITypeInfoImpl
**ppTI
;
3196 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3198 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3200 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3203 (pTypeLibImpl
->TypeInfoCount
)++;
3207 TRACE("(%p)\n", pTypeLibImpl
);
3208 return (ITypeLib2
*) pTypeLibImpl
;
3212 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3218 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3219 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3223 guid
->Data4
[0] = s
>> 8;
3224 guid
->Data4
[1] = s
& 0xff;
3227 for(i
= 0; i
< 6; i
++) {
3228 memcpy(b
, str
+ 24 + 2 * i
, 2);
3229 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3234 static WORD
SLTG_ReadString(const char *ptr
, BSTR
*pBstr
)
3240 bytelen
= *(const WORD
*)ptr
;
3241 if(bytelen
== 0xffff) return 2;
3242 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3243 *pBstr
= SysAllocStringLen(NULL
, len
);
3245 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, *pBstr
, len
);
3249 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3254 bytelen
= *(const WORD
*)ptr
;
3255 if(bytelen
== 0xffff) return 2;
3256 *str
= heap_alloc(bytelen
+ 1);
3257 memcpy(*str
, ptr
+ 2, bytelen
);
3258 (*str
)[bytelen
] = '\0';
3262 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3264 char *ptr
= pLibBlk
;
3267 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3268 FIXME("libblk magic = %04x\n", w
);
3273 if((w
= *(WORD
*)ptr
) != 0xffff) {
3274 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3279 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
3281 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
3283 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3286 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
3289 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3290 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3292 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= 0;
3295 ptr
+= 4; /* skip res12 */
3297 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
3300 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
3303 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
3306 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
3307 ptr
+= sizeof(GUID
);
3309 return ptr
- (char*)pLibBlk
;
3312 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3317 } sltg_ref_lookup_t
;
3319 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3320 HREFTYPE
*typelib_ref
)
3322 if(table
&& typeinfo_ref
< table
->num
)
3324 *typelib_ref
= table
->refs
[typeinfo_ref
];
3328 ERR_(typelib
)("Unable to find reference\n");
3333 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3338 if((*pType
& 0xe00) == 0xe00) {
3340 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3341 pTD
= pTD
->u
.lptdesc
;
3343 switch(*pType
& 0x3f) {
3346 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3347 pTD
= pTD
->u
.lptdesc
;
3350 case VT_USERDEFINED
:
3351 pTD
->vt
= VT_USERDEFINED
;
3352 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3358 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3361 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3363 pTD
->vt
= VT_CARRAY
;
3364 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3365 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3366 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3367 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3369 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3375 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3379 pTD
->vt
= VT_SAFEARRAY
;
3380 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3381 pTD
= pTD
->u
.lptdesc
;
3385 pTD
->vt
= *pType
& 0x3f;
3394 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3395 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3397 /* Handle [in/out] first */
3398 if((*pType
& 0xc000) == 0xc000)
3399 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3400 else if(*pType
& 0x8000)
3401 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3402 else if(*pType
& 0x4000)
3403 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3405 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3408 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3411 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3413 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3417 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3422 TLBRefType
*ref_type
;
3423 sltg_ref_lookup_t
*table
;
3424 HREFTYPE typelib_ref
;
3426 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3427 FIXME("Ref magic = %x\n", pRef
->magic
);
3430 name
= ( (char*)pRef
->names
+ pRef
->number
);
3432 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3433 table
->num
= pRef
->number
>> 3;
3435 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3437 /* We don't want the first href to be 0 */
3438 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3440 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3442 unsigned int lib_offs
, type_num
;
3444 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3446 name
+= SLTG_ReadStringA(name
, &refname
);
3447 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3448 FIXME_(typelib
)("Can't sscanf ref\n");
3449 if(lib_offs
!= 0xffff) {
3452 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3453 if(import
->offset
== lib_offs
)
3456 if(&import
->entry
== &pTL
->implib_list
) {
3457 char fname
[MAX_PATH
+1];
3460 import
= heap_alloc_zero(sizeof(*import
));
3461 import
->offset
= lib_offs
;
3462 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
3464 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3465 &import
->wVersionMajor
,
3466 &import
->wVersionMinor
,
3467 &import
->lcid
, fname
) != 4) {
3468 FIXME_(typelib
)("can't sscanf ref %s\n",
3469 pNameTable
+ lib_offs
+ 40);
3471 len
= strlen(fname
);
3472 if(fname
[len
-1] != '#')
3473 FIXME("fname = %s\n", fname
);
3474 fname
[len
-1] = '\0';
3475 import
->name
= TLB_MultiByteToBSTR(fname
);
3476 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3478 ref_type
->pImpTLInfo
= import
;
3480 /* Store a reference to IDispatch */
3481 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
, &IID_StdOle
) && type_num
== 4)
3482 pTL
->dispatch_href
= typelib_ref
;
3484 } else { /* internal ref */
3485 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3487 ref_type
->reference
= typelib_ref
;
3488 ref_type
->index
= type_num
;
3491 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3493 table
->refs
[ref
] = typelib_ref
;
3496 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3497 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3498 dump_TLBRefType(pTL
);
3502 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3503 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3505 SLTG_ImplInfo
*info
;
3506 TLBImplType
*pImplType
;
3507 /* I don't really get this structure, usually it's 0x16 bytes
3508 long, but iuser.tlb contains some that are 0x18 bytes long.
3509 That's ok because we can use the next ptr to jump to the next
3510 one. But how do we know the length of the last one? The WORD
3511 at offs 0x8 might be the clue. For now I'm just assuming that
3512 the last one is the regular 0x16 bytes. */
3514 info
= (SLTG_ImplInfo
*)pBlk
;
3516 pTI
->TypeAttr
.cImplTypes
++;
3517 if(info
->next
== 0xffff)
3519 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3522 info
= (SLTG_ImplInfo
*)pBlk
;
3523 pTI
->impltypes
= TLBImplType_Constructor(pTI
->TypeAttr
.cImplTypes
);
3524 pImplType
= pTI
->impltypes
;
3526 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3527 pImplType
->implflags
= info
->impltypeflags
;
3530 if(info
->next
== 0xffff)
3533 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3534 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3536 info
++; /* see comment at top of function */
3540 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3541 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3543 TLBVarDesc
*pVarDesc
;
3544 BSTR bstrPrevName
= NULL
;
3545 SLTG_Variable
*pItem
;
3549 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Constructor(cVars
);
3551 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3552 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
3554 pVarDesc
->vardesc
.memid
= pItem
->memid
;
3556 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3557 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3558 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3562 if (pItem
->name
== 0xfffe)
3563 pVarDesc
->Name
= SysAllocString(bstrPrevName
);
3565 pVarDesc
->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3567 TRACE_(typelib
)("name: %s\n", debugstr_w(pVarDesc
->Name
));
3568 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3569 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3571 if(pItem
->flags
& 0x02)
3572 pType
= &pItem
->type
;
3574 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3576 if (pItem
->flags
& ~0xda)
3577 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3579 SLTG_DoElem(pType
, pBlk
,
3580 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
3582 if (TRACE_ON(typelib
)) {
3584 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
3585 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3588 if (pItem
->flags
& 0x40) {
3589 TRACE_(typelib
)("VAR_DISPATCH\n");
3590 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
3592 else if (pItem
->flags
& 0x10) {
3593 TRACE_(typelib
)("VAR_CONST\n");
3594 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
3595 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
3596 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
3597 if (pItem
->flags
& 0x08)
3598 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3600 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
3606 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3608 TRACE_(typelib
)("len = %u\n", len
);
3609 if (len
== 0xffff) {
3612 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3613 str
= SysAllocStringLen(NULL
, alloc_len
);
3614 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3616 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3617 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
3626 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
3627 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3630 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
3635 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3636 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
3637 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
3640 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3641 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
3643 if (pItem
->flags
& 0x80)
3644 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3646 bstrPrevName
= pVarDesc
->Name
;
3648 pTI
->TypeAttr
.cVars
= cVars
;
3651 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3652 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3654 SLTG_Function
*pFunc
;
3656 TLBFuncDesc
*pFuncDesc
;
3658 pTI
->funcdescs
= TLBFuncDesc_Constructor(cFuncs
);
3660 pFuncDesc
= pTI
->funcdescs
;
3661 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
3662 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
3667 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
3668 case SLTG_FUNCTION_MAGIC
:
3669 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
3671 case SLTG_DISPATCH_FUNCTION_MAGIC
:
3672 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
3674 case SLTG_STATIC_FUNCTION_MAGIC
:
3675 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
3678 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
3681 pFuncDesc
->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
3683 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
3684 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
3685 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
3686 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
3687 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
3688 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
3690 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
3691 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
3693 if(pFunc
->retnextopt
& 0x80)
3694 pType
= &pFunc
->rettype
;
3696 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
3698 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
3700 pFuncDesc
->funcdesc
.lprgelemdescParam
=
3701 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
3702 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
3704 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3706 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
3707 char *paramName
= pNameTable
+ *pArg
;
3709 /* If arg type follows then paramName points to the 2nd
3710 letter of the name, else the next WORD is an offset to
3711 the arg type and paramName points to the first letter.
3712 So let's take one char off paramName and see if we're
3713 pointing at an alpha-numeric char. However if *pArg is
3714 0xffff or 0xfffe then the param has no name, the former
3715 meaning that the next WORD is the type, the latter
3716 meaning that the next WORD is an offset to the type. */
3721 else if(*pArg
== 0xfffe) {
3725 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3730 if(HaveOffs
) { /* the next word is an offset to type */
3731 pType
= (WORD
*)(pBlk
+ *pArg
);
3732 SLTG_DoElem(pType
, pBlk
,
3733 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3738 pArg
= SLTG_DoElem(pArg
, pBlk
,
3739 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3742 /* Are we an optional param ? */
3743 if(pFuncDesc
->funcdesc
.cParams
- param
<=
3744 pFuncDesc
->funcdesc
.cParamsOpt
)
3745 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3748 pFuncDesc
->pParamDesc
[param
].Name
=
3749 TLB_MultiByteToBSTR(paramName
);
3751 pFuncDesc
->pParamDesc
[param
].Name
=
3752 SysAllocString(pFuncDesc
->Name
);
3756 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3759 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3760 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3761 SLTG_TypeInfoTail
*pTITail
)
3764 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3766 if(pTIHeader
->href_table
!= 0xffffffff) {
3767 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3773 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3774 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
3776 heap_free(ref_lookup
);
3780 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3781 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3782 const SLTG_TypeInfoTail
*pTITail
)
3785 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3787 if(pTIHeader
->href_table
!= 0xffffffff) {
3788 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3794 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3795 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
3798 if (pTITail
->funcs_off
!= 0xffff)
3799 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3801 heap_free(ref_lookup
);
3803 if (TRACE_ON(typelib
))
3804 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->TypeAttr
.cFuncs
);
3807 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3808 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3809 const SLTG_TypeInfoTail
*pTITail
)
3811 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3814 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3815 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3816 const SLTG_TypeInfoTail
*pTITail
)
3819 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3821 if (pTITail
->simple_alias
) {
3822 /* if simple alias, no more processing required */
3823 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3827 if(pTIHeader
->href_table
!= 0xffffffff) {
3828 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3832 /* otherwise it is an offset to a type */
3833 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3835 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
, ref_lookup
);
3837 heap_free(ref_lookup
);
3840 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3841 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3842 const SLTG_TypeInfoTail
*pTITail
)
3844 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3845 if (pTIHeader
->href_table
!= 0xffffffff)
3846 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3849 if (pTITail
->vars_off
!= 0xffff)
3850 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3852 if (pTITail
->funcs_off
!= 0xffff)
3853 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3855 if (pTITail
->impls_off
!= 0xffff)
3856 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
3858 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3859 * of dispinterface functions including the IDispatch ones, so
3860 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3861 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3863 heap_free(ref_lookup
);
3864 if (TRACE_ON(typelib
))
3865 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->TypeAttr
.cFuncs
);
3868 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3869 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3870 const SLTG_TypeInfoTail
*pTITail
)
3872 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3875 static void SLTG_ProcessModule(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
);
3889 heap_free(ref_lookup
);
3890 if (TRACE_ON(typelib
))
3894 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3895 manageable copy of it into this */
3908 } SLTG_InternalOtherTypeInfo
;
3910 /****************************************************************************
3911 * ITypeLib2_Constructor_SLTG
3913 * loading a SLTG typelib from an in-memory image
3915 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3917 ITypeLibImpl
*pTypeLibImpl
;
3918 SLTG_Header
*pHeader
;
3919 SLTG_BlkEntry
*pBlkEntry
;
3923 LPVOID pBlk
, pFirstBlk
;
3924 SLTG_LibBlk
*pLibBlk
;
3925 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3926 char *pAfterOTIBlks
= NULL
;
3927 char *pNameTable
, *ptr
;
3930 ITypeInfoImpl
**ppTypeInfoImpl
;
3932 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3935 pTypeLibImpl
= TypeLibImpl_Constructor();
3936 if (!pTypeLibImpl
) return NULL
;
3940 TRACE_(typelib
)("header:\n");
3941 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
3942 pHeader
->nrOfFileBlks
);
3943 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3944 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
3945 pHeader
->SLTG_magic
);
3949 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3950 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3952 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3953 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3955 /* Next we have a magic block */
3956 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3958 /* Let's see if we're still in sync */
3959 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3960 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3961 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3964 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3965 sizeof(SLTG_DIR_MAGIC
))) {
3966 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
3970 pIndex
= (SLTG_Index
*)(pMagic
+1);
3972 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3974 pFirstBlk
= pPad9
+ 1;
3976 /* We'll set up a ptr to the main library block, which is the last one. */
3978 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3979 pBlkEntry
[order
].next
!= 0;
3980 order
= pBlkEntry
[order
].next
- 1, i
++) {
3981 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3985 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3987 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3992 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3994 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
3997 ptr
= (char*)pLibBlk
+ len
;
3999 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4003 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4005 w
= *(WORD
*)(ptr
+ 2);
4008 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4009 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4010 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4012 w
= *(WORD
*)(ptr
+ 4 + len
);
4014 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4016 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4017 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4018 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4020 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4021 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4022 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4024 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4025 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4028 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4029 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4030 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4031 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4032 len
+= sizeof(SLTG_OtherTypeInfo
);
4036 pAfterOTIBlks
= ptr
;
4038 /* Skip this WORD and get the next DWORD */
4039 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4041 /* Now add this to pLibBLk look at what we're pointing at and
4042 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4043 dust and we should be pointing at the beginning of the name
4046 pNameTable
= (char*)pLibBlk
+ len
;
4048 switch(*(WORD
*)pNameTable
) {
4055 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4059 pNameTable
+= 0x216;
4063 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4065 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
4068 /* Hopefully we now have enough ptrs set up to actually read in
4069 some TypeInfos. It's not clear which order to do them in, so
4070 I'll just follow the links along the BlkEntry chain and read
4071 them in the order in which they are in the file */
4073 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4074 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4076 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4077 pBlkEntry
[order
].next
!= 0;
4078 order
= pBlkEntry
[order
].next
- 1, i
++) {
4080 SLTG_TypeInfoHeader
*pTIHeader
;
4081 SLTG_TypeInfoTail
*pTITail
;
4082 SLTG_MemberHeader
*pMemHeader
;
4084 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4085 FIXME_(typelib
)("Index strings don't match\n");
4086 heap_free(pOtherTypeInfoBlks
);
4091 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4092 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4093 heap_free(pOtherTypeInfoBlks
);
4096 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4097 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4098 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4100 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4101 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4102 (*ppTypeInfoImpl
)->index
= i
;
4103 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
4104 pOtherTypeInfoBlks
[i
].name_offs
+
4106 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4107 (*ppTypeInfoImpl
)->TypeAttr
.guid
= pOtherTypeInfoBlks
[i
].uuid
;
4108 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
4109 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
4110 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
4111 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
4112 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4114 if((*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4115 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= TKIND_DISPATCH
;
4117 if((pTIHeader
->typeflags1
& 7) != 2)
4118 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4119 if(pTIHeader
->typeflags3
!= 2)
4120 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4122 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4123 debugstr_w((*ppTypeInfoImpl
)->Name
),
4124 typekind_desc
[pTIHeader
->typekind
],
4125 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
4126 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
4128 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4130 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4132 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
4133 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4134 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
4136 switch(pTIHeader
->typekind
) {
4138 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4139 pTIHeader
, pTITail
);
4143 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4144 pTIHeader
, pTITail
);
4147 case TKIND_INTERFACE
:
4148 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4149 pTIHeader
, pTITail
);
4153 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4154 pTIHeader
, pTITail
);
4158 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4159 pTIHeader
, pTITail
);
4162 case TKIND_DISPATCH
:
4163 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4164 pTIHeader
, pTITail
);
4168 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4169 pTIHeader
, pTITail
);
4173 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4178 /* could get cFuncs, cVars and cImplTypes from here
4179 but we've already set those */
4180 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4196 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4199 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4200 FIXME("Somehow processed %d TypeInfos\n", i
);
4201 heap_free(pOtherTypeInfoBlks
);
4205 heap_free(pOtherTypeInfoBlks
);
4206 return (ITypeLib2
*)pTypeLibImpl
;
4209 /* ITypeLib::QueryInterface
4211 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
4216 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4218 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4221 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4222 IsEqualIID(riid
,&IID_ITypeLib
)||
4223 IsEqualIID(riid
,&IID_ITypeLib2
))
4230 ITypeLib2_AddRef(iface
);
4231 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4234 TRACE("-- Interface: E_NOINTERFACE\n");
4235 return E_NOINTERFACE
;
4240 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4242 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4243 ULONG ref
= InterlockedIncrement(&This
->ref
);
4245 TRACE("(%p)->ref was %u\n",This
, ref
- 1);
4250 /* ITypeLib::Release
4252 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4254 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4255 ULONG ref
= InterlockedDecrement(&This
->ref
);
4257 TRACE("(%p)->(%u)\n",This
, ref
);
4261 TLBImpLib
*pImpLib
, *pImpLibNext
;
4262 TLBRefType
*ref_type
;
4266 /* remove cache entry */
4269 TRACE("removing from cache list\n");
4270 EnterCriticalSection(&cache_section
);
4271 if(This
->entry
.next
)
4272 list_remove(&This
->entry
);
4273 LeaveCriticalSection(&cache_section
);
4274 heap_free(This
->path
);
4276 TRACE(" destroying ITypeLib(%p)\n",This
);
4278 SysFreeString(This
->Name
);
4281 SysFreeString(This
->DocString
);
4282 This
->DocString
= NULL
;
4284 SysFreeString(This
->HelpFile
);
4285 This
->HelpFile
= NULL
;
4287 SysFreeString(This
->HelpStringDll
);
4288 This
->HelpStringDll
= NULL
;
4290 TLB_FreeCustData(&This
->custdata_list
);
4292 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4293 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4294 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4296 heap_free(This
->pTypeDesc
);
4298 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4300 if (pImpLib
->pImpTypeLib
)
4301 ITypeLib_Release((ITypeLib
*)pImpLib
->pImpTypeLib
);
4302 SysFreeString(pImpLib
->name
);
4304 list_remove(&pImpLib
->entry
);
4308 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4310 list_remove(&ref_type
->entry
);
4311 heap_free(ref_type
);
4314 for (i
= 0; i
< This
->TypeInfoCount
; ++i
)
4315 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4316 heap_free(This
->typeinfos
);
4324 /* ITypeLib::GetTypeInfoCount
4326 * Returns the number of type descriptions in the type library
4328 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4330 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4331 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4332 return This
->TypeInfoCount
;
4335 /* ITypeLib::GetTypeInfo
4337 * retrieves the specified type description in the library.
4339 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4342 ITypeInfo
**ppTInfo
)
4344 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4346 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4349 return E_INVALIDARG
;
4351 if(index
>= This
->TypeInfoCount
)
4352 return TYPE_E_ELEMENTNOTFOUND
;
4354 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[index
];
4355 ITypeInfo_AddRef(*ppTInfo
);
4361 /* ITypeLibs::GetTypeInfoType
4363 * Retrieves the type of a type description.
4365 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4370 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4372 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4375 return E_INVALIDARG
;
4377 if(index
>= This
->TypeInfoCount
)
4378 return TYPE_E_ELEMENTNOTFOUND
;
4380 *pTKind
= This
->typeinfos
[index
]->TypeAttr
.typekind
;
4385 /* ITypeLib::GetTypeInfoOfGuid
4387 * Retrieves the type description that corresponds to the specified GUID.
4390 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4393 ITypeInfo
**ppTInfo
)
4395 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4398 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4400 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4401 if(IsEqualIID(&This
->typeinfos
[i
]->TypeAttr
.guid
, guid
)){
4402 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[i
];
4403 ITypeInfo_AddRef(*ppTInfo
);
4408 return TYPE_E_ELEMENTNOTFOUND
;
4411 /* ITypeLib::GetLibAttr
4413 * Retrieves the structure that contains the library's attributes.
4416 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4420 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4422 TRACE("(%p, %p)\n", This
, attr
);
4424 if (!attr
) return E_INVALIDARG
;
4426 *attr
= heap_alloc(sizeof(**attr
));
4427 if (!*attr
) return E_OUTOFMEMORY
;
4429 **attr
= This
->LibAttr
;
4433 /* ITypeLib::GetTypeComp
4435 * Enables a client compiler to bind to a library's types, variables,
4436 * constants, and global functions.
4439 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4441 ITypeComp
**ppTComp
)
4443 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4445 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4446 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4447 ITypeComp_AddRef(*ppTComp
);
4452 /* ITypeLib::GetDocumentation
4454 * Retrieves the library's documentation string, the complete Help file name
4455 * and path, and the context identifier for the library Help topic in the Help
4458 * On a successful return all non-null BSTR pointers will have been set,
4461 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4465 BSTR
*pBstrDocString
,
4466 DWORD
*pdwHelpContext
,
4467 BSTR
*pBstrHelpFile
)
4469 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4471 HRESULT result
= E_INVALIDARG
;
4476 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4478 pBstrName
, pBstrDocString
,
4479 pdwHelpContext
, pBstrHelpFile
);
4483 /* documentation for the typelib */
4488 if(!(*pBstrName
= SysAllocString(This
->Name
)))
4496 if (This
->DocString
)
4498 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
4501 else if (This
->Name
)
4503 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
4507 *pBstrDocString
= NULL
;
4511 *pdwHelpContext
= This
->dwHelpContext
;
4517 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
4521 *pBstrHelpFile
= NULL
;
4528 /* for a typeinfo */
4529 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4531 if(SUCCEEDED(result
))
4533 result
= ITypeInfo_GetDocumentation(pTInfo
,
4537 pdwHelpContext
, pBstrHelpFile
);
4539 ITypeInfo_Release(pTInfo
);
4544 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4546 if (pBstrName
) SysFreeString (*pBstrName
);
4548 return STG_E_INSUFFICIENTMEMORY
;
4553 * Indicates whether a passed-in string contains the name of a type or member
4554 * described in the library.
4557 static HRESULT WINAPI
ITypeLib2_fnIsName(
4563 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4564 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), tic
, fdc
, vrc
, pc
;
4566 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4570 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
4571 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4572 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4573 for(fdc
= 0; fdc
< pTInfo
->TypeAttr
.cFuncs
; ++fdc
) {
4574 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
4575 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4576 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++)
4577 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
4578 goto ITypeLib2_fnIsName_exit
;
4580 for(vrc
= 0; vrc
< pTInfo
->TypeAttr
.cVars
; ++vrc
){
4581 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
4582 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4588 ITypeLib2_fnIsName_exit
:
4589 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4590 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4595 /* ITypeLib::FindName
4597 * Finds occurrences of a type description in a type library. This may be used
4598 * to quickly verify that a name exists in a type library.
4601 static HRESULT WINAPI
ITypeLib2_fnFindName(
4605 ITypeInfo
**ppTInfo
,
4609 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4610 UINT tic
, count
= 0;
4613 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
4615 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
4616 return E_INVALIDARG
;
4618 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
4619 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
) {
4620 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4624 if(!memcmp(name
, pTInfo
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4625 for(fdc
= 0; fdc
< pTInfo
->TypeAttr
.cFuncs
; ++fdc
) {
4626 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
4629 if(!memcmp(name
, func
->Name
, len
)) goto ITypeLib2_fnFindName_exit
;
4630 for(pc
= 0; pc
< func
->funcdesc
.cParams
; pc
++) {
4631 if(!memcmp(name
, func
->pParamDesc
[pc
].Name
, len
))
4632 goto ITypeLib2_fnFindName_exit
;
4636 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->TypeAttr
.cVars
, name
);
4638 goto ITypeLib2_fnFindName_exit
;
4641 ITypeLib2_fnFindName_exit
:
4642 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4643 ppTInfo
[count
]=(LPTYPEINFO
)pTInfo
;
4646 TRACE("found %d typeinfos\n", count
);
4653 /* ITypeLib::ReleaseTLibAttr
4655 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4658 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4660 TLIBATTR
*pTLibAttr
)
4662 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4663 TRACE("freeing (%p)\n",This
);
4664 heap_free(pTLibAttr
);
4668 /* ITypeLib2::GetCustData
4670 * gets the custom data
4672 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
4677 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4678 TLBCustData
*pCData
;
4680 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
4682 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
4684 return TYPE_E_ELEMENTNOTFOUND
;
4686 VariantInit(pVarVal
);
4687 VariantCopy(pVarVal
, &pCData
->data
);
4692 /* ITypeLib2::GetLibStatistics
4694 * Returns statistics about a type library that are required for efficient
4695 * sizing of hash tables.
4698 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4700 ULONG
*pcUniqueNames
,
4701 ULONG
*pcchUniqueNames
)
4703 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4705 FIXME("(%p): stub!\n", This
);
4707 if(pcUniqueNames
) *pcUniqueNames
=1;
4708 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4712 /* ITypeLib2::GetDocumentation2
4714 * Retrieves the library's documentation string, the complete Help file name
4715 * and path, the localization context to use, and the context ID for the
4716 * library Help topic in the Help file.
4719 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4723 BSTR
*pbstrHelpString
,
4724 DWORD
*pdwHelpStringContext
,
4725 BSTR
*pbstrHelpStringDll
)
4727 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4731 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4733 /* the help string should be obtained from the helpstringdll,
4734 * using the _DLLGetDocumentation function, based on the supplied
4735 * lcid. Nice to do sometime...
4739 /* documentation for the typelib */
4741 *pbstrHelpString
=SysAllocString(This
->DocString
);
4742 if(pdwHelpStringContext
)
4743 *pdwHelpStringContext
=This
->dwHelpContext
;
4744 if(pbstrHelpStringDll
)
4745 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
4751 /* for a typeinfo */
4752 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
4754 if(SUCCEEDED(result
))
4756 ITypeInfo2
* pTInfo2
;
4757 result
= ITypeInfo_QueryInterface(pTInfo
,
4759 (LPVOID
*) &pTInfo2
);
4761 if(SUCCEEDED(result
))
4763 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4767 pdwHelpStringContext
,
4768 pbstrHelpStringDll
);
4770 ITypeInfo2_Release(pTInfo2
);
4773 ITypeInfo_Release(pTInfo
);
4779 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
4781 TLBCustData
*pCData
;
4785 ct
= list_count(custdata_list
);
4787 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
4788 if(!pCustData
->prgCustData
)
4789 return E_OUTOFMEMORY
;
4791 pCustData
->cCustData
= ct
;
4793 cdi
= pCustData
->prgCustData
;
4794 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
4795 cdi
->guid
= pCData
->guid
;
4796 VariantCopy(&cdi
->varValue
, &pCData
->data
);
4804 /* ITypeLib2::GetAllCustData
4806 * Gets all custom data items for the library.
4809 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4811 CUSTDATA
*pCustData
)
4813 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4814 TRACE("%p %p\n", iface
, pCustData
);
4815 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
4818 static const ITypeLib2Vtbl tlbvt
= {
4819 ITypeLib2_fnQueryInterface
,
4821 ITypeLib2_fnRelease
,
4822 ITypeLib2_fnGetTypeInfoCount
,
4823 ITypeLib2_fnGetTypeInfo
,
4824 ITypeLib2_fnGetTypeInfoType
,
4825 ITypeLib2_fnGetTypeInfoOfGuid
,
4826 ITypeLib2_fnGetLibAttr
,
4827 ITypeLib2_fnGetTypeComp
,
4828 ITypeLib2_fnGetDocumentation
,
4830 ITypeLib2_fnFindName
,
4831 ITypeLib2_fnReleaseTLibAttr
,
4833 ITypeLib2_fnGetCustData
,
4834 ITypeLib2_fnGetLibStatistics
,
4835 ITypeLib2_fnGetDocumentation2
,
4836 ITypeLib2_fnGetAllCustData
4840 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4842 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4844 return ITypeLib2_QueryInterface((ITypeLib2
*)This
, riid
, ppv
);
4847 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4849 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4851 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4854 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4856 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4858 return ITypeLib2_Release((ITypeLib2
*)This
);
4861 static HRESULT WINAPI
ITypeLibComp_fnBind(
4866 ITypeInfo
** ppTInfo
,
4867 DESCKIND
* pDescKind
,
4870 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4871 int typemismatch
=0, i
;
4873 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4875 *pDescKind
= DESCKIND_NONE
;
4876 pBindPtr
->lptcomp
= NULL
;
4879 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4880 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
4881 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4883 /* FIXME: check wFlags here? */
4884 /* FIXME: we should use a hash table to look this info up using lHash
4885 * instead of an O(n) search */
4886 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4887 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4889 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4891 *pDescKind
= DESCKIND_TYPECOMP
;
4892 pBindPtr
->lptcomp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4893 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4894 TRACE("module or enum: %s\n", debugstr_w(szName
));
4899 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4900 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4902 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4905 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4906 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4908 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4911 else if (hr
== TYPE_E_TYPEMISMATCH
)
4915 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4916 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4918 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4920 ITypeInfo
*subtypeinfo
;
4922 DESCKIND subdesckind
;
4924 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4925 &subtypeinfo
, &subdesckind
, &subbindptr
);
4926 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4928 TYPEDESC tdesc_appobject
;
4929 const VARDESC vardesc_appobject
=
4932 NULL
, /* lpstrSchema */
4947 VAR_STATIC
/* varkind */
4950 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
4951 tdesc_appobject
.vt
= VT_USERDEFINED
;
4953 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
4955 /* cleanup things filled in by Bind call so we can put our
4956 * application object data in there instead */
4957 switch (subdesckind
)
4959 case DESCKIND_FUNCDESC
:
4960 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
4962 case DESCKIND_VARDESC
:
4963 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
4968 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
4970 if (pTypeInfo
->hreftype
== -1)
4971 FIXME("no hreftype for interface %p\n", pTypeInfo
);
4973 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
4977 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
4978 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4979 ITypeInfo_AddRef(*ppTInfo
);
4982 else if (hr
== TYPE_E_TYPEMISMATCH
)
4989 TRACE("type mismatch %s\n", debugstr_w(szName
));
4990 return TYPE_E_TYPEMISMATCH
;
4994 TRACE("name not found %s\n", debugstr_w(szName
));
4999 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5003 ITypeInfo
** ppTInfo
,
5004 ITypeComp
** ppTComp
)
5006 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5009 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5011 if(!szName
|| !ppTInfo
|| !ppTComp
)
5012 return E_INVALIDARG
;
5014 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
5016 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5017 /* FIXME: should use lHash to do the search */
5018 if (pTypeInfo
->Name
&& !strcmpiW(pTypeInfo
->Name
, szName
))
5020 TRACE("returning %p\n", pTypeInfo
);
5021 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->lpVtbl
;
5022 ITypeInfo_AddRef(*ppTInfo
);
5023 *ppTComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
5024 ITypeComp_AddRef(*ppTComp
);
5029 TRACE("not found\n");
5035 static const ITypeCompVtbl tlbtcvt
=
5038 ITypeLibComp_fnQueryInterface
,
5039 ITypeLibComp_fnAddRef
,
5040 ITypeLibComp_fnRelease
,
5042 ITypeLibComp_fnBind
,
5043 ITypeLibComp_fnBindType
5046 /*================== ITypeInfo(2) Methods ===================================*/
5047 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5049 ITypeInfoImpl
*pTypeInfoImpl
;
5051 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5054 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
5055 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
5056 pTypeInfoImpl
->ref
= 0;
5057 pTypeInfoImpl
->hreftype
= -1;
5058 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
5059 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
5060 list_init(&pTypeInfoImpl
->custdata_list
);
5062 TRACE("(%p)\n", pTypeInfoImpl
);
5063 return pTypeInfoImpl
;
5066 /* ITypeInfo::QueryInterface
5068 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5073 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
5075 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5078 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5079 IsEqualIID(riid
,&IID_ITypeInfo
)||
5080 IsEqualIID(riid
,&IID_ITypeInfo2
))
5084 ITypeInfo2_AddRef(iface
);
5085 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5088 TRACE("-- Interface: E_NOINTERFACE\n");
5089 return E_NOINTERFACE
;
5092 /* ITypeInfo::AddRef
5094 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5096 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5097 ULONG ref
= InterlockedIncrement(&This
->ref
);
5099 TRACE("(%p)->ref is %u\n",This
, ref
);
5101 if (ref
== 1 /* incremented from 0 */)
5102 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
5107 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5111 TRACE("destroying ITypeInfo(%p)\n",This
);
5113 SysFreeString(This
->Name
);
5116 SysFreeString(This
->DocString
);
5117 This
->DocString
= NULL
;
5119 SysFreeString(This
->DllName
);
5120 This
->DllName
= NULL
;
5122 for (i
= 0; i
< This
->TypeAttr
.cFuncs
; ++i
)
5124 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5125 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5127 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5128 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5130 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5131 heap_free(elemdesc
->u
.paramdesc
.pparamdescex
);
5133 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5134 SysFreeString(pFInfo
->pParamDesc
[j
].Name
);
5136 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5137 heap_free(pFInfo
->pParamDesc
);
5138 TLB_FreeCustData(&pFInfo
->custdata_list
);
5139 if (!IS_INTRESOURCE(pFInfo
->Entry
) && pFInfo
->Entry
!= (BSTR
)-1)
5140 SysFreeString(pFInfo
->Entry
);
5141 SysFreeString(pFInfo
->HelpString
);
5142 SysFreeString(pFInfo
->Name
);
5144 heap_free(This
->funcdescs
);
5146 for(i
= 0; i
< This
->TypeAttr
.cVars
; ++i
)
5148 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5149 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
5151 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5152 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5154 TLB_FreeCustData(&pVInfo
->custdata_list
);
5155 SysFreeString(pVInfo
->Name
);
5156 SysFreeString(pVInfo
->HelpString
);
5158 heap_free(This
->vardescs
);
5160 if(This
->impltypes
){
5161 for (i
= 0; i
< This
->TypeAttr
.cImplTypes
; ++i
){
5162 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5163 TLB_FreeCustData(&pImpl
->custdata_list
);
5165 heap_free(This
->impltypes
);
5168 TLB_FreeCustData(&This
->custdata_list
);
5173 /* ITypeInfo::Release
5175 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5177 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5178 ULONG ref
= InterlockedDecrement(&This
->ref
);
5180 TRACE("(%p)->(%u)\n",This
, ref
);
5184 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5185 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
5186 if (not_attached_to_typelib
)
5188 /* otherwise This will be freed when typelib is freed */
5194 /* ITypeInfo::GetTypeAttr
5196 * Retrieves a TYPEATTR structure that contains the attributes of the type
5200 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5201 LPTYPEATTR
*ppTypeAttr
)
5203 const ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5206 TRACE("(%p)\n",This
);
5208 size
= sizeof(**ppTypeAttr
);
5209 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5210 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
5212 *ppTypeAttr
= heap_alloc(size
);
5214 return E_OUTOFMEMORY
;
5216 **ppTypeAttr
= This
->TypeAttr
;
5218 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5219 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5220 &This
->TypeAttr
.tdescAlias
, *ppTypeAttr
+ 1);
5222 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5223 /* This should include all the inherited funcs */
5224 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ sizeof(void *);
5225 /* This is always the size of IDispatch's vtbl */
5226 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5227 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5232 /* ITypeInfo::GetTypeComp
5234 * Retrieves the ITypeComp interface for the type description, which enables a
5235 * client compiler to bind to the type description's members.
5238 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5239 ITypeComp
* *ppTComp
)
5241 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5243 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5245 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
5246 ITypeComp_AddRef(*ppTComp
);
5250 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5252 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5253 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5254 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5258 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5261 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5262 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5264 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5265 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5266 *buffer
+= sizeof(PARAMDESCEX
);
5267 *pparamdescex_dest
= *pparamdescex_src
;
5268 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5269 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5270 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5273 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5277 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5279 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5280 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5283 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5287 SIZE_T size
= sizeof(*src
);
5291 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5292 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5293 for (i
= 0; i
< src
->cParams
; i
++)
5295 size
+= sizeof(ELEMDESC
);
5296 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5299 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5300 if (!dest
) return E_OUTOFMEMORY
;
5303 if (dispinterface
) /* overwrite funckind */
5304 dest
->funckind
= FUNC_DISPATCH
;
5305 buffer
= (char *)(dest
+ 1);
5307 dest
->lprgscode
= (SCODE
*)buffer
;
5308 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5309 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5311 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5314 SysFreeString((BSTR
)dest
);
5318 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5319 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5320 for (i
= 0; i
< src
->cParams
; i
++)
5322 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5328 /* undo the above actions */
5329 for (i
= i
- 1; i
>= 0; i
--)
5330 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5331 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5332 SysFreeString((BSTR
)dest
);
5336 /* special treatment for dispinterfaces: this makes functions appear
5337 * to return their [retval] value when it is really returning an
5339 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5341 if (dest
->cParams
&&
5342 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5344 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5345 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5347 ERR("elemdesc should have started with VT_PTR instead of:\n");
5349 dump_ELEMDESC(elemdesc
);
5350 return E_UNEXPECTED
;
5353 /* copy last parameter to the return value. we are using a flat
5354 * buffer so there is no danger of leaking memory in
5356 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5358 /* remove the last parameter */
5362 /* otherwise this function is made to appear to have no return
5364 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5372 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5374 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5376 if (index
>= This
->TypeAttr
.cFuncs
)
5377 return TYPE_E_ELEMENTNOTFOUND
;
5379 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5383 /* internal function to make the inherited interfaces' methods appear
5384 * part of the interface */
5385 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5386 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5388 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5390 UINT implemented_funcs
= 0;
5395 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5399 ITypeInfo
*pSubTypeInfo
;
5402 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5406 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5409 &sub_funcs
, hrefoffset
);
5410 implemented_funcs
+= sub_funcs
;
5411 ITypeInfo_Release(pSubTypeInfo
);
5414 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5418 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
5422 if (index
< implemented_funcs
)
5423 return E_INVALIDARG
;
5424 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5428 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5430 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5433 switch (pTypeDesc
->vt
)
5435 case VT_USERDEFINED
:
5436 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5440 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5443 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5451 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5454 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5455 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5456 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5459 /* ITypeInfo::GetFuncDesc
5461 * Retrieves the FUNCDESC structure that contains information about a
5462 * specified function.
5465 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5466 LPFUNCDESC
*ppFuncDesc
)
5468 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5469 const FUNCDESC
*internal_funcdesc
;
5471 UINT hrefoffset
= 0;
5473 TRACE("(%p) index %d\n", This
, index
);
5475 if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5476 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5477 &internal_funcdesc
, NULL
,
5480 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5481 &internal_funcdesc
);
5484 WARN("description for function %d not found\n", index
);
5488 hr
= TLB_AllocAndInitFuncDesc(
5491 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
5493 if ((This
->TypeAttr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5494 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5496 TRACE("-- 0x%08x\n", hr
);
5500 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5504 SIZE_T size
= sizeof(*src
);
5507 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5508 if (src
->varkind
== VAR_CONST
)
5509 size
+= sizeof(VARIANT
);
5510 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5512 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5513 if (!dest
) return E_OUTOFMEMORY
;
5516 buffer
= (char *)(dest
+ 1);
5517 if (src
->lpstrSchema
)
5520 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5521 len
= strlenW(src
->lpstrSchema
);
5522 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5523 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5526 if (src
->varkind
== VAR_CONST
)
5530 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5531 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5532 buffer
+= sizeof(VARIANT
);
5533 VariantInit(dest
->u
.lpvarValue
);
5534 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5537 SysFreeString((BSTR
)dest
);
5541 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5544 if (src
->varkind
== VAR_CONST
)
5545 VariantClear(dest
->u
.lpvarValue
);
5546 SysFreeString((BSTR
)dest
);
5553 /* ITypeInfo::GetVarDesc
5555 * Retrieves a VARDESC structure that describes the specified variable.
5558 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5559 LPVARDESC
*ppVarDesc
)
5561 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5562 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
5564 TRACE("(%p) index %d\n", This
, index
);
5566 if(index
>= This
->TypeAttr
.cVars
)
5567 return TYPE_E_ELEMENTNOTFOUND
;
5569 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5572 /* ITypeInfo_GetNames
5574 * Retrieves the variable with the specified member ID (or the name of the
5575 * property or method and its parameters) that correspond to the specified
5578 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5579 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5581 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5582 const TLBFuncDesc
*pFDesc
;
5583 const TLBVarDesc
*pVDesc
;
5585 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5586 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
5589 /* function found, now return function and parameter names */
5590 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
5593 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
5595 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
5601 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
5604 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
5609 if(This
->impltypes
&&
5610 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
5611 /* recursive search */
5614 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
5615 if(SUCCEEDED(result
))
5617 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5618 ITypeInfo_Release(pTInfo
);
5621 WARN("Could not search inherited interface!\n");
5625 WARN("no names found\n");
5628 return TYPE_E_ELEMENTNOTFOUND
;
5635 /* ITypeInfo::GetRefTypeOfImplType
5637 * If a type description describes a COM class, it retrieves the type
5638 * description of the implemented interface types. For an interface,
5639 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5643 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
5648 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5651 TRACE("(%p) index %d\n", This
, index
);
5652 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
5656 /* only valid on dual interfaces;
5657 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5659 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
5661 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
5667 hr
= TYPE_E_ELEMENTNOTFOUND
;
5670 else if(index
== 0 && This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5672 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5673 *pRefType
= This
->pTypeLib
->dispatch_href
;
5677 if(index
>= This
->TypeAttr
.cImplTypes
)
5678 hr
= TYPE_E_ELEMENTNOTFOUND
;
5680 *pRefType
= This
->impltypes
[index
].hRef
;
5686 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
5688 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
5694 /* ITypeInfo::GetImplTypeFlags
5696 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5697 * or base interface in a type description.
5699 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
5700 UINT index
, INT
*pImplTypeFlags
)
5702 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5704 TRACE("(%p) index %d\n", This
, index
);
5706 if(This
->TypeAttr
.typekind
== TKIND_DISPATCH
&& index
== 0){
5707 *pImplTypeFlags
= 0;
5711 if(index
>= This
->TypeAttr
.cImplTypes
)
5712 return TYPE_E_ELEMENTNOTFOUND
;
5714 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
5720 * Maps between member names and member IDs, and parameter names and
5723 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
5724 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
5726 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5727 const TLBVarDesc
*pVDesc
;
5731 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
5734 /* init out parameters in case of failure */
5735 for (i
= 0; i
< cNames
; i
++)
5736 pMemId
[i
] = MEMBERID_NIL
;
5738 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
) {
5740 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
5741 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
5742 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
5743 for(i
=1; i
< cNames
; i
++){
5744 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
5745 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
5747 if( j
<pFDesc
->funcdesc
.cParams
)
5750 ret
=DISP_E_UNKNOWNNAME
;
5752 TRACE("-- 0x%08x\n", ret
);
5756 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->TypeAttr
.cVars
, *rgszNames
);
5759 *pMemId
= pVDesc
->vardesc
.memid
;
5762 /* not found, see if it can be found in an inherited interface */
5763 if(This
->impltypes
) {
5764 /* recursive search */
5766 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
5768 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
5769 ITypeInfo_Release(pTInfo
);
5772 WARN("Could not search inherited interface!\n");
5774 WARN("no names found\n");
5775 return DISP_E_UNKNOWNNAME
;
5781 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
5782 __ASM_GLOBAL_FUNC( call_method
,
5784 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5785 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5786 "movl %esp,%ebp\n\t"
5787 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5789 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5791 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5792 "movl 12(%ebp),%edx\n\t"
5793 "movl %esp,%edi\n\t"
5796 "subl %edx,%edi\n\t"
5797 "andl $~15,%edi\n\t"
5798 "movl %edi,%esp\n\t"
5799 "movl 12(%ebp),%ecx\n\t"
5800 "movl 16(%ebp),%esi\n\t"
5803 "1:\tcall *8(%ebp)\n\t"
5804 "subl %esp,%edi\n\t"
5805 "movl 20(%ebp),%ecx\n\t"
5806 "movl %edi,(%ecx)\n\t"
5807 "leal -8(%ebp),%esp\n\t"
5809 __ASM_CFI(".cfi_same_value %edi\n\t")
5811 __ASM_CFI(".cfi_same_value %esi\n\t")
5813 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5814 __ASM_CFI(".cfi_same_value %ebp\n\t")
5817 /* same function but returning floating point */
5818 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
5820 /* ITypeInfo::Invoke
5822 * Invokes a method, or accesses a property of an object, that implements the
5823 * interface described by the type description.
5826 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
5830 if (TRACE_ON(ole
)) {
5832 TRACE("Calling %p(",func
);
5833 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
5834 if (nrargs
> 30) TRACE("...");
5841 res
= call_method( func
, nrargs
, args
, &stack_offset
);
5844 FIXME("unsupported calling convention %d\n",callconv
);
5848 TRACE("returns %08x\n",res
);
5852 #elif defined(__x86_64__)
5854 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
5855 __ASM_GLOBAL_FUNC( call_method
,
5857 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5858 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5859 "movq %rsp,%rbp\n\t"
5860 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5862 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5864 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5865 "movq %rcx,%rax\n\t"
5868 "cmovgq %rdx,%rcx\n\t"
5869 "leaq 0(,%rcx,8),%rdx\n\t"
5870 "subq %rdx,%rsp\n\t"
5871 "andq $~15,%rsp\n\t"
5872 "movq %rsp,%rdi\n\t"
5875 "movq 0(%rsp),%rcx\n\t"
5876 "movq 8(%rsp),%rdx\n\t"
5877 "movq 16(%rsp),%r8\n\t"
5878 "movq 24(%rsp),%r9\n\t"
5879 "movq %rcx,%xmm0\n\t"
5880 "movq %rdx,%xmm1\n\t"
5881 "movq %r8,%xmm2\n\t"
5882 "movq %r9,%xmm3\n\t"
5884 "leaq -16(%rbp),%rsp\n\t"
5886 __ASM_CFI(".cfi_same_value %rdi\n\t")
5888 __ASM_CFI(".cfi_same_value %rsi\n\t")
5889 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5891 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5892 __ASM_CFI(".cfi_same_value %rbp\n\t")
5895 /* same function but returning floating point */
5896 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
5898 #endif /* __x86_64__ */
5900 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5903 ITypeInfo
*tinfo2
= NULL
;
5904 TYPEATTR
*tattr
= NULL
;
5906 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
5909 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5911 tdesc
->u
.hreftype
, hr
);
5914 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
5917 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
5918 ITypeInfo_Release(tinfo2
);
5922 switch (tattr
->typekind
)
5929 tdesc
= &tattr
->tdescAlias
;
5930 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
5933 case TKIND_INTERFACE
:
5934 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
5940 case TKIND_DISPATCH
:
5949 FIXME("TKIND_RECORD unhandled.\n");
5954 FIXME("TKIND_UNION unhandled.\n");
5959 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
5963 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
5964 ITypeInfo_Release(tinfo2
);
5968 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5972 /* enforce only one level of pointer indirection */
5973 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
5975 tdesc
= tdesc
->u
.lptdesc
;
5977 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5978 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5979 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5980 if ((tdesc
->vt
== VT_USERDEFINED
) ||
5981 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
5983 VARTYPE vt_userdefined
= 0;
5984 const TYPEDESC
*tdesc_userdefined
= tdesc
;
5985 if (tdesc
->vt
== VT_PTR
)
5987 vt_userdefined
= VT_BYREF
;
5988 tdesc_userdefined
= tdesc
->u
.lptdesc
;
5990 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
5992 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
5993 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
5995 *vt
|= vt_userdefined
;
6007 case VT_USERDEFINED
:
6008 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6015 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6016 hr
= DISP_E_BADVARTYPE
;
6020 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6035 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, GUID
*guid
)
6041 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6045 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6047 ITypeInfo_Release(tinfo2
);
6051 switch(tattr
->typekind
) {
6053 hres
= get_iface_guid(tinfo2
, &tattr
->tdescAlias
, guid
);
6056 case TKIND_INTERFACE
:
6057 case TKIND_DISPATCH
:
6058 *guid
= tattr
->guid
;
6062 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6063 hres
= E_UNEXPECTED
;
6066 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6067 ITypeInfo_Release(tinfo2
);
6071 /***********************************************************************
6072 * DispCallFunc (OLEAUT32.@)
6074 * Invokes a function of the specified calling convention, passing the
6075 * specified arguments and returns the result.
6078 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6079 * oVft [I] The offset in the vtable. See notes.
6080 * cc [I] Calling convention of the function to call.
6081 * vtReturn [I] The return type of the function.
6082 * cActuals [I] Number of parameters.
6083 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6084 * prgpvarg [I] The arguments to pass.
6085 * pvargResult [O] The return value of the function. Can be NULL.
6089 * Failure: HRESULT code.
6092 * The HRESULT return value of this function is not affected by the return
6093 * value of the user supplied function, which is returned in pvargResult.
6095 * If pvInstance is NULL then a non-object function is to be called and oVft
6096 * is the address of the function to call.
6098 * The cc parameter can be one of the following values:
6111 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6112 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6115 int argspos
, stack_offset
;
6120 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6121 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6122 pvargResult
, V_VT(pvargResult
));
6124 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6126 FIXME("unsupported calling convention %d\n",cc
);
6127 return E_INVALIDARG
;
6130 /* maximum size for an argument is sizeof(VARIANT) */
6131 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6133 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6137 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6138 func
= vtable
[oVft
/sizeof(void *)];
6139 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6141 else func
= (void *)oVft
;
6143 for (i
= 0; i
< cActuals
; i
++)
6145 VARIANT
*arg
= prgpvarg
[i
];
6156 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6157 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6161 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6162 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6164 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6165 args
[argspos
++] = V_BOOL(arg
);
6168 args
[argspos
++] = V_UI4(arg
);
6171 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6178 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6181 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6185 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6189 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6190 call_method( func
, argspos
, args
, &stack_offset
);
6195 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6198 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6202 if (stack_offset
&& cc
== CC_STDCALL
)
6204 WARN( "stack pointer off by %d\n", stack_offset
);
6205 return DISP_E_BADCALLEE
;
6207 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6208 TRACE("retval: "); dump_Variant(pvargResult
);
6211 #elif defined(__x86_64__)
6217 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6218 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6219 pvargResult
, V_VT(pvargResult
));
6221 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6223 FIXME("unsupported calling convention %d\n",cc
);
6224 return E_INVALIDARG
;
6227 /* maximum size for an argument is sizeof(DWORD_PTR) */
6228 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6230 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6234 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6235 func
= vtable
[oVft
/sizeof(void *)];
6236 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6238 else func
= (void *)oVft
;
6240 for (i
= 0; i
< cActuals
; i
++)
6242 VARIANT
*arg
= prgpvarg
[i
];
6248 args
[argspos
++] = (ULONG_PTR
)arg
;
6250 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6251 args
[argspos
++] = V_BOOL(arg
);
6254 args
[argspos
++] = V_UI8(arg
);
6257 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6264 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6268 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6272 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6273 call_method( func
, argspos
, args
);
6276 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6280 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6281 TRACE("retval: "); dump_Variant(pvargResult
);
6285 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6286 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6291 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
6293 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
6296 #define INVBUF_ELEMENT_SIZE \
6297 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6298 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6299 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6300 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6301 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6302 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6303 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6304 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6306 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6311 DISPPARAMS
*pDispParams
,
6312 VARIANT
*pVarResult
,
6313 EXCEPINFO
*pExcepInfo
,
6316 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6318 unsigned int var_index
;
6321 const TLBFuncDesc
*pFuncInfo
;
6324 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6325 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6328 if( This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6329 return DISP_E_MEMBERNOTFOUND
;
6333 ERR("NULL pDispParams not allowed\n");
6334 return E_INVALIDARG
;
6337 dump_DispParms(pDispParams
);
6339 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6341 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6342 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6343 return E_INVALIDARG
;
6346 /* we do this instead of using GetFuncDesc since it will return a fake
6347 * FUNCDESC for dispinterfaces and we want the real function description */
6348 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
6349 pFuncInfo
= &This
->funcdescs
[fdc
];
6350 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6351 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6352 !func_restricted( &pFuncInfo
->funcdesc
))
6356 if (fdc
< This
->TypeAttr
.cFuncs
) {
6357 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6361 TRACE("invoking:\n");
6362 dump_TLBFuncDescOne(pFuncInfo
);
6365 switch (func_desc
->funckind
) {
6366 case FUNC_PUREVIRTUAL
:
6367 case FUNC_VIRTUAL
: {
6368 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6370 VARIANT retval
; /* pointer for storing byref retvals in */
6371 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6372 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6373 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6374 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6375 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6376 UINT vargs_converted
=0;
6380 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6382 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6384 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6385 hres
= DISP_E_PARAMNOTFOUND
;
6390 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6392 ERR("functions with the vararg attribute do not support named arguments\n");
6393 hres
= DISP_E_NONAMEDARGS
;
6397 for (i
= 0; i
< func_desc
->cParams
; i
++)
6399 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6400 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6405 TRACE("changing args\n");
6406 for (i
= 0; i
< func_desc
->cParams
; i
++)
6408 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6409 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6410 VARIANTARG
*src_arg
;
6412 if (wParamFlags
& PARAMFLAG_FLCID
)
6415 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6417 V_I4(arg
) = This
->pTypeLib
->lcid
;
6426 for (j
= 0; j
< cNamedArgs
; j
++)
6427 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6429 src_arg
= &pDispParams
->rgvarg
[j
];
6434 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6436 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6440 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6442 /* under most conditions the caller is not allowed to
6443 * pass in a dispparam arg in the index of what would be
6444 * the retval parameter. however, there is an exception
6445 * where the extra parameter is used in an extra
6446 * IDispatch::Invoke below */
6447 if ((i
< pDispParams
->cArgs
) &&
6448 ((func_desc
->cParams
!= 1) || !pVarResult
||
6449 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6451 hres
= DISP_E_BADPARAMCOUNT
;
6455 /* note: this check is placed so that if the caller passes
6456 * in a VARIANTARG for the retval we just ignore it, like
6458 if (i
== func_desc
->cParams
- 1)
6461 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6462 memset(arg
, 0, sizeof(*arg
));
6463 V_VT(arg
) = rgvt
[i
];
6464 memset(&retval
, 0, sizeof(retval
));
6465 V_BYREF(arg
) = &retval
;
6469 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6470 hres
= E_UNEXPECTED
;
6476 dump_Variant(src_arg
);
6478 if(rgvt
[i
]!=V_VT(src_arg
))
6480 if (rgvt
[i
] == VT_VARIANT
)
6481 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6482 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6484 if (rgvt
[i
] == V_VT(src_arg
))
6485 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6488 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6489 if (wParamFlags
& PARAMFLAG_FIN
)
6490 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6491 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6493 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6495 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6498 SAFEARRAYBOUND bound
;
6502 bound
.cElements
= pDispParams
->cArgs
-i
;
6503 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6505 ERR("SafeArrayCreate failed\n");
6508 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6511 ERR("SafeArrayAccessData failed with %x\n", hres
);
6512 SafeArrayDestroy(a
);
6515 for (j
= 0; j
< bound
.cElements
; j
++)
6516 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6517 hres
= SafeArrayUnaccessData(a
);
6520 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6521 SafeArrayDestroy(a
);
6524 V_ARRAY(&rgvarg
[i
]) = a
;
6525 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6527 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6529 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6530 if (wParamFlags
& PARAMFLAG_FIN
)
6531 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6533 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
6534 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6535 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6537 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6539 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6540 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6544 /* FIXME: this doesn't work for VT_BYREF arguments if
6545 * they are not the same type as in the paramdesc */
6546 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6547 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6548 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6553 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6554 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6555 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6558 prgpvarg
[i
] = &rgvarg
[i
];
6562 prgpvarg
[i
] = src_arg
;
6565 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
6566 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
6567 && V_UNKNOWN(prgpvarg
[i
])) {
6568 IUnknown
*userdefined_iface
;
6571 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->vt
== VT_PTR
? tdesc
->u
.lptdesc
: tdesc
, &guid
);
6575 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
6577 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
6581 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
6582 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
6585 else if (wParamFlags
& PARAMFLAG_FOPT
)
6588 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6589 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6591 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6597 VARIANTARG
*missing_arg
;
6598 /* if the function wants a pointer to a variant then
6599 * set that up, otherwise just pass the VT_ERROR in
6600 * the argument by value */
6601 if (rgvt
[i
] & VT_BYREF
)
6603 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6604 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6605 V_VARIANTREF(arg
) = missing_arg
;
6609 V_VT(missing_arg
) = VT_ERROR
;
6610 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
6615 hres
= DISP_E_BADPARAMCOUNT
;
6619 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6621 /* VT_VOID is a special case for return types, so it is not
6622 * handled in the general function */
6623 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
6624 V_VT(&varresult
) = VT_EMPTY
;
6627 V_VT(&varresult
) = 0;
6628 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
6629 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6632 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
6633 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
6634 prgpvarg
, &varresult
);
6636 vargs_converted
= 0;
6638 for (i
= 0; i
< func_desc
->cParams
; i
++)
6640 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6641 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6643 if (wParamFlags
& PARAMFLAG_FLCID
)
6645 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
6649 TRACE("[retval] value: ");
6650 dump_Variant(prgpvarg
[i
]);
6655 VariantInit(pVarResult
);
6656 /* deref return value */
6657 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
6660 VARIANT_ClearInd(prgpvarg
[i
]);
6662 else if (vargs_converted
< pDispParams
->cArgs
)
6664 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6665 if (wParamFlags
& PARAMFLAG_FOUT
)
6667 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
6669 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
6673 ERR("failed to convert param %d to vt %d\n", i
,
6674 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
6679 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
6680 func_desc
->cParamsOpt
< 0 &&
6681 i
== func_desc
->cParams
-1)
6683 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
6686 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
6689 ERR("SafeArrayGetUBound failed with %x\n", hres
);
6692 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6695 ERR("SafeArrayAccessData failed with %x\n", hres
);
6698 for (j
= 0; j
<= ubound
; j
++)
6699 VariantClear(&v
[j
]);
6700 hres
= SafeArrayUnaccessData(a
);
6703 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6707 VariantClear(&rgvarg
[i
]);
6710 else if (wParamFlags
& PARAMFLAG_FOPT
)
6712 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6713 VariantClear(&rgvarg
[i
]);
6716 VariantClear(&missing_arg
[i
]);
6719 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
6721 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
6722 hres
= DISP_E_EXCEPTION
;
6725 IErrorInfo
*pErrorInfo
;
6726 pExcepInfo
->scode
= V_ERROR(&varresult
);
6727 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
6729 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
6730 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
6731 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
6732 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
6734 IErrorInfo_Release(pErrorInfo
);
6738 if (V_VT(&varresult
) != VT_ERROR
)
6740 TRACE("varresult value: ");
6741 dump_Variant(&varresult
);
6745 VariantClear(pVarResult
);
6746 *pVarResult
= varresult
;
6749 VariantClear(&varresult
);
6752 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
6753 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
6754 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
6755 (pDispParams
->cArgs
!= 0))
6757 if (V_VT(pVarResult
) == VT_DISPATCH
)
6759 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
6760 /* Note: not VariantClear; we still need the dispatch
6761 * pointer to be valid */
6762 VariantInit(pVarResult
);
6763 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
6764 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
6765 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
6766 IDispatch_Release(pDispatch
);
6770 VariantClear(pVarResult
);
6771 hres
= DISP_E_NOTACOLLECTION
;
6779 case FUNC_DISPATCH
: {
6782 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
6783 if (SUCCEEDED(hres
)) {
6784 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6785 hres
= IDispatch_Invoke(
6786 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
6787 pVarResult
,pExcepInfo
,pArgErr
6790 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
6791 IDispatch_Release(disp
);
6793 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6797 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
6802 TRACE("-- 0x%08x\n", hres
);
6805 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
6808 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
6809 if(FAILED(hres
)) return hres
;
6811 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6812 dump_VARDESC(var_desc
);
6813 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
6817 /* not found, look for it in inherited interfaces */
6818 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
6819 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
6820 if(This
->impltypes
) {
6821 /* recursive search */
6823 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6824 if(SUCCEEDED(hres
)){
6825 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
6826 ITypeInfo_Release(pTInfo
);
6829 WARN("Could not search inherited interface!\n");
6832 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
6833 return DISP_E_MEMBERNOTFOUND
;
6836 /* ITypeInfo::GetDocumentation
6838 * Retrieves the documentation string, the complete Help file name and path,
6839 * and the context ID for the Help topic for a specified type description.
6841 * (Can be tested by the Visual Basic Editor in Word for instance.)
6843 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
6844 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
6845 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
6847 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6848 const TLBFuncDesc
*pFDesc
;
6849 const TLBVarDesc
*pVDesc
;
6850 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6851 " HelpContext(%p) HelpFile(%p)\n",
6852 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6853 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6855 *pBstrName
=SysAllocString(This
->Name
);
6857 *pBstrDocString
=SysAllocString(This
->DocString
);
6859 *pdwHelpContext
=This
->dwHelpContext
;
6861 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
6863 }else {/* for a member */
6864 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
6867 *pBstrName
= SysAllocString(pFDesc
->Name
);
6869 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
6871 *pdwHelpContext
=pFDesc
->helpcontext
;
6874 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
6877 *pBstrName
= SysAllocString(pVDesc
->Name
);
6879 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
6881 *pdwHelpContext
=pVDesc
->HelpContext
;
6886 if(This
->impltypes
&&
6887 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
6888 /* recursive search */
6891 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6892 if(SUCCEEDED(result
)) {
6893 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
6894 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6895 ITypeInfo_Release(pTInfo
);
6898 WARN("Could not search inherited interface!\n");
6901 WARN("member %d not found\n", memid
);
6902 return TYPE_E_ELEMENTNOTFOUND
;
6905 /* ITypeInfo::GetDllEntry
6907 * Retrieves a description or specification of an entry point for a function
6910 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
6911 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
6914 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6915 const TLBFuncDesc
*pFDesc
;
6917 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
6919 if (pBstrDllName
) *pBstrDllName
= NULL
;
6920 if (pBstrName
) *pBstrName
= NULL
;
6921 if (pwOrdinal
) *pwOrdinal
= 0;
6923 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
6924 return TYPE_E_BADMODULEKIND
;
6926 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
6928 dump_TypeInfo(This
);
6930 dump_TLBFuncDescOne(pFDesc
);
6933 *pBstrDllName
= SysAllocString(This
->DllName
);
6935 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
6937 *pBstrName
= SysAllocString(pFDesc
->Entry
);
6945 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
6948 return TYPE_E_ELEMENTNOTFOUND
;
6951 /* internal function to make the inherited interfaces' methods appear
6952 * part of the interface */
6953 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
6954 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
6956 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6959 TRACE("%p, 0x%x\n", iface
, *hRefType
);
6961 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
6963 ITypeInfo
*pSubTypeInfo
;
6965 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
6969 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
6971 ITypeInfo_Release(pSubTypeInfo
);
6975 *hRefType
-= DISPATCH_HREF_OFFSET
;
6977 if (!(*hRefType
& DISPATCH_HREF_MASK
))
6978 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
6983 /* ITypeInfo::GetRefTypeInfo
6985 * If a type description references other type descriptions, it retrieves
6986 * the referenced type descriptions.
6988 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
6991 ITypeInfo
**ppTInfo
)
6993 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6994 HRESULT result
= E_FAIL
;
6996 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
6998 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6999 ITypeInfo_AddRef(*ppTInfo
);
7002 else if (hRefType
== -1 &&
7003 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
7004 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
7006 /* when we meet a DUAL dispinterface, we must create the interface
7009 ITypeInfoImpl
*pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7012 /* the interface version contains the same information as the dispinterface
7013 * copy the contents of the structs.
7015 *pTypeInfoImpl
= *This
;
7016 pTypeInfoImpl
->ref
= 0;
7018 /* change the type to interface */
7019 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7021 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
7023 /* the AddRef implicitly adds a reference to the parent typelib, which
7024 * stops the copied data from being destroyed until the new typeinfo's
7025 * refcount goes to zero, but we need to signal to the new instance to
7026 * not free its data structures when it is destroyed */
7027 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7029 ITypeInfo_AddRef(*ppTInfo
);
7033 } else if ((hRefType
!= -1) && (hRefType
& DISPATCH_HREF_MASK
) &&
7034 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
))
7036 HREFTYPE href_dispatch
= hRefType
;
7037 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7039 TLBRefType
*ref_type
;
7040 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7042 if(ref_type
->reference
== hRefType
)
7045 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7047 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7050 if(hRefType
!= -1) {
7051 ITypeLib
*pTLib
= NULL
;
7053 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7055 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7057 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7058 TRACE("typeinfo in imported typelib that is already loaded\n");
7059 pTLib
= (ITypeLib
*)ref_type
->pImpTLInfo
->pImpTypeLib
;
7060 ITypeLib_AddRef(pTLib
);
7063 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7064 result
= LoadRegTypeLib( &ref_type
->pImpTLInfo
->guid
,
7065 ref_type
->pImpTLInfo
->wVersionMajor
,
7066 ref_type
->pImpTLInfo
->wVersionMinor
,
7067 ref_type
->pImpTLInfo
->lcid
,
7070 if(FAILED(result
)) {
7071 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
7072 result
=LoadTypeLib(libnam
, &pTLib
);
7073 SysFreeString(libnam
);
7075 if(SUCCEEDED(result
)) {
7076 ref_type
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
7077 ITypeLib_AddRef(pTLib
);
7081 if(SUCCEEDED(result
)) {
7082 if(ref_type
->index
== TLB_REF_USE_GUID
)
7083 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, &ref_type
->guid
, ppTInfo
);
7085 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7088 ITypeLib_Release(pTLib
);
7093 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7094 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7098 /* ITypeInfo::AddressOfMember
7100 * Retrieves the addresses of static functions or variables, such as those
7103 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7104 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7106 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7112 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7114 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7118 module
= LoadLibraryW(dll
);
7121 ERR("couldn't load %s\n", debugstr_w(dll
));
7123 SysFreeString(entry
);
7124 return STG_E_FILENOTFOUND
;
7126 /* FIXME: store library somewhere where we can free it */
7131 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7132 entryA
= heap_alloc(len
);
7133 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7135 *ppv
= GetProcAddress(module
, entryA
);
7137 ERR("function not found %s\n", debugstr_a(entryA
));
7143 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7145 ERR("function not found %d\n", ordinal
);
7149 SysFreeString(entry
);
7152 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7157 /* ITypeInfo::CreateInstance
7159 * Creates a new instance of a type that describes a component object class
7162 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7163 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7165 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7169 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7175 WARN("Not able to aggregate\n");
7176 return CLASS_E_NOAGGREGATION
;
7179 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7180 if(FAILED(hr
)) return hr
;
7182 if(pTA
->typekind
!= TKIND_COCLASS
)
7184 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7190 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7193 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7194 TRACE("GetActiveObject rets %08x\n", hr
);
7197 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7198 IUnknown_Release(pUnk
);
7203 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7204 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7208 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
7212 /* ITypeInfo::GetMops
7214 * Retrieves marshalling information.
7216 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7219 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7220 FIXME("(%p %d) stub!\n", This
, memid
);
7225 /* ITypeInfo::GetContainingTypeLib
7227 * Retrieves the containing type library and the index of the type description
7228 * within that type library.
7230 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7231 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7233 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7235 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7237 *pIndex
=This
->index
;
7238 TRACE("returning pIndex=%d\n", *pIndex
);
7242 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7243 ITypeLib_AddRef(*ppTLib
);
7244 TRACE("returning ppTLib=%p\n", *ppTLib
);
7250 /* ITypeInfo::ReleaseTypeAttr
7252 * Releases a TYPEATTR previously returned by GetTypeAttr.
7255 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7256 TYPEATTR
* pTypeAttr
)
7258 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7259 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7260 heap_free(pTypeAttr
);
7263 /* ITypeInfo::ReleaseFuncDesc
7265 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7267 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7269 FUNCDESC
*pFuncDesc
)
7271 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7274 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7276 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7277 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7278 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7280 SysFreeString((BSTR
)pFuncDesc
);
7283 /* ITypeInfo::ReleaseVarDesc
7285 * Releases a VARDESC previously returned by GetVarDesc.
7287 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7290 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7291 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7293 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
7294 if (pVarDesc
->varkind
== VAR_CONST
)
7295 VariantClear(pVarDesc
->u
.lpvarValue
);
7296 SysFreeString((BSTR
)pVarDesc
);
7299 /* ITypeInfo2::GetTypeKind
7301 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7304 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7305 TYPEKIND
*pTypeKind
)
7307 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7308 *pTypeKind
=This
->TypeAttr
.typekind
;
7309 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7313 /* ITypeInfo2::GetTypeFlags
7315 * Returns the type flags without any allocations. This returns a DWORD type
7316 * flag, which expands the type flags without growing the TYPEATTR (type
7320 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7322 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7323 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
7324 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7328 /* ITypeInfo2::GetFuncIndexOfMemId
7329 * Binds to a specific member based on a known DISPID, where the member name
7330 * is not known (for example, when binding to a default member).
7333 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7334 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7336 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7340 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
7341 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7342 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7345 if(fdc
< This
->TypeAttr
.cFuncs
) {
7349 result
= TYPE_E_ELEMENTNOTFOUND
;
7351 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7352 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7356 /* TypeInfo2::GetVarIndexOfMemId
7358 * Binds to a specific member based on a known DISPID, where the member name
7359 * is not known (for example, when binding to a default member).
7362 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7363 MEMBERID memid
, UINT
*pVarIndex
)
7365 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7366 TLBVarDesc
*pVarInfo
;
7368 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7370 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
7372 return TYPE_E_ELEMENTNOTFOUND
;
7374 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7379 /* ITypeInfo2::GetCustData
7381 * Gets the custom data
7383 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7388 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7389 TLBCustData
*pCData
;
7391 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7393 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
7395 VariantInit( pVarVal
);
7397 VariantCopy( pVarVal
, &pCData
->data
);
7399 VariantClear( pVarVal
);
7403 /* ITypeInfo2::GetFuncCustData
7405 * Gets the custom data
7407 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7413 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7414 TLBCustData
*pCData
;
7415 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7417 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7419 if(index
>= This
->TypeAttr
.cFuncs
)
7420 return TYPE_E_ELEMENTNOTFOUND
;
7422 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
7424 return TYPE_E_ELEMENTNOTFOUND
;
7426 VariantInit(pVarVal
);
7427 VariantCopy(pVarVal
, &pCData
->data
);
7432 /* ITypeInfo2::GetParamCustData
7434 * Gets the custom data
7436 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7443 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7444 TLBCustData
*pCData
;
7445 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7447 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
7448 debugstr_guid(guid
), pVarVal
);
7450 if(indexFunc
>= This
->TypeAttr
.cFuncs
)
7451 return TYPE_E_ELEMENTNOTFOUND
;
7453 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7454 return TYPE_E_ELEMENTNOTFOUND
;
7456 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
7458 return TYPE_E_ELEMENTNOTFOUND
;
7460 VariantInit(pVarVal
);
7461 VariantCopy(pVarVal
, &pCData
->data
);
7466 /* ITypeInfo2::GetVarCustData
7468 * Gets the custom data
7470 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7476 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7477 TLBCustData
*pCData
;
7478 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
7480 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7482 if(index
>= This
->TypeAttr
.cVars
)
7483 return TYPE_E_ELEMENTNOTFOUND
;
7485 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
7487 return TYPE_E_ELEMENTNOTFOUND
;
7489 VariantInit(pVarVal
);
7490 VariantCopy(pVarVal
, &pCData
->data
);
7495 /* ITypeInfo2::GetImplCustData
7497 * Gets the custom data
7499 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7505 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7506 TLBCustData
*pCData
;
7507 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7509 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7511 if(index
>= This
->TypeAttr
.cImplTypes
)
7512 return TYPE_E_ELEMENTNOTFOUND
;
7514 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
7516 return TYPE_E_ELEMENTNOTFOUND
;
7518 VariantInit(pVarVal
);
7519 VariantCopy(pVarVal
, &pCData
->data
);
7524 /* ITypeInfo2::GetDocumentation2
7526 * Retrieves the documentation string, the complete Help file name and path,
7527 * the localization context to use, and the context ID for the library Help
7528 * topic in the Help file.
7531 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7535 BSTR
*pbstrHelpString
,
7536 DWORD
*pdwHelpStringContext
,
7537 BSTR
*pbstrHelpStringDll
)
7539 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7540 const TLBFuncDesc
*pFDesc
;
7541 const TLBVarDesc
*pVDesc
;
7542 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7543 "HelpStringContext(%p) HelpStringDll(%p)\n",
7544 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7545 pbstrHelpStringDll
);
7546 /* the help string should be obtained from the helpstringdll,
7547 * using the _DLLGetDocumentation function, based on the supplied
7548 * lcid. Nice to do sometime...
7550 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7552 *pbstrHelpString
=SysAllocString(This
->Name
);
7553 if(pdwHelpStringContext
)
7554 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7555 if(pbstrHelpStringDll
)
7556 *pbstrHelpStringDll
=
7557 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7559 }else {/* for a member */
7560 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
7563 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
7564 if(pdwHelpStringContext
)
7565 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7566 if(pbstrHelpStringDll
)
7567 *pbstrHelpStringDll
=
7568 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7571 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
7574 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
7575 if(pdwHelpStringContext
)
7576 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7577 if(pbstrHelpStringDll
)
7578 *pbstrHelpStringDll
=
7579 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7583 return TYPE_E_ELEMENTNOTFOUND
;
7586 /* ITypeInfo2::GetAllCustData
7588 * Gets all custom data items for the Type info.
7591 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
7593 CUSTDATA
*pCustData
)
7595 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7597 TRACE("%p %p\n", This
, pCustData
);
7599 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
7602 /* ITypeInfo2::GetAllFuncCustData
7604 * Gets all custom data items for the specified Function
7607 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
7610 CUSTDATA
*pCustData
)
7612 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7613 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7615 TRACE("%p %u %p\n", This
, index
, pCustData
);
7617 if(index
>= This
->TypeAttr
.cFuncs
)
7618 return TYPE_E_ELEMENTNOTFOUND
;
7620 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
7623 /* ITypeInfo2::GetAllParamCustData
7625 * Gets all custom data items for the Functions
7628 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
7629 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
7631 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7632 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7634 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
7636 if(indexFunc
>= This
->TypeAttr
.cFuncs
)
7637 return TYPE_E_ELEMENTNOTFOUND
;
7639 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7640 return TYPE_E_ELEMENTNOTFOUND
;
7642 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
7645 /* ITypeInfo2::GetAllVarCustData
7647 * Gets all custom data items for the specified Variable
7650 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
7651 UINT index
, CUSTDATA
*pCustData
)
7653 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7654 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
7656 TRACE("%p %u %p\n", This
, index
, pCustData
);
7658 if(index
>= This
->TypeAttr
.cVars
)
7659 return TYPE_E_ELEMENTNOTFOUND
;
7661 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
7664 /* ITypeInfo2::GetAllImplCustData
7666 * Gets all custom data items for the specified implementation type
7669 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
7672 CUSTDATA
*pCustData
)
7674 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7675 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7677 TRACE("%p %u %p\n", This
, index
, pCustData
);
7679 if(index
>= This
->TypeAttr
.cImplTypes
)
7680 return TYPE_E_ELEMENTNOTFOUND
;
7682 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
7685 static const ITypeInfo2Vtbl tinfvt
=
7688 ITypeInfo_fnQueryInterface
,
7690 ITypeInfo_fnRelease
,
7692 ITypeInfo_fnGetTypeAttr
,
7693 ITypeInfo_fnGetTypeComp
,
7694 ITypeInfo_fnGetFuncDesc
,
7695 ITypeInfo_fnGetVarDesc
,
7696 ITypeInfo_fnGetNames
,
7697 ITypeInfo_fnGetRefTypeOfImplType
,
7698 ITypeInfo_fnGetImplTypeFlags
,
7699 ITypeInfo_fnGetIDsOfNames
,
7701 ITypeInfo_fnGetDocumentation
,
7702 ITypeInfo_fnGetDllEntry
,
7703 ITypeInfo_fnGetRefTypeInfo
,
7704 ITypeInfo_fnAddressOfMember
,
7705 ITypeInfo_fnCreateInstance
,
7706 ITypeInfo_fnGetMops
,
7707 ITypeInfo_fnGetContainingTypeLib
,
7708 ITypeInfo_fnReleaseTypeAttr
,
7709 ITypeInfo_fnReleaseFuncDesc
,
7710 ITypeInfo_fnReleaseVarDesc
,
7712 ITypeInfo2_fnGetTypeKind
,
7713 ITypeInfo2_fnGetTypeFlags
,
7714 ITypeInfo2_fnGetFuncIndexOfMemId
,
7715 ITypeInfo2_fnGetVarIndexOfMemId
,
7716 ITypeInfo2_fnGetCustData
,
7717 ITypeInfo2_fnGetFuncCustData
,
7718 ITypeInfo2_fnGetParamCustData
,
7719 ITypeInfo2_fnGetVarCustData
,
7720 ITypeInfo2_fnGetImplTypeCustData
,
7721 ITypeInfo2_fnGetDocumentation2
,
7722 ITypeInfo2_fnGetAllCustData
,
7723 ITypeInfo2_fnGetAllFuncCustData
,
7724 ITypeInfo2_fnGetAllParamCustData
,
7725 ITypeInfo2_fnGetAllVarCustData
,
7726 ITypeInfo2_fnGetAllImplTypeCustData
,
7729 /******************************************************************************
7730 * CreateDispTypeInfo [OLEAUT32.31]
7732 * Build type information for an object so it can be called through an
7733 * IDispatch interface.
7736 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7737 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7740 * This call allows an objects methods to be accessed through IDispatch, by
7741 * building an ITypeInfo object that IDispatch can use to call through.
7743 HRESULT WINAPI
CreateDispTypeInfo(
7744 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
7745 LCID lcid
, /* [I] Locale Id */
7746 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
7748 ITypeInfoImpl
*pTIClass
, *pTIIface
;
7749 ITypeLibImpl
*pTypeLibImpl
;
7750 unsigned int param
, func
;
7751 TLBFuncDesc
*pFuncDesc
;
7755 pTypeLibImpl
= TypeLibImpl_Constructor();
7756 if (!pTypeLibImpl
) return E_FAIL
;
7758 pTypeLibImpl
->TypeInfoCount
= 2;
7759 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
7761 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
7762 pTIIface
->pTypeLib
= pTypeLibImpl
;
7763 pTIIface
->index
= 0;
7764 pTIIface
->Name
= NULL
;
7765 pTIIface
->dwHelpContext
= -1;
7766 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
7767 pTIIface
->TypeAttr
.lcid
= lcid
;
7768 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7769 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
7770 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
7771 pTIIface
->TypeAttr
.cbAlignment
= 2;
7772 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
7773 pTIIface
->TypeAttr
.cbSizeVft
= -1;
7774 pTIIface
->TypeAttr
.cFuncs
= 0;
7775 pTIIface
->TypeAttr
.cImplTypes
= 0;
7776 pTIIface
->TypeAttr
.cVars
= 0;
7777 pTIIface
->TypeAttr
.wTypeFlags
= 0;
7779 pTIIface
->funcdescs
= TLBFuncDesc_Constructor(pidata
->cMembers
);
7780 pFuncDesc
= pTIIface
->funcdescs
;
7781 for(func
= 0; func
< pidata
->cMembers
; func
++) {
7782 METHODDATA
*md
= pidata
->pmethdata
+ func
;
7783 pFuncDesc
->Name
= SysAllocString(md
->szName
);
7784 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
7785 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
7786 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
7787 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
7788 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
7789 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
7790 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
7791 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
7792 pFuncDesc
->funcdesc
.cScodes
= 0;
7793 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
7794 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
7795 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
7796 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
7797 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7798 md
->cArgs
* sizeof(ELEMDESC
));
7799 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
7800 for(param
= 0; param
< md
->cArgs
; param
++) {
7801 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
7802 pFuncDesc
->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
7804 pFuncDesc
->helpcontext
= 0;
7805 pFuncDesc
->HelpStringContext
= 0;
7806 pFuncDesc
->HelpString
= NULL
;
7807 pFuncDesc
->Entry
= NULL
;
7808 list_init(&pFuncDesc
->custdata_list
);
7809 pTIIface
->TypeAttr
.cFuncs
++;
7813 dump_TypeInfo(pTIIface
);
7815 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
7816 pTIClass
->pTypeLib
= pTypeLibImpl
;
7817 pTIClass
->index
= 1;
7818 pTIClass
->Name
= NULL
;
7819 pTIClass
->dwHelpContext
= -1;
7820 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
7821 pTIClass
->TypeAttr
.lcid
= lcid
;
7822 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
7823 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
7824 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
7825 pTIClass
->TypeAttr
.cbAlignment
= 2;
7826 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
7827 pTIClass
->TypeAttr
.cbSizeVft
= -1;
7828 pTIClass
->TypeAttr
.cFuncs
= 0;
7829 pTIClass
->TypeAttr
.cImplTypes
= 1;
7830 pTIClass
->TypeAttr
.cVars
= 0;
7831 pTIClass
->TypeAttr
.wTypeFlags
= 0;
7833 pTIClass
->impltypes
= TLBImplType_Constructor(1);
7835 ref
= heap_alloc_zero(sizeof(*ref
));
7836 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
7837 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
7839 dump_TypeInfo(pTIClass
);
7841 *pptinfo
= (ITypeInfo
*)pTIClass
;
7843 ITypeInfo_AddRef(*pptinfo
);
7844 ITypeLib_Release((ITypeLib
*)&pTypeLibImpl
->lpVtbl
);
7850 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
7852 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7854 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
7857 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
7859 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7861 return ITypeInfo_AddRef((ITypeInfo
*)This
);
7864 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
7866 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7868 return ITypeInfo_Release((ITypeInfo
*)This
);
7871 static HRESULT WINAPI
ITypeComp_fnBind(
7876 ITypeInfo
** ppTInfo
,
7877 DESCKIND
* pDescKind
,
7880 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7881 const TLBFuncDesc
*pFDesc
;
7882 const TLBVarDesc
*pVDesc
;
7883 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
7886 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7888 *pDescKind
= DESCKIND_NONE
;
7889 pBindPtr
->lpfuncdesc
= NULL
;
7892 for(fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
7893 pFDesc
= &This
->funcdescs
[fdc
];
7894 if (!strcmpiW(pFDesc
->Name
, szName
)) {
7895 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
7898 /* name found, but wrong flags */
7899 hr
= TYPE_E_TYPEMISMATCH
;
7903 if (fdc
< This
->TypeAttr
.cFuncs
)
7905 HRESULT hr
= TLB_AllocAndInitFuncDesc(
7907 &pBindPtr
->lpfuncdesc
,
7908 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
7911 *pDescKind
= DESCKIND_FUNCDESC
;
7912 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7913 ITypeInfo_AddRef(*ppTInfo
);
7916 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->TypeAttr
.cVars
, szName
);
7918 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
7921 *pDescKind
= DESCKIND_VARDESC
;
7922 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7923 ITypeInfo_AddRef(*ppTInfo
);
7927 /* FIXME: search each inherited interface, not just the first */
7928 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
7929 /* recursive search */
7933 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypes
[0].hRef
, &pTInfo
);
7936 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
7937 ITypeInfo_Release(pTInfo
);
7941 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7942 ITypeComp_Release(pTComp
);
7945 WARN("Could not search inherited interface!\n");
7947 if (hr
== DISP_E_MEMBERNOTFOUND
)
7949 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
7953 static HRESULT WINAPI
ITypeComp_fnBindType(
7957 ITypeInfo
** ppTInfo
,
7958 ITypeComp
** ppTComp
)
7960 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
7962 /* strange behaviour (does nothing) but like the
7965 if (!ppTInfo
|| !ppTComp
)
7974 static const ITypeCompVtbl tcompvt
=
7977 ITypeComp_fnQueryInterface
,
7979 ITypeComp_fnRelease
,
7982 ITypeComp_fnBindType