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 IUnknown_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");
1944 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
1945 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
1946 MSFT_ReadGuid(&(pNew
->guid
), entry
.GuidOffset
, pcx
);
1947 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
1948 list_add_head(custdata_list
, &pNew
->entry
);
1949 offset
= entry
.next
;
1954 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
,
1958 pTd
->vt
=type
& VT_TYPEMASK
;
1960 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
1962 if(pTd
->vt
== VT_USERDEFINED
)
1963 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, pTd
->u
.hreftype
);
1965 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
1968 static void MSFT_ResolveReferencedTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, TYPEDESC
*lpTypeDesc
)
1970 /* resolve referenced type if any */
1973 switch (lpTypeDesc
->vt
)
1976 lpTypeDesc
= lpTypeDesc
->u
.lptdesc
;
1980 lpTypeDesc
= & (lpTypeDesc
->u
.lpadesc
->tdescElem
);
1983 case VT_USERDEFINED
:
1984 MSFT_DoRefType(pcx
, pTI
->pTypeLib
,
1985 lpTypeDesc
->u
.hreftype
);
1997 MSFT_DoFuncs(TLBContext
* pcx
,
2002 TLBFuncDesc
** pptfd
)
2005 * member information is stored in a data structure at offset
2006 * indicated by the memoffset field of the typeinfo structure
2007 * There are several distinctive parts.
2008 * The first part starts with a field that holds the total length
2009 * of this (first) part excluding this field. Then follow the records,
2010 * for each member there is one record.
2012 * The first entry is always the length of the record (including this
2014 * The rest of the record depends on the type of the member. If there is
2015 * a field indicating the member type (function, variable, interface, etc)
2016 * I have not found it yet. At this time we depend on the information
2017 * in the type info and the usual order how things are stored.
2019 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2022 * Third is an equal sized array with file offsets to the name entry
2025 * The fourth and last (?) part is an array with offsets to the records
2026 * in the first part of this file segment.
2029 int infolen
, nameoffset
, reclength
, i
;
2030 int recoffset
= offset
+ sizeof(INT
);
2032 char *recbuf
= heap_alloc(0xffff);
2033 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2034 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2036 TRACE_(typelib
)("\n");
2038 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2040 *pptfd
= TLBFuncDesc_Constructor(cFuncs
);
2042 for ( i
= 0; i
< cFuncs
; i
++ )
2046 /* name, eventually add to a hash table */
2047 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2048 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2050 /* nameoffset is sometimes -1 on the second half of a propget/propput
2051 * pair of functions */
2052 if ((nameoffset
== -1) && (i
> 0))
2053 ptfd
->Name
= SysAllocString(ptfd_prev
->Name
);
2055 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2057 /* read the function information record */
2058 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2060 reclength
&= 0xffff;
2062 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2064 /* size without argument data */
2065 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2067 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2068 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2070 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2071 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2073 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2075 if (pFuncRec
->FKCCIC
& 0x2000 )
2077 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2078 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2079 ptfd
->Entry
= (BSTR
)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2082 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2085 ptfd
->Entry
= (BSTR
)-1;
2087 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2088 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2090 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2091 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2093 /* fill the FuncDesc Structure */
2094 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2095 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2097 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2098 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2099 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2100 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2101 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2102 ptfd
->funcdesc
.oVft
= pFuncRec
->VtableOffset
& ~1;
2103 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2107 &ptfd
->funcdesc
.elemdescFunc
.tdesc
,
2109 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2111 /* do the parameters/arguments */
2112 if(pFuncRec
->nrargs
)
2115 MSFT_ParameterInfo paraminfo
;
2117 ptfd
->funcdesc
.lprgelemdescParam
=
2118 heap_alloc_zero(pFuncRec
->nrargs
* sizeof(ELEMDESC
));
2120 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2122 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2123 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2125 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2127 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2134 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2137 if (paraminfo
.oName
== -1)
2138 /* this occurs for [propput] or [propget] methods, so
2139 * we should just set the name of the parameter to the
2140 * name of the method. */
2141 ptfd
->pParamDesc
[j
].Name
= SysAllocString(ptfd
->Name
);
2143 ptfd
->pParamDesc
[j
].Name
=
2144 MSFT_ReadName( pcx
, paraminfo
.oName
);
2145 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(ptfd
->pParamDesc
[j
].Name
));
2147 MSFT_ResolveReferencedTypes(pcx
, pTI
, &elemdesc
->tdesc
);
2150 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2151 (pFuncRec
->FKCCIC
& 0x1000) )
2153 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2155 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2157 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2159 pParamDesc
->pparamdescex
= heap_alloc_zero(sizeof(PARAMDESCEX
));
2160 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2162 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2166 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2169 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2170 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2171 pFuncRec
->FKCCIC
& 0x80 )
2174 pFuncRec
->oArgCustData
[j
],
2175 &ptfd
->pParamDesc
[j
].custdata_list
);
2178 /* SEEK value = jump to offset,
2179 * from there jump to the end of record,
2180 * go back by (j-1) arguments
2182 MSFT_ReadLEDWords( ¶minfo
,
2183 sizeof(MSFT_ParameterInfo
), pcx
,
2184 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2185 * sizeof(MSFT_ParameterInfo
)));
2189 /* scode is not used: archaic win16 stuff FIXME: right? */
2190 ptfd
->funcdesc
.cScodes
= 0 ;
2191 ptfd
->funcdesc
.lprgscode
= NULL
;
2195 recoffset
+= reclength
;
2200 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2201 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2203 int infolen
, nameoffset
, reclength
;
2205 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2210 TRACE_(typelib
)("\n");
2212 ptvd
= *pptvd
= TLBVarDesc_Constructor(cVars
);
2213 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2214 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2215 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2216 recoffset
+= offset
+sizeof(INT
);
2217 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2218 /* name, eventually add to a hash table */
2219 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2220 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2221 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2222 /* read the variable information record */
2223 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2225 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2228 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2229 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2231 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2232 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2234 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2235 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2237 /* fill the VarDesc Structure */
2238 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2239 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2240 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2241 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2242 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2243 &ptvd
->vardesc
.elemdescVar
.tdesc
, pTI
);
2244 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2245 if(pVarRec
->VarKind
== VAR_CONST
){
2246 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2247 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2248 pVarRec
->OffsValue
, pcx
);
2250 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2251 MSFT_ResolveReferencedTypes(pcx
, pTI
, &ptvd
->vardesc
.elemdescVar
.tdesc
);
2252 recoffset
+= reclength
;
2256 /* fill in data for a hreftype (offset). When the referenced type is contained
2257 * in the typelib, it's just an (file) offset in the type info base dir.
2258 * If comes from import, it's an offset+1 in the ImpInfo table
2260 static void MSFT_DoRefType(TLBContext
*pcx
, ITypeLibImpl
*pTL
,
2265 TRACE_(typelib
)("TLB context %p, TLB offset %x\n", pcx
, offset
);
2267 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
2269 if(ref
->reference
== offset
) return;
2272 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2273 list_add_tail(&pTL
->ref_list
, &ref
->entry
);
2275 if(!MSFT_HREFTYPE_INTHISFILE( offset
)) {
2276 /* external typelib */
2277 MSFT_ImpInfo impinfo
;
2280 TRACE_(typelib
)("offset %x, masked offset %x\n", offset
, offset
+ (offset
& 0xfffffffc));
2282 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
,
2283 pcx
->pTblDir
->pImpInfo
.offset
+ (offset
& 0xfffffffc));
2285 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2286 if(pImpLib
->offset
==impinfo
.oImpFile
)
2289 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2290 ref
->reference
= offset
;
2291 ref
->pImpTLInfo
= pImpLib
;
2292 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2293 MSFT_ReadGuid(&ref
->guid
, impinfo
.oGuid
, pcx
);
2294 TRACE("importing by guid %s\n", debugstr_guid(&ref
->guid
));
2295 ref
->index
= TLB_REF_USE_GUID
;
2297 ref
->index
= impinfo
.oGuid
;
2299 ERR("Cannot find a reference\n");
2300 ref
->reference
= -1;
2301 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2304 /* in this typelib */
2305 ref
->index
= MSFT_HREFTYPE_INDEX(offset
);
2306 ref
->reference
= offset
;
2307 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
2311 /* process Implemented Interfaces of a com class */
2312 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2316 MSFT_RefRecord refrec
;
2319 TRACE_(typelib
)("\n");
2321 pTI
->impltypes
= TLBImplType_Constructor(count
);
2322 pImpl
= pTI
->impltypes
;
2323 for(i
=0;i
<count
;i
++){
2324 if(offset
<0) break; /* paranoia */
2325 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2326 MSFT_DoRefType(pcx
, pTI
->pTypeLib
, refrec
.reftype
);
2327 pImpl
->hRef
= refrec
.reftype
;
2328 pImpl
->implflags
=refrec
.flags
;
2329 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2330 offset
=refrec
.onext
;
2335 * process a typeinfo record
2337 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2340 ITypeLibImpl
* pLibInfo
)
2342 MSFT_TypeInfoBase tiBase
;
2343 ITypeInfoImpl
*ptiRet
;
2345 TRACE_(typelib
)("count=%u\n", count
);
2347 ptiRet
= ITypeInfoImpl_Constructor();
2348 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2349 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2351 /* this is where we are coming from */
2352 ptiRet
->pTypeLib
= pLibInfo
;
2353 ptiRet
->index
=count
;
2354 /* fill in the typeattr fields */
2356 MSFT_ReadGuid(&ptiRet
->TypeAttr
.guid
, tiBase
.posguid
, pcx
);
2357 ptiRet
->TypeAttr
.lcid
=pLibInfo
->LibAttr
.lcid
; /* FIXME: correct? */
2358 ptiRet
->TypeAttr
.lpstrSchema
=NULL
; /* reserved */
2359 ptiRet
->TypeAttr
.cbSizeInstance
=tiBase
.size
;
2360 ptiRet
->TypeAttr
.typekind
=tiBase
.typekind
& 0xF;
2361 ptiRet
->TypeAttr
.cFuncs
=LOWORD(tiBase
.cElement
);
2362 ptiRet
->TypeAttr
.cVars
=HIWORD(tiBase
.cElement
);
2363 ptiRet
->TypeAttr
.cbAlignment
=(tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2364 ptiRet
->TypeAttr
.wTypeFlags
=tiBase
.flags
;
2365 ptiRet
->TypeAttr
.wMajorVerNum
=LOWORD(tiBase
.version
);
2366 ptiRet
->TypeAttr
.wMinorVerNum
=HIWORD(tiBase
.version
);
2367 ptiRet
->TypeAttr
.cImplTypes
=tiBase
.cImplTypes
;
2368 ptiRet
->TypeAttr
.cbSizeVft
=tiBase
.cbSizeVft
; /* FIXME: this is only the non inherited part */
2369 if(ptiRet
->TypeAttr
.typekind
== TKIND_ALIAS
)
2370 MSFT_GetTdesc(pcx
, tiBase
.datatype1
,
2371 &ptiRet
->TypeAttr
.tdescAlias
, ptiRet
);
2374 /* IDLDESC idldescType; *//* never saw this one != zero */
2376 /* name, eventually add to a hash table */
2377 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2378 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2379 TRACE_(typelib
)("reading %s\n", debugstr_w(ptiRet
->Name
));
2381 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2382 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2383 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2385 if (ptiRet
->TypeAttr
.typekind
== TKIND_MODULE
)
2386 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2388 /* note: InfoType's Help file and HelpStringDll come from the containing
2389 * library. Further HelpString and Docstring appear to be the same thing :(
2392 if(ptiRet
->TypeAttr
.cFuncs
>0 )
2393 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2394 ptiRet
->TypeAttr
.cVars
,
2395 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2397 if(ptiRet
->TypeAttr
.cVars
>0 )
2398 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->TypeAttr
.cFuncs
,
2399 ptiRet
->TypeAttr
.cVars
,
2400 tiBase
.memoffset
, &ptiRet
->vardescs
);
2401 if(ptiRet
->TypeAttr
.cImplTypes
>0 ) {
2402 switch(ptiRet
->TypeAttr
.typekind
)
2405 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->TypeAttr
.cImplTypes
,
2408 case TKIND_DISPATCH
:
2409 /* This is not -1 when the interface is a non-base dual interface or
2410 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2411 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2415 if (tiBase
.datatype1
!= -1)
2417 ptiRet
->impltypes
= TLBImplType_Constructor(1);
2418 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2419 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2423 ptiRet
->impltypes
= TLBImplType_Constructor(1);
2424 MSFT_DoRefType(pcx
, pLibInfo
, tiBase
.datatype1
);
2425 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2429 MSFT_CustData(pcx
, tiBase
.oCustData
, &ptiRet
->custdata_list
);
2431 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2432 debugstr_w(ptiRet
->Name
),
2433 debugstr_guid(&ptiRet
->TypeAttr
.guid
),
2434 typekind_desc
[ptiRet
->TypeAttr
.typekind
]);
2435 if (TRACE_ON(typelib
))
2436 dump_TypeInfo(ptiRet
);
2441 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2442 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2443 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2446 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2447 static CRITICAL_SECTION cache_section
;
2448 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2450 0, 0, &cache_section
,
2451 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2452 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2454 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2457 typedef struct TLB_PEFile
2459 const IUnknownVtbl
*lpvtbl
;
2462 HRSRC typelib_resource
;
2463 HGLOBAL typelib_global
;
2464 LPVOID typelib_base
;
2467 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2469 if (IsEqualIID(riid
, &IID_IUnknown
))
2472 IUnknown_AddRef(iface
);
2476 return E_NOINTERFACE
;
2479 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2481 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2482 return InterlockedIncrement(&This
->refs
);
2485 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2487 TLB_PEFile
*This
= (TLB_PEFile
*)iface
;
2488 ULONG refs
= InterlockedDecrement(&This
->refs
);
2491 if (This
->typelib_global
)
2492 FreeResource(This
->typelib_global
);
2494 FreeLibrary(This
->dll
);
2500 static const IUnknownVtbl TLB_PEFile_Vtable
=
2502 TLB_PEFile_QueryInterface
,
2507 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2511 This
= heap_alloc(sizeof(TLB_PEFile
));
2513 return E_OUTOFMEMORY
;
2515 This
->lpvtbl
= &TLB_PEFile_Vtable
;
2518 This
->typelib_resource
= NULL
;
2519 This
->typelib_global
= NULL
;
2520 This
->typelib_base
= NULL
;
2522 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2523 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2527 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2528 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2529 if (This
->typelib_resource
)
2531 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2532 if (This
->typelib_global
)
2534 This
->typelib_base
= LockResource(This
->typelib_global
);
2536 if (This
->typelib_base
)
2538 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2539 *ppBase
= This
->typelib_base
;
2540 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2547 TLB_PEFile_Release((IUnknown
*)&This
->lpvtbl
);
2548 return TYPE_E_CANTLOADLIBRARY
;
2551 typedef struct TLB_NEFile
2553 const IUnknownVtbl
*lpvtbl
;
2555 LPVOID typelib_base
;
2558 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2560 if (IsEqualIID(riid
, &IID_IUnknown
))
2563 IUnknown_AddRef(iface
);
2567 return E_NOINTERFACE
;
2570 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2572 TLB_NEFile
*This
= (TLB_NEFile
*)iface
;
2573 return InterlockedIncrement(&This
->refs
);
2576 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2578 TLB_NEFile
*This
= (TLB_NEFile
*)iface
;
2579 ULONG refs
= InterlockedDecrement(&This
->refs
);
2582 heap_free(This
->typelib_base
);
2588 static const IUnknownVtbl TLB_NEFile_Vtable
=
2590 TLB_NEFile_QueryInterface
,
2595 /***********************************************************************
2596 * read_xx_header [internal]
2598 static int read_xx_header( HFILE lzfd
)
2600 IMAGE_DOS_HEADER mzh
;
2603 LZSeek( lzfd
, 0, SEEK_SET
);
2604 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
2606 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
2609 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2610 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
2613 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
2615 if ( magic
[0] == 'N' && magic
[1] == 'E' )
2616 return IMAGE_OS2_SIGNATURE
;
2617 if ( magic
[0] == 'P' && magic
[1] == 'E' )
2618 return IMAGE_NT_SIGNATURE
;
2621 WARN("Can't handle %s files.\n", magic
);
2626 /***********************************************************************
2627 * find_ne_resource [internal]
2629 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
2630 DWORD
*resLen
, DWORD
*resOff
)
2632 IMAGE_OS2_HEADER nehd
;
2633 NE_TYPEINFO
*typeInfo
;
2634 NE_NAMEINFO
*nameInfo
;
2640 /* Read in NE header */
2641 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
2642 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return 0;
2644 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
2647 TRACE("No resources in NE dll\n" );
2651 /* Read in resource table */
2652 resTab
= heap_alloc( resTabSize
);
2653 if ( !resTab
) return FALSE
;
2655 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
2656 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
2658 heap_free( resTab
);
2663 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
2665 if (!IS_INTRESOURCE(typeid)) /* named type */
2667 BYTE len
= strlen( typeid );
2668 while (typeInfo
->type_id
)
2670 if (!(typeInfo
->type_id
& 0x8000))
2672 BYTE
*p
= resTab
+ typeInfo
->type_id
;
2673 if ((*p
== len
) && !strncasecmp( (char*)p
+1, typeid, len
)) goto found_type
;
2675 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2676 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2679 else /* numeric type id */
2681 WORD id
= LOWORD(typeid) | 0x8000;
2682 while (typeInfo
->type_id
)
2684 if (typeInfo
->type_id
== id
) goto found_type
;
2685 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
2686 typeInfo
->count
* sizeof(NE_NAMEINFO
));
2689 TRACE("No typeid entry found for %p\n", typeid );
2690 heap_free( resTab
);
2694 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
2696 if (!IS_INTRESOURCE(resid
)) /* named resource */
2698 BYTE len
= strlen( resid
);
2699 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2701 BYTE
*p
= resTab
+ nameInfo
->id
;
2702 if (nameInfo
->id
& 0x8000) continue;
2703 if ((*p
== len
) && !strncasecmp( (char*)p
+1, resid
, len
)) goto found_name
;
2706 else /* numeric resource id */
2708 WORD id
= LOWORD(resid
) | 0x8000;
2709 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
2710 if (nameInfo
->id
== id
) goto found_name
;
2712 TRACE("No resid entry found for %p\n", typeid );
2713 heap_free( resTab
);
2717 /* Return resource data */
2718 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
2719 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
2721 heap_free( resTab
);
2725 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
2729 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2732 This
= heap_alloc(sizeof(TLB_NEFile
));
2733 if (!This
) return E_OUTOFMEMORY
;
2735 This
->lpvtbl
= &TLB_NEFile_Vtable
;
2737 This
->typelib_base
= NULL
;
2739 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
2740 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
2742 DWORD reslen
, offset
;
2743 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
2745 This
->typelib_base
= heap_alloc(reslen
);
2746 if( !This
->typelib_base
)
2750 LZSeek( lzfd
, offset
, SEEK_SET
);
2751 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
2753 *ppBase
= This
->typelib_base
;
2754 *pdwTLBLength
= reslen
;
2755 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2761 if( lzfd
>= 0) LZClose( lzfd
);
2762 TLB_NEFile_Release((IUnknown
*)&This
->lpvtbl
);
2766 typedef struct TLB_Mapping
2768 const IUnknownVtbl
*lpvtbl
;
2772 LPVOID typelib_base
;
2775 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2777 if (IsEqualIID(riid
, &IID_IUnknown
))
2780 IUnknown_AddRef(iface
);
2784 return E_NOINTERFACE
;
2787 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
2789 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2790 return InterlockedIncrement(&This
->refs
);
2793 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
2795 TLB_Mapping
*This
= (TLB_Mapping
*)iface
;
2796 ULONG refs
= InterlockedDecrement(&This
->refs
);
2799 if (This
->typelib_base
)
2800 UnmapViewOfFile(This
->typelib_base
);
2802 CloseHandle(This
->mapping
);
2803 if (This
->file
!= INVALID_HANDLE_VALUE
)
2804 CloseHandle(This
->file
);
2810 static const IUnknownVtbl TLB_Mapping_Vtable
=
2812 TLB_Mapping_QueryInterface
,
2817 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2821 This
= heap_alloc(sizeof(TLB_Mapping
));
2823 return E_OUTOFMEMORY
;
2825 This
->lpvtbl
= &TLB_Mapping_Vtable
;
2827 This
->file
= INVALID_HANDLE_VALUE
;
2828 This
->mapping
= NULL
;
2829 This
->typelib_base
= NULL
;
2831 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
2832 if (INVALID_HANDLE_VALUE
!= This
->file
)
2834 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
2837 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
2838 if(This
->typelib_base
)
2840 /* retrieve file size */
2841 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
2842 *ppBase
= This
->typelib_base
;
2843 *ppFile
= (IUnknown
*)&This
->lpvtbl
;
2849 IUnknown_Release((IUnknown
*)&This
->lpvtbl
);
2850 return TYPE_E_CANTLOADLIBRARY
;
2853 /****************************************************************************
2856 * find the type of the typelib file and map the typelib resource into
2860 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
2861 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
2863 ITypeLibImpl
*entry
;
2866 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
2867 LPVOID pBase
= NULL
;
2868 DWORD dwTLBLength
= 0;
2869 IUnknown
*pFile
= NULL
;
2873 index_str
= strrchrW(pszFileName
, '\\');
2874 if(index_str
&& *++index_str
!= '\0')
2877 LONG idx
= strtolW(index_str
, &end_ptr
, 10);
2878 if(*end_ptr
== '\0')
2880 int str_len
= index_str
- pszFileName
- 1;
2882 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
2883 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
2888 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
2890 if(strchrW(file
, '\\'))
2892 lstrcpyW(pszPath
, file
);
2896 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
2897 pszPath
[len
] = '\\';
2898 memcpy(pszPath
+ len
+ 1, file
, (strlenW(file
) + 1) * sizeof(WCHAR
));
2902 if(file
!= pszFileName
) heap_free(file
);
2904 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
2906 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
2907 EnterCriticalSection(&cache_section
);
2908 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
2910 if (!strcmpiW(entry
->path
, pszPath
) && entry
->index
== index
)
2912 TRACE("cache hit\n");
2913 *ppTypeLib
= (ITypeLib2
*)entry
;
2914 ITypeLib_AddRef(*ppTypeLib
);
2915 LeaveCriticalSection(&cache_section
);
2919 LeaveCriticalSection(&cache_section
);
2921 /* now actually load and parse the typelib */
2923 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2924 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2925 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
2926 if (ret
== TYPE_E_CANTLOADLIBRARY
)
2927 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
2930 if (dwTLBLength
>= 4)
2932 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
2933 if (dwSignature
== MSFT_SIGNATURE
)
2934 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
2935 else if (dwSignature
== SLTG_SIGNATURE
)
2936 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
2939 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
2940 ret
= TYPE_E_CANTLOADLIBRARY
;
2944 ret
= TYPE_E_CANTLOADLIBRARY
;
2945 IUnknown_Release(pFile
);
2949 ITypeLibImpl
*impl
= (ITypeLibImpl
*)*ppTypeLib
;
2951 TRACE("adding to cache\n");
2952 impl
->path
= heap_alloc((strlenW(pszPath
)+1) * sizeof(WCHAR
));
2953 lstrcpyW(impl
->path
, pszPath
);
2954 /* We should really canonicalise the path here. */
2955 impl
->index
= index
;
2957 /* FIXME: check if it has added already in the meantime */
2958 EnterCriticalSection(&cache_section
);
2959 list_add_head(&tlb_cache
, &impl
->entry
);
2960 LeaveCriticalSection(&cache_section
);
2963 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
2968 /*================== ITypeLib(2) Methods ===================================*/
2970 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
2972 ITypeLibImpl
* pTypeLibImpl
;
2974 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
2975 if (!pTypeLibImpl
) return NULL
;
2977 pTypeLibImpl
->lpVtbl
= &tlbvt
;
2978 pTypeLibImpl
->lpVtblTypeComp
= &tlbtcvt
;
2979 pTypeLibImpl
->ref
= 1;
2981 list_init(&pTypeLibImpl
->implib_list
);
2982 list_init(&pTypeLibImpl
->custdata_list
);
2983 list_init(&pTypeLibImpl
->ref_list
);
2984 pTypeLibImpl
->dispatch_href
= -1;
2986 return pTypeLibImpl
;
2989 /****************************************************************************
2990 * ITypeLib2_Constructor_MSFT
2992 * loading an MSFT typelib from an in-memory image
2994 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
2998 MSFT_Header tlbHeader
;
2999 MSFT_SegDir tlbSegDir
;
3000 ITypeLibImpl
* pTypeLibImpl
;
3002 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3004 pTypeLibImpl
= TypeLibImpl_Constructor();
3005 if (!pTypeLibImpl
) return NULL
;
3007 /* get pointer to beginning of typelib data */
3011 cx
.pLibInfo
= pTypeLibImpl
;
3012 cx
.length
= dwTLBLength
;
3015 MSFT_ReadLEDWords((void*)&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3016 TRACE_(typelib
)("header:\n");
3017 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3018 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3019 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3022 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3024 /* there is a small amount of information here until the next important
3026 * the segment directory . Try to calculate the amount of data */
3027 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3029 /* now read the segment directory */
3030 TRACE("read segment directory (at %d)\n",lPSegDir
);
3031 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3032 cx
.pTblDir
= &tlbSegDir
;
3034 /* just check two entries */
3035 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3037 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3038 heap_free(pTypeLibImpl
);
3042 /* now fill our internal data */
3043 /* TLIBATTR fields */
3044 MSFT_ReadGuid(&pTypeLibImpl
->LibAttr
.guid
, tlbHeader
.posguid
, &cx
);
3046 pTypeLibImpl
->LibAttr
.lcid
= tlbHeader
.lcid2
;
3047 pTypeLibImpl
->LibAttr
.syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3048 pTypeLibImpl
->LibAttr
.wMajorVerNum
= LOWORD(tlbHeader
.version
);
3049 pTypeLibImpl
->LibAttr
.wMinorVerNum
= HIWORD(tlbHeader
.version
);
3050 pTypeLibImpl
->LibAttr
.wLibFlags
= (WORD
) tlbHeader
.flags
& 0xffff;/* check mask */
3052 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3054 /* name, eventually add to a hash table */
3055 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3058 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3059 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3061 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3064 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3065 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3068 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3071 if(tlbHeader
.CustomDataOffset
>= 0)
3073 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3076 /* fill in type descriptions */
3077 if(tlbSegDir
.pTypdescTab
.length
> 0)
3079 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3081 pTypeLibImpl
->ctTypeDesc
= cTD
;
3082 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3083 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3086 /* FIXME: add several sanity checks here */
3087 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3088 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3090 /* FIXME: check safearray */
3092 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3094 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3096 else if(td
[0] == VT_CARRAY
)
3098 /* array descr table here */
3099 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3101 else if(td
[0] == VT_USERDEFINED
)
3103 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3105 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3108 /* second time around to fill the array subscript info */
3111 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3112 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3114 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3115 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3118 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3120 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3122 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3124 for(j
= 0; j
<td
[2]; j
++)
3126 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3127 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3128 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3129 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3134 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3135 ERR("didn't find array description data\n");
3140 /* imported type libs */
3141 if(tlbSegDir
.pImpFiles
.offset
>0)
3144 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3147 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3151 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3152 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3153 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3155 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3156 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3157 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3158 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3161 name
= heap_alloc_zero(size
+1);
3162 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3163 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3166 MSFT_ReadGuid(&pImpLib
->guid
, oGuid
, &cx
);
3167 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3169 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3173 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3174 if(pTypeLibImpl
->dispatch_href
!= -1)
3175 MSFT_DoRefType(&cx
, pTypeLibImpl
, pTypeLibImpl
->dispatch_href
);
3178 if(tlbHeader
.nrtypeinfos
>= 0 )
3180 ITypeInfoImpl
**ppTI
;
3183 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3185 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3187 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3190 (pTypeLibImpl
->TypeInfoCount
)++;
3194 TRACE("(%p)\n", pTypeLibImpl
);
3195 return (ITypeLib2
*) pTypeLibImpl
;
3199 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3205 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3206 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3210 guid
->Data4
[0] = s
>> 8;
3211 guid
->Data4
[1] = s
& 0xff;
3214 for(i
= 0; i
< 6; i
++) {
3215 memcpy(b
, str
+ 24 + 2 * i
, 2);
3216 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3221 static WORD
SLTG_ReadString(const char *ptr
, BSTR
*pBstr
)
3227 bytelen
= *(const WORD
*)ptr
;
3228 if(bytelen
== 0xffff) return 2;
3229 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3230 *pBstr
= SysAllocStringLen(NULL
, len
);
3232 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, *pBstr
, len
);
3236 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3241 bytelen
= *(const WORD
*)ptr
;
3242 if(bytelen
== 0xffff) return 2;
3243 *str
= heap_alloc(bytelen
+ 1);
3244 memcpy(*str
, ptr
+ 2, bytelen
);
3245 (*str
)[bytelen
] = '\0';
3249 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3251 char *ptr
= pLibBlk
;
3254 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3255 FIXME("libblk magic = %04x\n", w
);
3260 if((w
= *(WORD
*)ptr
) != 0xffff) {
3261 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3266 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
);
3268 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
);
3270 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3273 pTypeLibImpl
->LibAttr
.syskind
= *(WORD
*)ptr
;
3276 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3277 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3279 pTypeLibImpl
->lcid
= pTypeLibImpl
->LibAttr
.lcid
= 0;
3282 ptr
+= 4; /* skip res12 */
3284 pTypeLibImpl
->LibAttr
.wLibFlags
= *(WORD
*)ptr
;
3287 pTypeLibImpl
->LibAttr
.wMajorVerNum
= *(WORD
*)ptr
;
3290 pTypeLibImpl
->LibAttr
.wMinorVerNum
= *(WORD
*)ptr
;
3293 memcpy(&pTypeLibImpl
->LibAttr
.guid
, ptr
, sizeof(GUID
));
3294 ptr
+= sizeof(GUID
);
3296 return ptr
- (char*)pLibBlk
;
3299 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3304 } sltg_ref_lookup_t
;
3306 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3307 HREFTYPE
*typelib_ref
)
3309 if(table
&& typeinfo_ref
< table
->num
)
3311 *typelib_ref
= table
->refs
[typeinfo_ref
];
3315 ERR_(typelib
)("Unable to find reference\n");
3320 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3325 if((*pType
& 0xe00) == 0xe00) {
3327 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3328 pTD
= pTD
->u
.lptdesc
;
3330 switch(*pType
& 0x3f) {
3333 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3334 pTD
= pTD
->u
.lptdesc
;
3337 case VT_USERDEFINED
:
3338 pTD
->vt
= VT_USERDEFINED
;
3339 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3345 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3348 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3350 pTD
->vt
= VT_CARRAY
;
3351 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3352 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3353 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3354 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3356 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3362 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3366 pTD
->vt
= VT_SAFEARRAY
;
3367 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3368 pTD
= pTD
->u
.lptdesc
;
3372 pTD
->vt
= *pType
& 0x3f;
3381 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3382 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3384 /* Handle [in/out] first */
3385 if((*pType
& 0xc000) == 0xc000)
3386 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3387 else if(*pType
& 0x8000)
3388 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3389 else if(*pType
& 0x4000)
3390 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3392 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3395 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3398 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3400 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3404 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3409 TLBRefType
*ref_type
;
3410 sltg_ref_lookup_t
*table
;
3411 HREFTYPE typelib_ref
;
3413 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3414 FIXME("Ref magic = %x\n", pRef
->magic
);
3417 name
= ( (char*)pRef
->names
+ pRef
->number
);
3419 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3420 table
->num
= pRef
->number
>> 3;
3422 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3424 /* We don't want the first href to be 0 */
3425 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3427 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3429 unsigned int lib_offs
, type_num
;
3431 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3433 name
+= SLTG_ReadStringA(name
, &refname
);
3434 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3435 FIXME_(typelib
)("Can't sscanf ref\n");
3436 if(lib_offs
!= 0xffff) {
3439 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3440 if(import
->offset
== lib_offs
)
3443 if(&import
->entry
== &pTL
->implib_list
) {
3444 char fname
[MAX_PATH
+1];
3447 import
= heap_alloc_zero(sizeof(*import
));
3448 import
->offset
= lib_offs
;
3449 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4,
3451 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3452 &import
->wVersionMajor
,
3453 &import
->wVersionMinor
,
3454 &import
->lcid
, fname
) != 4) {
3455 FIXME_(typelib
)("can't sscanf ref %s\n",
3456 pNameTable
+ lib_offs
+ 40);
3458 len
= strlen(fname
);
3459 if(fname
[len
-1] != '#')
3460 FIXME("fname = %s\n", fname
);
3461 fname
[len
-1] = '\0';
3462 import
->name
= TLB_MultiByteToBSTR(fname
);
3463 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3465 ref_type
->pImpTLInfo
= import
;
3467 /* Store a reference to IDispatch */
3468 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
, &IID_StdOle
) && type_num
== 4)
3469 pTL
->dispatch_href
= typelib_ref
;
3471 } else { /* internal ref */
3472 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3474 ref_type
->reference
= typelib_ref
;
3475 ref_type
->index
= type_num
;
3478 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3480 table
->refs
[ref
] = typelib_ref
;
3483 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3484 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3485 dump_TLBRefType(pTL
);
3489 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3490 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3492 SLTG_ImplInfo
*info
;
3493 TLBImplType
*pImplType
;
3494 /* I don't really get this structure, usually it's 0x16 bytes
3495 long, but iuser.tlb contains some that are 0x18 bytes long.
3496 That's ok because we can use the next ptr to jump to the next
3497 one. But how do we know the length of the last one? The WORD
3498 at offs 0x8 might be the clue. For now I'm just assuming that
3499 the last one is the regular 0x16 bytes. */
3501 info
= (SLTG_ImplInfo
*)pBlk
;
3503 pTI
->TypeAttr
.cImplTypes
++;
3504 if(info
->next
== 0xffff)
3506 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3509 info
= (SLTG_ImplInfo
*)pBlk
;
3510 pTI
->impltypes
= TLBImplType_Constructor(pTI
->TypeAttr
.cImplTypes
);
3511 pImplType
= pTI
->impltypes
;
3513 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3514 pImplType
->implflags
= info
->impltypeflags
;
3517 if(info
->next
== 0xffff)
3520 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3521 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3523 info
++; /* see comment at top of function */
3527 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
3528 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3530 TLBVarDesc
*pVarDesc
;
3531 BSTR bstrPrevName
= NULL
;
3532 SLTG_Variable
*pItem
;
3536 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Constructor(cVars
);
3538 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
3539 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
3541 pVarDesc
->vardesc
.memid
= pItem
->memid
;
3543 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
3544 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
3545 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
3549 if (pItem
->name
== 0xfffe)
3550 pVarDesc
->Name
= SysAllocString(bstrPrevName
);
3552 pVarDesc
->Name
= TLB_MultiByteToBSTR(pItem
->name
+ pNameTable
);
3554 TRACE_(typelib
)("name: %s\n", debugstr_w(pVarDesc
->Name
));
3555 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
3556 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
3558 if(pItem
->flags
& 0x02)
3559 pType
= &pItem
->type
;
3561 pType
= (WORD
*)(pBlk
+ pItem
->type
);
3563 if (pItem
->flags
& ~0xda)
3564 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
3566 SLTG_DoElem(pType
, pBlk
,
3567 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
3569 if (TRACE_ON(typelib
)) {
3571 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
3572 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
3575 if (pItem
->flags
& 0x40) {
3576 TRACE_(typelib
)("VAR_DISPATCH\n");
3577 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
3579 else if (pItem
->flags
& 0x10) {
3580 TRACE_(typelib
)("VAR_CONST\n");
3581 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
3582 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
3583 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
3584 if (pItem
->flags
& 0x08)
3585 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
3587 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
3593 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
3595 TRACE_(typelib
)("len = %u\n", len
);
3596 if (len
== 0xffff) {
3599 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
3600 str
= SysAllocStringLen(NULL
, alloc_len
);
3601 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
3603 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
3604 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
3613 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
3614 *(INT
*)(pBlk
+ pItem
->byte_offs
);
3617 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
3622 TRACE_(typelib
)("VAR_PERINSTANCE\n");
3623 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
3624 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
3627 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
3628 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
3630 if (pItem
->flags
& 0x80)
3631 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
3633 bstrPrevName
= pVarDesc
->Name
;
3635 pTI
->TypeAttr
.cVars
= cVars
;
3638 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
3639 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
3641 SLTG_Function
*pFunc
;
3643 TLBFuncDesc
*pFuncDesc
;
3645 pTI
->funcdescs
= TLBFuncDesc_Constructor(cFuncs
);
3647 pFuncDesc
= pTI
->funcdescs
;
3648 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
3649 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
3654 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
3655 case SLTG_FUNCTION_MAGIC
:
3656 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
3658 case SLTG_DISPATCH_FUNCTION_MAGIC
:
3659 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
3661 case SLTG_STATIC_FUNCTION_MAGIC
:
3662 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
3665 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
3668 pFuncDesc
->Name
= TLB_MultiByteToBSTR(pFunc
->name
+ pNameTable
);
3670 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
3671 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
3672 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
3673 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
3674 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
3675 pFuncDesc
->funcdesc
.oVft
= pFunc
->vtblpos
& ~1;
3677 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
3678 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
3680 if(pFunc
->retnextopt
& 0x80)
3681 pType
= &pFunc
->rettype
;
3683 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
3685 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
3687 pFuncDesc
->funcdesc
.lprgelemdescParam
=
3688 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
3689 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
3691 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
3693 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
3694 char *paramName
= pNameTable
+ *pArg
;
3696 /* If arg type follows then paramName points to the 2nd
3697 letter of the name, else the next WORD is an offset to
3698 the arg type and paramName points to the first letter.
3699 So let's take one char off paramName and see if we're
3700 pointing at an alpha-numeric char. However if *pArg is
3701 0xffff or 0xfffe then the param has no name, the former
3702 meaning that the next WORD is the type, the latter
3703 meaning that the next WORD is an offset to the type. */
3708 else if(*pArg
== 0xfffe) {
3712 else if(paramName
[-1] && !isalnum(paramName
[-1]))
3717 if(HaveOffs
) { /* the next word is an offset to type */
3718 pType
= (WORD
*)(pBlk
+ *pArg
);
3719 SLTG_DoElem(pType
, pBlk
,
3720 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3725 pArg
= SLTG_DoElem(pArg
, pBlk
,
3726 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
3729 /* Are we an optional param ? */
3730 if(pFuncDesc
->funcdesc
.cParams
- param
<=
3731 pFuncDesc
->funcdesc
.cParamsOpt
)
3732 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
3735 pFuncDesc
->pParamDesc
[param
].Name
=
3736 TLB_MultiByteToBSTR(paramName
);
3738 pFuncDesc
->pParamDesc
[param
].Name
=
3739 SysAllocString(pFuncDesc
->Name
);
3743 pTI
->TypeAttr
.cFuncs
= cFuncs
;
3746 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
3747 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3748 SLTG_TypeInfoTail
*pTITail
)
3751 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3753 if(pTIHeader
->href_table
!= 0xffffffff) {
3754 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3760 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3761 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
3763 heap_free(ref_lookup
);
3767 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
3768 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3769 const SLTG_TypeInfoTail
*pTITail
)
3772 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3774 if(pTIHeader
->href_table
!= 0xffffffff) {
3775 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3781 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
3782 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
3785 if (pTITail
->funcs_off
!= 0xffff)
3786 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3788 heap_free(ref_lookup
);
3790 if (TRACE_ON(typelib
))
3791 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->TypeAttr
.cFuncs
);
3794 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
3795 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3796 const SLTG_TypeInfoTail
*pTITail
)
3798 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3801 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
3802 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3803 const SLTG_TypeInfoTail
*pTITail
)
3806 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3808 if (pTITail
->simple_alias
) {
3809 /* if simple alias, no more processing required */
3810 pTI
->TypeAttr
.tdescAlias
.vt
= pTITail
->tdescalias_vt
;
3814 if(pTIHeader
->href_table
!= 0xffffffff) {
3815 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3819 /* otherwise it is an offset to a type */
3820 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
3822 SLTG_DoType(pType
, pBlk
, &pTI
->TypeAttr
.tdescAlias
, ref_lookup
);
3824 heap_free(ref_lookup
);
3827 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
3828 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3829 const SLTG_TypeInfoTail
*pTITail
)
3831 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3832 if (pTIHeader
->href_table
!= 0xffffffff)
3833 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3836 if (pTITail
->vars_off
!= 0xffff)
3837 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3839 if (pTITail
->funcs_off
!= 0xffff)
3840 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3842 if (pTITail
->impls_off
!= 0xffff)
3843 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
3845 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
3846 * of dispinterface functions including the IDispatch ones, so
3847 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
3848 pTI
->TypeAttr
.cbSizeVft
= pTI
->TypeAttr
.cFuncs
* sizeof(void *);
3850 heap_free(ref_lookup
);
3851 if (TRACE_ON(typelib
))
3852 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->TypeAttr
.cFuncs
);
3855 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
3856 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3857 const SLTG_TypeInfoTail
*pTITail
)
3859 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
3862 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
3863 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
3864 const SLTG_TypeInfoTail
*pTITail
)
3866 sltg_ref_lookup_t
*ref_lookup
= NULL
;
3867 if (pTIHeader
->href_table
!= 0xffffffff)
3868 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
3871 if (pTITail
->vars_off
!= 0xffff)
3872 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
3874 if (pTITail
->funcs_off
!= 0xffff)
3875 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
3876 heap_free(ref_lookup
);
3877 if (TRACE_ON(typelib
))
3881 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
3882 managable copy of it into this */
3895 } SLTG_InternalOtherTypeInfo
;
3897 /****************************************************************************
3898 * ITypeLib2_Constructor_SLTG
3900 * loading a SLTG typelib from an in-memory image
3902 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
3904 ITypeLibImpl
*pTypeLibImpl
;
3905 SLTG_Header
*pHeader
;
3906 SLTG_BlkEntry
*pBlkEntry
;
3910 LPVOID pBlk
, pFirstBlk
;
3911 SLTG_LibBlk
*pLibBlk
;
3912 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
3913 char *pAfterOTIBlks
= NULL
;
3914 char *pNameTable
, *ptr
;
3917 ITypeInfoImpl
**ppTypeInfoImpl
;
3919 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3922 pTypeLibImpl
= TypeLibImpl_Constructor();
3923 if (!pTypeLibImpl
) return NULL
;
3927 TRACE_(typelib
)("header:\n");
3928 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
3929 pHeader
->nrOfFileBlks
);
3930 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
3931 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
3932 pHeader
->SLTG_magic
);
3936 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
3937 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
3939 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
3940 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
3942 /* Next we have a magic block */
3943 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
3945 /* Let's see if we're still in sync */
3946 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
3947 sizeof(SLTG_COMPOBJ_MAGIC
))) {
3948 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
3951 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
3952 sizeof(SLTG_DIR_MAGIC
))) {
3953 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
3957 pIndex
= (SLTG_Index
*)(pMagic
+1);
3959 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
3961 pFirstBlk
= pPad9
+ 1;
3963 /* We'll set up a ptr to the main library block, which is the last one. */
3965 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
3966 pBlkEntry
[order
].next
!= 0;
3967 order
= pBlkEntry
[order
].next
- 1, i
++) {
3968 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
3972 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
3974 /* Now there's 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
3979 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
3981 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
3984 ptr
= (char*)pLibBlk
+ len
;
3986 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
3990 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
3992 w
= *(WORD
*)(ptr
+ 2);
3995 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
3996 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
3997 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
3999 w
= *(WORD
*)(ptr
+ 4 + len
);
4001 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4003 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4004 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4005 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4007 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4008 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4009 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4011 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4012 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4015 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4016 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4017 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4018 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4019 len
+= sizeof(SLTG_OtherTypeInfo
);
4023 pAfterOTIBlks
= ptr
;
4025 /* Skip this WORD and get the next DWORD */
4026 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4028 /* Now add this to pLibBLk look at what we're pointing at and
4029 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4030 dust and we should be pointing at the beginning of the name
4033 pNameTable
= (char*)pLibBlk
+ len
;
4035 switch(*(WORD
*)pNameTable
) {
4042 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4046 pNameTable
+= 0x216;
4050 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4052 pTypeLibImpl
->Name
= TLB_MultiByteToBSTR(pNameTable
+ pLibBlk
->name
);
4055 /* Hopefully we now have enough ptrs set up to actually read in
4056 some TypeInfos. It's not clear which order to do them in, so
4057 I'll just follow the links along the BlkEntry chain and read
4058 them in the order in which they are in the file */
4060 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4061 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4063 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4064 pBlkEntry
[order
].next
!= 0;
4065 order
= pBlkEntry
[order
].next
- 1, i
++) {
4067 SLTG_TypeInfoHeader
*pTIHeader
;
4068 SLTG_TypeInfoTail
*pTITail
;
4069 SLTG_MemberHeader
*pMemHeader
;
4071 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
,
4072 pOtherTypeInfoBlks
[i
].index_name
)) {
4073 FIXME_(typelib
)("Index strings don't match\n");
4078 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4079 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4082 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4083 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4084 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4086 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4087 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4088 (*ppTypeInfoImpl
)->index
= i
;
4089 (*ppTypeInfoImpl
)->Name
= TLB_MultiByteToBSTR(
4090 pOtherTypeInfoBlks
[i
].name_offs
+
4092 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4093 (*ppTypeInfoImpl
)->TypeAttr
.guid
= pOtherTypeInfoBlks
[i
].uuid
;
4094 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= pTIHeader
->typekind
;
4095 (*ppTypeInfoImpl
)->TypeAttr
.wMajorVerNum
= pTIHeader
->major_version
;
4096 (*ppTypeInfoImpl
)->TypeAttr
.wMinorVerNum
= pTIHeader
->minor_version
;
4097 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
=
4098 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4100 if((*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4101 (*ppTypeInfoImpl
)->TypeAttr
.typekind
= TKIND_DISPATCH
;
4103 if((pTIHeader
->typeflags1
& 7) != 2)
4104 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4105 if(pTIHeader
->typeflags3
!= 2)
4106 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4108 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4109 debugstr_w((*ppTypeInfoImpl
)->Name
),
4110 typekind_desc
[pTIHeader
->typekind
],
4111 debugstr_guid(&(*ppTypeInfoImpl
)->TypeAttr
.guid
),
4112 (*ppTypeInfoImpl
)->TypeAttr
.wTypeFlags
);
4114 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4116 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4118 (*ppTypeInfoImpl
)->TypeAttr
.cbAlignment
= pTITail
->cbAlignment
;
4119 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4120 (*ppTypeInfoImpl
)->TypeAttr
.cbSizeVft
= pTITail
->cbSizeVft
;
4122 switch(pTIHeader
->typekind
) {
4124 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4125 pTIHeader
, pTITail
);
4129 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4130 pTIHeader
, pTITail
);
4133 case TKIND_INTERFACE
:
4134 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4135 pTIHeader
, pTITail
);
4139 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4140 pTIHeader
, pTITail
);
4144 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4145 pTIHeader
, pTITail
);
4148 case TKIND_DISPATCH
:
4149 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4150 pTIHeader
, pTITail
);
4154 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4155 pTIHeader
, pTITail
);
4159 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4164 /* could get cFuncs, cVars and cImplTypes from here
4165 but we've already set those */
4166 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4182 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4185 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4186 FIXME("Somehow processed %d TypeInfos\n", i
);
4190 heap_free(pOtherTypeInfoBlks
);
4191 return (ITypeLib2
*)pTypeLibImpl
;
4194 /* ITypeLib::QueryInterface
4196 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(
4201 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4203 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4206 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4207 IsEqualIID(riid
,&IID_ITypeLib
)||
4208 IsEqualIID(riid
,&IID_ITypeLib2
))
4215 ITypeLib2_AddRef(iface
);
4216 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
4219 TRACE("-- Interface: E_NOINTERFACE\n");
4220 return E_NOINTERFACE
;
4225 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4227 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4228 ULONG ref
= InterlockedIncrement(&This
->ref
);
4230 TRACE("(%p)->ref was %u\n",This
, ref
- 1);
4235 /* ITypeLib::Release
4237 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4239 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4240 ULONG ref
= InterlockedDecrement(&This
->ref
);
4242 TRACE("(%p)->(%u)\n",This
, ref
);
4246 TLBImpLib
*pImpLib
, *pImpLibNext
;
4247 TLBRefType
*ref_type
;
4251 /* remove cache entry */
4254 TRACE("removing from cache list\n");
4255 EnterCriticalSection(&cache_section
);
4256 if(This
->entry
.next
)
4257 list_remove(&This
->entry
);
4258 LeaveCriticalSection(&cache_section
);
4259 heap_free(This
->path
);
4261 TRACE(" destroying ITypeLib(%p)\n",This
);
4263 SysFreeString(This
->Name
);
4266 SysFreeString(This
->DocString
);
4267 This
->DocString
= NULL
;
4269 SysFreeString(This
->HelpFile
);
4270 This
->HelpFile
= NULL
;
4272 SysFreeString(This
->HelpStringDll
);
4273 This
->HelpStringDll
= NULL
;
4275 TLB_FreeCustData(&This
->custdata_list
);
4277 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4278 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4279 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4281 heap_free(This
->pTypeDesc
);
4283 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4285 if (pImpLib
->pImpTypeLib
)
4286 ITypeLib_Release((ITypeLib
*)pImpLib
->pImpTypeLib
);
4287 SysFreeString(pImpLib
->name
);
4289 list_remove(&pImpLib
->entry
);
4293 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, cursor2
, &This
->ref_list
, TLBRefType
, entry
)
4295 list_remove(&ref_type
->entry
);
4296 heap_free(ref_type
);
4299 for (i
= 0; i
< This
->TypeInfoCount
; ++i
)
4300 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4301 heap_free(This
->typeinfos
);
4309 /* ITypeLib::GetTypeInfoCount
4311 * Returns the number of type descriptions in the type library
4313 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4315 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4316 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4317 return This
->TypeInfoCount
;
4320 /* ITypeLib::GetTypeInfo
4322 * retrieves the specified type description in the library.
4324 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4327 ITypeInfo
**ppTInfo
)
4329 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4331 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4334 return E_INVALIDARG
;
4336 if(index
>= This
->TypeInfoCount
)
4337 return TYPE_E_ELEMENTNOTFOUND
;
4339 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[index
];
4340 ITypeInfo_AddRef(*ppTInfo
);
4346 /* ITypeLibs::GetTypeInfoType
4348 * Retrieves the type of a type description.
4350 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4355 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4357 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4360 return E_INVALIDARG
;
4362 if(index
>= This
->TypeInfoCount
)
4363 return TYPE_E_ELEMENTNOTFOUND
;
4365 *pTKind
= This
->typeinfos
[index
]->TypeAttr
.typekind
;
4370 /* ITypeLib::GetTypeInfoOfGuid
4372 * Retrieves the type description that corresponds to the specified GUID.
4375 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4378 ITypeInfo
**ppTInfo
)
4380 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4383 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4385 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4386 if(IsEqualIID(&This
->typeinfos
[i
]->TypeAttr
.guid
, guid
)){
4387 *ppTInfo
= (ITypeInfo
*)This
->typeinfos
[i
];
4388 ITypeInfo_AddRef(*ppTInfo
);
4393 return TYPE_E_ELEMENTNOTFOUND
;
4396 /* ITypeLib::GetLibAttr
4398 * Retrieves the structure that contains the library's attributes.
4401 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4405 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4407 TRACE("(%p, %p)\n", This
, attr
);
4409 if (!attr
) return E_INVALIDARG
;
4411 *attr
= heap_alloc(sizeof(**attr
));
4412 if (!*attr
) return E_OUTOFMEMORY
;
4414 **attr
= This
->LibAttr
;
4418 /* ITypeLib::GetTypeComp
4420 * Enables a client compiler to bind to a library's types, variables,
4421 * constants, and global functions.
4424 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4426 ITypeComp
**ppTComp
)
4428 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4430 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4431 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
4432 ITypeComp_AddRef(*ppTComp
);
4437 /* ITypeLib::GetDocumentation
4439 * Retrieves the library's documentation string, the complete Help file name
4440 * and path, and the context identifier for the library Help topic in the Help
4443 * On a successful return all non-null BSTR pointers will have been set,
4446 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4450 BSTR
*pBstrDocString
,
4451 DWORD
*pdwHelpContext
,
4452 BSTR
*pBstrHelpFile
)
4454 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4456 HRESULT result
= E_INVALIDARG
;
4461 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4463 pBstrName
, pBstrDocString
,
4464 pdwHelpContext
, pBstrHelpFile
);
4468 /* documentation for the typelib */
4473 if(!(*pBstrName
= SysAllocString(This
->Name
)))
4481 if (This
->DocString
)
4483 if(!(*pBstrDocString
= SysAllocString(This
->DocString
)))
4486 else if (This
->Name
)
4488 if(!(*pBstrDocString
= SysAllocString(This
->Name
)))
4492 *pBstrDocString
= NULL
;
4496 *pdwHelpContext
= This
->dwHelpContext
;
4502 if(!(*pBstrHelpFile
= SysAllocString(This
->HelpFile
)))
4506 *pBstrHelpFile
= NULL
;
4513 /* for a typeinfo */
4514 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4516 if(SUCCEEDED(result
))
4518 result
= ITypeInfo_GetDocumentation(pTInfo
,
4522 pdwHelpContext
, pBstrHelpFile
);
4524 ITypeInfo_Release(pTInfo
);
4529 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
4531 if (pBstrName
) SysFreeString (*pBstrName
);
4533 return STG_E_INSUFFICIENTMEMORY
;
4538 * Indicates whether a passed-in string contains the name of a type or member
4539 * described in the library.
4542 static HRESULT WINAPI
ITypeLib2_fnIsName(
4548 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4549 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), tic
, fdc
, vrc
, pc
;
4551 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
4555 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
4556 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4557 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4558 for(fdc
= 0; fdc
< pTInfo
->TypeAttr
.cFuncs
; ++fdc
) {
4559 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
4560 if(!memcmp(szNameBuf
,pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4561 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++)
4562 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
4563 goto ITypeLib2_fnIsName_exit
;
4565 for(vrc
= 0; vrc
< pTInfo
->TypeAttr
.cVars
; ++vrc
){
4566 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
4567 if(!memcmp(szNameBuf
,pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
4573 ITypeLib2_fnIsName_exit
:
4574 TRACE("(%p)slow! search for %s: %s found!\n", This
,
4575 debugstr_w(szNameBuf
), *pfName
?"NOT":"");
4580 /* ITypeLib::FindName
4582 * Finds occurrences of a type description in a type library. This may be used
4583 * to quickly verify that a name exists in a type library.
4586 static HRESULT WINAPI
ITypeLib2_fnFindName(
4590 ITypeInfo
**ppTInfo
,
4594 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4596 UINT tic
, fdc
, pc
, count
= 0;
4597 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
);
4599 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
4600 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
4601 if(!memcmp(szNameBuf
,pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4602 for(fdc
= 0; fdc
< pTInfo
->TypeAttr
.cFuncs
; ++fdc
) {
4603 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
4604 if(!memcmp(szNameBuf
,pFInfo
->Name
,nNameBufLen
)) goto ITypeLib2_fnFindName_exit
;
4605 for(pc
= 0;pc
< pFInfo
->funcdesc
.cParams
; pc
++) {
4606 if(!memcmp(szNameBuf
,pFInfo
->pParamDesc
[pc
].Name
,nNameBufLen
))
4607 goto ITypeLib2_fnFindName_exit
;
4611 pVInfo
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->TypeAttr
.cVars
, szNameBuf
);
4613 goto ITypeLib2_fnFindName_exit
;
4616 ITypeLib2_fnFindName_exit
:
4617 ITypeInfo_AddRef((ITypeInfo
*)pTInfo
);
4618 ppTInfo
[count
]=(LPTYPEINFO
)pTInfo
;
4621 TRACE("(%p)slow! search for %d with %s: found %d TypeInfos!\n",
4622 This
, *pcFound
, debugstr_w(szNameBuf
), count
);
4629 /* ITypeLib::ReleaseTLibAttr
4631 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
4634 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
4636 TLIBATTR
*pTLibAttr
)
4638 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4639 TRACE("freeing (%p)\n",This
);
4640 heap_free(pTLibAttr
);
4644 /* ITypeLib2::GetCustData
4646 * gets the custom data
4648 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
4653 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4654 TLBCustData
*pCData
;
4656 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
4658 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
4660 return TYPE_E_ELEMENTNOTFOUND
;
4662 VariantInit(pVarVal
);
4663 VariantCopy(pVarVal
, &pCData
->data
);
4668 /* ITypeLib2::GetLibStatistics
4670 * Returns statistics about a type library that are required for efficient
4671 * sizing of hash tables.
4674 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
4676 ULONG
*pcUniqueNames
,
4677 ULONG
*pcchUniqueNames
)
4679 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4681 FIXME("(%p): stub!\n", This
);
4683 if(pcUniqueNames
) *pcUniqueNames
=1;
4684 if(pcchUniqueNames
) *pcchUniqueNames
=1;
4688 /* ITypeLib2::GetDocumentation2
4690 * Retrieves the library's documentation string, the complete Help file name
4691 * and path, the localization context to use, and the context ID for the
4692 * library Help topic in the Help file.
4695 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
4699 BSTR
*pbstrHelpString
,
4700 DWORD
*pdwHelpStringContext
,
4701 BSTR
*pbstrHelpStringDll
)
4703 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4707 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
4709 /* the help string should be obtained from the helpstringdll,
4710 * using the _DLLGetDocumentation function, based on the supplied
4711 * lcid. Nice to do sometime...
4715 /* documentation for the typelib */
4717 *pbstrHelpString
=SysAllocString(This
->DocString
);
4718 if(pdwHelpStringContext
)
4719 *pdwHelpStringContext
=This
->dwHelpContext
;
4720 if(pbstrHelpStringDll
)
4721 *pbstrHelpStringDll
=SysAllocString(This
->HelpStringDll
);
4727 /* for a typeinfo */
4728 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
4730 if(SUCCEEDED(result
))
4732 ITypeInfo2
* pTInfo2
;
4733 result
= ITypeInfo_QueryInterface(pTInfo
,
4735 (LPVOID
*) &pTInfo2
);
4737 if(SUCCEEDED(result
))
4739 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
4743 pdwHelpStringContext
,
4744 pbstrHelpStringDll
);
4746 ITypeInfo2_Release(pTInfo2
);
4749 ITypeInfo_Release(pTInfo
);
4755 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
4757 TLBCustData
*pCData
;
4761 ct
= list_count(custdata_list
);
4763 pCustData
->prgCustData
= heap_alloc_zero(ct
* sizeof(CUSTDATAITEM
));
4764 if(!pCustData
->prgCustData
)
4765 return E_OUTOFMEMORY
;
4767 pCustData
->cCustData
= ct
;
4769 cdi
= pCustData
->prgCustData
;
4770 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
4771 cdi
->guid
= pCData
->guid
;
4772 VariantCopy(&cdi
->varValue
, &pCData
->data
);
4780 /* ITypeLib2::GetAllCustData
4782 * Gets all custom data items for the library.
4785 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
4787 CUSTDATA
*pCustData
)
4789 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
4790 TRACE("%p %p\n", iface
, pCustData
);
4791 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
4794 static const ITypeLib2Vtbl tlbvt
= {
4795 ITypeLib2_fnQueryInterface
,
4797 ITypeLib2_fnRelease
,
4798 ITypeLib2_fnGetTypeInfoCount
,
4799 ITypeLib2_fnGetTypeInfo
,
4800 ITypeLib2_fnGetTypeInfoType
,
4801 ITypeLib2_fnGetTypeInfoOfGuid
,
4802 ITypeLib2_fnGetLibAttr
,
4803 ITypeLib2_fnGetTypeComp
,
4804 ITypeLib2_fnGetDocumentation
,
4806 ITypeLib2_fnFindName
,
4807 ITypeLib2_fnReleaseTLibAttr
,
4809 ITypeLib2_fnGetCustData
,
4810 ITypeLib2_fnGetLibStatistics
,
4811 ITypeLib2_fnGetDocumentation2
,
4812 ITypeLib2_fnGetAllCustData
4816 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
4818 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4820 return ITypeLib2_QueryInterface((ITypeLib
*)This
, riid
, ppv
);
4823 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
4825 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4827 return ITypeLib2_AddRef((ITypeLib2
*)This
);
4830 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
4832 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4834 return ITypeLib2_Release((ITypeLib2
*)This
);
4837 static HRESULT WINAPI
ITypeLibComp_fnBind(
4842 ITypeInfo
** ppTInfo
,
4843 DESCKIND
* pDescKind
,
4846 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4847 int typemismatch
=0, i
;
4849 TRACE("(%s, 0x%x, 0x%x, %p, %p, %p)\n", debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4851 *pDescKind
= DESCKIND_NONE
;
4852 pBindPtr
->lptcomp
= NULL
;
4855 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4856 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
4857 TRACE("testing %s\n", debugstr_w(pTypeInfo
->Name
));
4859 /* FIXME: check wFlags here? */
4860 /* FIXME: we should use a hash table to look this info up using lHash
4861 * instead of an O(n) search */
4862 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
) ||
4863 (pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
))
4865 if (pTypeInfo
->Name
&& !strcmpW(pTypeInfo
->Name
, szName
))
4867 *pDescKind
= DESCKIND_TYPECOMP
;
4868 pBindPtr
->lptcomp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4869 ITypeComp_AddRef(pBindPtr
->lptcomp
);
4870 TRACE("module or enum: %s\n", debugstr_w(szName
));
4875 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_MODULE
) ||
4876 (pTypeInfo
->TypeAttr
.typekind
== TKIND_ENUM
))
4878 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4881 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
4882 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
4884 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
4887 else if (hr
== TYPE_E_TYPEMISMATCH
)
4891 if ((pTypeInfo
->TypeAttr
.typekind
== TKIND_COCLASS
) &&
4892 (pTypeInfo
->TypeAttr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
4894 ITypeComp
*pSubTypeComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
4896 ITypeInfo
*subtypeinfo
;
4898 DESCKIND subdesckind
;
4900 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
4901 &subtypeinfo
, &subdesckind
, &subbindptr
);
4902 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
4904 TYPEDESC tdesc_appobject
;
4905 const VARDESC vardesc_appobject
=
4908 NULL
, /* lpstrSchema */
4923 VAR_STATIC
/* varkind */
4926 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
4927 tdesc_appobject
.vt
= VT_USERDEFINED
;
4929 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
4931 /* cleanup things filled in by Bind call so we can put our
4932 * application object data in there instead */
4933 switch (subdesckind
)
4935 case DESCKIND_FUNCDESC
:
4936 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
4938 case DESCKIND_VARDESC
:
4939 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
4944 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
4946 if (pTypeInfo
->hreftype
== -1)
4947 FIXME("no hreftype for interface %p\n", pTypeInfo
);
4949 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
4953 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
4954 *ppTInfo
= (ITypeInfo
*)pTypeInfo
;
4955 ITypeInfo_AddRef(*ppTInfo
);
4958 else if (hr
== TYPE_E_TYPEMISMATCH
)
4965 TRACE("type mismatch %s\n", debugstr_w(szName
));
4966 return TYPE_E_TYPEMISMATCH
;
4970 TRACE("name not found %s\n", debugstr_w(szName
));
4975 static HRESULT WINAPI
ITypeLibComp_fnBindType(
4979 ITypeInfo
** ppTInfo
,
4980 ITypeComp
** ppTComp
)
4982 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
4985 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
4987 if(!szName
|| !ppTInfo
|| !ppTComp
)
4988 return E_INVALIDARG
;
4990 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
4992 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
4993 /* FIXME: should use lHash to do the search */
4994 if (pTypeInfo
->Name
&& !strcmpiW(pTypeInfo
->Name
, szName
))
4996 TRACE("returning %p\n", pTypeInfo
);
4997 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->lpVtbl
;
4998 ITypeInfo_AddRef(*ppTInfo
);
4999 *ppTComp
= (ITypeComp
*)&pTypeInfo
->lpVtblTypeComp
;
5000 ITypeComp_AddRef(*ppTComp
);
5005 TRACE("not found\n");
5011 static const ITypeCompVtbl tlbtcvt
=
5014 ITypeLibComp_fnQueryInterface
,
5015 ITypeLibComp_fnAddRef
,
5016 ITypeLibComp_fnRelease
,
5018 ITypeLibComp_fnBind
,
5019 ITypeLibComp_fnBindType
5022 /*================== ITypeInfo(2) Methods ===================================*/
5023 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5025 ITypeInfoImpl
*pTypeInfoImpl
;
5027 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5030 pTypeInfoImpl
->lpVtbl
= &tinfvt
;
5031 pTypeInfoImpl
->lpVtblTypeComp
= &tcompvt
;
5032 pTypeInfoImpl
->ref
= 0;
5033 pTypeInfoImpl
->hreftype
= -1;
5034 pTypeInfoImpl
->TypeAttr
.memidConstructor
= MEMBERID_NIL
;
5035 pTypeInfoImpl
->TypeAttr
.memidDestructor
= MEMBERID_NIL
;
5036 list_init(&pTypeInfoImpl
->custdata_list
);
5038 TRACE("(%p)\n", pTypeInfoImpl
);
5039 return pTypeInfoImpl
;
5042 /* ITypeInfo::QueryInterface
5044 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5049 ITypeLibImpl
*This
= (ITypeLibImpl
*)iface
;
5051 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5054 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5055 IsEqualIID(riid
,&IID_ITypeInfo
)||
5056 IsEqualIID(riid
,&IID_ITypeInfo2
))
5060 ITypeInfo_AddRef(iface
);
5061 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5064 TRACE("-- Interface: E_NOINTERFACE\n");
5065 return E_NOINTERFACE
;
5068 /* ITypeInfo::AddRef
5070 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5072 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5073 ULONG ref
= InterlockedIncrement(&This
->ref
);
5075 TRACE("(%p)->ref is %u\n",This
, ref
);
5077 if (ref
== 1 /* incremented from 0 */)
5078 ITypeLib2_AddRef((ITypeLib2
*)This
->pTypeLib
);
5083 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5087 TRACE("destroying ITypeInfo(%p)\n",This
);
5089 SysFreeString(This
->Name
);
5092 SysFreeString(This
->DocString
);
5093 This
->DocString
= NULL
;
5095 SysFreeString(This
->DllName
);
5096 This
->DllName
= NULL
;
5098 for (i
= 0; i
< This
->TypeAttr
.cFuncs
; ++i
)
5100 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5101 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5103 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5104 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5106 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5107 heap_free(elemdesc
->u
.paramdesc
.pparamdescex
);
5109 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5110 SysFreeString(pFInfo
->pParamDesc
[j
].Name
);
5112 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5113 heap_free(pFInfo
->pParamDesc
);
5114 TLB_FreeCustData(&pFInfo
->custdata_list
);
5115 if (!IS_INTRESOURCE(pFInfo
->Entry
) && pFInfo
->Entry
!= (BSTR
)-1)
5116 SysFreeString(pFInfo
->Entry
);
5117 SysFreeString(pFInfo
->HelpString
);
5118 SysFreeString(pFInfo
->Name
);
5120 heap_free(This
->funcdescs
);
5122 for(i
= 0; i
< This
->TypeAttr
.cVars
; ++i
)
5124 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5125 if (pVInfo
->vardesc
.varkind
== VAR_CONST
)
5127 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5128 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5130 TLB_FreeCustData(&pVInfo
->custdata_list
);
5131 SysFreeString(pVInfo
->Name
);
5132 SysFreeString(pVInfo
->HelpString
);
5134 heap_free(This
->vardescs
);
5136 if(This
->impltypes
){
5137 for (i
= 0; i
< This
->TypeAttr
.cImplTypes
; ++i
){
5138 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5139 TLB_FreeCustData(&pImpl
->custdata_list
);
5141 heap_free(This
->impltypes
);
5144 TLB_FreeCustData(&This
->custdata_list
);
5149 /* ITypeInfo::Release
5151 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5153 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5154 ULONG ref
= InterlockedDecrement(&This
->ref
);
5156 TRACE("(%p)->(%u)\n",This
, ref
);
5160 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5161 ITypeLib2_Release((ITypeLib2
*)This
->pTypeLib
);
5162 if (not_attached_to_typelib
)
5164 /* otherwise This will be freed when typelib is freed */
5170 /* ITypeInfo::GetTypeAttr
5172 * Retrieves a TYPEATTR structure that contains the attributes of the type
5176 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5177 LPTYPEATTR
*ppTypeAttr
)
5179 const ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5182 TRACE("(%p)\n",This
);
5184 size
= sizeof(**ppTypeAttr
);
5185 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5186 size
+= TLB_SizeTypeDesc(&This
->TypeAttr
.tdescAlias
, FALSE
);
5188 *ppTypeAttr
= heap_alloc(size
);
5190 return E_OUTOFMEMORY
;
5192 **ppTypeAttr
= This
->TypeAttr
;
5194 if (This
->TypeAttr
.typekind
== TKIND_ALIAS
)
5195 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
,
5196 &This
->TypeAttr
.tdescAlias
, *ppTypeAttr
+ 1);
5198 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5199 /* This should include all the inherited funcs */
5200 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ sizeof(void *);
5201 /* This is always the size of IDispatch's vtbl */
5202 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5203 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5208 /* ITypeInfo::GetTypeComp
5210 * Retrieves the ITypeComp interface for the type description, which enables a
5211 * client compiler to bind to the type description's members.
5214 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5215 ITypeComp
* *ppTComp
)
5217 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5219 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5221 *ppTComp
= (ITypeComp
*)&This
->lpVtblTypeComp
;
5222 ITypeComp_AddRef(*ppTComp
);
5226 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5228 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5229 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5230 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5234 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5237 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5238 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5240 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5241 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5242 *buffer
+= sizeof(PARAMDESCEX
);
5243 *pparamdescex_dest
= *pparamdescex_src
;
5244 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5245 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5246 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5249 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5253 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5255 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5256 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5259 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5263 SIZE_T size
= sizeof(*src
);
5267 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5268 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5269 for (i
= 0; i
< src
->cParams
; i
++)
5271 size
+= sizeof(ELEMDESC
);
5272 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5275 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5276 if (!dest
) return E_OUTOFMEMORY
;
5279 if (dispinterface
) /* overwrite funckind */
5280 dest
->funckind
= FUNC_DISPATCH
;
5281 buffer
= (char *)(dest
+ 1);
5283 dest
->lprgscode
= (SCODE
*)buffer
;
5284 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5285 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5287 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5290 SysFreeString((BSTR
)dest
);
5294 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5295 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5296 for (i
= 0; i
< src
->cParams
; i
++)
5298 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5304 /* undo the above actions */
5305 for (i
= i
- 1; i
>= 0; i
--)
5306 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5307 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5308 SysFreeString((BSTR
)dest
);
5312 /* special treatment for dispinterfaces: this makes functions appear
5313 * to return their [retval] value when it is really returning an
5315 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5317 if (dest
->cParams
&&
5318 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5320 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5321 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5323 ERR("elemdesc should have started with VT_PTR instead of:\n");
5325 dump_ELEMDESC(elemdesc
);
5326 return E_UNEXPECTED
;
5329 /* copy last parameter to the return value. we are using a flat
5330 * buffer so there is no danger of leaking memory in
5332 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5334 /* remove the last parameter */
5338 /* otherwise this function is made to appear to have no return
5340 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5348 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5350 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5352 if (index
>= This
->TypeAttr
.cFuncs
)
5353 return TYPE_E_ELEMENTNOTFOUND
;
5355 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5359 /* internal function to make the inherited interfaces' methods appear
5360 * part of the interface */
5361 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5362 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5364 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5366 UINT implemented_funcs
= 0;
5371 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5375 ITypeInfo
*pSubTypeInfo
;
5378 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5382 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5385 &sub_funcs
, hrefoffset
);
5386 implemented_funcs
+= sub_funcs
;
5387 ITypeInfo_Release(pSubTypeInfo
);
5390 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5394 *funcs
= implemented_funcs
+ This
->TypeAttr
.cFuncs
;
5398 if (index
< implemented_funcs
)
5399 return E_INVALIDARG
;
5400 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5404 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5406 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5409 switch (pTypeDesc
->vt
)
5411 case VT_USERDEFINED
:
5412 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5416 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5419 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5427 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5430 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5431 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5432 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5435 /* ITypeInfo::GetFuncDesc
5437 * Retrieves the FUNCDESC structure that contains information about a
5438 * specified function.
5441 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5442 LPFUNCDESC
*ppFuncDesc
)
5444 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5445 const FUNCDESC
*internal_funcdesc
;
5447 UINT hrefoffset
= 0;
5449 TRACE("(%p) index %d\n", This
, index
);
5451 if (This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5452 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5453 &internal_funcdesc
, NULL
,
5456 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5457 &internal_funcdesc
);
5460 WARN("description for function %d not found\n", index
);
5464 hr
= TLB_AllocAndInitFuncDesc(
5467 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
5469 if ((This
->TypeAttr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5470 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5472 TRACE("-- 0x%08x\n", hr
);
5476 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5480 SIZE_T size
= sizeof(*src
);
5483 if (src
->lpstrSchema
) size
+= (strlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
5484 if (src
->varkind
== VAR_CONST
)
5485 size
+= sizeof(VARIANT
);
5486 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
5488 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
5489 if (!dest
) return E_OUTOFMEMORY
;
5492 buffer
= (char *)(dest
+ 1);
5493 if (src
->lpstrSchema
)
5496 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
5497 len
= strlenW(src
->lpstrSchema
);
5498 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
5499 buffer
+= (len
+ 1) * sizeof(WCHAR
);
5502 if (src
->varkind
== VAR_CONST
)
5506 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
5507 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
5508 buffer
+= sizeof(VARIANT
);
5509 VariantInit(dest
->u
.lpvarValue
);
5510 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
5513 SysFreeString((BSTR
)dest
);
5517 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
5520 if (src
->varkind
== VAR_CONST
)
5521 VariantClear(dest
->u
.lpvarValue
);
5522 SysFreeString((BSTR
)dest
);
5529 /* ITypeInfo::GetVarDesc
5531 * Retrieves a VARDESC structure that describes the specified variable.
5534 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
5535 LPVARDESC
*ppVarDesc
)
5537 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5538 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
5540 TRACE("(%p) index %d\n", This
, index
);
5542 if(index
>= This
->TypeAttr
.cVars
)
5543 return TYPE_E_ELEMENTNOTFOUND
;
5545 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
5548 /* ITypeInfo_GetNames
5550 * Retrieves the variable with the specified member ID (or the name of the
5551 * property or method and its parameters) that correspond to the specified
5554 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
5555 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
5557 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5558 const TLBFuncDesc
*pFDesc
;
5559 const TLBVarDesc
*pVDesc
;
5561 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
5562 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
5565 /* function found, now return function and parameter names */
5566 for(i
=0; i
<cMaxNames
&& i
<= pFDesc
->funcdesc
.cParams
; i
++)
5569 *rgBstrNames
=SysAllocString(pFDesc
->Name
);
5571 rgBstrNames
[i
]=SysAllocString(pFDesc
->pParamDesc
[i
-1].Name
);
5577 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
5580 *rgBstrNames
=SysAllocString(pVDesc
->Name
);
5585 if(This
->impltypes
&&
5586 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
5587 /* recursive search */
5590 result
=ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
,
5592 if(SUCCEEDED(result
))
5594 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
5595 ITypeInfo_Release(pTInfo
);
5598 WARN("Could not search inherited interface!\n");
5602 WARN("no names found\n");
5605 return TYPE_E_ELEMENTNOTFOUND
;
5612 /* ITypeInfo::GetRefTypeOfImplType
5614 * If a type description describes a COM class, it retrieves the type
5615 * description of the implemented interface types. For an interface,
5616 * GetRefTypeOfImplType returns the type information for inherited interfaces,
5620 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
5625 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5628 TRACE("(%p) index %d\n", This
, index
);
5629 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
5633 /* only valid on dual interfaces;
5634 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
5636 if( This
->TypeAttr
.typekind
!= TKIND_DISPATCH
) return E_INVALIDARG
;
5638 if (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
)
5644 hr
= TYPE_E_ELEMENTNOTFOUND
;
5647 else if(index
== 0 && This
->TypeAttr
.typekind
== TKIND_DISPATCH
)
5649 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
5650 *pRefType
= This
->pTypeLib
->dispatch_href
;
5654 if(index
>= This
->TypeAttr
.cImplTypes
)
5655 hr
= TYPE_E_ELEMENTNOTFOUND
;
5657 *pRefType
= This
->impltypes
[index
].hRef
;
5663 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
5665 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
5671 /* ITypeInfo::GetImplTypeFlags
5673 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
5674 * or base interface in a type description.
5676 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
5677 UINT index
, INT
*pImplTypeFlags
)
5679 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5681 TRACE("(%p) index %d\n", This
, index
);
5683 if(This
->TypeAttr
.typekind
== TKIND_DISPATCH
&& index
== 0){
5684 *pImplTypeFlags
= 0;
5688 if(index
>= This
->TypeAttr
.cImplTypes
)
5689 return TYPE_E_ELEMENTNOTFOUND
;
5691 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
5697 * Maps between member names and member IDs, and parameter names and
5700 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
5701 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
5703 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
5704 const TLBVarDesc
*pVDesc
;
5708 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
5711 /* init out parameters in case of failure */
5712 for (i
= 0; i
< cNames
; i
++)
5713 pMemId
[i
] = MEMBERID_NIL
;
5715 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
) {
5717 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
5718 if(!lstrcmpiW(*rgszNames
, pFDesc
->Name
)) {
5719 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
5720 for(i
=1; i
< cNames
; i
++){
5721 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
5722 if(!lstrcmpiW(rgszNames
[i
],pFDesc
->pParamDesc
[j
].Name
))
5724 if( j
<pFDesc
->funcdesc
.cParams
)
5727 ret
=DISP_E_UNKNOWNNAME
;
5729 TRACE("-- 0x%08x\n", ret
);
5733 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->TypeAttr
.cVars
, *rgszNames
);
5736 *pMemId
= pVDesc
->vardesc
.memid
;
5739 /* not found, see if it can be found in an inherited interface */
5740 if(This
->impltypes
) {
5741 /* recursive search */
5743 ret
=ITypeInfo_GetRefTypeInfo(iface
,
5744 This
->impltypes
[0].hRef
, &pTInfo
);
5746 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
5747 ITypeInfo_Release(pTInfo
);
5750 WARN("Could not search inherited interface!\n");
5752 WARN("no names found\n");
5753 return DISP_E_UNKNOWNNAME
;
5759 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
5760 __ASM_GLOBAL_FUNC( call_method
,
5762 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
5763 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
5764 "movl %esp,%ebp\n\t"
5765 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
5767 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
5769 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
5770 "movl 12(%ebp),%edx\n\t"
5771 "movl %esp,%edi\n\t"
5774 "subl %edx,%edi\n\t"
5775 "andl $~15,%edi\n\t"
5776 "movl %edi,%esp\n\t"
5777 "movl 12(%ebp),%ecx\n\t"
5778 "movl 16(%ebp),%esi\n\t"
5781 "1:\tcall *8(%ebp)\n\t"
5782 "subl %esp,%edi\n\t"
5783 "movl 20(%ebp),%ecx\n\t"
5784 "movl %edi,(%ecx)\n\t"
5785 "leal -8(%ebp),%esp\n\t"
5787 __ASM_CFI(".cfi_same_value %edi\n\t")
5789 __ASM_CFI(".cfi_same_value %esi\n\t")
5791 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
5792 __ASM_CFI(".cfi_same_value %ebp\n\t")
5795 /* same function but returning floating point */
5796 static double (* const call_double_method
)(void*,int,const DWORD
*,int*) = (void *)call_method
;
5798 /* ITypeInfo::Invoke
5800 * Invokes a method, or accesses a property of an object, that implements the
5801 * interface described by the type description.
5804 _invoke(FARPROC func
,CALLCONV callconv
, int nrargs
, DWORD
*args
) {
5808 if (TRACE_ON(ole
)) {
5810 TRACE("Calling %p(",func
);
5811 for (i
=0;i
<min(nrargs
,30);i
++) TRACE("%08x,",args
[i
]);
5812 if (nrargs
> 30) TRACE("...");
5819 res
= call_method( func
, nrargs
, args
, &stack_offset
);
5822 FIXME("unsupported calling convention %d\n",callconv
);
5826 TRACE("returns %08x\n",res
);
5830 #elif defined(__x86_64__)
5832 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
5833 __ASM_GLOBAL_FUNC( call_method
,
5835 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
5836 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
5837 "movq %rsp,%rbp\n\t"
5838 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
5840 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
5842 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
5843 "movq %rcx,%rax\n\t"
5846 "cmovgq %rdx,%rcx\n\t"
5847 "leaq 0(,%rcx,8),%rdx\n\t"
5848 "subq %rdx,%rsp\n\t"
5849 "andq $~15,%rsp\n\t"
5850 "movq %rsp,%rdi\n\t"
5853 "movq 0(%rsp),%rcx\n\t"
5854 "movq 8(%rsp),%rdx\n\t"
5855 "movq 16(%rsp),%r8\n\t"
5856 "movq 24(%rsp),%r9\n\t"
5857 "movq %rcx,%xmm0\n\t"
5858 "movq %rdx,%xmm1\n\t"
5859 "movq %r8,%xmm2\n\t"
5860 "movq %r9,%xmm3\n\t"
5862 "leaq -16(%rbp),%rsp\n\t"
5864 __ASM_CFI(".cfi_same_value %rdi\n\t")
5866 __ASM_CFI(".cfi_same_value %rsi\n\t")
5867 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
5869 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
5870 __ASM_CFI(".cfi_same_value %rbp\n\t")
5873 /* same function but returning floating point */
5874 static double (CDECL
* const call_double_method
)(void*,int,const DWORD_PTR
*) = (void *)call_method
;
5876 #endif /* __x86_64__ */
5878 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5881 ITypeInfo
*tinfo2
= NULL
;
5882 TYPEATTR
*tattr
= NULL
;
5884 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
5887 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
5889 tdesc
->u
.hreftype
, hr
);
5892 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
5895 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
5896 ITypeInfo_Release(tinfo2
);
5900 switch (tattr
->typekind
)
5907 tdesc
= &tattr
->tdescAlias
;
5908 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
5911 case TKIND_INTERFACE
:
5912 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
5918 case TKIND_DISPATCH
:
5927 FIXME("TKIND_RECORD unhandled.\n");
5932 FIXME("TKIND_UNION unhandled.\n");
5937 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
5941 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
5942 ITypeInfo_Release(tinfo2
);
5946 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
5950 /* enforce only one level of pointer indirection */
5951 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
5953 tdesc
= tdesc
->u
.lptdesc
;
5955 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
5956 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
5957 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
5958 if ((tdesc
->vt
== VT_USERDEFINED
) ||
5959 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
5961 VARTYPE vt_userdefined
= 0;
5962 const TYPEDESC
*tdesc_userdefined
= tdesc
;
5963 if (tdesc
->vt
== VT_PTR
)
5965 vt_userdefined
= VT_BYREF
;
5966 tdesc_userdefined
= tdesc
->u
.lptdesc
;
5968 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
5970 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
5971 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
5973 *vt
|= vt_userdefined
;
5985 case VT_USERDEFINED
:
5986 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
5993 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
5994 hr
= DISP_E_BADVARTYPE
;
5998 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6013 /***********************************************************************
6014 * DispCallFunc (OLEAUT32.@)
6016 * Invokes a function of the specified calling convention, passing the
6017 * specified arguments and returns the result.
6020 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6021 * oVft [I] The offset in the vtable. See notes.
6022 * cc [I] Calling convention of the function to call.
6023 * vtReturn [I] The return type of the function.
6024 * cActuals [I] Number of parameters.
6025 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6026 * prgpvarg [I] The arguments to pass.
6027 * pvargResult [O] The return value of the function. Can be NULL.
6031 * Failure: HRESULT code.
6034 * The HRESULT return value of this function is not affected by the return
6035 * value of the user supplied function, which is returned in pvargResult.
6037 * If pvInstance is NULL then a non-object function is to be called and oVft
6038 * is the address of the function to call.
6040 * The cc parameter can be one of the following values:
6053 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6054 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6057 int argspos
, stack_offset
;
6062 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6063 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6064 pvargResult
, V_VT(pvargResult
));
6066 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6068 FIXME("unsupported calling convention %d\n",cc
);
6069 return E_INVALIDARG
;
6072 /* maximum size for an argument is sizeof(VARIANT) */
6073 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6075 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6079 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6080 func
= vtable
[oVft
/sizeof(void *)];
6081 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6083 else func
= (void *)oVft
;
6085 for (i
= 0; i
< cActuals
; i
++)
6087 VARIANT
*arg
= prgpvarg
[i
];
6098 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6099 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6103 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6104 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6106 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6107 args
[argspos
++] = V_BOOL(arg
);
6110 args
[argspos
++] = V_UI4(arg
);
6113 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6120 call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6123 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6127 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6131 args
[0] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6132 call_method( func
, argspos
, args
, &stack_offset
);
6137 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6140 V_UI4(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1, &stack_offset
);
6144 if (stack_offset
&& cc
== CC_STDCALL
)
6146 WARN( "stack pointer off by %d\n", stack_offset
);
6147 return DISP_E_BADCALLEE
;
6149 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6150 TRACE("retval: "); dump_Variant(pvargResult
);
6153 #elif defined(__x86_64__)
6159 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6160 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6161 pvargResult
, V_VT(pvargResult
));
6163 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6165 FIXME("unsupported calling convention %d\n",cc
);
6166 return E_INVALIDARG
;
6169 /* maximum size for an argument is sizeof(DWORD_PTR) */
6170 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6172 /* start at 1 in case we need to pass a pointer to the return value as arg 0 */
6176 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6177 func
= vtable
[oVft
/sizeof(void *)];
6178 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6180 else func
= (void *)oVft
;
6182 for (i
= 0; i
< cActuals
; i
++)
6184 VARIANT
*arg
= prgpvarg
[i
];
6190 args
[argspos
++] = (ULONG_PTR
)arg
;
6192 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6193 args
[argspos
++] = V_BOOL(arg
);
6196 args
[argspos
++] = V_UI8(arg
);
6199 TRACE("arg %u: type %d\n",i
,prgvt
[i
]);
6206 V_R4(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6210 V_R8(pvargResult
) = call_double_method( func
, argspos
- 1, args
+ 1 );
6214 args
[0] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6215 call_method( func
, argspos
, args
);
6218 V_UI8(pvargResult
) = call_method( func
, argspos
- 1, args
+ 1 );
6222 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6223 TRACE("retval: "); dump_Variant(pvargResult
);
6227 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6228 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6233 #define INVBUF_ELEMENT_SIZE \
6234 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
6235 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
6236 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
6237 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
6238 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
6239 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
6240 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
6241 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
6243 static HRESULT WINAPI
ITypeInfo_fnInvoke(
6248 DISPPARAMS
*pDispParams
,
6249 VARIANT
*pVarResult
,
6250 EXCEPINFO
*pExcepInfo
,
6253 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6255 unsigned int var_index
;
6258 const TLBFuncDesc
*pFuncInfo
;
6261 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
6262 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
6265 if( This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
6266 return DISP_E_MEMBERNOTFOUND
;
6270 ERR("NULL pDispParams not allowed\n");
6271 return E_INVALIDARG
;
6274 dump_DispParms(pDispParams
);
6276 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
6278 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
6279 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
6280 return E_INVALIDARG
;
6283 /* we do this instead of using GetFuncDesc since it will return a fake
6284 * FUNCDESC for dispinterfaces and we want the real function description */
6285 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
6286 pFuncInfo
= &This
->funcdescs
[fdc
];
6287 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
6288 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
6289 (pFuncInfo
->funcdesc
.wFuncFlags
& FUNCFLAG_FRESTRICTED
) == 0)
6293 if (fdc
< This
->TypeAttr
.cFuncs
) {
6294 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
6298 TRACE("invoking:\n");
6299 dump_TLBFuncDescOne(pFuncInfo
);
6302 switch (func_desc
->funckind
) {
6303 case FUNC_PUREVIRTUAL
:
6304 case FUNC_VIRTUAL
: {
6305 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
6307 VARIANT retval
; /* pointer for storing byref retvals in */
6308 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
6309 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
6310 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
6311 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
6312 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
6313 UINT vargs_converted
=0;
6317 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
6319 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
6321 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
6322 hres
= DISP_E_PARAMNOTFOUND
;
6327 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
6329 ERR("functions with the vararg attribute do not support named arguments\n");
6330 hres
= DISP_E_NONAMEDARGS
;
6334 for (i
= 0; i
< func_desc
->cParams
; i
++)
6336 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
6337 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
6342 TRACE("changing args\n");
6343 for (i
= 0; i
< func_desc
->cParams
; i
++)
6345 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6346 VARIANTARG
*src_arg
;
6348 if (wParamFlags
& PARAMFLAG_FLCID
)
6351 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6353 V_I4(arg
) = This
->pTypeLib
->lcid
;
6362 for (j
= 0; j
< cNamedArgs
; j
++)
6363 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
6365 src_arg
= &pDispParams
->rgvarg
[j
];
6370 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
6372 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6376 if (wParamFlags
& PARAMFLAG_FRETVAL
)
6378 /* under most conditions the caller is not allowed to
6379 * pass in a dispparam arg in the index of what would be
6380 * the retval parameter. however, there is an exception
6381 * where the extra parameter is used in an extra
6382 * IDispatch::Invoke below */
6383 if ((i
< pDispParams
->cArgs
) &&
6384 ((func_desc
->cParams
!= 1) || !pVarResult
||
6385 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
6387 hres
= DISP_E_BADPARAMCOUNT
;
6391 /* note: this check is placed so that if the caller passes
6392 * in a VARIANTARG for the retval we just ignore it, like
6394 if (i
== func_desc
->cParams
- 1)
6397 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6398 memset(arg
, 0, sizeof(*arg
));
6399 V_VT(arg
) = rgvt
[i
];
6400 memset(&retval
, 0, sizeof(retval
));
6401 V_BYREF(arg
) = &retval
;
6405 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
6406 hres
= E_UNEXPECTED
;
6412 dump_Variant(src_arg
);
6414 if (rgvt
[i
] == VT_VARIANT
)
6415 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
6416 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
6418 if (rgvt
[i
] == V_VT(src_arg
))
6419 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
6422 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6423 if (wParamFlags
& PARAMFLAG_FIN
)
6424 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
6425 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
6427 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6429 else if (rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) && func_desc
->cParamsOpt
< 0 && i
== func_desc
->cParams
-1)
6432 SAFEARRAYBOUND bound
;
6436 bound
.cElements
= pDispParams
->cArgs
-i
;
6437 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
6439 ERR("SafeArrayCreate failed\n");
6442 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6445 ERR("SafeArrayAccessData failed with %x\n", hres
);
6448 for (j
= 0; j
< bound
.cElements
; j
++)
6449 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
6450 hres
= SafeArrayUnaccessData(a
);
6453 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6456 V_ARRAY(&rgvarg
[i
]) = a
;
6457 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6459 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
6461 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6462 if (wParamFlags
& PARAMFLAG_FIN
)
6463 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
6465 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
6466 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
6467 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6469 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
6471 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
6472 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6476 /* FIXME: this doesn't work for VT_BYREF arguments if
6477 * they are not the same type as in the paramdesc */
6478 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
6479 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
6480 V_VT(&rgvarg
[i
]) = rgvt
[i
];
6485 ERR("failed to convert param %d to %s%s from %s%s\n", i
,
6486 debugstr_vt(rgvt
[i
]), debugstr_vf(rgvt
[i
]),
6487 debugstr_VT(src_arg
), debugstr_VF(src_arg
));
6490 prgpvarg
[i
] = &rgvarg
[i
];
6492 else if (wParamFlags
& PARAMFLAG_FOPT
)
6495 arg
= prgpvarg
[i
] = &rgvarg
[i
];
6496 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6498 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
6504 VARIANTARG
*missing_arg
;
6505 /* if the function wants a pointer to a variant then
6506 * set that up, otherwise just pass the VT_ERROR in
6507 * the argument by value */
6508 if (rgvt
[i
] & VT_BYREF
)
6510 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
6511 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
6512 V_VARIANTREF(arg
) = missing_arg
;
6516 V_VT(missing_arg
) = VT_ERROR
;
6517 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
6522 hres
= DISP_E_BADPARAMCOUNT
;
6526 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6528 /* VT_VOID is a special case for return types, so it is not
6529 * handled in the general function */
6530 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
6531 V_VT(&varresult
) = VT_EMPTY
;
6534 V_VT(&varresult
) = 0;
6535 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
6536 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
6539 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
, func_desc
->callconv
,
6540 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
6541 prgpvarg
, &varresult
);
6543 vargs_converted
= 0;
6545 for (i
= 0; i
< func_desc
->cParams
; i
++)
6547 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
6548 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
6550 if (wParamFlags
& PARAMFLAG_FLCID
)
6552 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
6556 TRACE("[retval] value: ");
6557 dump_Variant(prgpvarg
[i
]);
6562 VariantInit(pVarResult
);
6563 /* deref return value */
6564 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
6567 VARIANT_ClearInd(prgpvarg
[i
]);
6569 else if (vargs_converted
< pDispParams
->cArgs
)
6571 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
6572 if (wParamFlags
& PARAMFLAG_FOUT
)
6574 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
6576 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
6580 ERR("failed to convert param %d to vt %d\n", i
,
6581 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
6586 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
6587 func_desc
->cParamsOpt
< 0 &&
6588 i
== func_desc
->cParams
-1)
6590 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
6593 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
6596 ERR("SafeArrayGetUBound failed with %x\n", hres
);
6599 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
6602 ERR("SafeArrayAccessData failed with %x\n", hres
);
6605 for (j
= 0; j
<= ubound
; j
++)
6606 VariantClear(&v
[j
]);
6607 hres
= SafeArrayUnaccessData(a
);
6610 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
6614 VariantClear(&rgvarg
[i
]);
6617 else if (wParamFlags
& PARAMFLAG_FOPT
)
6619 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
6620 VariantClear(&rgvarg
[i
]);
6623 VariantClear(&missing_arg
[i
]);
6626 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
6628 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
6629 hres
= DISP_E_EXCEPTION
;
6632 IErrorInfo
*pErrorInfo
;
6633 pExcepInfo
->scode
= V_ERROR(&varresult
);
6634 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
6636 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
6637 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
6638 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
6639 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
6641 IErrorInfo_Release(pErrorInfo
);
6645 if (V_VT(&varresult
) != VT_ERROR
)
6647 TRACE("varresult value: ");
6648 dump_Variant(&varresult
);
6652 VariantClear(pVarResult
);
6653 *pVarResult
= varresult
;
6656 VariantClear(&varresult
);
6659 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
6660 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
6661 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
6662 (pDispParams
->cArgs
!= 0))
6664 if (V_VT(pVarResult
) == VT_DISPATCH
)
6666 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
6667 /* Note: not VariantClear; we still need the dispatch
6668 * pointer to be valid */
6669 VariantInit(pVarResult
);
6670 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
6671 GetSystemDefaultLCID(), INVOKE_PROPERTYGET
,
6672 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
6673 IDispatch_Release(pDispatch
);
6677 VariantClear(pVarResult
);
6678 hres
= DISP_E_NOTACOLLECTION
;
6686 case FUNC_DISPATCH
: {
6689 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
6690 if (SUCCEEDED(hres
)) {
6691 FIXME("Calling Invoke in IDispatch iface. untested!\n");
6692 hres
= IDispatch_Invoke(
6693 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
6694 pVarResult
,pExcepInfo
,pArgErr
6697 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
6698 IDispatch_Release(disp
);
6700 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
6704 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
6709 TRACE("-- 0x%08x\n", hres
);
6712 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
6715 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
6716 if(FAILED(hres
)) return hres
;
6718 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
6719 dump_VARDESC(var_desc
);
6720 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
6724 /* not found, look for it in inherited interfaces */
6725 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
6726 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
6727 if(This
->impltypes
) {
6728 /* recursive search */
6730 hres
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6731 if(SUCCEEDED(hres
)){
6732 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
6733 ITypeInfo_Release(pTInfo
);
6736 WARN("Could not search inherited interface!\n");
6739 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
6740 return DISP_E_MEMBERNOTFOUND
;
6743 /* ITypeInfo::GetDocumentation
6745 * Retrieves the documentation string, the complete Help file name and path,
6746 * and the context ID for the Help topic for a specified type description.
6748 * (Can be tested by the Visual Basic Editor in Word for instance.)
6750 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
6751 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
6752 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
6754 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6755 const TLBFuncDesc
*pFDesc
;
6756 const TLBVarDesc
*pVDesc
;
6757 TRACE("(%p) memid %d Name(%p) DocString(%p)"
6758 " HelpContext(%p) HelpFile(%p)\n",
6759 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6760 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
6762 *pBstrName
=SysAllocString(This
->Name
);
6764 *pBstrDocString
=SysAllocString(This
->DocString
);
6766 *pdwHelpContext
=This
->dwHelpContext
;
6768 *pBstrHelpFile
=SysAllocString(This
->DocString
);/* FIXME */
6770 }else {/* for a member */
6771 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
6774 *pBstrName
= SysAllocString(pFDesc
->Name
);
6776 *pBstrDocString
=SysAllocString(pFDesc
->HelpString
);
6778 *pdwHelpContext
=pFDesc
->helpcontext
;
6781 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
6784 *pBstrName
= SysAllocString(pVDesc
->Name
);
6786 *pBstrDocString
=SysAllocString(pVDesc
->HelpString
);
6788 *pdwHelpContext
=pVDesc
->HelpContext
;
6793 if(This
->impltypes
&&
6794 (This
->TypeAttr
.typekind
==TKIND_INTERFACE
|| This
->TypeAttr
.typekind
==TKIND_DISPATCH
)) {
6795 /* recursive search */
6798 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
,
6800 if(SUCCEEDED(result
)) {
6801 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
6802 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
6803 ITypeInfo_Release(pTInfo
);
6806 WARN("Could not search inherited interface!\n");
6809 WARN("member %d not found\n", memid
);
6810 return TYPE_E_ELEMENTNOTFOUND
;
6813 /* ITypeInfo::GetDllEntry
6815 * Retrieves a description or specification of an entry point for a function
6818 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
6819 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
6822 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6823 const TLBFuncDesc
*pFDesc
;
6825 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
6827 if (pBstrDllName
) *pBstrDllName
= NULL
;
6828 if (pBstrName
) *pBstrName
= NULL
;
6829 if (pwOrdinal
) *pwOrdinal
= 0;
6831 if (This
->TypeAttr
.typekind
!= TKIND_MODULE
)
6832 return TYPE_E_BADMODULEKIND
;
6834 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
6836 dump_TypeInfo(This
);
6838 dump_TLBFuncDescOne(pFDesc
);
6841 *pBstrDllName
= SysAllocString(This
->DllName
);
6843 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
6845 *pBstrName
= SysAllocString(pFDesc
->Entry
);
6853 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
6856 return TYPE_E_ELEMENTNOTFOUND
;
6859 /* internal function to make the inherited interfaces' methods appear
6860 * part of the interface */
6861 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
6862 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
6864 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6867 TRACE("%p, 0x%x\n", iface
, *hRefType
);
6869 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
6871 ITypeInfo
*pSubTypeInfo
;
6873 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
6877 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
6879 ITypeInfo_Release(pSubTypeInfo
);
6883 *hRefType
-= DISPATCH_HREF_OFFSET
;
6885 if (!(*hRefType
& DISPATCH_HREF_MASK
))
6886 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
6891 /* ITypeInfo::GetRefTypeInfo
6893 * If a type description references other type descriptions, it retrieves
6894 * the referenced type descriptions.
6896 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
6899 ITypeInfo
**ppTInfo
)
6901 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
6902 HRESULT result
= E_FAIL
;
6904 if ((This
->hreftype
!= -1) && (This
->hreftype
== hRefType
))
6906 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
6907 ITypeInfo_AddRef(*ppTInfo
);
6910 else if (hRefType
== -1 &&
6911 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
) &&
6912 (This
->TypeAttr
.wTypeFlags
& TYPEFLAG_FDUAL
))
6914 /* when we meet a DUAL dispinterface, we must create the interface
6917 ITypeInfoImpl
*pTypeInfoImpl
= ITypeInfoImpl_Constructor();
6920 /* the interface version contains the same information as the dispinterface
6921 * copy the contents of the structs.
6923 *pTypeInfoImpl
= *This
;
6924 pTypeInfoImpl
->ref
= 0;
6926 /* change the type to interface */
6927 pTypeInfoImpl
->TypeAttr
.typekind
= TKIND_INTERFACE
;
6929 *ppTInfo
= (ITypeInfo
*) pTypeInfoImpl
;
6931 /* the AddRef implicitly adds a reference to the parent typelib, which
6932 * stops the copied data from being destroyed until the new typeinfo's
6933 * refcount goes to zero, but we need to signal to the new instance to
6934 * not free its data structures when it is destroyed */
6935 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
6937 ITypeInfo_AddRef(*ppTInfo
);
6941 } else if ((hRefType
!= -1) && (hRefType
& DISPATCH_HREF_MASK
) &&
6942 (This
->TypeAttr
.typekind
== TKIND_DISPATCH
))
6944 HREFTYPE href_dispatch
= hRefType
;
6945 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
6947 TLBRefType
*ref_type
;
6948 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
6950 if(ref_type
->reference
== hRefType
)
6953 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
6955 FIXME("Can't find pRefType for ref %x\n", hRefType
);
6958 if(hRefType
!= -1) {
6959 ITypeLib
*pTLib
= NULL
;
6961 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
6963 result
= ITypeInfo_GetContainingTypeLib(iface
, &pTLib
, &Index
);
6965 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
6966 TRACE("typeinfo in imported typelib that is already loaded\n");
6967 pTLib
= (ITypeLib
*)ref_type
->pImpTLInfo
->pImpTypeLib
;
6968 ITypeLib2_AddRef(pTLib
);
6971 TRACE("typeinfo in imported typelib that isn't already loaded\n");
6972 result
= LoadRegTypeLib( &ref_type
->pImpTLInfo
->guid
,
6973 ref_type
->pImpTLInfo
->wVersionMajor
,
6974 ref_type
->pImpTLInfo
->wVersionMinor
,
6975 ref_type
->pImpTLInfo
->lcid
,
6978 if(FAILED(result
)) {
6979 BSTR libnam
=SysAllocString(ref_type
->pImpTLInfo
->name
);
6980 result
=LoadTypeLib(libnam
, &pTLib
);
6981 SysFreeString(libnam
);
6983 if(SUCCEEDED(result
)) {
6984 ref_type
->pImpTLInfo
->pImpTypeLib
= (ITypeLibImpl
*)pTLib
;
6985 ITypeLib2_AddRef(pTLib
);
6989 if(SUCCEEDED(result
)) {
6990 if(ref_type
->index
== TLB_REF_USE_GUID
)
6991 result
= ITypeLib2_GetTypeInfoOfGuid(pTLib
,
6995 result
= ITypeLib2_GetTypeInfo(pTLib
, ref_type
->index
,
6999 ITypeLib2_Release(pTLib
);
7004 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7005 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7009 /* ITypeInfo::AddressOfMember
7011 * Retrieves the addresses of static functions or variables, such as those
7014 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7015 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7017 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7023 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7025 hr
= ITypeInfo_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7029 module
= LoadLibraryW(dll
);
7032 ERR("couldn't load %s\n", debugstr_w(dll
));
7034 SysFreeString(entry
);
7035 return STG_E_FILENOTFOUND
;
7037 /* FIXME: store library somewhere where we can free it */
7042 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7043 entryA
= heap_alloc(len
);
7044 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7046 *ppv
= GetProcAddress(module
, entryA
);
7048 ERR("function not found %s\n", debugstr_a(entryA
));
7054 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7056 ERR("function not found %d\n", ordinal
);
7060 SysFreeString(entry
);
7063 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7068 /* ITypeInfo::CreateInstance
7070 * Creates a new instance of a type that describes a component object class
7073 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7074 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7076 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7080 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7086 WARN("Not able to aggregate\n");
7087 return CLASS_E_NOAGGREGATION
;
7090 hr
= ITypeInfo_GetTypeAttr(iface
, &pTA
);
7091 if(FAILED(hr
)) return hr
;
7093 if(pTA
->typekind
!= TKIND_COCLASS
)
7095 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7101 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7104 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7105 TRACE("GetActiveObject rets %08x\n", hr
);
7108 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
7109 IUnknown_Release(pUnk
);
7114 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
7115 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
7119 ITypeInfo_ReleaseTypeAttr(iface
, pTA
);
7123 /* ITypeInfo::GetMops
7125 * Retrieves marshalling information.
7127 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
7130 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7131 FIXME("(%p %d) stub!\n", This
, memid
);
7136 /* ITypeInfo::GetContainingTypeLib
7138 * Retrieves the containing type library and the index of the type description
7139 * within that type library.
7141 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
7142 ITypeLib
* *ppTLib
, UINT
*pIndex
)
7144 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7146 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
7148 *pIndex
=This
->index
;
7149 TRACE("returning pIndex=%d\n", *pIndex
);
7153 *ppTLib
=(LPTYPELIB
)(This
->pTypeLib
);
7154 ITypeLib2_AddRef(*ppTLib
);
7155 TRACE("returning ppTLib=%p\n", *ppTLib
);
7161 /* ITypeInfo::ReleaseTypeAttr
7163 * Releases a TYPEATTR previously returned by GetTypeAttr.
7166 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
7167 TYPEATTR
* pTypeAttr
)
7169 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7170 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
7171 heap_free(pTypeAttr
);
7174 /* ITypeInfo::ReleaseFuncDesc
7176 * Releases a FUNCDESC previously returned by GetFuncDesc. *
7178 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
7180 FUNCDESC
*pFuncDesc
)
7182 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7185 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
7187 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
7188 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
7189 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
7191 SysFreeString((BSTR
)pFuncDesc
);
7194 /* ITypeInfo::ReleaseVarDesc
7196 * Releases a VARDESC previously returned by GetVarDesc.
7198 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
7201 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7202 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
7204 TLB_FreeElemDesc(&pVarDesc
->elemdescVar
);
7205 if (pVarDesc
->varkind
== VAR_CONST
)
7206 VariantClear(pVarDesc
->u
.lpvarValue
);
7207 SysFreeString((BSTR
)pVarDesc
);
7210 /* ITypeInfo2::GetTypeKind
7212 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
7215 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
7216 TYPEKIND
*pTypeKind
)
7218 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7219 *pTypeKind
=This
->TypeAttr
.typekind
;
7220 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
7224 /* ITypeInfo2::GetTypeFlags
7226 * Returns the type flags without any allocations. This returns a DWORD type
7227 * flag, which expands the type flags without growing the TYPEATTR (type
7231 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
7233 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7234 *pTypeFlags
=This
->TypeAttr
.wTypeFlags
;
7235 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
7239 /* ITypeInfo2::GetFuncIndexOfMemId
7240 * Binds to a specific member based on a known DISPID, where the member name
7241 * is not known (for example, when binding to a default member).
7244 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
7245 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
7247 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7251 for (fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
7252 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
7253 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
7256 if(fdc
< This
->TypeAttr
.cFuncs
) {
7260 result
= TYPE_E_ELEMENTNOTFOUND
;
7262 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
7263 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
7267 /* TypeInfo2::GetVarIndexOfMemId
7269 * Binds to a specific member based on a known DISPID, where the member name
7270 * is not known (for example, when binding to a default member).
7273 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
7274 MEMBERID memid
, UINT
*pVarIndex
)
7276 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7277 TLBVarDesc
*pVarInfo
;
7279 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
7281 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
7283 return TYPE_E_ELEMENTNOTFOUND
;
7285 *pVarIndex
= (pVarInfo
- This
->vardescs
);
7290 /* ITypeInfo2::GetCustData
7292 * Gets the custom data
7294 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
7299 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7300 TLBCustData
*pCData
;
7302 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7304 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
7306 VariantInit( pVarVal
);
7308 VariantCopy( pVarVal
, &pCData
->data
);
7310 VariantClear( pVarVal
);
7314 /* ITypeInfo2::GetFuncCustData
7316 * Gets the custom data
7318 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
7324 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7325 TLBCustData
*pCData
;
7326 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7328 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7330 if(index
>= This
->TypeAttr
.cFuncs
)
7331 return TYPE_E_ELEMENTNOTFOUND
;
7333 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
7335 return TYPE_E_ELEMENTNOTFOUND
;
7337 VariantInit(pVarVal
);
7338 VariantCopy(pVarVal
, &pCData
->data
);
7343 /* ITypeInfo2::GetParamCustData
7345 * Gets the custom data
7347 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
7354 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7355 TLBCustData
*pCData
;
7356 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7358 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
7359 debugstr_guid(guid
), pVarVal
);
7361 if(indexFunc
>= This
->TypeAttr
.cFuncs
)
7362 return TYPE_E_ELEMENTNOTFOUND
;
7364 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7365 return TYPE_E_ELEMENTNOTFOUND
;
7367 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
7369 return TYPE_E_ELEMENTNOTFOUND
;
7371 VariantInit(pVarVal
);
7372 VariantCopy(pVarVal
, &pCData
->data
);
7377 /* ITypeInfo2::GetVarCustData
7379 * Gets the custom data
7381 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
7387 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7388 TLBCustData
*pCData
;
7389 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
7391 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
7393 if(index
>= This
->TypeAttr
.cVars
)
7394 return TYPE_E_ELEMENTNOTFOUND
;
7396 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
7398 return TYPE_E_ELEMENTNOTFOUND
;
7400 VariantInit(pVarVal
);
7401 VariantCopy(pVarVal
, &pCData
->data
);
7406 /* ITypeInfo2::GetImplCustData
7408 * Gets the custom data
7410 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
7416 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7417 TLBCustData
*pCData
;
7418 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7420 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
7422 if(index
>= This
->TypeAttr
.cImplTypes
)
7423 return TYPE_E_ELEMENTNOTFOUND
;
7425 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
7427 return TYPE_E_ELEMENTNOTFOUND
;
7429 VariantInit(pVarVal
);
7430 VariantCopy(pVarVal
, &pCData
->data
);
7435 /* ITypeInfo2::GetDocumentation2
7437 * Retrieves the documentation string, the complete Help file name and path,
7438 * the localization context to use, and the context ID for the library Help
7439 * topic in the Help file.
7442 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
7446 BSTR
*pbstrHelpString
,
7447 DWORD
*pdwHelpStringContext
,
7448 BSTR
*pbstrHelpStringDll
)
7450 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7451 const TLBFuncDesc
*pFDesc
;
7452 const TLBVarDesc
*pVDesc
;
7453 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
7454 "HelpStringContext(%p) HelpStringDll(%p)\n",
7455 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
7456 pbstrHelpStringDll
);
7457 /* the help string should be obtained from the helpstringdll,
7458 * using the _DLLGetDocumentation function, based on the supplied
7459 * lcid. Nice to do sometime...
7461 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7463 *pbstrHelpString
=SysAllocString(This
->Name
);
7464 if(pdwHelpStringContext
)
7465 *pdwHelpStringContext
=This
->dwHelpStringContext
;
7466 if(pbstrHelpStringDll
)
7467 *pbstrHelpStringDll
=
7468 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7470 }else {/* for a member */
7471 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->TypeAttr
.cFuncs
, memid
);
7474 *pbstrHelpString
=SysAllocString(pFDesc
->HelpString
);
7475 if(pdwHelpStringContext
)
7476 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
7477 if(pbstrHelpStringDll
)
7478 *pbstrHelpStringDll
=
7479 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7482 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->TypeAttr
.cVars
, memid
);
7485 *pbstrHelpString
=SysAllocString(pVDesc
->HelpString
);
7486 if(pdwHelpStringContext
)
7487 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
7488 if(pbstrHelpStringDll
)
7489 *pbstrHelpStringDll
=
7490 SysAllocString(This
->pTypeLib
->HelpStringDll
);/* FIXME */
7494 return TYPE_E_ELEMENTNOTFOUND
;
7497 /* ITypeInfo2::GetAllCustData
7499 * Gets all custom data items for the Type info.
7502 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
7504 CUSTDATA
*pCustData
)
7506 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7508 TRACE("%p %p\n", This
, pCustData
);
7510 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
7513 /* ITypeInfo2::GetAllFuncCustData
7515 * Gets all custom data items for the specified Function
7518 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
7521 CUSTDATA
*pCustData
)
7523 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7524 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
7526 TRACE("%p %u %p\n", This
, index
, pCustData
);
7528 if(index
>= This
->TypeAttr
.cFuncs
)
7529 return TYPE_E_ELEMENTNOTFOUND
;
7531 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
7534 /* ITypeInfo2::GetAllParamCustData
7536 * Gets all custom data items for the Functions
7539 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
7540 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
7542 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7543 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
7545 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
7547 if(indexFunc
>= This
->TypeAttr
.cFuncs
)
7548 return TYPE_E_ELEMENTNOTFOUND
;
7550 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
7551 return TYPE_E_ELEMENTNOTFOUND
;
7553 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
7556 /* ITypeInfo2::GetAllVarCustData
7558 * Gets all custom data items for the specified Variable
7561 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
7562 UINT index
, CUSTDATA
*pCustData
)
7564 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7565 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
7567 TRACE("%p %u %p\n", This
, index
, pCustData
);
7569 if(index
>= This
->TypeAttr
.cVars
)
7570 return TYPE_E_ELEMENTNOTFOUND
;
7572 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
7575 /* ITypeInfo2::GetAllImplCustData
7577 * Gets all custom data items for the specified implementation type
7580 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
7583 CUSTDATA
*pCustData
)
7585 ITypeInfoImpl
*This
= (ITypeInfoImpl
*)iface
;
7586 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
7588 TRACE("%p %u %p\n", This
, index
, pCustData
);
7590 if(index
>= This
->TypeAttr
.cImplTypes
)
7591 return TYPE_E_ELEMENTNOTFOUND
;
7593 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
7596 static const ITypeInfo2Vtbl tinfvt
=
7599 ITypeInfo_fnQueryInterface
,
7601 ITypeInfo_fnRelease
,
7603 ITypeInfo_fnGetTypeAttr
,
7604 ITypeInfo_fnGetTypeComp
,
7605 ITypeInfo_fnGetFuncDesc
,
7606 ITypeInfo_fnGetVarDesc
,
7607 ITypeInfo_fnGetNames
,
7608 ITypeInfo_fnGetRefTypeOfImplType
,
7609 ITypeInfo_fnGetImplTypeFlags
,
7610 ITypeInfo_fnGetIDsOfNames
,
7612 ITypeInfo_fnGetDocumentation
,
7613 ITypeInfo_fnGetDllEntry
,
7614 ITypeInfo_fnGetRefTypeInfo
,
7615 ITypeInfo_fnAddressOfMember
,
7616 ITypeInfo_fnCreateInstance
,
7617 ITypeInfo_fnGetMops
,
7618 ITypeInfo_fnGetContainingTypeLib
,
7619 ITypeInfo_fnReleaseTypeAttr
,
7620 ITypeInfo_fnReleaseFuncDesc
,
7621 ITypeInfo_fnReleaseVarDesc
,
7623 ITypeInfo2_fnGetTypeKind
,
7624 ITypeInfo2_fnGetTypeFlags
,
7625 ITypeInfo2_fnGetFuncIndexOfMemId
,
7626 ITypeInfo2_fnGetVarIndexOfMemId
,
7627 ITypeInfo2_fnGetCustData
,
7628 ITypeInfo2_fnGetFuncCustData
,
7629 ITypeInfo2_fnGetParamCustData
,
7630 ITypeInfo2_fnGetVarCustData
,
7631 ITypeInfo2_fnGetImplTypeCustData
,
7632 ITypeInfo2_fnGetDocumentation2
,
7633 ITypeInfo2_fnGetAllCustData
,
7634 ITypeInfo2_fnGetAllFuncCustData
,
7635 ITypeInfo2_fnGetAllParamCustData
,
7636 ITypeInfo2_fnGetAllVarCustData
,
7637 ITypeInfo2_fnGetAllImplTypeCustData
,
7640 /******************************************************************************
7641 * CreateDispTypeInfo [OLEAUT32.31]
7643 * Build type information for an object so it can be called through an
7644 * IDispatch interface.
7647 * Success: S_OK. pptinfo contains the created ITypeInfo object.
7648 * Failure: E_INVALIDARG, if one or more arguments is invalid.
7651 * This call allows an objects methods to be accessed through IDispatch, by
7652 * building an ITypeInfo object that IDispatch can use to call through.
7654 HRESULT WINAPI
CreateDispTypeInfo(
7655 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
7656 LCID lcid
, /* [I] Locale Id */
7657 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
7659 ITypeInfoImpl
*pTIClass
, *pTIIface
;
7660 ITypeLibImpl
*pTypeLibImpl
;
7661 unsigned int param
, func
;
7662 TLBFuncDesc
*pFuncDesc
;
7666 pTypeLibImpl
= TypeLibImpl_Constructor();
7667 if (!pTypeLibImpl
) return E_FAIL
;
7669 pTypeLibImpl
->TypeInfoCount
= 2;
7670 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
7672 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
7673 pTIIface
->pTypeLib
= pTypeLibImpl
;
7674 pTIIface
->index
= 0;
7675 pTIIface
->Name
= NULL
;
7676 pTIIface
->dwHelpContext
= -1;
7677 memset(&pTIIface
->TypeAttr
.guid
, 0, sizeof(GUID
));
7678 pTIIface
->TypeAttr
.lcid
= lcid
;
7679 pTIIface
->TypeAttr
.typekind
= TKIND_INTERFACE
;
7680 pTIIface
->TypeAttr
.wMajorVerNum
= 0;
7681 pTIIface
->TypeAttr
.wMinorVerNum
= 0;
7682 pTIIface
->TypeAttr
.cbAlignment
= 2;
7683 pTIIface
->TypeAttr
.cbSizeInstance
= -1;
7684 pTIIface
->TypeAttr
.cbSizeVft
= -1;
7685 pTIIface
->TypeAttr
.cFuncs
= 0;
7686 pTIIface
->TypeAttr
.cImplTypes
= 0;
7687 pTIIface
->TypeAttr
.cVars
= 0;
7688 pTIIface
->TypeAttr
.wTypeFlags
= 0;
7690 pTIIface
->funcdescs
= TLBFuncDesc_Constructor(pidata
->cMembers
);
7691 pFuncDesc
= pTIIface
->funcdescs
;
7692 for(func
= 0; func
< pidata
->cMembers
; func
++) {
7693 METHODDATA
*md
= pidata
->pmethdata
+ func
;
7694 pFuncDesc
->Name
= SysAllocString(md
->szName
);
7695 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
7696 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
7697 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
7698 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
7699 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
7700 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
7701 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
7702 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
7703 pFuncDesc
->funcdesc
.cScodes
= 0;
7704 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
7705 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
7706 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
7707 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
7708 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
7709 md
->cArgs
* sizeof(ELEMDESC
));
7710 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
7711 for(param
= 0; param
< md
->cArgs
; param
++) {
7712 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
7713 pFuncDesc
->pParamDesc
[param
].Name
= SysAllocString(md
->ppdata
[param
].szName
);
7715 pFuncDesc
->helpcontext
= 0;
7716 pFuncDesc
->HelpStringContext
= 0;
7717 pFuncDesc
->HelpString
= NULL
;
7718 pFuncDesc
->Entry
= NULL
;
7719 list_init(&pFuncDesc
->custdata_list
);
7720 pTIIface
->TypeAttr
.cFuncs
++;
7724 dump_TypeInfo(pTIIface
);
7726 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
7727 pTIClass
->pTypeLib
= pTypeLibImpl
;
7728 pTIClass
->index
= 1;
7729 pTIClass
->Name
= NULL
;
7730 pTIClass
->dwHelpContext
= -1;
7731 memset(&pTIClass
->TypeAttr
.guid
, 0, sizeof(GUID
));
7732 pTIClass
->TypeAttr
.lcid
= lcid
;
7733 pTIClass
->TypeAttr
.typekind
= TKIND_COCLASS
;
7734 pTIClass
->TypeAttr
.wMajorVerNum
= 0;
7735 pTIClass
->TypeAttr
.wMinorVerNum
= 0;
7736 pTIClass
->TypeAttr
.cbAlignment
= 2;
7737 pTIClass
->TypeAttr
.cbSizeInstance
= -1;
7738 pTIClass
->TypeAttr
.cbSizeVft
= -1;
7739 pTIClass
->TypeAttr
.cFuncs
= 0;
7740 pTIClass
->TypeAttr
.cImplTypes
= 1;
7741 pTIClass
->TypeAttr
.cVars
= 0;
7742 pTIClass
->TypeAttr
.wTypeFlags
= 0;
7744 pTIClass
->impltypes
= TLBImplType_Constructor(1);
7746 ref
= heap_alloc_zero(sizeof(*ref
));
7747 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
7748 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
7750 dump_TypeInfo(pTIClass
);
7752 *pptinfo
= (ITypeInfo
*)pTIClass
;
7754 ITypeInfo_AddRef(*pptinfo
);
7755 ITypeLib_Release((ITypeLib
*)&pTypeLibImpl
->lpVtbl
);
7761 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
7763 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7765 return ITypeInfo_QueryInterface((ITypeInfo
*)This
, riid
, ppv
);
7768 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
7770 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7772 return ITypeInfo_AddRef((ITypeInfo
*)This
);
7775 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
7777 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7779 return ITypeInfo_Release((ITypeInfo
*)This
);
7782 static HRESULT WINAPI
ITypeComp_fnBind(
7787 ITypeInfo
** ppTInfo
,
7788 DESCKIND
* pDescKind
,
7791 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
7792 const TLBFuncDesc
*pFDesc
;
7793 const TLBVarDesc
*pVDesc
;
7794 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
7797 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7799 *pDescKind
= DESCKIND_NONE
;
7800 pBindPtr
->lpfuncdesc
= NULL
;
7803 for(fdc
= 0; fdc
< This
->TypeAttr
.cFuncs
; ++fdc
){
7804 pFDesc
= &This
->funcdescs
[fdc
];
7805 if (!strcmpiW(pFDesc
->Name
, szName
)) {
7806 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
7809 /* name found, but wrong flags */
7810 hr
= TYPE_E_TYPEMISMATCH
;
7814 if (fdc
< This
->TypeAttr
.cFuncs
)
7816 HRESULT hr
= TLB_AllocAndInitFuncDesc(
7818 &pBindPtr
->lpfuncdesc
,
7819 This
->TypeAttr
.typekind
== TKIND_DISPATCH
);
7822 *pDescKind
= DESCKIND_FUNCDESC
;
7823 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7824 ITypeInfo_AddRef(*ppTInfo
);
7827 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->TypeAttr
.cVars
, szName
);
7829 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
7832 *pDescKind
= DESCKIND_VARDESC
;
7833 *ppTInfo
= (ITypeInfo
*)&This
->lpVtbl
;
7834 ITypeInfo_AddRef(*ppTInfo
);
7838 /* FIXME: search each inherited interface, not just the first */
7839 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
7840 /* recursive search */
7844 hr
=ITypeInfo_GetRefTypeInfo((ITypeInfo
*)&This
->lpVtbl
, This
->impltypes
[0].hRef
, &pTInfo
);
7847 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
7848 ITypeInfo_Release(pTInfo
);
7852 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
7853 ITypeComp_Release(pTComp
);
7856 WARN("Could not search inherited interface!\n");
7858 if (hr
== DISP_E_MEMBERNOTFOUND
)
7860 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
7864 static HRESULT WINAPI
ITypeComp_fnBindType(
7868 ITypeInfo
** ppTInfo
,
7869 ITypeComp
** ppTComp
)
7871 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
7873 /* strange behaviour (does nothing) but like the
7876 if (!ppTInfo
|| !ppTComp
)
7885 static const ITypeCompVtbl tcompvt
=
7888 ITypeComp_fnQueryInterface
,
7890 ITypeComp_fnRelease
,
7893 ITypeComp_fnBindType