4 * Copyright 1997 Marcus Meissner
6 * 2000 Francois Jacques
7 * 2001 Huw D M Davies for CodeWeavers
8 * 2004 Alastair Bridgewater
9 * 2005 Robert Shearman, for CodeWeavers
10 * 2013 Andrew Eikum for CodeWeavers
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * --------------------------------------------------------------------------------------
27 * Known problems (2000, Francois Jacques)
29 * - Tested using OLEVIEW (Platform SDK tool) only.
31 * - dual interface dispinterfaces. vtable-interface ITypeInfo instances are
32 * creating by doing a straight copy of the dispinterface instance and just changing
33 * its typekind. Pointed structures aren't copied - only the address of the pointers.
35 * - locale stuff is partially implemented but hasn't been tested.
37 * - typelib file is still read in its entirety, but it is released now.
39 * --------------------------------------------------------------------------------------
40 * Known problems left from previous implementation (1999, Rein Klazes) :
42 * -. Data structures are straightforward, but slow for look-ups.
43 * -. (related) nothing is hashed
44 * -. Most error return values are just guessed not checked with windows
46 * -. lousy fatal error handling
68 #include "wine/debug.h"
71 #include "wine/list.h"
73 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
74 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
76 static const BOOL is_win64
= sizeof(void *) > sizeof(int);
90 WORD type_id
; /* Type identifier */
91 WORD count
; /* Number of resources of this type */
92 DWORD resloader
; /* SetResourceHandler() */
98 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
99 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
100 static void TLB_FreeVarDesc(VARDESC
*);
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
)
176 INT best_maj
= -1, best_min
= -1;
179 lstrcpyW( buffer
, L
"Typelib\\" );
180 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
182 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
185 len
= sizeof(key_name
);
187 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
191 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
193 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
195 if (*wMaj
== 0xffff && *wMin
== 0xffff)
197 if (v_maj
> best_maj
) best_maj
= v_maj
;
198 if (v_min
> best_min
) best_min
= v_min
;
200 else if (*wMaj
== v_maj
)
207 break; /* exact match */
209 if (*wMin
!= 0xffff && v_min
>= *wMin
&& v_min
> best_min
) best_min
= v_min
;
212 len
= sizeof(key_name
);
216 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
218 if (*wMaj
== 0xffff && *wMin
== 0xffff)
220 if (best_maj
>= 0 && best_min
>= 0)
228 if (*wMaj
== best_maj
&& best_min
>= 0)
236 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
237 /* buffer must be at least 60 characters long */
238 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
240 lstrcpyW( buffer
, L
"Typelib\\" );
241 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
242 swprintf( buffer
+ lstrlenW(buffer
), 20, L
"\\%x.%x", wMaj
, wMin
);
246 /* get the path of an interface key, in the form "Interface\\<guid>" */
247 /* buffer must be at least 50 characters long */
248 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
250 lstrcpyW( buffer
, L
"Interface\\" );
251 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
255 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
256 /* buffer must be at least 16 characters long */
257 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
259 swprintf( buffer
, 16, L
"%lx\\", lcid
);
262 case SYS_WIN16
: lstrcatW( buffer
, L
"win16" ); break;
263 case SYS_WIN32
: lstrcatW( buffer
, L
"win32" ); break;
264 case SYS_WIN64
: lstrcatW( buffer
, L
"win64" ); break;
266 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
272 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
274 struct tlibredirect_data
288 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
289 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
290 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
292 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
296 WCHAR Path
[MAX_PATH
];
299 TRACE_(typelib
)("%s, %x.%x, %#lx, %p\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
303 ACTCTX_SECTION_KEYED_DATA data
;
305 data
.cbSize
= sizeof(data
);
306 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
308 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
312 if ((wMaj
!= 0xffff || wMin
!= 0xffff) && (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
))
313 return TYPE_E_LIBNOTREGISTERED
;
315 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
316 len
= SearchPathW( NULL
, nameW
, NULL
, ARRAY_SIZE( Path
), Path
, NULL
);
317 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
319 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
320 *path
= SysAllocString( Path
);
325 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
326 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
328 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
329 if (res
== ERROR_FILE_NOT_FOUND
)
331 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
332 return TYPE_E_LIBNOTREGISTERED
;
334 else if (res
!= ERROR_SUCCESS
)
336 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
337 return TYPE_E_REGISTRYACCESS
;
342 LONG dwPathLen
= sizeof(Path
);
344 get_lcid_subkey( myLCID
, syskind
, buffer
);
346 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
350 else if (myLCID
== lcid
)
352 /* try with sub-langid */
353 myLCID
= SUBLANGID(lcid
);
355 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
357 /* try with system langid */
367 *path
= SysAllocString( Path
);
372 TRACE_(typelib
)("-- %#lx\n", hr
);
376 /****************************************************************************
377 * QueryPathOfRegTypeLib [OLEAUT32.164]
379 * Gets the path to a registered type library.
382 * guid [I] referenced guid
383 * wMaj [I] major version
384 * wMin [I] minor version
386 * path [O] path of typelib
390 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
391 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
394 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
397 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, is_win64
? SYS_WIN64
: SYS_WIN32
, lcid
, path
, TRUE
);
401 return query_typelib_path( guid
, wMaj
, wMin
, is_win64
? SYS_WIN32
: SYS_WIN64
, lcid
, path
, redir
);
404 /******************************************************************************
405 * CreateTypeLib [OLEAUT32.160] creates a typelib
411 HRESULT WINAPI
CreateTypeLib(
412 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
414 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
418 /******************************************************************************
419 * LoadTypeLib [OLEAUT32.161]
421 * Loads a type library
424 * szFile [I] Name of file to load from.
425 * pptLib [O] Pointer that receives ITypeLib object on success.
432 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
434 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
436 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
437 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
440 /******************************************************************************
441 * LoadTypeLibEx [OLEAUT32.183]
443 * Loads and optionally registers a type library
449 HRESULT WINAPI
LoadTypeLibEx(
450 LPCOLESTR szFile
, /* [in] Name of file to load from */
451 REGKIND regkind
, /* [in] Specify kind of registration */
452 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
454 WCHAR szPath
[MAX_PATH
+1];
457 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
459 if (!szFile
|| !pptLib
)
464 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
469 case REGKIND_DEFAULT
:
470 /* don't register typelibs supplied with full path. Experimentation confirms the following */
471 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
472 (szFile
[0] && (szFile
[1] == ':'))) break;
473 /* else fall-through */
475 case REGKIND_REGISTER
:
476 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
478 ITypeLib_Release(*pptLib
);
486 TRACE(" returns %#lx\n",res
);
490 /******************************************************************************
491 * LoadRegTypeLib [OLEAUT32.162]
493 * Loads a registered type library.
496 * rguid [I] GUID of the registered type library.
497 * wVerMajor [I] major version.
498 * wVerMinor [I] minor version.
499 * lcid [I] locale ID.
500 * ppTLib [O] pointer that receives an ITypeLib object on success.
504 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
507 HRESULT WINAPI
LoadRegTypeLib(
519 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
523 res
= LoadTypeLib(bstr
, ppTLib
);
526 if ((wVerMajor
!=0xffff || wVerMinor
!=0xffff) && *ppTLib
)
530 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
533 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
534 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
538 ITypeLib_Release(*ppTLib
);
540 res
= TYPE_E_LIBNOTREGISTERED
;
546 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
551 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
556 get_interface_key( &tattr
->guid
, keyName
);
557 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
558 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
560 const WCHAR
*proxy_clsid
;
562 if (tattr
->typekind
== TKIND_INTERFACE
|| (tattr
->wTypeFlags
& TYPEFLAG_FDUAL
))
563 proxy_clsid
= L
"{00020424-0000-0000-C000-000000000046}";
565 proxy_clsid
= L
"{00020420-0000-0000-C000-000000000046}";
568 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
569 (BYTE
*)name
, (lstrlenW(name
)+1) * sizeof(OLECHAR
));
571 if (!RegCreateKeyExW(key
, L
"ProxyStubClsid", 0, NULL
, 0, KEY_WRITE
| flag
, NULL
, &subKey
, NULL
))
573 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
, (const BYTE
*)proxy_clsid
, (lstrlenW(proxy_clsid
) + 1) * sizeof(WCHAR
));
577 if (!RegCreateKeyExW(key
, L
"ProxyStubClsid32", 0, NULL
, 0, KEY_WRITE
| flag
, NULL
, &subKey
, NULL
))
579 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
, (const BYTE
*)proxy_clsid
, (lstrlenW(proxy_clsid
) + 1) * sizeof(WCHAR
));
583 if (RegCreateKeyExW(key
, L
"TypeLib", 0, NULL
, 0,
584 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
588 StringFromGUID2(&libattr
->guid
, buffer
, 40);
589 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
590 (BYTE
*)buffer
, (lstrlenW(buffer
)+1) * sizeof(WCHAR
));
591 swprintf(buffer
, ARRAY_SIZE(buffer
), L
"%x.%x", libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
592 RegSetValueExW(subKey
, L
"Version", 0, REG_SZ
, (BYTE
*)buffer
, (lstrlenW(buffer
)+1) * sizeof(WCHAR
));
600 /******************************************************************************
601 * RegisterTypeLib [OLEAUT32.163]
602 * Adds information about a type library to the System Registry
604 * Docs: ITypeLib FAR * ptlib
605 * Docs: OLECHAR FAR* szFullPath
606 * Docs: OLECHAR FAR* szHelpDir
612 HRESULT WINAPI
RegisterTypeLib(ITypeLib
*ptlib
, const WCHAR
*szFullPath
, const WCHAR
*szHelpDir
)
623 if (ptlib
== NULL
|| szFullPath
== NULL
)
626 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
629 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
632 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
633 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
638 /* Set the human-readable name of the typelib to
639 the typelib's doc, if it exists, else to the typelib's name. */
640 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, &libName
, &doc
, NULL
, NULL
)))
642 else if (doc
|| libName
)
644 WCHAR
*name
= doc
? doc
: libName
;
646 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
647 (BYTE
*)name
, (lstrlenW(name
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
651 SysFreeString(libName
);
654 /* Make up the name of the typelib path subkey */
655 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
657 /* Create the typelib path subkey */
658 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
659 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
661 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
662 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
670 /* Create the flags subkey */
671 if (res
== S_OK
&& RegCreateKeyExW(key
, L
"FLAGS", 0, NULL
, 0,
672 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
676 /* FIXME: is %u correct? */
677 swprintf(buf
, ARRAY_SIZE(buf
), L
"%u", attr
->wLibFlags
);
678 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
679 (BYTE
*)buf
, (lstrlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
687 /* create the helpdir subkey */
688 if (res
== S_OK
&& RegCreateKeyExW(key
, L
"HELPDIR", 0, NULL
, 0,
689 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
691 BSTR freeHelpDir
= NULL
;
694 /* if we created a new key, and helpDir was null, set the helpdir
695 to the directory which contains the typelib. However,
696 if we just opened an existing key, we leave the helpdir alone */
697 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
698 szHelpDir
= freeHelpDir
= SysAllocString(szFullPath
);
699 file_name
= wcsrchr(szHelpDir
, '\\');
700 if (file_name
&& file_name
[1]) {
701 /* possible remove a numeric \index (resource-id) */
702 WCHAR
*end_ptr
= file_name
+ 1;
703 while ('0' <= *end_ptr
&& *end_ptr
<= '9') end_ptr
++;
707 file_name
= wcsrchr(szHelpDir
, '\\');
714 /* if we have an szHelpDir, set it! */
715 if (szHelpDir
!= NULL
) {
716 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
717 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
722 SysFreeString(freeHelpDir
);
733 /* register OLE Automation-compatible interfaces for this typelib */
734 types
= ITypeLib_GetTypeInfoCount(ptlib
);
735 for (tidx
=0; tidx
<types
; tidx
++) {
736 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
737 LPOLESTR name
= NULL
;
738 ITypeInfo
*tinfo
= NULL
;
740 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
743 case TKIND_INTERFACE
:
744 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
745 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
749 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
750 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
754 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
759 TYPEATTR
*tattr
= NULL
;
760 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
763 TRACE_(typelib
)("guid=%s, flags=%04x (",
764 debugstr_guid(&tattr
->guid
),
767 if (TRACE_ON(typelib
)) {
768 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
788 /* Register all dispinterfaces (which includes dual interfaces) and
789 oleautomation interfaces */
790 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
791 kind
== TKIND_DISPATCH
)
794 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
796 /* register interface<->typelib coupling */
797 TLB_register_interface(attr
, name
, tattr
, 0);
799 /* register TLBs into the opposite registry view, too */
800 if(opposite
== KEY_WOW64_32KEY
||
801 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
802 TLB_register_interface(attr
, name
, tattr
, opposite
);
805 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
808 ITypeInfo_Release(tinfo
);
815 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
820 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
822 WCHAR subKeyName
[50];
825 /* the path to the type */
826 get_interface_key( guid
, subKeyName
);
828 /* Delete its bits */
829 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
832 RegDeleteKeyW(subKey
, L
"ProxyStubClsid");
833 RegDeleteKeyW(subKey
, L
"ProxyStubClsid32");
834 RegDeleteKeyW(subKey
, L
"TypeLib");
836 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
839 /******************************************************************************
840 * UnRegisterTypeLib [OLEAUT32.186]
841 * Removes information about a type library from the System Registry
848 HRESULT WINAPI
UnRegisterTypeLib(
849 REFGUID libid
, /* [in] Guid of the library */
850 WORD wVerMajor
, /* [in] major version */
851 WORD wVerMinor
, /* [in] minor version */
852 LCID lcid
, /* [in] locale id */
855 BSTR tlibPath
= NULL
;
858 WCHAR subKeyName
[50];
861 BOOL deleteOtherStuff
;
863 TYPEATTR
* typeAttr
= NULL
;
865 ITypeInfo
* typeInfo
= NULL
;
866 ITypeLib
* typeLib
= NULL
;
869 TRACE("(IID: %s)\n",debugstr_guid(libid
));
871 /* Create the path to the key */
872 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
874 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
876 TRACE("Unsupported syskind %i\n", syskind
);
877 result
= E_INVALIDARG
;
881 /* get the path to the typelib on disk */
882 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
883 result
= E_INVALIDARG
;
887 /* Try and open the key to the type library. */
888 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
889 result
= E_INVALIDARG
;
893 /* Try and load the type library */
894 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
895 result
= TYPE_E_INVALIDSTATE
;
899 /* remove any types registered with this typelib */
900 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
901 for (i
=0; i
<numTypes
; i
++) {
902 /* get the kind of type */
903 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
907 /* skip non-interfaces, and get type info for the type */
908 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
911 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
914 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
918 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
919 kind
== TKIND_DISPATCH
)
922 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
924 TLB_unregister_interface(&typeAttr
->guid
, 0);
926 /* unregister TLBs into the opposite registry view, too */
927 if(opposite
== KEY_WOW64_32KEY
||
928 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
929 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
934 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
936 if (typeInfo
) ITypeInfo_Release(typeInfo
);
940 /* Now, delete the type library path subkey */
941 get_lcid_subkey( lcid
, syskind
, subKeyName
);
942 RegDeleteKeyW(key
, subKeyName
);
943 *wcsrchr( subKeyName
, '\\' ) = 0; /* remove last path component */
944 RegDeleteKeyW(key
, subKeyName
);
946 /* check if there is anything besides the FLAGS/HELPDIR keys.
947 If there is, we don't delete them */
948 tmpLength
= ARRAY_SIZE(subKeyName
);
949 deleteOtherStuff
= TRUE
;
951 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
952 tmpLength
= ARRAY_SIZE(subKeyName
);
954 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
955 if (!wcscmp(subKeyName
, L
"FLAGS")) continue;
956 if (!wcscmp(subKeyName
, L
"HELPDIR")) continue;
957 deleteOtherStuff
= FALSE
;
961 /* only delete the other parts of the key if we're absolutely sure */
962 if (deleteOtherStuff
) {
963 RegDeleteKeyW(key
, L
"FLAGS");
964 RegDeleteKeyW(key
, L
"HELPDIR");
968 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
969 *wcsrchr( keyName
, '\\' ) = 0; /* remove last path component */
970 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
974 SysFreeString(tlibPath
);
975 if (typeLib
) ITypeLib_Release(typeLib
);
976 if (key
) RegCloseKey(key
);
980 /******************************************************************************
981 * RegisterTypeLibForUser [OLEAUT32.442]
982 * Adds information about a type library to the user registry
984 * Docs: ITypeLib FAR * ptlib
985 * Docs: OLECHAR FAR* szFullPath
986 * Docs: OLECHAR FAR* szHelpDir
992 HRESULT WINAPI
RegisterTypeLibForUser(
993 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
994 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
995 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
998 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
999 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1000 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1003 /******************************************************************************
1004 * UnRegisterTypeLibForUser [OLEAUT32.443]
1005 * Removes information about a type library from the user registry
1011 HRESULT WINAPI
UnRegisterTypeLibForUser(
1012 REFGUID libid
, /* [in] GUID of the library */
1013 WORD wVerMajor
, /* [in] major version */
1014 WORD wVerMinor
, /* [in] minor version */
1015 LCID lcid
, /* [in] locale id */
1018 FIXME("%s, %u, %u, %#lx, %u unregistering the typelib system-wide\n",
1019 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1020 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1023 /*======================= ITypeLib implementation =======================*/
1025 typedef struct tagTLBGuid
{
1032 typedef struct tagTLBCustData
1039 /* data structure for import typelibs */
1040 typedef struct tagTLBImpLib
1042 int offset
; /* offset in the file (MSFT)
1043 offset in nametable (SLTG)
1044 just used to identify library while reading
1046 TLBGuid
*guid
; /* libid */
1047 BSTR name
; /* name */
1049 LCID lcid
; /* lcid of imported typelib */
1051 WORD wVersionMajor
; /* major version number */
1052 WORD wVersionMinor
; /* minor version number */
1054 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1055 NULL if not yet loaded */
1059 typedef struct tagTLBString
{
1065 /* internal ITypeLib data */
1066 typedef struct tagITypeLibImpl
1068 ITypeLib2 ITypeLib2_iface
;
1069 ITypeComp ITypeComp_iface
;
1070 ICreateTypeLib2 ICreateTypeLib2_iface
;
1081 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1082 * exported to the application as a UNICODE string.
1084 struct list string_list
;
1085 struct list name_list
;
1086 struct list guid_list
;
1088 const TLBString
*Name
;
1089 const TLBString
*DocString
;
1090 const TLBString
*HelpFile
;
1091 const TLBString
*HelpStringDll
;
1092 DWORD dwHelpContext
;
1093 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1094 struct tagITypeInfoImpl
**typeinfos
;
1095 struct list custdata_list
;
1096 struct list implib_list
;
1097 int ctTypeDesc
; /* number of items in type desc array */
1098 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1099 library. Only used while reading MSFT
1101 struct list ref_list
; /* list of ref types in this typelib */
1102 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1105 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1111 static const ITypeLib2Vtbl tlbvt
;
1112 static const ITypeCompVtbl tlbtcvt
;
1113 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1115 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1117 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1120 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1122 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1125 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1127 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1130 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1132 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1135 /* ITypeLib methods */
1136 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1137 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1139 /*======================= ITypeInfo implementation =======================*/
1141 /* data for referenced types */
1142 typedef struct tagTLBRefType
1144 INT index
; /* Type index for internal ref or for external ref
1145 it the format is SLTG. -2 indicates to
1149 TLBGuid
*guid
; /* guid of the referenced type */
1150 /* if index == TLB_REF_USE_GUID */
1152 HREFTYPE reference
; /* The href of this ref */
1153 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1154 TLB_REF_INTERNAL for internal refs
1155 TLB_REF_NOT_FOUND for broken refs */
1160 #define TLB_REF_USE_GUID -2
1162 #define TLB_REF_INTERNAL (void*)-2
1163 #define TLB_REF_NOT_FOUND (void*)-1
1165 /* internal Parameter data */
1166 typedef struct tagTLBParDesc
1168 const TLBString
*Name
;
1169 struct list custdata_list
;
1172 /* internal Function data */
1173 typedef struct tagTLBFuncDesc
1175 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1176 const TLBString
*Name
; /* the name of this function */
1177 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1179 int HelpStringContext
;
1180 const TLBString
*HelpString
;
1181 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1182 struct list custdata_list
;
1185 /* internal Variable data */
1186 typedef struct tagTLBVarDesc
1188 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1189 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1190 const TLBString
*Name
; /* the name of this variable */
1192 int HelpStringContext
;
1193 const TLBString
*HelpString
;
1194 struct list custdata_list
;
1197 /* internal implemented interface data */
1198 typedef struct tagTLBImplType
1200 HREFTYPE hRef
; /* hRef of interface */
1201 int implflags
; /* IMPLFLAG_*s */
1202 struct list custdata_list
;
1205 /* internal TypeInfo data */
1206 typedef struct tagITypeInfoImpl
1208 ITypeInfo2 ITypeInfo2_iface
;
1209 ITypeComp ITypeComp_iface
;
1210 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1212 BOOL not_attached_to_typelib
;
1217 TYPEDESC
*tdescAlias
;
1219 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1220 int index
; /* index in this typelib; */
1221 HREFTYPE hreftype
; /* hreftype for app object binding */
1222 /* type libs seem to store the doc strings in ascii
1223 * so why should we do it in unicode?
1225 const TLBString
*Name
;
1226 const TLBString
*DocString
;
1227 const TLBString
*DllName
;
1228 const TLBString
*Schema
;
1229 DWORD dwHelpContext
;
1230 DWORD dwHelpStringContext
;
1233 TLBFuncDesc
*funcdescs
;
1236 TLBVarDesc
*vardescs
;
1238 /* Implemented Interfaces */
1239 TLBImplType
*impltypes
;
1241 struct list
*pcustdata_list
;
1242 struct list custdata_list
;
1245 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1247 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1250 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1252 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1255 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1257 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1260 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1262 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1265 static const ITypeInfo2Vtbl tinfvt
;
1266 static const ITypeCompVtbl tcompvt
;
1267 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1269 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1270 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1272 typedef struct tagTLBContext
1274 unsigned int oStart
; /* start of TLB in file */
1275 unsigned int pos
; /* current pos */
1276 unsigned int length
; /* total length */
1277 void *mapping
; /* memory mapping */
1278 MSFT_SegDir
* pTblDir
;
1279 ITypeLibImpl
* pLibInfo
;
1283 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1285 return str
!= NULL
? str
->str
: NULL
;
1288 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1292 return memcmp(left
, str
->str
, len
);
1295 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1297 return guid
!= NULL
? &guid
->guid
: NULL
;
1300 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1302 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1305 static int get_ptr_size(SYSKIND syskind
)
1315 WARN("Unhandled syskind: 0x%x\n", syskind
);
1322 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1323 if (pTD
->vt
& VT_RESERVED
)
1324 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1325 if (pTD
->vt
& VT_BYREF
)
1326 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1327 if (pTD
->vt
& VT_ARRAY
)
1328 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1329 if (pTD
->vt
& VT_VECTOR
)
1330 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1331 switch(pTD
->vt
& VT_TYPEMASK
) {
1332 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1333 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1334 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1335 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1336 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1337 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1338 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1339 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1340 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1341 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1342 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1343 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1344 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1345 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1346 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1347 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1348 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1349 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1350 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1351 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1352 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %lx", pTD
->hreftype
); break;
1353 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1354 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1355 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1356 dump_TypeDesc(pTD
->lptdesc
, szVarType
+ 7);
1358 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1359 dump_TypeDesc(pTD
->lptdesc
, szVarType
+ 13);
1361 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1362 pTD
->lpadesc
->cDims
); /* FIXME print out sizes */
1363 dump_TypeDesc(&pTD
->lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1366 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1370 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1372 USHORT flags
= edesc
->paramdesc
.wParamFlags
;
1373 dump_TypeDesc(&edesc
->tdesc
,buf
);
1374 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1375 MESSAGE("\t\tu.paramdesc.wParamFlags");
1376 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1377 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1378 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1379 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1380 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1381 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1382 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1383 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1384 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->paramdesc
.pparamdescex
);
1386 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1388 MESSAGE("memid is %#lx\n", funcdesc
->memid
);
1389 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1390 MESSAGE("Param %d:\n",i
);
1391 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1393 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1394 switch (funcdesc
->funckind
) {
1395 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1396 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1397 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1398 case FUNC_STATIC
: MESSAGE("static");break;
1399 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1400 default: MESSAGE("unknown");break;
1402 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1403 switch (funcdesc
->invkind
) {
1404 case INVOKE_FUNC
: MESSAGE("func");break;
1405 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1406 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1407 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1409 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1410 switch (funcdesc
->callconv
) {
1411 case CC_CDECL
: MESSAGE("cdecl");break;
1412 case CC_PASCAL
: MESSAGE("pascal");break;
1413 case CC_STDCALL
: MESSAGE("stdcall");break;
1414 case CC_SYSCALL
: MESSAGE("syscall");break;
1417 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1418 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1419 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1421 MESSAGE("\telemdescFunc (return value type):\n");
1422 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1425 static const char * const typekind_desc
[] =
1438 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1441 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1442 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1443 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1446 dump_FUNCDESC(&(pfd
->funcdesc
));
1448 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1449 if(pfd
->Entry
== NULL
)
1450 MESSAGE("\tentry: (null)\n");
1451 else if(pfd
->Entry
== (void*)-1)
1452 MESSAGE("\tentry: invalid\n");
1453 else if(IS_INTRESOURCE(pfd
->Entry
))
1454 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1456 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1458 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1462 dump_TLBFuncDescOne(pfd
);
1467 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1471 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1477 static void dump_TLBImpLib(const TLBImpLib
*import
)
1479 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1480 debugstr_w(import
->name
));
1481 TRACE_(typelib
)("v%d.%d lcid %#lx offset=%x\n", import
->wVersionMajor
, import
->wVersionMinor
, import
->lcid
, import
->offset
);
1484 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1488 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1490 TRACE_(typelib
)("href:%#lx\n", ref
->reference
);
1491 if(ref
->index
== -1)
1492 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1494 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1496 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1498 TRACE_(typelib
)("in lib\n");
1499 dump_TLBImpLib(ref
->pImpTLInfo
);
1504 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1509 TRACE_(typelib
)("implementing/inheriting interface hRef = %lx implflags %x\n",
1510 impl
->hRef
, impl
->implflags
);
1516 static void dump_DispParms(const DISPPARAMS
* pdp
)
1520 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1522 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1524 TRACE("named args:\n");
1525 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1526 TRACE( "\t0x%lx\n", pdp
->rgdispidNamedArgs
[index
] );
1529 if (pdp
->cArgs
&& pdp
->rgvarg
)
1532 for (index
= 0; index
< pdp
->cArgs
; index
++)
1533 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1537 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1539 TRACE("%p ref %lu\n", pty
, pty
->ref
);
1540 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1541 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1542 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1543 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1544 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1545 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1546 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1548 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1549 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1550 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1553 static void dump_VARDESC(const VARDESC
*v
)
1555 MESSAGE("memid %ld\n",v
->memid
);
1556 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1557 MESSAGE("oInst %ld\n", v
->oInst
);
1558 dump_ELEMDESC(&(v
->elemdescVar
));
1559 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1560 MESSAGE("varkind %d\n",v
->varkind
);
1563 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1565 /* VT_LPWSTR is largest type that, may appear in type description */
1566 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1567 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1568 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1569 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1570 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1571 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1572 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1573 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1576 static void TLB_abort(void)
1581 /* returns the size required for a deep copy of a typedesc into a
1583 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1587 if (alloc_initial_space
)
1588 size
+= sizeof(TYPEDESC
);
1594 size
+= TLB_SizeTypeDesc(tdesc
->lptdesc
, TRUE
);
1597 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->lpadesc
->cDims
]);
1598 size
+= TLB_SizeTypeDesc(&tdesc
->lpadesc
->tdescElem
, FALSE
);
1604 /* deep copy a typedesc into a flat buffer */
1605 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1610 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1619 dest
->lptdesc
= buffer
;
1620 buffer
= TLB_CopyTypeDesc(NULL
, src
->lptdesc
, buffer
);
1623 dest
->lpadesc
= buffer
;
1624 memcpy(dest
->lpadesc
, src
->lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->lpadesc
->cDims
]));
1625 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->lpadesc
->cDims
]);
1626 buffer
= TLB_CopyTypeDesc(&dest
->lpadesc
->tdescElem
, &src
->lpadesc
->tdescElem
, buffer
);
1632 /* free custom data allocated by MSFT_CustData */
1633 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1635 TLBCustData
*cd
, *cdn
;
1636 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1638 list_remove(&cd
->entry
);
1639 VariantClear(&cd
->data
);
1644 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1649 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1650 ret
= SysAllocStringLen(NULL
, len
- 1);
1651 if (!ret
) return ret
;
1652 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1656 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1660 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1662 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
)
1663 return &typeinfo
->funcdescs
[i
];
1669 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl
*typeinfo
, MEMBERID memid
, INVOKEKIND invkind
)
1673 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1675 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
&& typeinfo
->funcdescs
[i
].funcdesc
.invkind
== invkind
)
1676 return &typeinfo
->funcdescs
[i
];
1682 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1686 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1688 if (typeinfo
->vardescs
[i
].vardesc
.memid
== memid
)
1689 return &typeinfo
->vardescs
[i
];
1695 static inline TLBVarDesc
*TLB_get_vardesc_by_name(ITypeInfoImpl
*typeinfo
, const OLECHAR
*name
)
1699 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1701 if (!lstrcmpiW(TLB_get_bstr(typeinfo
->vardescs
[i
].Name
), name
))
1702 return &typeinfo
->vardescs
[i
];
1708 static inline TLBCustData
*TLB_get_custdata_by_guid(const struct list
*custdata_list
, REFGUID guid
)
1710 TLBCustData
*cust_data
;
1711 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1712 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1717 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeLibImpl
*typelib
, const OLECHAR
*name
)
1721 for (i
= 0; i
< typelib
->TypeInfoCount
; ++i
)
1723 if (!lstrcmpiW(TLB_get_bstr(typelib
->typeinfos
[i
]->Name
), name
))
1724 return typelib
->typeinfos
[i
];
1730 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1732 list_init(&var_desc
->custdata_list
);
1735 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1739 ret
= calloc(n
, sizeof(TLBVarDesc
));
1744 TLBVarDesc_Constructor(&ret
[n
-1]);
1751 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1755 ret
= calloc(n
, sizeof(TLBParDesc
));
1760 list_init(&ret
[n
-1].custdata_list
);
1767 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1769 list_init(&func_desc
->custdata_list
);
1772 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1776 ret
= calloc(n
, sizeof(TLBFuncDesc
));
1781 TLBFuncDesc_Constructor(&ret
[n
-1]);
1788 static void TLBImplType_Constructor(TLBImplType
*impl
)
1790 list_init(&impl
->custdata_list
);
1793 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1797 ret
= calloc(n
, sizeof(TLBImplType
));
1802 TLBImplType_Constructor(&ret
[n
-1]);
1809 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1810 const GUID
*new_guid
, HREFTYPE hreftype
)
1814 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1815 if (IsEqualGUID(&guid
->guid
, new_guid
))
1819 guid
= malloc(sizeof(TLBGuid
));
1823 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1824 guid
->hreftype
= hreftype
;
1826 list_add_tail(guid_list
, &guid
->entry
);
1831 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1833 TLBCustData
*cust_data
;
1845 return DISP_E_BADVARTYPE
;
1848 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1851 cust_data
= malloc(sizeof(TLBCustData
));
1853 return E_OUTOFMEMORY
;
1855 cust_data
->guid
= tlbguid
;
1856 VariantInit(&cust_data
->data
);
1858 list_add_tail(custdata_list
, &cust_data
->entry
);
1860 VariantClear(&cust_data
->data
);
1862 return VariantCopy(&cust_data
->data
, var
);
1865 /* Used to update list pointers after list itself was moved. */
1866 static void TLB_relink_custdata(struct list
*custdata_list
)
1868 if (custdata_list
->prev
== custdata_list
->next
)
1869 list_init(custdata_list
);
1872 custdata_list
->prev
->next
= custdata_list
;
1873 custdata_list
->next
->prev
= custdata_list
;
1877 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1884 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1885 if (wcscmp(str
->str
, new_str
) == 0)
1889 str
= malloc(sizeof(TLBString
));
1893 str
->str
= SysAllocString(new_str
);
1899 list_add_tail(string_list
, &str
->entry
);
1904 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1905 ULONG
*size
, WORD
*align
)
1911 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1915 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1917 ITypeInfo_Release(other
);
1922 *size
= attr
->cbSizeInstance
;
1924 *align
= attr
->cbAlignment
;
1926 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1927 ITypeInfo_Release(other
);
1932 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1933 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1935 ULONG i
, sub
, ptr_size
;
1938 ptr_size
= get_ptr_size(sys
);
1977 *size
= sizeof(DATE
);
1980 *size
= sizeof(VARIANT
);
1981 if(get_ptr_size(sys
) != sizeof(void*))
1982 *size
+= is_win64
? -8 : 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1985 *size
= sizeof(DECIMAL
);
1992 for(i
= 0; i
< tdesc
->lpadesc
->cDims
; ++i
)
1993 *size
+= tdesc
->lpadesc
->rgbounds
[i
].cElements
;
1994 hr
= TLB_size_instance(info
, sys
, &tdesc
->lpadesc
->tdescElem
, &sub
, align
);
1999 case VT_USERDEFINED
:
2000 return TLB_get_size_from_hreftype(info
, tdesc
->hreftype
, size
, align
);
2002 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2016 /**********************************************************************
2018 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2021 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2023 if (where
!= DO_NOT_SEEK
)
2025 where
+= pcx
->oStart
;
2026 if (where
> pcx
->length
)
2029 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
2037 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2039 TRACE_(typelib
)("pos=0x%08x len %#lx, %u, %u, %#lx\n",
2040 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2042 MSFT_Seek(pcx
, where
);
2043 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2044 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2049 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2054 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2055 FromLEDWords(buffer
, ret
);
2060 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2065 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2066 FromLEWords(buffer
, ret
);
2071 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2074 MSFT_GuidEntry entry
;
2077 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2079 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2082 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2084 guid
= malloc(sizeof(TLBGuid
));
2086 guid
->offset
= offs
;
2087 guid
->guid
= entry
.guid
;
2088 guid
->hreftype
= entry
.hreftype
;
2090 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2092 offs
+= sizeof(MSFT_GuidEntry
);
2096 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2100 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2101 if(ret
->offset
== offset
){
2102 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2110 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2112 MSFT_NameIntro niName
;
2116 ERR_(typelib
)("bad offset %d\n", offset
);
2120 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2121 pcx
->pTblDir
->pNametab
.offset
+offset
);
2123 return niName
.hreftype
;
2126 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2129 MSFT_NameIntro intro
;
2131 int offs
= 0, lengthInChars
;
2133 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2137 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2140 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2141 intro
.namelen
&= 0xFF;
2142 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2144 len_piece
= (len_piece
+ 4) & ~0x3;
2148 string
= malloc(len_piece
+ 1);
2149 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2150 string
[intro
.namelen
] = '\0';
2152 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2153 string
, -1, NULL
, 0);
2154 if (!lengthInChars
) {
2156 return E_UNEXPECTED
;
2159 tlbstr
= malloc(sizeof(TLBString
));
2161 tlbstr
->offset
= offs
;
2162 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2163 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2167 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2173 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2177 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2178 if (tlbstr
->offset
== offset
) {
2179 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2187 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2191 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2192 if (tlbstr
->offset
== offset
) {
2193 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2202 * read a value and fill a VARIANT structure
2204 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2208 TRACE_(typelib
)("\n");
2210 if(offset
<0) { /* data are packed in here */
2211 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2212 V_I4(pVar
) = offset
& 0x3ffffff;
2215 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2216 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2217 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2218 switch (V_VT(pVar
)){
2219 case VT_EMPTY
: /* FIXME: is this right? */
2220 case VT_NULL
: /* FIXME: is this right? */
2221 case VT_I2
: /* this should not happen */
2232 case VT_VOID
: /* FIXME: is this right? */
2240 case VT_DECIMAL
: /* FIXME: is this right? */
2243 /* pointer types with known behaviour */
2246 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2248 V_BSTR(pVar
) = NULL
;
2251 ptr
= calloc(1, size
);
2252 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2253 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, size
, NULL
, 0 );
2254 V_BSTR(pVar
)=SysAllocStringLen(NULL
,len
);
2255 MultiByteToWideChar(CP_ACP
, 0, ptr
, size
, V_BSTR(pVar
), len
);
2260 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2267 case VT_USERDEFINED
:
2273 case VT_STREAMED_OBJECT
:
2274 case VT_STORED_OBJECT
:
2275 case VT_BLOB_OBJECT
:
2280 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2284 if(size
>0) /* (big|small) endian correct? */
2285 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2289 * create a linked list with custom data
2291 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2297 TRACE_(typelib
)("\n");
2299 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2303 pNew
= calloc(1, sizeof(TLBCustData
));
2304 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2305 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2306 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2307 list_add_head(custdata_list
, &pNew
->entry
);
2308 offset
= entry
.next
;
2313 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2316 pTd
->vt
=type
& VT_TYPEMASK
;
2318 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2320 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2323 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2325 return (invkind
== INVOKE_PROPERTYGET
||
2326 invkind
== INVOKE_PROPERTYPUT
||
2327 invkind
== INVOKE_PROPERTYPUTREF
);
2331 MSFT_DoFuncs(TLBContext
* pcx
,
2336 TLBFuncDesc
** pptfd
)
2339 * member information is stored in a data structure at offset
2340 * indicated by the memoffset field of the typeinfo structure
2341 * There are several distinctive parts.
2342 * The first part starts with a field that holds the total length
2343 * of this (first) part excluding this field. Then follow the records,
2344 * for each member there is one record.
2346 * The first entry is always the length of the record (including this
2348 * The rest of the record depends on the type of the member. If there is
2349 * a field indicating the member type (function, variable, interface, etc)
2350 * I have not found it yet. At this time we depend on the information
2351 * in the type info and the usual order how things are stored.
2353 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2356 * Third is an equal sized array with file offsets to the name entry
2359 * The fourth and last (?) part is an array with offsets to the records
2360 * in the first part of this file segment.
2363 int infolen
, nameoffset
, reclength
, i
;
2364 int recoffset
= offset
+ sizeof(INT
);
2366 char *recbuf
= malloc(0xffff);
2367 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2368 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2370 TRACE_(typelib
)("\n");
2372 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2374 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2376 for ( i
= 0; i
< cFuncs
; i
++ )
2380 /* name, eventually add to a hash table */
2381 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2382 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2384 /* read the function information record */
2385 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2387 reclength
&= 0xffff;
2389 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2391 /* size without argument data */
2392 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2393 if (pFuncRec
->FKCCIC
& 0x1000)
2394 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2396 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2397 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2399 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2400 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2402 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2404 if (pFuncRec
->FKCCIC
& 0x2000 )
2406 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2407 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2408 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2411 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2414 ptfd
->Entry
= (TLBString
*)-1;
2416 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2417 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2419 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2420 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2422 /* fill the FuncDesc Structure */
2423 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2424 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2426 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2427 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2428 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2429 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2430 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2431 if (ptfd
->funcdesc
.funckind
== FUNC_DISPATCH
)
2432 ptfd
->funcdesc
.oVft
= 0;
2434 ptfd
->funcdesc
.oVft
= (unsigned short)(pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2435 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2437 /* nameoffset is sometimes -1 on the second half of a propget/propput
2438 * pair of functions */
2439 if ((nameoffset
== -1) && (i
> 0) &&
2440 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2441 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2442 ptfd
->Name
= ptfd_prev
->Name
;
2444 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2448 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2450 /* do the parameters/arguments */
2451 if(pFuncRec
->nrargs
)
2454 MSFT_ParameterInfo paraminfo
;
2456 ptfd
->funcdesc
.lprgelemdescParam
=
2457 calloc(pFuncRec
->nrargs
, sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
));
2459 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2461 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2462 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2464 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2466 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2472 elemdesc
->paramdesc
.wParamFlags
= paraminfo
.Flags
;
2475 if (paraminfo
.oName
!= -1)
2476 ptfd
->pParamDesc
[j
].Name
=
2477 MSFT_ReadName( pcx
, paraminfo
.oName
);
2478 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2481 if ( (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2482 (pFuncRec
->FKCCIC
& 0x1000) )
2484 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2486 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2488 PARAMDESC
* pParamDesc
= &elemdesc
->paramdesc
;
2490 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2491 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2493 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2497 elemdesc
->paramdesc
.pparamdescex
= NULL
;
2500 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2501 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2502 pFuncRec
->FKCCIC
& 0x80 )
2505 pFuncRec
->oArgCustData
[j
],
2506 &ptfd
->pParamDesc
[j
].custdata_list
);
2509 /* SEEK value = jump to offset,
2510 * from there jump to the end of record,
2511 * go back by (j-1) arguments
2513 MSFT_ReadLEDWords( ¶minfo
,
2514 sizeof(MSFT_ParameterInfo
), pcx
,
2515 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2516 * sizeof(MSFT_ParameterInfo
)));
2520 /* scode is not used: archaic win16 stuff FIXME: right? */
2521 ptfd
->funcdesc
.cScodes
= 0 ;
2522 ptfd
->funcdesc
.lprgscode
= NULL
;
2526 recoffset
+= reclength
;
2531 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2532 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2534 int infolen
, nameoffset
, reclength
;
2536 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2541 TRACE_(typelib
)("\n");
2543 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2544 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2545 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2546 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2547 recoffset
+= offset
+sizeof(INT
);
2548 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2549 /* name, eventually add to a hash table */
2550 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2551 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2552 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2553 /* read the variable information record */
2554 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2556 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2559 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2560 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2562 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2563 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2565 if (reclength
> FIELD_OFFSET(MSFT_VarRecord
, oCustData
))
2566 MSFT_CustData(pcx
, pVarRec
->oCustData
, &ptvd
->custdata_list
);
2568 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2569 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2571 /* fill the VarDesc Structure */
2572 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2573 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2574 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2575 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2576 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2577 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2578 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2579 if(pVarRec
->VarKind
== VAR_CONST
){
2580 ptvd
->vardesc
.lpvarValue
= calloc(1, sizeof(VARIANT
));
2581 MSFT_ReadValue(ptvd
->vardesc
.lpvarValue
,
2582 pVarRec
->OffsValue
, pcx
);
2584 ptvd
->vardesc
.oInst
=pVarRec
->OffsValue
;
2585 recoffset
+= reclength
;
2589 /* process Implemented Interfaces of a com class */
2590 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2594 MSFT_RefRecord refrec
;
2597 TRACE_(typelib
)("\n");
2599 pTI
->impltypes
= TLBImplType_Alloc(count
);
2600 pImpl
= pTI
->impltypes
;
2601 for(i
=0;i
<count
;i
++){
2602 if(offset
<0) break; /* paranoia */
2603 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2604 pImpl
->hRef
= refrec
.reftype
;
2605 pImpl
->implflags
=refrec
.flags
;
2606 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2607 offset
=refrec
.onext
;
2612 /* when a typelib is loaded in a different 32/64-bit mode, we need to resize pointers
2613 * and some structures, and fix the alignment */
2614 static void TLB_fix_typeinfo_ptr_size(ITypeInfoImpl
*info
)
2616 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2617 switch(info
->tdescAlias
->vt
){
2625 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2626 info
->typeattr
.cbAlignment
= sizeof(void*);
2629 case VT_USERDEFINED
:
2630 TLB_size_instance(info
, is_win64
? SYS_WIN64
: SYS_WIN32
, info
->tdescAlias
,
2631 &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2634 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2635 info
->typeattr
.cbAlignment
= sizeof(void *);
2638 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2639 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2641 info
->typeattr
.cbAlignment
= sizeof(void*);
2644 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2645 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2646 info
->typeattr
.typekind
== TKIND_COCLASS
){
2647 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2648 info
->typeattr
.cbAlignment
= sizeof(void*);
2653 * process a typeinfo record
2655 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2658 ITypeLibImpl
* pLibInfo
)
2660 MSFT_TypeInfoBase tiBase
;
2661 ITypeInfoImpl
*ptiRet
;
2663 TRACE_(typelib
)("count=%u\n", count
);
2665 ptiRet
= ITypeInfoImpl_Constructor();
2666 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2667 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2669 /* this is where we are coming from */
2670 ptiRet
->pTypeLib
= pLibInfo
;
2671 ptiRet
->index
=count
;
2673 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2674 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2675 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2676 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2677 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2678 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2679 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2680 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2681 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2682 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2683 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2684 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2685 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2686 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2688 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2689 ptiRet
->tdescAlias
= malloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2690 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2694 /* IDLDESC idldescType; *//* never saw this one != zero */
2696 /* name, eventually add to a hash table */
2697 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2698 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2699 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2701 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2702 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2703 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2705 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2706 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2708 /* note: InfoType's Help file and HelpStringDll come from the containing
2709 * library. Further HelpString and Docstring appear to be the same thing :(
2712 if(ptiRet
->typeattr
.cFuncs
>0 )
2713 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2714 ptiRet
->typeattr
.cVars
,
2715 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2717 if(ptiRet
->typeattr
.cVars
>0 )
2718 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2719 ptiRet
->typeattr
.cVars
,
2720 tiBase
.memoffset
, &ptiRet
->vardescs
);
2721 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2722 switch(ptiRet
->typeattr
.typekind
)
2725 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2728 case TKIND_DISPATCH
:
2729 /* This is not -1 when the interface is a non-base dual interface or
2730 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2731 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2735 if (tiBase
.datatype1
!= -1)
2737 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2738 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2742 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2743 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2747 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2749 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2750 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2751 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2752 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2753 if (TRACE_ON(typelib
))
2754 dump_TypeInfo(ptiRet
);
2759 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2762 INT16 len_str
, len_piece
;
2763 int offs
= 0, lengthInChars
;
2765 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2769 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2772 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2773 len_piece
= len_str
+ sizeof(INT16
);
2775 len_piece
= (len_piece
+ 4) & ~0x3;
2779 string
= malloc(len_piece
+ 1);
2780 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2781 string
[len_str
] = '\0';
2783 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2784 string
, -1, NULL
, 0);
2785 if (!lengthInChars
) {
2787 return E_UNEXPECTED
;
2790 tlbstr
= malloc(sizeof(TLBString
));
2792 tlbstr
->offset
= offs
;
2793 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2794 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2798 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2804 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2809 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2810 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2811 MSFT_ImpInfo impinfo
;
2814 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2816 ref
= calloc(1, sizeof(TLBRefType
));
2817 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2819 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2820 if(pImpLib
->offset
==impinfo
.oImpFile
)
2823 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2824 ref
->reference
= offs
;
2825 ref
->pImpTLInfo
= pImpLib
;
2826 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2827 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2828 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2829 ref
->index
= TLB_REF_USE_GUID
;
2831 ref
->index
= impinfo
.oGuid
;
2833 ERR("Cannot find a reference\n");
2834 ref
->reference
= -1;
2835 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2838 offs
+= sizeof(impinfo
);
2844 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2845 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2846 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2849 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2850 static CRITICAL_SECTION cache_section
;
2851 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2853 0, 0, &cache_section
,
2854 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2855 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2857 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2860 typedef struct TLB_PEFile
2862 IUnknown IUnknown_iface
;
2865 HRSRC typelib_resource
;
2866 HGLOBAL typelib_global
;
2867 LPVOID typelib_base
;
2870 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2872 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2875 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2877 if (IsEqualIID(riid
, &IID_IUnknown
))
2880 IUnknown_AddRef(iface
);
2884 return E_NOINTERFACE
;
2887 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2889 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2890 return InterlockedIncrement(&This
->refs
);
2893 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2895 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2896 ULONG refs
= InterlockedDecrement(&This
->refs
);
2899 if (This
->typelib_global
)
2900 FreeResource(This
->typelib_global
);
2902 FreeLibrary(This
->dll
);
2908 static const IUnknownVtbl TLB_PEFile_Vtable
=
2910 TLB_PEFile_QueryInterface
,
2915 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2918 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2920 This
= malloc(sizeof(TLB_PEFile
));
2922 return E_OUTOFMEMORY
;
2924 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2927 This
->typelib_resource
= NULL
;
2928 This
->typelib_global
= NULL
;
2929 This
->typelib_base
= NULL
;
2931 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2932 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2936 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), L
"TYPELIB");
2937 if (This
->typelib_resource
)
2939 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2940 if (This
->typelib_global
)
2942 This
->typelib_base
= LockResource(This
->typelib_global
);
2944 if (This
->typelib_base
)
2946 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2947 *ppBase
= This
->typelib_base
;
2948 *ppFile
= &This
->IUnknown_iface
;
2954 TRACE("No TYPELIB resource found\n");
2958 TLB_PEFile_Release(&This
->IUnknown_iface
);
2962 typedef struct TLB_NEFile
2964 IUnknown IUnknown_iface
;
2966 LPVOID typelib_base
;
2969 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2971 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2974 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2976 if (IsEqualIID(riid
, &IID_IUnknown
))
2979 IUnknown_AddRef(iface
);
2983 return E_NOINTERFACE
;
2986 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2988 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2989 return InterlockedIncrement(&This
->refs
);
2992 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2994 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2995 ULONG refs
= InterlockedDecrement(&This
->refs
);
2998 free(This
->typelib_base
);
3004 static const IUnknownVtbl TLB_NEFile_Vtable
=
3006 TLB_NEFile_QueryInterface
,
3011 /***********************************************************************
3012 * read_xx_header [internal]
3014 static int read_xx_header( HFILE lzfd
)
3016 IMAGE_DOS_HEADER mzh
;
3019 LZSeek( lzfd
, 0, SEEK_SET
);
3020 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3022 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3025 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3026 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3029 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3031 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3032 return IMAGE_OS2_SIGNATURE
;
3033 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3034 return IMAGE_NT_SIGNATURE
;
3037 WARN("Can't handle %s files.\n", magic
);
3042 /***********************************************************************
3043 * find_ne_resource [internal]
3045 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3046 DWORD
*resLen
, DWORD
*resOff
)
3048 IMAGE_OS2_HEADER nehd
;
3049 NE_TYPEINFO
*typeInfo
;
3050 NE_NAMEINFO
*nameInfo
;
3056 /* Read in NE header */
3057 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3058 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3060 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3063 TRACE("No resources in NE dll\n" );
3067 /* Read in resource table */
3068 resTab
= malloc( resTabSize
);
3069 if ( !resTab
) return FALSE
;
3071 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3072 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3079 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3081 if (!IS_INTRESOURCE(typeid)) /* named type */
3083 BYTE len
= strlen( typeid );
3084 while (typeInfo
->type_id
)
3086 if (!(typeInfo
->type_id
& 0x8000))
3088 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3089 if ((*p
== len
) && !_strnicmp( (char*)p
+1, typeid, len
)) goto found_type
;
3091 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3092 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3095 else /* numeric type id */
3097 WORD id
= LOWORD(typeid) | 0x8000;
3098 while (typeInfo
->type_id
)
3100 if (typeInfo
->type_id
== id
) goto found_type
;
3101 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3102 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3105 TRACE("No typeid entry found for %p\n", typeid );
3110 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3112 if (!IS_INTRESOURCE(resid
)) /* named resource */
3114 BYTE len
= strlen( resid
);
3115 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3117 BYTE
*p
= resTab
+ nameInfo
->id
;
3118 if (nameInfo
->id
& 0x8000) continue;
3119 if ((*p
== len
) && !_strnicmp( (char*)p
+1, resid
, len
)) goto found_name
;
3122 else /* numeric resource id */
3124 WORD id
= LOWORD(resid
) | 0x8000;
3125 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3126 if (nameInfo
->id
== id
) goto found_name
;
3128 TRACE("No resid entry found for %p\n", typeid );
3133 /* Return resource data */
3134 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3135 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3141 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3145 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3148 This
= malloc(sizeof(TLB_NEFile
));
3149 if (!This
) return E_OUTOFMEMORY
;
3151 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3153 This
->typelib_base
= NULL
;
3155 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3156 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3158 DWORD reslen
, offset
;
3159 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3161 This
->typelib_base
= malloc(reslen
);
3162 if( !This
->typelib_base
)
3166 LZSeek( lzfd
, offset
, SEEK_SET
);
3167 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3169 *ppBase
= This
->typelib_base
;
3170 *pdwTLBLength
= reslen
;
3171 *ppFile
= &This
->IUnknown_iface
;
3177 if( lzfd
>= 0) LZClose( lzfd
);
3178 TLB_NEFile_Release(&This
->IUnknown_iface
);
3182 typedef struct TLB_Mapping
3184 IUnknown IUnknown_iface
;
3188 LPVOID typelib_base
;
3191 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3193 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3196 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3198 if (IsEqualIID(riid
, &IID_IUnknown
))
3201 IUnknown_AddRef(iface
);
3205 return E_NOINTERFACE
;
3208 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3210 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3211 return InterlockedIncrement(&This
->refs
);
3214 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3216 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3217 ULONG refs
= InterlockedDecrement(&This
->refs
);
3220 if (This
->typelib_base
)
3221 UnmapViewOfFile(This
->typelib_base
);
3223 CloseHandle(This
->mapping
);
3224 if (This
->file
!= INVALID_HANDLE_VALUE
)
3225 CloseHandle(This
->file
);
3231 static const IUnknownVtbl TLB_Mapping_Vtable
=
3233 TLB_Mapping_QueryInterface
,
3238 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3242 This
= malloc(sizeof(TLB_Mapping
));
3244 return E_OUTOFMEMORY
;
3246 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3248 This
->file
= INVALID_HANDLE_VALUE
;
3249 This
->mapping
= NULL
;
3250 This
->typelib_base
= NULL
;
3252 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3253 if (INVALID_HANDLE_VALUE
!= This
->file
)
3255 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3258 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3259 if(This
->typelib_base
)
3261 /* retrieve file size */
3262 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3263 *ppBase
= This
->typelib_base
;
3264 *ppFile
= &This
->IUnknown_iface
;
3270 IUnknown_Release(&This
->IUnknown_iface
);
3271 return TYPE_E_CANTLOADLIBRARY
;
3274 /****************************************************************************
3277 * find the type of the typelib file and map the typelib resource into
3281 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3282 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3284 ITypeLibImpl
*entry
;
3287 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3288 LPVOID pBase
= NULL
;
3289 DWORD dwTLBLength
= 0;
3290 IUnknown
*pFile
= NULL
;
3295 index_str
= wcsrchr(pszFileName
, '\\');
3296 if(index_str
&& *++index_str
!= '\0')
3299 LONG idx
= wcstol(index_str
, &end_ptr
, 10);
3300 if(*end_ptr
== '\0')
3302 int str_len
= index_str
- pszFileName
- 1;
3304 file
= malloc((str_len
+ 1) * sizeof(WCHAR
));
3305 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3310 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3312 if(wcschr(file
, '\\'))
3314 lstrcpyW(pszPath
, file
);
3318 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3319 pszPath
[len
] = '\\';
3320 memcpy(pszPath
+ len
+ 1, file
, (lstrlenW(file
) + 1) * sizeof(WCHAR
));
3324 if(file
!= pszFileName
) free(file
);
3326 h
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3327 if(h
!= INVALID_HANDLE_VALUE
){
3328 GetFinalPathNameByHandleW(h
, pszPath
, cchPath
, FILE_NAME_NORMALIZED
| VOLUME_NAME_DOS
);
3332 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3334 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3335 EnterCriticalSection(&cache_section
);
3336 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3338 if (!wcsicmp(entry
->path
, pszPath
) && entry
->index
== index
)
3340 TRACE("cache hit\n");
3341 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3342 ITypeLib2_AddRef(*ppTypeLib
);
3343 LeaveCriticalSection(&cache_section
);
3347 LeaveCriticalSection(&cache_section
);
3349 /* now actually load and parse the typelib */
3351 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3352 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3353 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3354 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3355 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3358 if (dwTLBLength
>= 4)
3360 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3361 if (dwSignature
== MSFT_SIGNATURE
)
3362 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3363 else if (dwSignature
== SLTG_SIGNATURE
)
3364 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3367 FIXME("Header type magic %#lx not supported.\n", dwSignature
);
3368 ret
= TYPE_E_CANTLOADLIBRARY
;
3372 ret
= TYPE_E_CANTLOADLIBRARY
;
3373 IUnknown_Release(pFile
);
3377 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3379 TRACE("adding to cache\n");
3380 impl
->path
= wcsdup(pszPath
);
3381 /* We should really canonicalise the path here. */
3382 impl
->index
= index
;
3384 /* FIXME: check if it has added already in the meantime */
3385 EnterCriticalSection(&cache_section
);
3386 list_add_head(&tlb_cache
, &impl
->entry
);
3387 LeaveCriticalSection(&cache_section
);
3393 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
3395 ret
= TYPE_E_CANTLOADLIBRARY
;
3402 /*================== ITypeLib(2) Methods ===================================*/
3404 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3406 ITypeLibImpl
* pTypeLibImpl
;
3408 pTypeLibImpl
= calloc(1, sizeof(ITypeLibImpl
));
3409 if (!pTypeLibImpl
) return NULL
;
3411 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3412 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3413 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3414 pTypeLibImpl
->ref
= 1;
3416 list_init(&pTypeLibImpl
->implib_list
);
3417 list_init(&pTypeLibImpl
->custdata_list
);
3418 list_init(&pTypeLibImpl
->name_list
);
3419 list_init(&pTypeLibImpl
->string_list
);
3420 list_init(&pTypeLibImpl
->guid_list
);
3421 list_init(&pTypeLibImpl
->ref_list
);
3422 pTypeLibImpl
->dispatch_href
= -1;
3424 return pTypeLibImpl
;
3427 /****************************************************************************
3428 * ITypeLib2_Constructor_MSFT
3430 * loading an MSFT typelib from an in-memory image
3432 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3436 MSFT_Header tlbHeader
;
3437 MSFT_SegDir tlbSegDir
;
3438 ITypeLibImpl
* pTypeLibImpl
;
3441 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3443 pTypeLibImpl
= TypeLibImpl_Constructor();
3444 if (!pTypeLibImpl
) return NULL
;
3446 /* get pointer to beginning of typelib data */
3450 cx
.pLibInfo
= pTypeLibImpl
;
3451 cx
.length
= dwTLBLength
;
3454 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3455 TRACE_(typelib
)("header:\n");
3456 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3457 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3458 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3461 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3463 /* there is a small amount of information here until the next important
3465 * the segment directory . Try to calculate the amount of data */
3466 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3468 /* now read the segment directory */
3469 TRACE("read segment directory (at %ld)\n",lPSegDir
);
3470 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3471 cx
.pTblDir
= &tlbSegDir
;
3473 /* just check two entries */
3474 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3476 ERR("cannot find the table directory, ptr %#lx\n",lPSegDir
);
3481 MSFT_ReadAllNames(&cx
);
3482 MSFT_ReadAllStrings(&cx
);
3483 MSFT_ReadAllGuids(&cx
);
3485 /* now fill our internal data */
3486 /* TLIBATTR fields */
3487 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3489 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3490 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3491 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3492 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3493 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3495 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3496 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3498 /* name, eventually add to a hash table */
3499 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3502 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3503 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3505 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3508 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3509 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3512 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3515 if(tlbHeader
.CustomDataOffset
>= 0)
3517 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3520 /* fill in type descriptions */
3521 if(tlbSegDir
.pTypdescTab
.length
> 0)
3523 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3525 pTypeLibImpl
->ctTypeDesc
= cTD
;
3526 pTypeLibImpl
->pTypeDesc
= calloc(cTD
, sizeof(TYPEDESC
));
3527 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3530 /* FIXME: add several sanity checks here */
3531 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3532 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3534 /* FIXME: check safearray */
3536 pTypeLibImpl
->pTypeDesc
[i
].lptdesc
= &std_typedesc
[td
[2]];
3538 pTypeLibImpl
->pTypeDesc
[i
].lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3540 else if(td
[0] == VT_CARRAY
)
3542 /* array descr table here */
3543 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3545 else if(td
[0] == VT_USERDEFINED
)
3547 pTypeLibImpl
->pTypeDesc
[i
].hreftype
= MAKELONG(td
[2],td
[3]);
3549 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3552 /* second time around to fill the array subscript info */
3555 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3556 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3558 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].lpadesc
);
3559 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
= calloc(1, sizeof(ARRAYDESC
) + sizeof(SAFEARRAYBOUND
) * (td
[3] - 1));
3562 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3564 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3566 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->cDims
= td
[2];
3568 for(j
= 0; j
<td
[2]; j
++)
3570 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->rgbounds
[j
].cElements
,
3571 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3572 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->rgbounds
[j
].lLbound
,
3573 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3578 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
= NULL
;
3579 ERR("didn't find array description data\n");
3584 /* imported type libs */
3585 if(tlbSegDir
.pImpFiles
.offset
>0)
3588 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3591 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3595 pImpLib
= calloc(1, sizeof(TLBImpLib
));
3596 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3597 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3599 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3600 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3601 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3602 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3605 name
= calloc(1, size
+ 1);
3606 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3607 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3610 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3611 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3613 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3617 MSFT_ReadAllRefs(&cx
);
3619 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3622 if(tlbHeader
.nrtypeinfos
>= 0 )
3624 ITypeInfoImpl
**ppTI
;
3626 ppTI
= pTypeLibImpl
->typeinfos
= calloc(tlbHeader
.nrtypeinfos
, sizeof(ITypeInfoImpl
*));
3628 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3630 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3633 (pTypeLibImpl
->TypeInfoCount
)++;
3637 if (pTypeLibImpl
->ptr_size
!= sizeof(void *))
3639 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3640 TLB_fix_typeinfo_ptr_size(pTypeLibImpl
->typeinfos
[i
]);
3643 TRACE("(%p)\n", pTypeLibImpl
);
3644 return &pTypeLibImpl
->ITypeLib2_iface
;
3648 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3654 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3655 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3659 guid
->Data4
[0] = s
>> 8;
3660 guid
->Data4
[1] = s
& 0xff;
3663 for(i
= 0; i
< 6; i
++) {
3664 memcpy(b
, str
+ 24 + 2 * i
, 2);
3665 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3670 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3677 bytelen
= *(const WORD
*)ptr
;
3678 if(bytelen
== 0xffff) return 2;
3680 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3681 tmp_str
= SysAllocStringLen(NULL
, len
);
3683 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3684 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3685 SysFreeString(tmp_str
);
3690 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3695 bytelen
= *(const WORD
*)ptr
;
3696 if(bytelen
== 0xffff) return 2;
3697 *str
= malloc(bytelen
+ 1);
3698 memcpy(*str
, ptr
+ 2, bytelen
);
3699 (*str
)[bytelen
] = '\0';
3703 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3708 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3709 if (tlbstr
->offset
== offset
)
3713 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3714 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3715 SysFreeString(tmp_str
);
3720 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3722 char *ptr
= pLibBlk
;
3725 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3726 FIXME("libblk magic = %04x\n", w
);
3731 if((w
= *(WORD
*)ptr
) != 0xffff) {
3732 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w
);
3737 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3739 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3741 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3744 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3745 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3748 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3749 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3751 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3754 ptr
+= 4; /* skip res12 */
3756 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3759 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3762 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3765 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3766 ptr
+= sizeof(GUID
);
3768 return ptr
- (char*)pLibBlk
;
3771 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3776 } sltg_ref_lookup_t
;
3778 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3779 HREFTYPE
*typelib_ref
)
3781 if(table
&& typeinfo_ref
< table
->num
)
3783 *typelib_ref
= table
->refs
[typeinfo_ref
];
3787 ERR_(typelib
)("Unable to find reference\n");
3792 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3797 if((*pType
& 0xe00) == 0xe00) {
3799 pTD
->lptdesc
= calloc(1, sizeof(TYPEDESC
));
3802 switch(*pType
& 0x3f) {
3805 pTD
->lptdesc
= calloc(1, sizeof(TYPEDESC
));
3809 case VT_USERDEFINED
:
3810 pTD
->vt
= VT_USERDEFINED
;
3811 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->hreftype
);
3817 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3820 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3822 pTD
->vt
= VT_CARRAY
;
3823 pTD
->lpadesc
= calloc(1, sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3824 pTD
->lpadesc
->cDims
= pSA
->cDims
;
3825 memcpy(pTD
->lpadesc
->rgbounds
, pSA
->rgsabound
,
3826 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3828 pTD
= &pTD
->lpadesc
->tdescElem
;
3834 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3838 pTD
->vt
= VT_SAFEARRAY
;
3839 pTD
->lptdesc
= calloc(1, sizeof(TYPEDESC
));
3844 pTD
->vt
= *pType
& 0x3f;
3853 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3854 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3856 /* Handle [in/out] first */
3857 if((*pType
& 0xc000) == 0xc000)
3858 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3859 else if(*pType
& 0x8000)
3860 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3861 else if(*pType
& 0x4000)
3862 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3864 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3867 pElem
->paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3870 pElem
->paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3872 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3876 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3881 TLBRefType
*ref_type
;
3882 sltg_ref_lookup_t
*table
;
3883 HREFTYPE typelib_ref
;
3885 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3886 FIXME("Ref magic = %x\n", pRef
->magic
);
3889 name
= ( (char*)pRef
->names
+ pRef
->number
);
3891 table
= malloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3892 table
->num
= pRef
->number
>> 3;
3894 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3896 /* We don't want the first href to be 0 */
3897 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3899 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3901 unsigned int lib_offs
, type_num
;
3903 ref_type
= calloc(1, sizeof(TLBRefType
));
3905 name
+= SLTG_ReadStringA(name
, &refname
);
3906 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3907 FIXME_(typelib
)("Can't sscanf ref\n");
3908 if(lib_offs
!= 0xffff) {
3911 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3912 if(import
->offset
== lib_offs
)
3915 if(&import
->entry
== &pTL
->implib_list
) {
3916 char fname
[MAX_PATH
+1];
3920 import
= calloc(1, sizeof(*import
));
3921 import
->offset
= lib_offs
;
3922 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3923 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3924 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
3925 &import
->wVersionMajor
,
3926 &import
->wVersionMinor
,
3927 &import
->lcid
, fname
) != 4) {
3928 FIXME_(typelib
)("can't sscanf ref %s\n",
3929 pNameTable
+ lib_offs
+ 40);
3931 len
= strlen(fname
);
3932 if(fname
[len
-1] != '#')
3933 FIXME("fname = %s\n", fname
);
3934 fname
[len
-1] = '\0';
3935 import
->name
= TLB_MultiByteToBSTR(fname
);
3936 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3938 ref_type
->pImpTLInfo
= import
;
3940 /* Store a reference to IDispatch */
3941 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3942 pTL
->dispatch_href
= typelib_ref
;
3944 } else { /* internal ref */
3945 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3947 ref_type
->reference
= typelib_ref
;
3948 ref_type
->index
= type_num
;
3951 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3953 table
->refs
[ref
] = typelib_ref
;
3956 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3957 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3958 dump_TLBRefType(pTL
);
3962 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3963 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3965 SLTG_ImplInfo
*info
;
3966 TLBImplType
*pImplType
;
3967 /* I don't really get this structure, usually it's 0x16 bytes
3968 long, but iuser.tlb contains some that are 0x18 bytes long.
3969 That's ok because we can use the next ptr to jump to the next
3970 one. But how do we know the length of the last one? The WORD
3971 at offs 0x8 might be the clue. For now I'm just assuming that
3972 the last one is the regular 0x16 bytes. */
3974 info
= (SLTG_ImplInfo
*)pBlk
;
3976 pTI
->typeattr
.cImplTypes
++;
3977 if(info
->next
== 0xffff)
3979 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3982 info
= (SLTG_ImplInfo
*)pBlk
;
3983 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
3984 pImplType
= pTI
->impltypes
;
3986 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3987 pImplType
->implflags
= info
->impltypeflags
;
3990 if(info
->next
== 0xffff)
3993 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3994 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3996 info
++; /* see comment at top of function */
4000 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4001 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4003 TLBVarDesc
*pVarDesc
;
4004 const TLBString
*prevName
= NULL
;
4005 SLTG_Variable
*pItem
;
4009 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4011 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4012 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4014 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4016 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4017 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4018 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4022 if (pItem
->name
== 0xfffe)
4023 pVarDesc
->Name
= prevName
;
4025 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4027 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4028 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4029 TRACE_(typelib
)("memid = %#lx\n", pItem
->memid
);
4031 if(pItem
->flags
& 0x02)
4032 pType
= &pItem
->type
;
4034 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4036 if (pItem
->flags
& ~0xda)
4037 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4039 SLTG_DoElem(pType
, pBlk
,
4040 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4042 if (TRACE_ON(typelib
)) {
4044 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4045 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4048 if (pItem
->flags
& 0x40) {
4049 TRACE_(typelib
)("VAR_DISPATCH\n");
4050 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4052 else if (pItem
->flags
& 0x10) {
4053 TRACE_(typelib
)("VAR_CONST\n");
4054 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4055 pVarDesc
->vardesc
.lpvarValue
= malloc(sizeof(VARIANT
));
4056 V_VT(pVarDesc
->vardesc
.lpvarValue
) = VT_INT
;
4057 if (pItem
->flags
& 0x08)
4058 V_INT(pVarDesc
->vardesc
.lpvarValue
) = pItem
->byte_offs
;
4060 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4066 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4068 TRACE_(typelib
)("len = %u\n", len
);
4069 if (len
== 0xffff) {
4072 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4073 str
= SysAllocStringLen(NULL
, alloc_len
);
4074 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4076 V_VT(pVarDesc
->vardesc
.lpvarValue
) = VT_BSTR
;
4077 V_BSTR(pVarDesc
->vardesc
.lpvarValue
) = str
;
4086 V_INT(pVarDesc
->vardesc
.lpvarValue
) =
4087 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4090 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4095 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4096 pVarDesc
->vardesc
.oInst
= pItem
->byte_offs
;
4097 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4100 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4101 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4103 if (pItem
->flags
& 0x80)
4104 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4106 prevName
= pVarDesc
->Name
;
4108 pTI
->typeattr
.cVars
= cVars
;
4111 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4112 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4114 SLTG_Function
*pFunc
;
4116 TLBFuncDesc
*pFuncDesc
;
4118 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4120 pFuncDesc
= pTI
->funcdescs
;
4121 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4122 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4127 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4128 case SLTG_FUNCTION_MAGIC
:
4129 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4131 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4132 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4134 case SLTG_STATIC_FUNCTION_MAGIC
:
4135 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4138 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4141 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4143 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4144 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4145 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4146 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4147 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4148 if (pFuncDesc
->funcdesc
.funckind
== FUNC_DISPATCH
)
4149 pFuncDesc
->funcdesc
.oVft
= 0;
4151 pFuncDesc
->funcdesc
.oVft
= (unsigned short)(pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4153 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4154 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4156 if(pFunc
->retnextopt
& 0x80)
4157 pType
= &pFunc
->rettype
;
4159 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4161 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4163 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4164 calloc(pFuncDesc
->funcdesc
.cParams
, sizeof(ELEMDESC
));
4165 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4167 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4169 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4170 char *paramName
= pNameTable
+ *pArg
;
4172 /* If arg type follows then paramName points to the 2nd
4173 letter of the name, else the next WORD is an offset to
4174 the arg type and paramName points to the first letter.
4175 So let's take one char off paramName and see if we're
4176 pointing at an alphanumeric char. However if *pArg is
4177 0xffff or 0xfffe then the param has no name, the former
4178 meaning that the next WORD is the type, the latter
4179 meaning that the next WORD is an offset to the type. */
4184 else if(*pArg
== 0xfffe) {
4188 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4193 if(HaveOffs
) { /* the next word is an offset to type */
4194 pType
= (WORD
*)(pBlk
+ *pArg
);
4195 SLTG_DoElem(pType
, pBlk
,
4196 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4201 pArg
= SLTG_DoElem(pArg
, pBlk
,
4202 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4205 /* Are we an optional param ? */
4206 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4207 pFuncDesc
->funcdesc
.cParamsOpt
)
4208 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4211 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4212 paramName
- pNameTable
, pTI
->pTypeLib
);
4214 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4218 pTI
->typeattr
.cFuncs
= cFuncs
;
4221 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4222 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4223 SLTG_TypeInfoTail
*pTITail
)
4226 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4228 if(pTIHeader
->href_table
!= 0xffffffff) {
4229 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4235 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4236 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4242 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4243 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4244 const SLTG_TypeInfoTail
*pTITail
)
4247 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4249 if(pTIHeader
->href_table
!= 0xffffffff) {
4250 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4256 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4257 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4260 if (pTITail
->funcs_off
!= 0xffff)
4261 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4265 if (TRACE_ON(typelib
))
4266 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4269 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4270 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4271 const SLTG_TypeInfoTail
*pTITail
)
4273 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4276 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4277 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4278 const SLTG_TypeInfoTail
*pTITail
)
4281 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4283 if (pTITail
->simple_alias
) {
4284 /* if simple alias, no more processing required */
4285 pTI
->tdescAlias
= calloc(1, sizeof(TYPEDESC
));
4286 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4290 if(pTIHeader
->href_table
!= 0xffffffff) {
4291 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4295 /* otherwise it is an offset to a type */
4296 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4298 pTI
->tdescAlias
= malloc(sizeof(TYPEDESC
));
4299 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4304 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4305 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4306 const SLTG_TypeInfoTail
*pTITail
)
4308 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4309 if (pTIHeader
->href_table
!= 0xffffffff)
4310 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4313 if (pTITail
->vars_off
!= 0xffff)
4314 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4316 if (pTITail
->funcs_off
!= 0xffff)
4317 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4319 if (pTITail
->impls_off
!= 0xffff)
4320 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4322 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4323 * of dispinterface functions including the IDispatch ones, so
4324 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4325 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4328 if (TRACE_ON(typelib
))
4329 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4332 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4333 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4334 const SLTG_TypeInfoTail
*pTITail
)
4336 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4339 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4340 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4341 const SLTG_TypeInfoTail
*pTITail
)
4343 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4344 if (pTIHeader
->href_table
!= 0xffffffff)
4345 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4348 if (pTITail
->vars_off
!= 0xffff)
4349 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4351 if (pTITail
->funcs_off
!= 0xffff)
4352 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4354 if (TRACE_ON(typelib
))
4358 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4359 manageable copy of it into this */
4372 } SLTG_InternalOtherTypeInfo
;
4374 /****************************************************************************
4375 * ITypeLib2_Constructor_SLTG
4377 * loading a SLTG typelib from an in-memory image
4379 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4381 ITypeLibImpl
*pTypeLibImpl
;
4382 SLTG_Header
*pHeader
;
4383 SLTG_BlkEntry
*pBlkEntry
;
4387 LPVOID pBlk
, pFirstBlk
;
4388 SLTG_LibBlk
*pLibBlk
;
4389 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4390 char *pAfterOTIBlks
= NULL
;
4391 char *pNameTable
, *ptr
;
4394 ITypeInfoImpl
**ppTypeInfoImpl
;
4396 TRACE_(typelib
)("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
4399 pTypeLibImpl
= TypeLibImpl_Constructor();
4400 if (!pTypeLibImpl
) return NULL
;
4404 TRACE_(typelib
)("header:\n");
4405 TRACE_(typelib
)("\tmagic %#lx, file blocks = %d\n", pHeader
->SLTG_magic
,
4406 pHeader
->nrOfFileBlks
);
4407 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
)
4409 FIXME_(typelib
)("Header type magic %#lx not supported.\n", pHeader
->SLTG_magic
);
4413 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4414 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4416 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4417 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4419 /* Next we have a magic block */
4420 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4422 /* Let's see if we're still in sync */
4423 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4424 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4425 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4428 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4429 sizeof(SLTG_DIR_MAGIC
))) {
4430 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4434 pIndex
= (SLTG_Index
*)(pMagic
+1);
4436 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4438 pFirstBlk
= pPad9
+ 1;
4440 /* We'll set up a ptr to the main library block, which is the last one. */
4442 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4443 pBlkEntry
[order
].next
!= 0;
4444 order
= pBlkEntry
[order
].next
- 1) {
4445 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4449 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4451 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4456 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4458 pOtherTypeInfoBlks
= calloc(pTypeLibImpl
->TypeInfoCount
, sizeof(*pOtherTypeInfoBlks
));
4461 ptr
= (char*)pLibBlk
+ len
;
4463 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4467 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4469 w
= *(WORD
*)(ptr
+ 2);
4472 pOtherTypeInfoBlks
[i
].index_name
= malloc(w
+ 1);
4473 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4474 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4476 w
= *(WORD
*)(ptr
+ 4 + len
);
4478 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4480 pOtherTypeInfoBlks
[i
].other_name
= malloc(w
+ 1);
4481 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4482 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4484 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4485 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4486 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4488 pOtherTypeInfoBlks
[i
].extra
= malloc(extra
);
4489 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4492 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4493 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4494 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4495 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4496 len
+= sizeof(SLTG_OtherTypeInfo
);
4500 pAfterOTIBlks
= ptr
;
4502 /* Skip this WORD and get the next DWORD */
4503 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4505 /* Now add this to pLibBLk look at what we're pointing at and
4506 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4507 dust and we should be pointing at the beginning of the name
4510 pNameTable
= (char*)pLibBlk
+ len
;
4512 switch(*(WORD
*)pNameTable
) {
4519 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4523 pNameTable
+= 0x216;
4527 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4529 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4532 /* Hopefully we now have enough ptrs set up to actually read in
4533 some TypeInfos. It's not clear which order to do them in, so
4534 I'll just follow the links along the BlkEntry chain and read
4535 them in the order in which they are in the file */
4537 pTypeLibImpl
->typeinfos
= calloc(pTypeLibImpl
->TypeInfoCount
, sizeof(ITypeInfoImpl
*));
4538 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4540 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4541 pBlkEntry
[order
].next
!= 0;
4542 order
= pBlkEntry
[order
].next
- 1, i
++) {
4544 SLTG_TypeInfoHeader
*pTIHeader
;
4545 SLTG_TypeInfoTail
*pTITail
;
4546 SLTG_MemberHeader
*pMemHeader
;
4548 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4549 FIXME_(typelib
)("Index strings don't match\n");
4550 free(pOtherTypeInfoBlks
);
4555 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4556 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4557 free(pOtherTypeInfoBlks
);
4560 TRACE_(typelib
)("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, "
4561 "pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
4562 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4564 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4565 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4566 (*ppTypeInfoImpl
)->index
= i
;
4567 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4568 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4569 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4570 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4571 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4572 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4573 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4574 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4576 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4577 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4579 if((pTIHeader
->typeflags1
& 7) != 2)
4580 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4581 if(pTIHeader
->typeflags3
!= 2)
4582 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4584 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4585 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4586 typekind_desc
[pTIHeader
->typekind
],
4587 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4588 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4590 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4592 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4594 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4595 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4596 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4598 switch(pTIHeader
->typekind
) {
4600 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4601 pTIHeader
, pTITail
);
4605 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4606 pTIHeader
, pTITail
);
4609 case TKIND_INTERFACE
:
4610 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4611 pTIHeader
, pTITail
);
4615 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4616 pTIHeader
, pTITail
);
4620 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4621 pTIHeader
, pTITail
);
4624 case TKIND_DISPATCH
:
4625 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4626 pTIHeader
, pTITail
);
4630 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4631 pTIHeader
, pTITail
);
4635 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4640 /* could get cFuncs, cVars and cImplTypes from here
4641 but we've already set those */
4642 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4658 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4661 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4662 FIXME("Somehow processed %d TypeInfos\n", i
);
4663 free(pOtherTypeInfoBlks
);
4667 free(pOtherTypeInfoBlks
);
4668 return &pTypeLibImpl
->ITypeLib2_iface
;
4671 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4673 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4675 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4677 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4678 IsEqualIID(riid
,&IID_ITypeLib
)||
4679 IsEqualIID(riid
,&IID_ITypeLib2
))
4681 *ppv
= &This
->ITypeLib2_iface
;
4683 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4684 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4686 *ppv
= &This
->ICreateTypeLib2_iface
;
4691 TRACE("-- Interface: E_NOINTERFACE\n");
4692 return E_NOINTERFACE
;
4695 IUnknown_AddRef((IUnknown
*)*ppv
);
4699 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4701 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4702 ULONG ref
= InterlockedIncrement(&This
->ref
);
4704 TRACE("%p, refcount %lu.\n", iface
, ref
);
4709 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4711 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4714 EnterCriticalSection(&cache_section
);
4715 ref
= InterlockedDecrement(&This
->ref
);
4717 TRACE("%p, refcount %lu.\n", iface
, ref
);
4721 TLBImpLib
*pImpLib
, *pImpLibNext
;
4722 TLBRefType
*ref_type
, *ref_type_next
;
4723 TLBString
*tlbstr
, *tlbstr_next
;
4724 TLBGuid
*tlbguid
, *tlbguid_next
;
4727 /* remove cache entry */
4730 TRACE("removing from cache list\n");
4731 if(This
->entry
.next
)
4732 list_remove(&This
->entry
);
4735 TRACE(" destroying ITypeLib(%p)\n",This
);
4737 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4738 list_remove(&tlbstr
->entry
);
4739 SysFreeString(tlbstr
->str
);
4743 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4744 list_remove(&tlbstr
->entry
);
4745 SysFreeString(tlbstr
->str
);
4749 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4750 list_remove(&tlbguid
->entry
);
4754 TLB_FreeCustData(&This
->custdata_list
);
4756 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4757 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4758 free(This
->pTypeDesc
[i
].lpadesc
);
4760 free(This
->pTypeDesc
);
4762 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4764 if (pImpLib
->pImpTypeLib
)
4765 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4766 SysFreeString(pImpLib
->name
);
4768 list_remove(&pImpLib
->entry
);
4772 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4774 list_remove(&ref_type
->entry
);
4778 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4779 free(This
->typeinfos
[i
]->tdescAlias
);
4780 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4782 free(This
->typeinfos
);
4786 LeaveCriticalSection(&cache_section
);
4790 /* ITypeLib::GetTypeInfoCount
4792 * Returns the number of type descriptions in the type library
4794 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4796 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4797 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4798 return This
->TypeInfoCount
;
4801 /* ITypeLib::GetTypeInfo
4803 * retrieves the specified type description in the library.
4805 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4808 ITypeInfo
**ppTInfo
)
4810 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4812 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4815 return E_INVALIDARG
;
4817 if(index
>= This
->TypeInfoCount
)
4818 return TYPE_E_ELEMENTNOTFOUND
;
4820 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4821 ITypeInfo_AddRef(*ppTInfo
);
4827 /* ITypeLibs::GetTypeInfoType
4829 * Retrieves the type of a type description.
4831 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4836 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4838 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4841 return E_INVALIDARG
;
4843 if(index
>= This
->TypeInfoCount
)
4844 return TYPE_E_ELEMENTNOTFOUND
;
4846 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4851 /* ITypeLib::GetTypeInfoOfGuid
4853 * Retrieves the type description that corresponds to the specified GUID.
4856 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4859 ITypeInfo
**ppTInfo
)
4861 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4864 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4866 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4867 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4868 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4869 ITypeInfo_AddRef(*ppTInfo
);
4874 return TYPE_E_ELEMENTNOTFOUND
;
4877 /* ITypeLib::GetLibAttr
4879 * Retrieves the structure that contains the library's attributes.
4882 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4886 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4888 TRACE("(%p, %p)\n", This
, attr
);
4890 if (!attr
) return E_INVALIDARG
;
4892 *attr
= malloc(sizeof(**attr
));
4893 if (!*attr
) return E_OUTOFMEMORY
;
4895 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4896 (*attr
)->lcid
= This
->set_lcid
;
4897 (*attr
)->syskind
= This
->syskind
;
4898 (*attr
)->wMajorVerNum
= This
->ver_major
;
4899 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4900 (*attr
)->wLibFlags
= This
->libflags
;
4905 /* ITypeLib::GetTypeComp
4907 * Enables a client compiler to bind to a library's types, variables,
4908 * constants, and global functions.
4911 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4913 ITypeComp
**ppTComp
)
4915 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4917 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4918 *ppTComp
= &This
->ITypeComp_iface
;
4919 ITypeComp_AddRef(*ppTComp
);
4924 /* ITypeLib::GetDocumentation
4926 * Retrieves the library's documentation string, the complete Help file name
4927 * and path, and the context identifier for the library Help topic in the Help
4930 * On a successful return all non-null BSTR pointers will have been set,
4933 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4937 BSTR
*pBstrDocString
,
4938 DWORD
*pdwHelpContext
,
4939 BSTR
*pBstrHelpFile
)
4941 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4942 HRESULT result
= E_INVALIDARG
;
4945 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4947 pBstrName
, pBstrDocString
,
4948 pdwHelpContext
, pBstrHelpFile
);
4952 /* documentation for the typelib */
4957 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4965 if (This
->DocString
)
4967 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4971 *pBstrDocString
= NULL
;
4975 *pdwHelpContext
= This
->dwHelpContext
;
4981 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4985 *pBstrHelpFile
= NULL
;
4992 /* for a typeinfo */
4993 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4995 if(SUCCEEDED(result
))
4997 result
= ITypeInfo_GetDocumentation(pTInfo
,
5001 pdwHelpContext
, pBstrHelpFile
);
5003 ITypeInfo_Release(pTInfo
);
5008 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5010 if (pBstrName
) SysFreeString (*pBstrName
);
5012 return STG_E_INSUFFICIENTMEMORY
;
5017 * Indicates whether a passed-in string contains the name of a type or member
5018 * described in the library.
5021 static HRESULT WINAPI
ITypeLib2_fnIsName(
5027 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5029 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5031 TRACE("%p, %s, %#lx, %p.\n", iface
, debugstr_w(szNameBuf
), lHashVal
, pfName
);
5034 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5035 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5036 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5037 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5038 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5040 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5041 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5042 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5043 goto ITypeLib2_fnIsName_exit
;
5046 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5047 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5048 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5054 ITypeLib2_fnIsName_exit
:
5055 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5056 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5061 /* ITypeLib::FindName
5063 * Finds occurrences of a type description in a type library. This may be used
5064 * to quickly verify that a name exists in a type library.
5067 static HRESULT WINAPI
ITypeLib2_fnFindName(
5071 ITypeInfo
**ppTInfo
,
5075 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5080 TRACE("%p, %s %#lx, %p, %p, %p.\n", iface
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5082 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5083 return E_INVALIDARG
;
5085 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5086 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5087 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5091 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5092 memid
[count
] = MEMBERID_NIL
;
5093 goto ITypeLib2_fnFindName_exit
;
5096 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5097 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5099 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5100 memid
[count
] = func
->funcdesc
.memid
;
5101 goto ITypeLib2_fnFindName_exit
;
5105 var
= TLB_get_vardesc_by_name(pTInfo
, name
);
5107 memid
[count
] = var
->vardesc
.memid
;
5108 goto ITypeLib2_fnFindName_exit
;
5112 ITypeLib2_fnFindName_exit
:
5113 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5114 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5117 TRACE("found %d typeinfos\n", count
);
5124 /* ITypeLib::ReleaseTLibAttr
5126 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5129 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5131 TLIBATTR
*pTLibAttr
)
5133 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5134 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5138 /* ITypeLib2::GetCustData
5140 * gets the custom data
5142 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5147 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5148 TLBCustData
*pCData
;
5150 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5152 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5154 return TYPE_E_ELEMENTNOTFOUND
;
5156 VariantInit(pVarVal
);
5157 VariantCopy(pVarVal
, &pCData
->data
);
5162 /* ITypeLib2::GetLibStatistics
5164 * Returns statistics about a type library that are required for efficient
5165 * sizing of hash tables.
5168 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5170 ULONG
*pcUniqueNames
,
5171 ULONG
*pcchUniqueNames
)
5173 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5175 FIXME("(%p): stub!\n", This
);
5177 if(pcUniqueNames
) *pcUniqueNames
=1;
5178 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5182 /* ITypeLib2::GetDocumentation2
5184 * Retrieves the library's documentation string, the complete Help file name
5185 * and path, the localization context to use, and the context ID for the
5186 * library Help topic in the Help file.
5189 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5193 BSTR
*pbstrHelpString
,
5194 DWORD
*pdwHelpStringContext
,
5195 BSTR
*pbstrHelpStringDll
)
5197 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5201 FIXME("%p, %d, %#lx, partially implemented stub!\n", iface
, index
, lcid
);
5203 /* the help string should be obtained from the helpstringdll,
5204 * using the _DLLGetDocumentation function, based on the supplied
5205 * lcid. Nice to do sometime...
5209 /* documentation for the typelib */
5211 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5212 if(pdwHelpStringContext
)
5213 *pdwHelpStringContext
=This
->dwHelpContext
;
5214 if(pbstrHelpStringDll
)
5215 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5221 /* for a typeinfo */
5222 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5224 if(SUCCEEDED(result
))
5226 ITypeInfo2
* pTInfo2
;
5227 result
= ITypeInfo_QueryInterface(pTInfo
,
5229 (LPVOID
*) &pTInfo2
);
5231 if(SUCCEEDED(result
))
5233 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5237 pdwHelpStringContext
,
5238 pbstrHelpStringDll
);
5240 ITypeInfo2_Release(pTInfo2
);
5243 ITypeInfo_Release(pTInfo
);
5249 static HRESULT
TLB_copy_all_custdata(const struct list
*custdata_list
, CUSTDATA
*pCustData
)
5251 TLBCustData
*pCData
;
5256 ct
= list_count(custdata_list
);
5258 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5259 if(!pCustData
->prgCustData
)
5260 return E_OUTOFMEMORY
;
5262 pCustData
->cCustData
= ct
;
5264 cdi
= pCustData
->prgCustData
;
5265 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5266 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5267 VariantInit(&cdi
->varValue
);
5268 hr
= VariantCopy(&cdi
->varValue
, &pCData
->data
);
5269 if(FAILED(hr
)) break;
5277 /* ITypeLib2::GetAllCustData
5279 * Gets all custom data items for the library.
5282 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5284 CUSTDATA
*pCustData
)
5286 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5287 TRACE("(%p)->(%p)\n", This
, pCustData
);
5288 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5291 static const ITypeLib2Vtbl tlbvt
= {
5292 ITypeLib2_fnQueryInterface
,
5294 ITypeLib2_fnRelease
,
5295 ITypeLib2_fnGetTypeInfoCount
,
5296 ITypeLib2_fnGetTypeInfo
,
5297 ITypeLib2_fnGetTypeInfoType
,
5298 ITypeLib2_fnGetTypeInfoOfGuid
,
5299 ITypeLib2_fnGetLibAttr
,
5300 ITypeLib2_fnGetTypeComp
,
5301 ITypeLib2_fnGetDocumentation
,
5303 ITypeLib2_fnFindName
,
5304 ITypeLib2_fnReleaseTLibAttr
,
5306 ITypeLib2_fnGetCustData
,
5307 ITypeLib2_fnGetLibStatistics
,
5308 ITypeLib2_fnGetDocumentation2
,
5309 ITypeLib2_fnGetAllCustData
5313 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5315 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5317 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5320 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5322 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5324 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5327 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5329 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5331 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5334 static HRESULT WINAPI
ITypeLibComp_fnBind(
5339 ITypeInfo
** ppTInfo
,
5340 DESCKIND
* pDescKind
,
5343 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5344 BOOL typemismatch
= FALSE
;
5347 TRACE("%p, %s, %#lx, %#x, %p, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5349 *pDescKind
= DESCKIND_NONE
;
5350 pBindPtr
->lptcomp
= NULL
;
5353 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5354 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5355 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5357 /* FIXME: check wFlags here? */
5358 /* FIXME: we should use a hash table to look this info up using lHash
5359 * instead of an O(n) search */
5360 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5361 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5363 if (pTypeInfo
->Name
&& !wcscmp(pTypeInfo
->Name
->str
, szName
))
5365 *pDescKind
= DESCKIND_TYPECOMP
;
5366 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5367 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5368 TRACE("module or enum: %s\n", debugstr_w(szName
));
5373 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5374 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5376 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5379 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5380 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5382 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5385 else if (hr
== TYPE_E_TYPEMISMATCH
)
5386 typemismatch
= TRUE
;
5389 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5390 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5392 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5394 ITypeInfo
*subtypeinfo
;
5396 DESCKIND subdesckind
;
5398 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5399 &subtypeinfo
, &subdesckind
, &subbindptr
);
5400 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5402 TYPEDESC tdesc_appobject
;
5403 const VARDESC vardesc_appobject
=
5406 NULL
, /* lpstrSchema */
5421 VAR_STATIC
/* varkind */
5424 tdesc_appobject
.hreftype
= pTypeInfo
->hreftype
;
5425 tdesc_appobject
.vt
= VT_USERDEFINED
;
5427 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5429 /* cleanup things filled in by Bind call so we can put our
5430 * application object data in there instead */
5431 switch (subdesckind
)
5433 case DESCKIND_FUNCDESC
:
5434 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5436 case DESCKIND_VARDESC
:
5437 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5442 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5444 if (pTypeInfo
->hreftype
== -1)
5445 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5447 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5451 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5452 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5453 ITypeInfo_AddRef(*ppTInfo
);
5456 else if (hr
== TYPE_E_TYPEMISMATCH
)
5457 typemismatch
= TRUE
;
5463 TRACE("type mismatch %s\n", debugstr_w(szName
));
5464 return TYPE_E_TYPEMISMATCH
;
5468 TRACE("name not found %s\n", debugstr_w(szName
));
5473 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5477 ITypeInfo
** ppTInfo
,
5478 ITypeComp
** ppTComp
)
5480 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5481 ITypeInfoImpl
*info
;
5483 TRACE("%p, %s, %#lx, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5485 if(!szName
|| !ppTInfo
|| !ppTComp
)
5486 return E_INVALIDARG
;
5488 info
= TLB_get_typeinfo_by_name(This
, szName
);
5495 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5496 ITypeInfo_AddRef(*ppTInfo
);
5497 *ppTComp
= &info
->ITypeComp_iface
;
5498 ITypeComp_AddRef(*ppTComp
);
5503 static const ITypeCompVtbl tlbtcvt
=
5506 ITypeLibComp_fnQueryInterface
,
5507 ITypeLibComp_fnAddRef
,
5508 ITypeLibComp_fnRelease
,
5510 ITypeLibComp_fnBind
,
5511 ITypeLibComp_fnBindType
5514 /*================== ITypeInfo(2) Methods ===================================*/
5515 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5517 ITypeInfoImpl
*pTypeInfoImpl
;
5519 pTypeInfoImpl
= calloc(1, sizeof(ITypeInfoImpl
));
5522 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5523 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5524 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5525 pTypeInfoImpl
->ref
= 0;
5526 pTypeInfoImpl
->hreftype
= -1;
5527 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5528 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5529 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5530 list_init(pTypeInfoImpl
->pcustdata_list
);
5532 TRACE("(%p)\n", pTypeInfoImpl
);
5533 return pTypeInfoImpl
;
5536 /* ITypeInfo::QueryInterface
5538 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5543 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5545 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5548 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5549 IsEqualIID(riid
,&IID_ITypeInfo
)||
5550 IsEqualIID(riid
,&IID_ITypeInfo2
))
5551 *ppvObject
= &This
->ITypeInfo2_iface
;
5552 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5553 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5554 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5555 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5556 *ppvObject
= &This
->ITypeComp_iface
;
5559 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5560 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5563 TRACE("-- Interface: E_NOINTERFACE\n");
5564 return E_NOINTERFACE
;
5567 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5569 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5570 ULONG ref
= InterlockedIncrement(&This
->ref
);
5572 TRACE("%p, refcount %lu.\n", iface
, ref
);
5574 if (ref
== 1 /* incremented from 0 */)
5575 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5580 static void typeinfo_release_funcdesc(TLBFuncDesc
*func
)
5584 for (i
= 0; i
< func
->funcdesc
.cParams
; ++i
)
5586 ELEMDESC
*elemdesc
= &func
->funcdesc
.lprgelemdescParam
[i
];
5587 if (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5588 VariantClear(&elemdesc
->paramdesc
.pparamdescex
->varDefaultValue
);
5589 TLB_FreeCustData(&func
->pParamDesc
[i
].custdata_list
);
5591 free(func
->funcdesc
.lprgelemdescParam
);
5592 free(func
->pParamDesc
);
5593 TLB_FreeCustData(&func
->custdata_list
);
5596 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5600 TRACE("destroying ITypeInfo(%p)\n",This
);
5602 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5604 typeinfo_release_funcdesc(&This
->funcdescs
[i
]);
5606 free(This
->funcdescs
);
5608 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5610 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5611 if (pVInfo
->vardesc_create
) {
5612 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5613 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5614 VariantClear(pVInfo
->vardesc
.lpvarValue
);
5615 free(pVInfo
->vardesc
.lpvarValue
);
5617 TLB_FreeCustData(&pVInfo
->custdata_list
);
5619 free(This
->vardescs
);
5621 if(This
->impltypes
){
5622 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5623 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5624 TLB_FreeCustData(&pImpl
->custdata_list
);
5626 free(This
->impltypes
);
5629 TLB_FreeCustData(&This
->custdata_list
);
5634 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5636 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5637 ULONG ref
= InterlockedDecrement(&This
->ref
);
5639 TRACE("%p, refcount %lu.\n", iface
, ref
);
5643 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5644 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5645 if (not_attached_to_typelib
)
5647 /* otherwise This will be freed when typelib is freed */
5653 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5654 LPTYPEATTR
*ppTypeAttr
)
5656 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5659 TRACE("(%p)\n",This
);
5661 size
= sizeof(**ppTypeAttr
);
5662 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5663 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5665 *ppTypeAttr
= malloc(size
);
5667 return E_OUTOFMEMORY
;
5669 **ppTypeAttr
= This
->typeattr
;
5670 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5672 if (This
->tdescAlias
)
5673 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5675 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5676 /* This should include all the inherited funcs */
5677 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5678 /* This is always the size of IDispatch's vtbl */
5679 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5680 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5685 /* ITypeInfo::GetTypeComp
5687 * Retrieves the ITypeComp interface for the type description, which enables a
5688 * client compiler to bind to the type description's members.
5691 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5692 ITypeComp
* *ppTComp
)
5694 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5696 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5698 *ppTComp
= &This
->ITypeComp_iface
;
5699 ITypeComp_AddRef(*ppTComp
);
5703 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5705 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5706 if (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5707 size
+= sizeof(*elemdesc
->paramdesc
.pparamdescex
);
5711 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5714 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5715 if (src
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5717 const PARAMDESCEX
*pparamdescex_src
= src
->paramdesc
.pparamdescex
;
5718 PARAMDESCEX
*pparamdescex_dest
= dest
->paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5719 *buffer
+= sizeof(PARAMDESCEX
);
5720 *pparamdescex_dest
= *pparamdescex_src
;
5721 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5722 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5723 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5724 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5727 dest
->paramdesc
.pparamdescex
= NULL
;
5731 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5733 if (V_VT(var
) == VT_INT
)
5734 return VariantChangeType(var
, var
, 0, VT_I4
);
5735 else if (V_VT(var
) == VT_UINT
)
5736 return VariantChangeType(var
, var
, 0, VT_UI4
);
5741 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5743 if (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5744 VariantClear(&elemdesc
->paramdesc
.pparamdescex
->varDefaultValue
);
5747 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5751 SIZE_T size
= sizeof(*src
);
5755 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5756 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5757 for (i
= 0; i
< src
->cParams
; i
++)
5759 size
+= sizeof(ELEMDESC
);
5760 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5763 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5764 if (!dest
) return E_OUTOFMEMORY
;
5767 if (dispinterface
) /* overwrite funckind */
5768 dest
->funckind
= FUNC_DISPATCH
;
5769 buffer
= (char *)(dest
+ 1);
5771 dest
->oVft
= dest
->oVft
& 0xFFFC;
5773 if (dest
->cScodes
) {
5774 dest
->lprgscode
= (SCODE
*)buffer
;
5775 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5776 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5778 dest
->lprgscode
= NULL
;
5780 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5783 SysFreeString((BSTR
)dest
);
5787 if (dest
->cParams
) {
5788 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5789 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5790 for (i
= 0; i
< src
->cParams
; i
++)
5792 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5798 /* undo the above actions */
5799 for (i
= i
- 1; i
>= 0; i
--)
5800 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5801 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5802 SysFreeString((BSTR
)dest
);
5806 dest
->lprgelemdescParam
= NULL
;
5808 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5809 * This accounts for several arguments that are separate in the signature of
5810 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5811 if (dispinterface
&& (src
->funckind
!= FUNC_DISPATCH
))
5813 /* functions that have a [retval] parameter return this value into pVarResult.
5814 * [retval] is always the last parameter (if present) */
5815 if (dest
->cParams
&&
5816 (dest
->lprgelemdescParam
[dest
->cParams
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5818 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5819 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5821 ERR("elemdesc should have started with VT_PTR instead of:\n");
5823 dump_ELEMDESC(elemdesc
);
5824 return E_UNEXPECTED
;
5827 /* the type pointed to by this [retval] becomes elemdescFunc,
5828 * i.e. the function signature's return type.
5829 * We are using a flat buffer so there is no danger of leaking memory */
5830 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.lptdesc
;
5832 /* remove the last parameter */
5835 else if (dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5836 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5837 * not pVarResult. So the function signature should show no return value. */
5838 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5840 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5841 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5842 if (dest
->cParams
&& (dest
->lprgelemdescParam
[dest
->cParams
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
5850 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5852 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5853 if (var_desc
->varkind
== VAR_CONST
)
5854 VariantClear(var_desc
->lpvarValue
);
5855 SysFreeString((BSTR
)var_desc
);
5858 /* internal function to make the inherited interfaces' methods appear
5859 * part of the interface */
5860 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5861 UINT index
, const TLBFuncDesc
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5863 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5865 UINT implemented_funcs
= 0;
5870 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5874 ITypeInfo
*pSubTypeInfo
;
5877 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5881 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5884 &sub_funcs
, hrefoffset
);
5885 implemented_funcs
+= sub_funcs
;
5886 ITypeInfo_Release(pSubTypeInfo
);
5889 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5893 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5897 if (index
< implemented_funcs
)
5898 return E_INVALIDARG
;
5899 index
-= implemented_funcs
;
5901 if (index
>= This
->typeattr
.cFuncs
)
5902 return TYPE_E_ELEMENTNOTFOUND
;
5904 *ppFuncDesc
= &This
->funcdescs
[index
];
5908 static HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const TLBFuncDesc
**func_desc
, UINT
*hrefoffset
)
5910 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5912 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5913 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface
, index
, func_desc
, NULL
, hrefoffset
);
5915 if (index
>= This
->typeattr
.cFuncs
)
5916 return TYPE_E_ELEMENTNOTFOUND
;
5918 *func_desc
= &This
->funcdescs
[index
];
5922 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5924 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5927 switch (pTypeDesc
->vt
)
5929 case VT_USERDEFINED
:
5930 pTypeDesc
->hreftype
+= hrefoffset
;
5934 pTypeDesc
= pTypeDesc
->lptdesc
;
5937 pTypeDesc
= &pTypeDesc
->lpadesc
->tdescElem
;
5945 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5948 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5949 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5950 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5953 /* ITypeInfo::GetFuncDesc
5955 * Retrieves the FUNCDESC structure that contains information about a
5956 * specified function.
5959 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5960 LPFUNCDESC
*ppFuncDesc
)
5962 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5963 const TLBFuncDesc
*internal_funcdesc
;
5965 UINT hrefoffset
= 0;
5967 TRACE("(%p) index %d\n", This
, index
);
5970 return E_INVALIDARG
;
5972 if (This
->needs_layout
)
5973 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5975 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5976 &internal_funcdesc
, &hrefoffset
);
5979 WARN("description for function %d not found\n", index
);
5983 hr
= TLB_AllocAndInitFuncDesc(
5984 &internal_funcdesc
->funcdesc
,
5986 This
->typeattr
.typekind
== TKIND_DISPATCH
);
5988 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5989 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5991 TRACE("-- %#lx.\n", hr
);
5995 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
5999 SIZE_T size
= sizeof(*src
);
6002 if (src
->lpstrSchema
) size
+= (lstrlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6003 if (src
->varkind
== VAR_CONST
)
6004 size
+= sizeof(VARIANT
);
6005 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6007 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6008 if (!dest
) return E_OUTOFMEMORY
;
6011 buffer
= (char *)(dest
+ 1);
6012 if (src
->lpstrSchema
)
6015 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6016 len
= lstrlenW(src
->lpstrSchema
);
6017 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6018 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6021 if (src
->varkind
== VAR_CONST
)
6025 dest
->lpvarValue
= (VARIANT
*)buffer
;
6026 *dest
->lpvarValue
= *src
->lpvarValue
;
6027 buffer
+= sizeof(VARIANT
);
6028 VariantInit(dest
->lpvarValue
);
6029 hr
= VariantCopy(dest
->lpvarValue
, src
->lpvarValue
);
6032 SysFreeString((BSTR
)dest
);
6036 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6039 if (src
->varkind
== VAR_CONST
)
6040 VariantClear(dest
->lpvarValue
);
6041 SysFreeString((BSTR
)dest
);
6048 /* ITypeInfo::GetVarDesc
6050 * Retrieves a VARDESC structure that describes the specified variable.
6053 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6054 LPVARDESC
*ppVarDesc
)
6056 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6057 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6059 TRACE("(%p) index %d\n", This
, index
);
6061 if(index
>= This
->typeattr
.cVars
)
6062 return TYPE_E_ELEMENTNOTFOUND
;
6064 if (This
->needs_layout
)
6065 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6067 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6070 /* internal function to make the inherited interfaces' methods appear
6071 * part of the interface, remembering if the top-level was dispinterface */
6072 static HRESULT
typeinfo_getnames( ITypeInfo
*iface
, MEMBERID memid
, BSTR
*names
,
6073 UINT max_names
, UINT
*num_names
, BOOL dispinterface
)
6075 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
6076 const TLBFuncDesc
*func_desc
;
6077 const TLBVarDesc
*var_desc
;
6082 func_desc
= TLB_get_funcdesc_by_memberid(This
, memid
);
6085 UINT params
= func_desc
->funcdesc
.cParams
;
6086 if (!max_names
|| !func_desc
->Name
)
6089 *names
= SysAllocString(TLB_get_bstr(func_desc
->Name
));
6092 if (dispinterface
&& (func_desc
->funcdesc
.funckind
!= FUNC_DISPATCH
))
6094 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6095 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
6096 --params
; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6097 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
6098 --params
; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6101 for (i
= 0; i
< params
; i
++)
6103 if (*num_names
>= max_names
|| !func_desc
->pParamDesc
[i
].Name
)
6105 names
[*num_names
] = SysAllocString(TLB_get_bstr(func_desc
->pParamDesc
[i
].Name
));
6111 var_desc
= TLB_get_vardesc_by_memberid(This
, memid
);
6114 *names
= SysAllocString(TLB_get_bstr(var_desc
->Name
));
6119 if (This
->impltypes
&&
6120 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
))
6122 /* recursive search */
6125 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &parent
);
6126 if (SUCCEEDED(result
))
6128 result
= typeinfo_getnames(parent
, memid
, names
, max_names
, num_names
, dispinterface
);
6129 ITypeInfo_Release(parent
);
6132 WARN("Could not search inherited interface!\n");
6136 WARN("no names found\n");
6139 return TYPE_E_ELEMENTNOTFOUND
;
6144 /* ITypeInfo_GetNames
6146 * Retrieves the variable with the specified member ID (or the name of the
6147 * property or method and its parameters) that correspond to the specified
6150 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6151 BSTR
*names
, UINT max_names
, UINT
*num_names
)
6153 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6155 TRACE("%p, %#lx, %p, %d, %p\n", iface
, memid
, names
, max_names
, num_names
);
6157 if (!names
) return E_INVALIDARG
;
6159 return typeinfo_getnames((ITypeInfo
*)iface
, memid
, names
, max_names
, num_names
,
6160 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6163 /* ITypeInfo::GetRefTypeOfImplType
6165 * If a type description describes a COM class, it retrieves the type
6166 * description of the implemented interface types. For an interface,
6167 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6171 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6176 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6179 TRACE("(%p) index %d\n", This
, index
);
6180 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6184 /* only valid on dual interfaces;
6185 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6188 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6194 hr
= TYPE_E_ELEMENTNOTFOUND
;
6197 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6199 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6200 *pRefType
= This
->pTypeLib
->dispatch_href
;
6204 if(index
>= This
->typeattr
.cImplTypes
)
6205 hr
= TYPE_E_ELEMENTNOTFOUND
;
6207 *pRefType
= This
->impltypes
[index
].hRef
;
6208 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6216 TRACE("SUCCESS -- hRef %#lx.\n", *pRefType
);
6218 TRACE("FAILURE -- hresult %#lx.\n", hr
);
6224 /* ITypeInfo::GetImplTypeFlags
6226 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6227 * or base interface in a type description.
6229 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6230 UINT index
, INT
*pImplTypeFlags
)
6232 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6234 TRACE("(%p) index %d\n", This
, index
);
6237 return E_INVALIDARG
;
6239 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6240 *pImplTypeFlags
= 0;
6244 if(index
>= This
->typeattr
.cImplTypes
)
6245 return TYPE_E_ELEMENTNOTFOUND
;
6247 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6253 * Maps between member names and member IDs, and parameter names and
6256 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6257 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6259 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6260 const TLBVarDesc
*pVDesc
;
6264 TRACE("%p, %s, %d.\n", iface
, debugstr_w(*rgszNames
), cNames
);
6266 /* init out parameters in case of failure */
6267 for (i
= 0; i
< cNames
; i
++)
6268 pMemId
[i
] = MEMBERID_NIL
;
6270 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6272 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6273 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6274 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6275 for(i
=1; i
< cNames
; i
++){
6276 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6277 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6279 if( j
<pFDesc
->funcdesc
.cParams
)
6282 ret
=DISP_E_UNKNOWNNAME
;
6284 TRACE("-- %#lx.\n", ret
);
6288 pVDesc
= TLB_get_vardesc_by_name(This
, *rgszNames
);
6291 *pMemId
= pVDesc
->vardesc
.memid
;
6294 /* not found, see if it can be found in an inherited interface */
6295 if(This
->impltypes
) {
6296 /* recursive search */
6298 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6300 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6301 ITypeInfo_Release(pTInfo
);
6304 WARN("Could not search inherited interface!\n");
6306 WARN("no names found\n");
6307 return DISP_E_UNKNOWNNAME
;
6313 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6314 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6316 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6317 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6319 int argspos
= 0, stack_offset
;
6324 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6325 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6326 pvargResult
, V_VT(pvargResult
));
6328 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6330 FIXME("unsupported calling convention %d\n",cc
);
6331 return E_INVALIDARG
;
6334 /* maximum size for an argument is sizeof(VARIANT) */
6335 args
= malloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6339 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6340 func
= vtable
[oVft
/sizeof(void *)];
6341 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6343 else func
= (void *)oVft
;
6349 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6352 WARN("invalid return type %u\n", vtReturn
);
6354 return E_INVALIDARG
;
6359 for (i
= 0; i
< cActuals
; i
++)
6361 VARIANT
*arg
= prgpvarg
[i
];
6372 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6373 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6377 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6378 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6380 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6381 args
[argspos
++] = V_BOOL(arg
);
6384 args
[argspos
++] = V_UI4(arg
);
6387 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6395 call_method( func
, argspos
, args
, &stack_offset
);
6398 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6402 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6407 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6410 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6414 if (stack_offset
&& cc
== CC_STDCALL
)
6416 WARN( "stack pointer off by %d\n", stack_offset
);
6417 return DISP_E_BADCALLEE
;
6419 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6420 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6424 #elif defined(__x86_64__)
6426 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6427 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6429 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6430 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6437 TRACE("%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d).\n",
6438 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6439 pvargResult
, V_VT(pvargResult
));
6441 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6443 FIXME("unsupported calling convention %d\n",cc
);
6444 return E_INVALIDARG
;
6447 /* maximum size for an argument is sizeof(DWORD_PTR) */
6448 args
= malloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6452 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6453 func
= vtable
[oVft
/sizeof(void *)];
6454 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6456 else func
= (void *)oVft
;
6462 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6465 WARN("invalid return type %u\n", vtReturn
);
6467 return E_INVALIDARG
;
6472 for (i
= 0; i
< cActuals
; i
++)
6474 VARIANT
*arg
= prgpvarg
[i
];
6480 args
[argspos
++] = (ULONG_PTR
)arg
;
6482 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6483 args
[argspos
++] = V_BOOL(arg
);
6486 args
[argspos
++] = V_UI8(arg
);
6489 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6495 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6499 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6503 call_method( func
, argspos
, args
);
6506 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6510 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6511 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6515 #elif defined(__arm__)
6517 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6518 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6519 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6521 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6522 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6535 int rcount
; /* 32-bit register index count */
6536 int scount
= 0; /* single-precision float register index count */
6537 int dcount
= 0; /* double-precision float register index count */
6539 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6540 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6542 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6544 FIXME("unsupported calling convention %d\n",cc
);
6545 return E_INVALIDARG
;
6553 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6554 func
= vtable
[oVft
/sizeof(void *)];
6555 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6557 else func
= (void *)oVft
;
6559 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6560 /* first as it will need to be in the 'r' registers: */
6565 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6568 WARN("invalid return type %u\n", vtReturn
);
6569 return E_INVALIDARG
;
6570 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6574 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6575 args
= malloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6577 for (i
= 0; i
< cActuals
; i
++)
6579 VARIANT
*arg
= prgpvarg
[i
];
6580 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6581 int ntemp
; /* Used for counting words split between registers and stack */
6585 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6587 dcount
= max( (scount
+ 1) / 2, dcount
);
6590 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6594 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6595 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6596 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6599 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6604 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6605 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6606 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6610 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6611 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6612 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6613 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6616 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6618 /* 8-byte align 'r' and/or stack: */
6620 rcount
+= (rcount
% 2);
6624 argspos
+= (argspos
% 2);
6626 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6630 regs
.r
[rcount
++] = *pdwarg
++;
6632 args
[argspos
++] = *pdwarg
++;
6636 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6637 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6639 regs
.sd
.s
[scount
++] = V_R4(arg
);
6641 args
[argspos
++] = V_UI4(arg
);
6643 /* extend parameters to 32 bits */
6645 if (rcount
< 4) regs
.r
[rcount
++] = V_I1(arg
);
6646 else args
[argspos
++] = V_I1(arg
);
6649 if (rcount
< 4) regs
.r
[rcount
++] = V_UI1(arg
);
6650 else args
[argspos
++] = V_UI1(arg
);
6653 if (rcount
< 4) regs
.r
[rcount
++] = V_I2(arg
);
6654 else args
[argspos
++] = V_I2(arg
);
6657 if (rcount
< 4) regs
.r
[rcount
++] = V_UI2(arg
);
6658 else args
[argspos
++] = V_UI2(arg
);
6661 if (rcount
< 4) regs
.r
[rcount
++] = V_BOOL(arg
);
6662 else args
[argspos
++] = V_BOOL(arg
);
6665 if (rcount
< 4) regs
.r
[rcount
++] = V_UI4(arg
);
6666 else args
[argspos
++] = V_UI4(arg
);
6669 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6672 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
6676 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6678 call_method( func
, argspos
, args
, (DWORD
*)®s
);
6681 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
6685 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
6690 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6693 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6697 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6698 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6702 #elif defined(__aarch64__)
6704 extern DWORD_PTR CDECL
call_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6705 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6706 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6708 HRESULT WINAPI
DispCallFunc( void *instance
, ULONG_PTR offset
, CALLCONV cc
, VARTYPE ret_type
, UINT count
,
6709 VARTYPE
*types
, VARIANTARG
**vargs
, VARIANT
*result
)
6724 int rcount
; /* 64-bit register index count */
6725 int fpcount
= 0; /* float register index count */
6727 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6728 instance
, offset
, cc
, ret_type
, count
, types
, vargs
, result
, V_VT(result
));
6730 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6732 FIXME("unsupported calling convention %d\n",cc
);
6733 return E_INVALIDARG
;
6741 const FARPROC
*vtable
= *(FARPROC
**)instance
;
6742 func
= vtable
[offset
/sizeof(void *)];
6743 regs
.x
[rcount
++] = (DWORD_PTR
)instance
; /* the This pointer is always the first parameter */
6745 else func
= (void *)offset
;
6747 /* maximum size for an argument is 16 */
6748 args
= malloc( 16 * count
);
6750 for (i
= 0; i
< count
; i
++)
6752 VARIANT
*arg
= vargs
[i
];
6757 if (fpcount
< 8) regs
.fp
[fpcount
++].f
= V_R4(arg
);
6758 else *(float *)&args
[argspos
++] = V_R4(arg
);
6762 if (fpcount
< 8) regs
.fp
[fpcount
++].d
= V_R8(arg
);
6763 else *(double *)&args
[argspos
++] = V_R8(arg
);
6768 memcpy( ®s
.x
[rcount
], arg
, sizeof(*arg
) );
6773 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6778 if (rcount
< 8) regs
.x
[rcount
++] = (DWORD_PTR
)arg
;
6779 else args
[argspos
++] = (DWORD_PTR
)arg
;
6781 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6782 if (rcount
< 8) regs
.x
[rcount
++] = V_BOOL(arg
);
6783 else args
[argspos
++] = V_BOOL(arg
);
6786 if (rcount
< 8) regs
.x
[rcount
++] = V_UI8(arg
);
6787 else args
[argspos
++] = V_UI8(arg
);
6790 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(types
[i
]), debugstr_variant(arg
));
6793 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 16-byte */
6799 return E_INVALIDARG
;
6802 regs
.x
[8] = (DWORD_PTR
)result
; /* x8 is a pointer to the result */
6803 call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6806 V_R4(result
) = call_float_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6810 V_R8(result
) = call_double_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6813 V_UI8(result
) = call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6817 if (ret_type
!= VT_VARIANT
) V_VT(result
) = ret_type
;
6818 TRACE("retval: %s\n", debugstr_variant(result
));
6822 #else /* __aarch64__ */
6824 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6825 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6827 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6828 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6834 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6837 ITypeInfo
*tinfo2
= NULL
;
6838 TYPEATTR
*tattr
= NULL
;
6840 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->hreftype
, &tinfo2
);
6843 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, hr %#lx.\n", tdesc
->hreftype
, hr
);
6846 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6849 ERR("ITypeInfo_GetTypeAttr failed, hr %#lx.\n", hr
);
6850 ITypeInfo_Release(tinfo2
);
6854 switch (tattr
->typekind
)
6861 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6864 case TKIND_INTERFACE
:
6865 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6871 case TKIND_DISPATCH
:
6880 FIXME("TKIND_RECORD unhandled.\n");
6885 FIXME("TKIND_UNION unhandled.\n");
6890 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6894 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6895 ITypeInfo_Release(tinfo2
);
6899 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6903 /* enforce only one level of pointer indirection */
6904 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6906 tdesc
= tdesc
->lptdesc
;
6908 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6909 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6910 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6911 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6912 ((tdesc
->vt
== VT_PTR
) && (tdesc
->lptdesc
->vt
== VT_USERDEFINED
)))
6914 VARTYPE vt_userdefined
= 0;
6915 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6916 if (tdesc
->vt
== VT_PTR
)
6918 vt_userdefined
= VT_BYREF
;
6919 tdesc_userdefined
= tdesc
->lptdesc
;
6921 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6923 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6924 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6926 *vt
|= vt_userdefined
;
6938 case VT_USERDEFINED
:
6939 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6946 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6947 hr
= DISP_E_BADVARTYPE
;
6951 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->lptdesc
, vt
);
6966 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
6973 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
6977 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6979 ITypeInfo_Release(tinfo2
);
6983 switch(tattr
->typekind
) {
6985 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.hreftype
, guid
);
6988 case TKIND_INTERFACE
:
6989 case TKIND_DISPATCH
:
6990 *guid
= tattr
->guid
;
6994 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
6996 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
6997 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
7001 if (i
== tattr
->cImplTypes
)
7004 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
7005 if (SUCCEEDED(hres
))
7006 hres
= get_iface_guid(tinfo2
, href
, guid
);
7010 ERR("Unexpected typekind %d\n", tattr
->typekind
);
7011 hres
= E_UNEXPECTED
;
7014 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7015 ITypeInfo_Release(tinfo2
);
7019 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7021 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7024 #define INVBUF_ELEMENT_SIZE \
7025 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7026 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7027 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7028 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7029 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7030 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7031 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7032 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7034 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7039 DISPPARAMS
*pDispParams
,
7040 VARIANT
*pVarResult
,
7041 EXCEPINFO
*pExcepInfo
,
7044 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7046 unsigned int var_index
;
7049 const TLBFuncDesc
*pFuncInfo
;
7052 TRACE("%p, %p, %ld, %#x, %p, %p, %p, %p.\n", iface
, pIUnk
, memid
, wFlags
, pDispParams
,
7053 pVarResult
, pExcepInfo
, pArgErr
);
7055 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7056 return DISP_E_MEMBERNOTFOUND
;
7060 ERR("NULL pDispParams not allowed\n");
7061 return E_INVALIDARG
;
7064 dump_DispParms(pDispParams
);
7066 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7068 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7069 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7070 return E_INVALIDARG
;
7073 /* we do this instead of using GetFuncDesc since it will return a fake
7074 * FUNCDESC for dispinterfaces and we want the real function description */
7075 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7076 pFuncInfo
= &This
->funcdescs
[fdc
];
7077 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7078 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7079 !func_restricted( &pFuncInfo
->funcdesc
))
7083 if (fdc
< This
->typeattr
.cFuncs
) {
7084 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7088 TRACE("invoking:\n");
7089 dump_TLBFuncDescOne(pFuncInfo
);
7092 switch (func_desc
->funckind
) {
7093 case FUNC_PUREVIRTUAL
:
7094 case FUNC_VIRTUAL
: {
7095 void *buffer
= calloc(func_desc
->cParams
, INVBUF_ELEMENT_SIZE
);
7097 VARIANT retval
= {{{0}}}; /* pointer for storing byref retvals in */
7098 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7099 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7100 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7101 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7102 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7103 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7104 UINT vargs_converted
=0;
7109 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7111 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7113 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7114 hres
= DISP_E_PARAMNOTFOUND
;
7119 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7121 ERR("functions with the vararg attribute do not support named arguments\n");
7122 hres
= DISP_E_NONAMEDARGS
;
7126 for (i
= 0; i
< func_desc
->cParams
; i
++)
7128 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7129 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7134 TRACE("changing args\n");
7135 for (i
= 0; i
< func_desc
->cParams
; i
++)
7137 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
;
7138 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7139 VARIANTARG
*src_arg
;
7141 if (wParamFlags
& PARAMFLAG_FLCID
)
7143 prgpvarg
[i
] = &rgvarg
[i
];
7144 V_VT(prgpvarg
[i
]) = VT_I4
;
7145 V_I4(prgpvarg
[i
]) = This
->pTypeLib
->lcid
;
7151 for (j
= 0; j
< cNamedArgs
; j
++)
7153 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7155 src_arg
= &pDispParams
->rgvarg
[j
];
7160 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7162 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7166 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7168 /* under most conditions the caller is not allowed to
7169 * pass in a dispparam arg in the index of what would be
7170 * the retval parameter. however, there is an exception
7171 * where the extra parameter is used in an extra
7172 * IDispatch::Invoke below */
7173 if ((i
< pDispParams
->cArgs
) &&
7174 ((func_desc
->cParams
!= 1) || !pVarResult
||
7175 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7177 hres
= DISP_E_BADPARAMCOUNT
;
7181 /* note: this check is placed so that if the caller passes
7182 * in a VARIANTARG for the retval we just ignore it, like
7184 if (i
== func_desc
->cParams
- 1)
7186 prgpvarg
[i
] = &rgvarg
[i
];
7187 V_BYREF(prgpvarg
[i
]) = &retval
;
7188 V_VT(prgpvarg
[i
]) = rgvt
[i
];
7192 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7193 hres
= E_UNEXPECTED
;
7197 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7198 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7200 TRACE("%s\n", debugstr_variant(src_arg
));
7202 if(rgvt
[i
]!=V_VT(src_arg
))
7204 if (rgvt
[i
] == VT_VARIANT
)
7205 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7206 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7208 if (rgvt
[i
] == V_VT(src_arg
))
7209 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7212 if (wParamFlags
& PARAMFLAG_FIN
)
7213 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7214 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7216 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7218 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7220 SAFEARRAYBOUND bound
;
7224 bound
.cElements
= pDispParams
->cArgs
-i
;
7225 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7227 ERR("SafeArrayCreate failed\n");
7230 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7233 ERR("SafeArrayAccessData failed with %#lx.\n", hres
);
7234 SafeArrayDestroy(a
);
7237 for (j
= 0; j
< bound
.cElements
; j
++)
7238 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7239 hres
= SafeArrayUnaccessData(a
);
7242 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres
);
7243 SafeArrayDestroy(a
);
7246 if (rgvt
[i
] & VT_BYREF
)
7247 V_BYREF(&rgvarg
[i
]) = &a
;
7249 V_ARRAY(&rgvarg
[i
]) = a
;
7250 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7252 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7254 if (wParamFlags
& PARAMFLAG_FIN
)
7255 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7257 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7258 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7259 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7261 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7263 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7264 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7268 /* FIXME: this doesn't work for VT_BYREF arguments if
7269 * they are not the same type as in the paramdesc */
7270 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7271 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7272 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7277 ERR("failed to convert param %d to %s from %s\n", i
,
7278 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7281 prgpvarg
[i
] = &rgvarg
[i
];
7285 prgpvarg
[i
] = src_arg
;
7288 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->lptdesc
->vt
== VT_USERDEFINED
))
7289 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7290 && V_UNKNOWN(prgpvarg
[i
])) {
7291 IUnknown
*userdefined_iface
;
7294 if (tdesc
->vt
== VT_PTR
)
7295 tdesc
= tdesc
->lptdesc
;
7297 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->hreftype
, &guid
);
7301 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7303 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7307 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7308 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7311 else if (wParamFlags
& PARAMFLAG_FOPT
)
7314 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7315 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7317 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].paramdesc
.pparamdescex
->varDefaultValue
);
7323 /* if the function wants a pointer to a variant then
7324 * set that up, otherwise just pass the VT_ERROR in
7325 * the argument by value */
7326 if (rgvt
[i
] & VT_BYREF
)
7328 V_VT(&missing_arg
[i
]) = VT_ERROR
;
7329 V_ERROR(&missing_arg
[i
]) = DISP_E_PARAMNOTFOUND
;
7331 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7332 V_VARIANTREF(arg
) = &missing_arg
[i
];
7336 V_VT(arg
) = VT_ERROR
;
7337 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
7341 else if (func_desc
->cParamsOpt
< 0 && ((rgvt
[i
] & ~VT_BYREF
) == (VT_VARIANT
| VT_ARRAY
)))
7343 hres
= SafeArrayAllocDescriptorEx( VT_EMPTY
, 1, &a
);
7344 if (FAILED(hres
)) break;
7345 if (rgvt
[i
] & VT_BYREF
)
7346 V_BYREF(&rgvarg
[i
]) = &a
;
7348 V_ARRAY(&rgvarg
[i
]) = a
;
7349 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7350 prgpvarg
[i
] = &rgvarg
[i
];
7354 hres
= DISP_E_BADPARAMCOUNT
;
7358 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7360 /* VT_VOID is a special case for return types, so it is not
7361 * handled in the general function */
7362 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7363 V_VT(&varresult
) = VT_EMPTY
;
7366 V_VT(&varresult
) = 0;
7367 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7368 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7371 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7372 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7373 prgpvarg
, &varresult
);
7375 vargs_converted
= 0;
7377 for (i
= 0; i
< func_desc
->cParams
; i
++)
7379 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
;
7381 if (wParamFlags
& PARAMFLAG_FLCID
)
7383 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7385 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7389 VariantInit(pVarResult
);
7390 /* deref return value */
7391 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7394 VARIANT_ClearInd(prgpvarg
[i
]);
7396 else if (vargs_converted
< pDispParams
->cArgs
)
7398 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7399 if (wParamFlags
& PARAMFLAG_FOUT
)
7401 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7403 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7407 ERR("failed to convert param %d to vt %d\n", i
,
7408 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7413 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7414 func_desc
->cParamsOpt
< 0 &&
7415 i
== func_desc
->cParams
-1)
7417 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7420 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7423 ERR("SafeArrayGetUBound failed with %#lx.\n", hres
);
7426 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7429 ERR("SafeArrayAccessData failed with %#lx.\n", hres
);
7432 for (j
= 0; j
<= ubound
; j
++)
7433 VariantClear(&v
[j
]);
7434 hres
= SafeArrayUnaccessData(a
);
7437 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres
);
7441 VariantClear(&rgvarg
[i
]);
7444 else if (wParamFlags
& PARAMFLAG_FOPT
)
7446 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7447 VariantClear(&rgvarg
[i
]);
7450 VariantClear(&missing_arg
[i
]);
7453 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7455 WARN("invoked function failed with error %#lx.\n", V_ERROR(&varresult
));
7456 hres
= DISP_E_EXCEPTION
;
7459 IErrorInfo
*pErrorInfo
;
7460 pExcepInfo
->scode
= V_ERROR(&varresult
);
7461 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7463 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7464 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7465 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7466 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7468 IErrorInfo_Release(pErrorInfo
);
7472 if (V_VT(&varresult
) != VT_ERROR
)
7474 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7478 VariantClear(pVarResult
);
7479 *pVarResult
= varresult
;
7482 VariantClear(&varresult
);
7485 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7486 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7487 (func_desc
->lprgelemdescParam
[0].paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7488 (pDispParams
->cArgs
!= 0))
7490 if (V_VT(pVarResult
) == VT_DISPATCH
)
7492 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7493 /* Note: not VariantClear; we still need the dispatch
7494 * pointer to be valid */
7495 VariantInit(pVarResult
);
7496 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7497 GetSystemDefaultLCID(), wFlags
,
7498 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7499 IDispatch_Release(pDispatch
);
7503 VariantClear(pVarResult
);
7504 hres
= DISP_E_NOTACOLLECTION
;
7512 case FUNC_DISPATCH
: {
7515 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7516 if (SUCCEEDED(hres
)) {
7517 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7518 hres
= IDispatch_Invoke(
7519 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7520 pVarResult
,pExcepInfo
,pArgErr
7523 FIXME("IDispatch::Invoke failed with %#lx. (Could be not a real error?)\n", hres
);
7524 IDispatch_Release(disp
);
7526 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7530 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7535 TRACE("-- %#lx\n", hres
);
7538 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7541 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7542 if(FAILED(hres
)) return hres
;
7544 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7545 dump_VARDESC(var_desc
);
7546 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7550 /* not found, check for special error cases */
7551 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
)
7553 const FUNCDESC
*func_desc
= &This
->funcdescs
[fdc
].funcdesc
;
7554 if (memid
== func_desc
->memid
)
7556 if ((wFlags
& INVOKE_PROPERTYPUT
) && (func_desc
->invkind
& INVOKE_PROPERTYGET
))
7558 int count_inputs
= 0;
7559 for (i
= 0; i
< func_desc
->cParams
; i
++)
7561 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
;
7562 if (!(wParamFlags
& PARAMFLAG_FRETVAL
))
7566 if (count_inputs
== 0 || pDispParams
->cArgs
== count_inputs
+ 1)
7567 return DISP_E_BADPARAMCOUNT
;
7572 /* not found, look for it in inherited interfaces */
7573 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7574 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7575 if(This
->impltypes
) {
7576 /* recursive search */
7578 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7579 if(SUCCEEDED(hres
)){
7580 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7581 ITypeInfo_Release(pTInfo
);
7584 WARN("Could not search inherited interface!\n");
7587 WARN("did not find member id %ld, flags 0x%x!\n", memid
, wFlags
);
7588 return DISP_E_MEMBERNOTFOUND
;
7591 /* ITypeInfo::GetDocumentation
7593 * Retrieves the documentation string, the complete Help file name and path,
7594 * and the context ID for the Help topic for a specified type description.
7596 * (Can be tested by the Visual Basic Editor in Word for instance.)
7598 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7599 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7600 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7602 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7603 const TLBFuncDesc
*pFDesc
;
7604 const TLBVarDesc
*pVDesc
;
7605 TRACE("%p, %ld, %p, %p, %p, %p.\n",
7606 iface
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7607 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7609 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7611 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7613 *pdwHelpContext
=This
->dwHelpContext
;
7615 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7617 }else {/* for a member */
7618 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
7621 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7623 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7625 *pdwHelpContext
=pFDesc
->helpcontext
;
7627 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7630 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
7633 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7635 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7637 *pdwHelpContext
=pVDesc
->HelpContext
;
7639 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7644 if(This
->impltypes
&&
7645 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7646 /* recursive search */
7649 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7650 if(SUCCEEDED(result
)) {
7651 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7652 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7653 ITypeInfo_Release(pTInfo
);
7656 WARN("Could not search inherited interface!\n");
7659 WARN("member %ld not found\n", memid
);
7660 return TYPE_E_ELEMENTNOTFOUND
;
7663 /* ITypeInfo::GetDllEntry
7665 * Retrieves a description or specification of an entry point for a function
7668 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7669 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7672 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7673 const TLBFuncDesc
*pFDesc
;
7675 TRACE("%p, %#lx, %d, %p, %p, %p.\n", iface
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7677 if (pBstrDllName
) *pBstrDllName
= NULL
;
7678 if (pBstrName
) *pBstrName
= NULL
;
7679 if (pwOrdinal
) *pwOrdinal
= 0;
7681 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7682 return TYPE_E_BADMODULEKIND
;
7684 pFDesc
= TLB_get_funcdesc_by_memberid_invkind(This
, memid
, invKind
);
7685 if (!pFDesc
) return TYPE_E_ELEMENTNOTFOUND
;
7687 dump_TypeInfo(This
);
7688 if (TRACE_ON(ole
)) dump_TLBFuncDescOne(pFDesc
);
7690 if (pBstrDllName
) *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7692 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1))
7694 if (pBstrName
) *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7695 if (pwOrdinal
) *pwOrdinal
= -1;
7699 if (pBstrName
) *pBstrName
= NULL
;
7700 if (pwOrdinal
) *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7705 /* internal function to make the inherited interfaces' methods appear
7706 * part of the interface */
7707 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7708 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7710 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7713 TRACE("%p, %#lx.\n", iface
, *hRefType
);
7715 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7717 ITypeInfo
*pSubTypeInfo
;
7719 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7723 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7725 ITypeInfo_Release(pSubTypeInfo
);
7729 *hRefType
-= DISPATCH_HREF_OFFSET
;
7731 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7732 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7737 /* ITypeInfo::GetRefTypeInfo
7739 * If a type description references other type descriptions, it retrieves
7740 * the referenced type descriptions.
7742 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7745 ITypeInfo
**ppTInfo
)
7747 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7748 ITypeInfo
*type_info
= NULL
;
7749 HRESULT result
= E_FAIL
;
7750 TLBRefType
*ref_type
;
7754 return E_INVALIDARG
;
7756 if ((INT
)hRefType
< 0) {
7757 ITypeInfoImpl
*pTypeInfoImpl
;
7759 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7760 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7761 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7762 return TYPE_E_ELEMENTNOTFOUND
;
7764 /* when we meet a DUAL typeinfo, we must create the alternate
7767 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7769 *pTypeInfoImpl
= *This
;
7770 pTypeInfoImpl
->ref
= 0;
7771 list_init(&pTypeInfoImpl
->custdata_list
);
7773 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7774 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7776 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7778 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7779 /* the AddRef implicitly adds a reference to the parent typelib, which
7780 * stops the copied data from being destroyed until the new typeinfo's
7781 * refcount goes to zero, but we need to signal to the new instance to
7782 * not free its data structures when it is destroyed */
7783 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7784 ITypeInfo_AddRef(*ppTInfo
);
7786 TRACE("got dual interface %p\n", *ppTInfo
);
7790 if ((hRefType
& DISPATCH_HREF_MASK
) && (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7791 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &hRefType
, ppTInfo
);
7793 if(!(hRefType
& 0x1))
7795 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7797 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7800 type_info
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7801 ITypeInfo_AddRef(type_info
);
7809 ITypeLib
*pTLib
= NULL
;
7811 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7813 if(ref_type
->reference
== (hRefType
& (~0x3)))
7816 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7818 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
7822 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7824 TRACE("internal reference\n");
7825 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7827 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7828 TRACE("typeinfo in imported typelib that is already loaded\n");
7829 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7830 ITypeLib_AddRef(pTLib
);
7833 /* Search in cached typelibs */
7834 ITypeLibImpl
*entry
;
7836 EnterCriticalSection(&cache_section
);
7837 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
7840 && IsEqualIID(&entry
->guid
->guid
, TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
))
7841 && entry
->ver_major
== ref_type
->pImpTLInfo
->wVersionMajor
7842 && entry
->ver_minor
== ref_type
->pImpTLInfo
->wVersionMinor
7843 && entry
->set_lcid
== ref_type
->pImpTLInfo
->lcid
)
7845 TRACE("got cached %p\n", entry
);
7846 pTLib
= (ITypeLib
*)&entry
->ITypeLib2_iface
;
7847 ITypeLib_AddRef(pTLib
);
7852 LeaveCriticalSection(&cache_section
);
7858 /* Search on disk */
7859 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7860 ref_type
->pImpTLInfo
->wVersionMajor
,
7861 ref_type
->pImpTLInfo
->wVersionMinor
,
7862 This
->pTypeLib
->syskind
,
7863 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7865 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7867 result
= LoadTypeLib(libnam
, &pTLib
);
7868 SysFreeString(libnam
);
7871 if(SUCCEEDED(result
)) {
7872 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7873 ITypeLib_AddRef(pTLib
);
7877 if(SUCCEEDED(result
)) {
7878 if(ref_type
->index
== TLB_REF_USE_GUID
)
7879 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), &type_info
);
7881 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, &type_info
);
7884 ITypeLib_Release(pTLib
);
7887 WARN("(%p) failed hreftype %#lx.\n", iface
, hRefType
);
7892 if ((hRefType
& 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info
, -2, ppTInfo
)))
7893 ITypeInfo_Release(type_info
);
7894 else *ppTInfo
= type_info
;
7896 TRACE("%p, hreftype %#lx, loaded %s (%p)\n", iface
, hRefType
,
7897 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7901 /* ITypeInfo::AddressOfMember
7903 * Retrieves the addresses of static functions or variables, such as those
7906 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7907 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7914 TRACE("%p, %lx, %#x, %p.\n", iface
, memid
, invKind
, ppv
);
7916 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7920 module
= LoadLibraryW(dll
);
7923 ERR("couldn't load %s\n", debugstr_w(dll
));
7925 SysFreeString(entry
);
7926 return STG_E_FILENOTFOUND
;
7928 /* FIXME: store library somewhere where we can free it */
7933 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7934 entryA
= malloc(len
);
7935 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7937 *ppv
= GetProcAddress(module
, entryA
);
7939 ERR("function not found %s\n", debugstr_a(entryA
));
7945 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7947 ERR("function not found %d\n", ordinal
);
7951 SysFreeString(entry
);
7954 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7959 /* ITypeInfo::CreateInstance
7961 * Creates a new instance of a type that describes a component object class
7964 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7965 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7967 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7971 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
7977 WARN("Not able to aggregate\n");
7978 return CLASS_E_NOAGGREGATION
;
7981 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
7982 if(FAILED(hr
)) return hr
;
7984 if(pTA
->typekind
!= TKIND_COCLASS
)
7986 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
7992 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
7995 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
7996 TRACE("GetActiveObject rets %#lx.\n", hr
);
7999 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8000 IUnknown_Release(pUnk
);
8005 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8006 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8010 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8014 /* ITypeInfo::GetMops
8016 * Retrieves marshalling information.
8018 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
, BSTR
*pBstrMops
)
8020 FIXME("%p, %ld stub!\n", iface
, memid
);
8025 /* ITypeInfo::GetContainingTypeLib
8027 * Retrieves the containing type library and the index of the type description
8028 * within that type library.
8030 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8031 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8033 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8035 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8037 *pIndex
=This
->index
;
8038 TRACE("returning pIndex=%d\n", *pIndex
);
8042 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8043 ITypeLib_AddRef(*ppTLib
);
8044 TRACE("returning ppTLib=%p\n", *ppTLib
);
8050 /* ITypeInfo::ReleaseTypeAttr
8052 * Releases a TYPEATTR previously returned by Get
8055 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8056 TYPEATTR
* pTypeAttr
)
8058 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8059 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8063 /* ITypeInfo::ReleaseFuncDesc
8065 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8067 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8069 FUNCDESC
*pFuncDesc
)
8071 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8074 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8076 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8077 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8078 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8080 SysFreeString((BSTR
)pFuncDesc
);
8083 /* ITypeInfo::ReleaseVarDesc
8085 * Releases a VARDESC previously returned by GetVarDesc.
8087 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8090 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8091 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8093 TLB_FreeVarDesc(pVarDesc
);
8096 /* ITypeInfo2::GetTypeKind
8098 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8101 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8102 TYPEKIND
*pTypeKind
)
8104 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8105 *pTypeKind
= This
->typeattr
.typekind
;
8106 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8110 /* ITypeInfo2::GetTypeFlags
8112 * Returns the type flags without any allocations. This returns a DWORD type
8113 * flag, which expands the type flags without growing the TYPEATTR (type
8117 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8119 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8120 TRACE("%p, %p.\n", iface
, pTypeFlags
);
8121 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8125 /* ITypeInfo2::GetFuncIndexOfMemId
8126 * Binds to a specific member based on a known DISPID, where the member name
8127 * is not known (for example, when binding to a default member).
8130 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8131 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8133 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8137 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8138 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8139 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8142 if(fdc
< This
->typeattr
.cFuncs
) {
8146 result
= TYPE_E_ELEMENTNOTFOUND
;
8148 TRACE("%p, %#lx, %#x, hr %#lx.\n", iface
, memid
, invKind
, result
);
8152 /* TypeInfo2::GetVarIndexOfMemId
8154 * Binds to a specific member based on a known DISPID, where the member name
8155 * is not known (for example, when binding to a default member).
8158 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8159 MEMBERID memid
, UINT
*pVarIndex
)
8161 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8162 TLBVarDesc
*pVarInfo
;
8164 TRACE("%p, %ld, %p.\n", iface
, memid
, pVarIndex
);
8166 pVarInfo
= TLB_get_vardesc_by_memberid(This
, memid
);
8168 return TYPE_E_ELEMENTNOTFOUND
;
8170 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8175 /* ITypeInfo2::GetCustData
8177 * Gets the custom data
8179 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8184 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8185 TLBCustData
*pCData
;
8187 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8189 if(!guid
|| !pVarVal
)
8190 return E_INVALIDARG
;
8192 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8194 VariantInit( pVarVal
);
8196 VariantCopy( pVarVal
, &pCData
->data
);
8198 VariantClear( pVarVal
);
8202 /* ITypeInfo2::GetFuncCustData
8204 * Gets the custom data
8206 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8212 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8213 const TLBFuncDesc
*desc
;
8218 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8220 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &desc
, &hrefoffset
);
8223 WARN("description for function %d not found\n", index
);
8227 VariantInit(pVarVal
);
8228 data
= TLB_get_custdata_by_guid(&desc
->custdata_list
, guid
);
8229 return data
? VariantCopy(pVarVal
, &data
->data
) : S_OK
;
8232 /* ITypeInfo2::GetParamCustData
8234 * Gets the custom data
8236 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8243 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8244 const TLBFuncDesc
*pFDesc
;
8245 TLBCustData
*pCData
;
8249 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8250 debugstr_guid(guid
), pVarVal
);
8252 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8256 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8257 return TYPE_E_ELEMENTNOTFOUND
;
8259 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8261 return TYPE_E_ELEMENTNOTFOUND
;
8263 VariantInit(pVarVal
);
8264 VariantCopy(pVarVal
, &pCData
->data
);
8269 /* ITypeInfo2::GetVarCustData
8271 * Gets the custom data
8273 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8279 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8280 TLBCustData
*pCData
;
8281 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8283 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8285 if(index
>= This
->typeattr
.cVars
)
8286 return TYPE_E_ELEMENTNOTFOUND
;
8288 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8290 return TYPE_E_ELEMENTNOTFOUND
;
8292 VariantInit(pVarVal
);
8293 VariantCopy(pVarVal
, &pCData
->data
);
8298 /* ITypeInfo2::GetImplCustData
8300 * Gets the custom data
8302 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8308 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8309 TLBCustData
*pCData
;
8310 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8312 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8314 if(index
>= This
->typeattr
.cImplTypes
)
8315 return TYPE_E_ELEMENTNOTFOUND
;
8317 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8319 return TYPE_E_ELEMENTNOTFOUND
;
8321 VariantInit(pVarVal
);
8322 VariantCopy(pVarVal
, &pCData
->data
);
8327 /* ITypeInfo2::GetDocumentation2
8329 * Retrieves the documentation string, the complete Help file name and path,
8330 * the localization context to use, and the context ID for the library Help
8331 * topic in the Help file.
8334 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8338 BSTR
*pbstrHelpString
,
8339 DWORD
*pdwHelpStringContext
,
8340 BSTR
*pbstrHelpStringDll
)
8342 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8343 const TLBFuncDesc
*pFDesc
;
8344 const TLBVarDesc
*pVDesc
;
8345 TRACE("%p, %ld, %#lx, %p, %p, %p.\n",
8346 iface
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8347 pbstrHelpStringDll
);
8348 /* the help string should be obtained from the helpstringdll,
8349 * using the _DLLGetDocumentation function, based on the supplied
8350 * lcid. Nice to do sometime...
8352 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8354 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8355 if(pdwHelpStringContext
)
8356 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8357 if(pbstrHelpStringDll
)
8358 *pbstrHelpStringDll
=
8359 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8361 }else {/* for a member */
8362 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
8365 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8366 if(pdwHelpStringContext
)
8367 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8368 if(pbstrHelpStringDll
)
8369 *pbstrHelpStringDll
=
8370 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8373 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
8376 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8377 if(pdwHelpStringContext
)
8378 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8379 if(pbstrHelpStringDll
)
8380 *pbstrHelpStringDll
=
8381 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8385 return TYPE_E_ELEMENTNOTFOUND
;
8388 /* ITypeInfo2::GetAllCustData
8390 * Gets all custom data items for the Type info.
8393 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8395 CUSTDATA
*pCustData
)
8397 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8399 TRACE("%p %p\n", This
, pCustData
);
8401 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8404 /* ITypeInfo2::GetAllFuncCustData
8406 * Gets all custom data items for the specified Function
8409 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8412 CUSTDATA
*pCustData
)
8414 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8415 const TLBFuncDesc
*pFDesc
;
8419 TRACE("%p %u %p\n", This
, index
, pCustData
);
8421 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &pFDesc
, &hrefoffset
);
8425 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8428 /* ITypeInfo2::GetAllParamCustData
8430 * Gets all custom data items for the Functions
8433 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8434 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8436 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8437 const TLBFuncDesc
*pFDesc
;
8441 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8443 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8447 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8448 return TYPE_E_ELEMENTNOTFOUND
;
8450 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8453 /* ITypeInfo2::GetAllVarCustData
8455 * Gets all custom data items for the specified Variable
8458 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8459 UINT index
, CUSTDATA
*pCustData
)
8461 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8462 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8464 TRACE("%p %u %p\n", This
, index
, pCustData
);
8466 if(index
>= This
->typeattr
.cVars
)
8467 return TYPE_E_ELEMENTNOTFOUND
;
8469 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8472 /* ITypeInfo2::GetAllImplCustData
8474 * Gets all custom data items for the specified implementation type
8477 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8480 CUSTDATA
*pCustData
)
8482 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8483 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8485 TRACE("%p %u %p\n", This
, index
, pCustData
);
8487 if(index
>= This
->typeattr
.cImplTypes
)
8488 return TYPE_E_ELEMENTNOTFOUND
;
8490 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8493 static const ITypeInfo2Vtbl tinfvt
=
8496 ITypeInfo_fnQueryInterface
,
8498 ITypeInfo_fnRelease
,
8500 ITypeInfo_fnGetTypeAttr
,
8501 ITypeInfo_fnGetTypeComp
,
8502 ITypeInfo_fnGetFuncDesc
,
8503 ITypeInfo_fnGetVarDesc
,
8504 ITypeInfo_fnGetNames
,
8505 ITypeInfo_fnGetRefTypeOfImplType
,
8506 ITypeInfo_fnGetImplTypeFlags
,
8507 ITypeInfo_fnGetIDsOfNames
,
8509 ITypeInfo_fnGetDocumentation
,
8510 ITypeInfo_fnGetDllEntry
,
8511 ITypeInfo_fnGetRefTypeInfo
,
8512 ITypeInfo_fnAddressOfMember
,
8513 ITypeInfo_fnCreateInstance
,
8514 ITypeInfo_fnGetMops
,
8515 ITypeInfo_fnGetContainingTypeLib
,
8516 ITypeInfo_fnReleaseTypeAttr
,
8517 ITypeInfo_fnReleaseFuncDesc
,
8518 ITypeInfo_fnReleaseVarDesc
,
8520 ITypeInfo2_fnGetTypeKind
,
8521 ITypeInfo2_fnGetTypeFlags
,
8522 ITypeInfo2_fnGetFuncIndexOfMemId
,
8523 ITypeInfo2_fnGetVarIndexOfMemId
,
8524 ITypeInfo2_fnGetCustData
,
8525 ITypeInfo2_fnGetFuncCustData
,
8526 ITypeInfo2_fnGetParamCustData
,
8527 ITypeInfo2_fnGetVarCustData
,
8528 ITypeInfo2_fnGetImplTypeCustData
,
8529 ITypeInfo2_fnGetDocumentation2
,
8530 ITypeInfo2_fnGetAllCustData
,
8531 ITypeInfo2_fnGetAllFuncCustData
,
8532 ITypeInfo2_fnGetAllParamCustData
,
8533 ITypeInfo2_fnGetAllVarCustData
,
8534 ITypeInfo2_fnGetAllImplTypeCustData
,
8537 /******************************************************************************
8538 * CreateDispTypeInfo [OLEAUT32.31]
8540 * Build type information for an object so it can be called through an
8541 * IDispatch interface.
8544 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8545 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8548 * This call allows an objects methods to be accessed through IDispatch, by
8549 * building an ITypeInfo object that IDispatch can use to call through.
8551 HRESULT WINAPI
CreateDispTypeInfo(
8552 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8553 LCID lcid
, /* [I] Locale Id */
8554 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8556 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8557 ITypeLibImpl
*pTypeLibImpl
;
8558 unsigned int param
, func
;
8559 TLBFuncDesc
*pFuncDesc
;
8563 pTypeLibImpl
= TypeLibImpl_Constructor();
8564 if (!pTypeLibImpl
) return E_FAIL
;
8566 pTypeLibImpl
->TypeInfoCount
= 2;
8567 pTypeLibImpl
->typeinfos
= calloc(pTypeLibImpl
->TypeInfoCount
, sizeof(ITypeInfoImpl
*));
8569 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8570 pTIIface
->pTypeLib
= pTypeLibImpl
;
8571 pTIIface
->index
= 0;
8572 pTIIface
->Name
= NULL
;
8573 pTIIface
->dwHelpContext
= -1;
8574 pTIIface
->guid
= NULL
;
8575 pTIIface
->typeattr
.lcid
= lcid
;
8576 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8577 pTIIface
->typeattr
.wMajorVerNum
= 0;
8578 pTIIface
->typeattr
.wMinorVerNum
= 0;
8579 pTIIface
->typeattr
.cbAlignment
= 2;
8580 pTIIface
->typeattr
.cbSizeInstance
= -1;
8581 pTIIface
->typeattr
.cbSizeVft
= -1;
8582 pTIIface
->typeattr
.cFuncs
= 0;
8583 pTIIface
->typeattr
.cImplTypes
= 0;
8584 pTIIface
->typeattr
.cVars
= 0;
8585 pTIIface
->typeattr
.wTypeFlags
= 0;
8586 pTIIface
->hreftype
= 0;
8588 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8589 pFuncDesc
= pTIIface
->funcdescs
;
8590 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8591 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8592 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8593 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8594 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8595 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8596 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8597 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8598 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8599 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8600 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8601 pFuncDesc
->funcdesc
.cScodes
= 0;
8602 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8603 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8604 pFuncDesc
->funcdesc
.elemdescFunc
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8605 pFuncDesc
->funcdesc
.elemdescFunc
.paramdesc
.pparamdescex
= NULL
;
8606 pFuncDesc
->funcdesc
.lprgelemdescParam
= calloc(md
->cArgs
, sizeof(ELEMDESC
));
8607 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8608 for(param
= 0; param
< md
->cArgs
; param
++) {
8609 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8610 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8612 pFuncDesc
->helpcontext
= 0;
8613 pFuncDesc
->HelpStringContext
= 0;
8614 pFuncDesc
->HelpString
= NULL
;
8615 pFuncDesc
->Entry
= NULL
;
8616 list_init(&pFuncDesc
->custdata_list
);
8617 pTIIface
->typeattr
.cFuncs
++;
8621 dump_TypeInfo(pTIIface
);
8623 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8624 pTIClass
->pTypeLib
= pTypeLibImpl
;
8625 pTIClass
->index
= 1;
8626 pTIClass
->Name
= NULL
;
8627 pTIClass
->dwHelpContext
= -1;
8628 pTIClass
->guid
= NULL
;
8629 pTIClass
->typeattr
.lcid
= lcid
;
8630 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8631 pTIClass
->typeattr
.wMajorVerNum
= 0;
8632 pTIClass
->typeattr
.wMinorVerNum
= 0;
8633 pTIClass
->typeattr
.cbAlignment
= 2;
8634 pTIClass
->typeattr
.cbSizeInstance
= -1;
8635 pTIClass
->typeattr
.cbSizeVft
= -1;
8636 pTIClass
->typeattr
.cFuncs
= 0;
8637 pTIClass
->typeattr
.cImplTypes
= 1;
8638 pTIClass
->typeattr
.cVars
= 0;
8639 pTIClass
->typeattr
.wTypeFlags
= 0;
8640 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8642 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8644 ref
= calloc(1, sizeof(*ref
));
8645 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8646 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8648 dump_TypeInfo(pTIClass
);
8650 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8652 ITypeInfo_AddRef(*pptinfo
);
8653 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8659 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8661 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8663 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8666 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8668 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8670 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8673 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8675 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8677 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8680 static HRESULT WINAPI
ITypeComp_fnBind(
8685 ITypeInfo
** ppTInfo
,
8686 DESCKIND
* pDescKind
,
8689 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8690 const TLBFuncDesc
*pFDesc
;
8691 const TLBVarDesc
*pVDesc
;
8692 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8695 TRACE("%p, %s, %#lx, 0x%x, %p, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8697 *pDescKind
= DESCKIND_NONE
;
8698 pBindPtr
->lpfuncdesc
= NULL
;
8701 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8702 pFDesc
= &This
->funcdescs
[fdc
];
8703 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8704 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8707 /* name found, but wrong flags */
8708 hr
= TYPE_E_TYPEMISMATCH
;
8712 if (fdc
< This
->typeattr
.cFuncs
)
8714 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8716 &pBindPtr
->lpfuncdesc
,
8717 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8720 *pDescKind
= DESCKIND_FUNCDESC
;
8721 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8722 ITypeInfo_AddRef(*ppTInfo
);
8725 pVDesc
= TLB_get_vardesc_by_name(This
, szName
);
8727 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8730 *pDescKind
= DESCKIND_VARDESC
;
8731 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8732 ITypeInfo_AddRef(*ppTInfo
);
8737 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8738 /* recursive search */
8742 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8745 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8746 ITypeInfo_Release(pTInfo
);
8750 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8751 ITypeComp_Release(pTComp
);
8752 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8753 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8755 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8756 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8757 SysFreeString((BSTR
)tmp
);
8761 WARN("Could not search inherited interface!\n");
8763 if (hr
== DISP_E_MEMBERNOTFOUND
)
8765 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8769 static HRESULT WINAPI
ITypeComp_fnBindType(
8773 ITypeInfo
** ppTInfo
,
8774 ITypeComp
** ppTComp
)
8776 TRACE("%s, %#lx, %p, %p.\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8778 /* strange behaviour (does nothing) but like the
8781 if (!ppTInfo
|| !ppTComp
)
8790 static const ITypeCompVtbl tcompvt
=
8793 ITypeComp_fnQueryInterface
,
8795 ITypeComp_fnRelease
,
8798 ITypeComp_fnBindType
8801 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8802 ICreateTypeLib2
** ppctlib
)
8807 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8809 if (!szFile
) return E_INVALIDARG
;
8811 This
= TypeLibImpl_Constructor();
8813 return E_OUTOFMEMORY
;
8815 This
->lcid
= GetSystemDefaultLCID();
8816 This
->syskind
= syskind
;
8817 This
->ptr_size
= get_ptr_size(syskind
);
8819 This
->path
= wcsdup(szFile
);
8821 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8822 return E_OUTOFMEMORY
;
8825 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8826 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8830 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8831 REFIID riid
, void **object
)
8833 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8835 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8838 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8840 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8842 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8845 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8847 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8849 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8852 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8853 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8855 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8856 ITypeInfoImpl
*info
;
8859 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8861 if (!ctinfo
|| !name
)
8862 return E_INVALIDARG
;
8864 info
= TLB_get_typeinfo_by_name(This
, name
);
8866 return TYPE_E_NAMECONFLICT
;
8868 This
->typeinfos
= realloc(This
->typeinfos
, sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8870 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8872 info
->pTypeLib
= This
;
8873 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8874 info
->index
= This
->TypeInfoCount
;
8875 info
->typeattr
.typekind
= kind
;
8876 info
->typeattr
.cbAlignment
= 4;
8878 switch (info
->typeattr
.typekind
) {
8880 case TKIND_INTERFACE
:
8881 case TKIND_DISPATCH
:
8883 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
8887 info
->typeattr
.cbSizeInstance
= 0;
8890 info
->typeattr
.cbSizeInstance
= 2;
8893 info
->typeattr
.cbSizeInstance
= -0x75;
8896 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
8897 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
8901 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8902 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8904 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8908 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8910 ++This
->TypeInfoCount
;
8915 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8918 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8920 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8923 return E_INVALIDARG
;
8925 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8930 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8931 WORD majorVerNum
, WORD minorVerNum
)
8933 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8935 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8937 This
->ver_major
= majorVerNum
;
8938 This
->ver_minor
= minorVerNum
;
8943 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8946 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8948 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8950 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8955 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8958 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8960 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8963 return E_INVALIDARG
;
8965 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8970 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8971 LPOLESTR helpFileName
)
8973 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8975 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
8978 return E_INVALIDARG
;
8980 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
8985 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
8988 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8990 TRACE("%p, %ld.\n", iface
, helpContext
);
8992 This
->dwHelpContext
= helpContext
;
8997 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9000 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9002 TRACE("%p, %#lx.\n", iface
, lcid
);
9004 This
->set_lcid
= lcid
;
9009 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9012 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9014 TRACE("%p %x\n", This
, libFlags
);
9016 This
->libflags
= libFlags
;
9021 typedef struct tagWMSFT_SegContents
{
9024 } WMSFT_SegContents
;
9026 typedef struct tagWMSFT_TLBFile
{
9028 WMSFT_SegContents typeinfo_seg
;
9029 WMSFT_SegContents impfile_seg
;
9030 WMSFT_SegContents impinfo_seg
;
9031 WMSFT_SegContents ref_seg
;
9032 WMSFT_SegContents guidhash_seg
;
9033 WMSFT_SegContents guid_seg
;
9034 WMSFT_SegContents namehash_seg
;
9035 WMSFT_SegContents name_seg
;
9036 WMSFT_SegContents string_seg
;
9037 WMSFT_SegContents typdesc_seg
;
9038 WMSFT_SegContents arraydesc_seg
;
9039 WMSFT_SegContents custdata_seg
;
9040 WMSFT_SegContents cdguids_seg
;
9042 WMSFT_SegContents aux_seg
;
9045 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9046 WMSFT_TLBFile
*file
)
9052 file
->string_seg
.len
= 0;
9053 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9056 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9058 return E_UNEXPECTED
;
9060 size
+= sizeof(INT16
);
9062 size
= (size
+ 4) & ~0x3;
9066 file
->string_seg
.len
+= size
;
9068 /* temporarily use str->offset to store the length of the aligned,
9069 * converted string */
9073 file
->string_seg
.data
= data
= malloc(file
->string_seg
.len
);
9076 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9079 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9080 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9082 free(file
->string_seg
.data
);
9083 return E_UNEXPECTED
;
9086 *((INT16
*)data
) = size
;
9088 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9092 str
->offset
= last_offs
;
9099 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9100 WMSFT_TLBFile
*file
)
9105 MSFT_NameIntro
*last_intro
= NULL
;
9107 file
->header
.nametablecount
= 0;
9108 file
->header
.nametablechars
= 0;
9110 file
->name_seg
.len
= 0;
9111 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9114 size
= lstrlenW(str
->str
);
9115 file
->header
.nametablechars
+= size
;
9116 file
->header
.nametablecount
++;
9118 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9120 return E_UNEXPECTED
;
9122 size
+= sizeof(MSFT_NameIntro
);
9124 size
= (size
+ 4) & ~0x3;
9128 file
->name_seg
.len
+= size
;
9130 /* temporarily use str->offset to store the length of the aligned,
9131 * converted string */
9135 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9136 file
->name_seg
.data
= data
= malloc(file
->name_seg
.len
+ 1);
9139 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9141 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9143 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9144 data
+ sizeof(MSFT_NameIntro
),
9145 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9147 free(file
->name_seg
.data
);
9148 return E_UNEXPECTED
;
9150 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9152 intro
->hreftype
= -1; /* TODO? */
9153 intro
->namelen
= size
& 0xFF;
9154 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9155 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9156 intro
->namelen
|= hash
<< 16;
9157 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9158 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9160 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9161 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9163 /* update str->offset to actual value to use in other
9164 * compilation functions that require positions within
9165 * the string table */
9169 str
->offset
= last_offs
;
9174 last_intro
->hreftype
= 0; /* last one is 0? */
9179 static inline int hash_guid(GUID
*guid
)
9183 for (i
= 0; i
< 8; i
++)
9184 hash
^= ((const short *)guid
)[i
];
9189 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9192 MSFT_GuidEntry
*entry
;
9194 int hash_key
, *guidhashtab
;
9196 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9197 file
->guid_seg
.data
= malloc(file
->guid_seg
.len
);
9199 entry
= file
->guid_seg
.data
;
9201 guidhashtab
= file
->guidhash_seg
.data
;
9202 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9203 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9204 entry
->hreftype
= guid
->hreftype
;
9206 hash_key
= hash_guid(&guid
->guid
);
9207 entry
->next_hash
= guidhashtab
[hash_key
];
9208 guidhashtab
[hash_key
] = offs
;
9210 guid
->offset
= offs
;
9211 offs
+= sizeof(MSFT_GuidEntry
);
9218 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9221 VARTYPE arg_type
= V_VT(value
);
9224 DWORD ret
= file
->custdata_seg
.len
;
9226 if(arg_type
== VT_INT
)
9228 if(arg_type
== VT_UINT
)
9232 if(V_VT(value
) != arg_type
) {
9233 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9235 ERR("VariantChangeType failed: %#lx.\n", hres
);
9240 /* Check if default value can be stored in-place */
9245 if(V_UI4(&v
) > 0x3ffffff)
9258 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9261 /* have to allocate space in custdata_seg */
9270 /* Construct the data to be allocated */
9273 if(file
->custdata_seg
.data
){
9274 file
->custdata_seg
.data
= realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9275 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9276 file
->custdata_seg
.len
+= sizeof(int) * 2;
9278 file
->custdata_seg
.len
= sizeof(int) * 2;
9279 data
= file
->custdata_seg
.data
= malloc(file
->custdata_seg
.len
);
9282 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9283 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9285 /* TODO: Check if the encoded data is already present in custdata_seg */
9291 int mb_len
= WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), NULL
, 0, NULL
, NULL
);
9292 int i
, len
= (6 + mb_len
+ 3) & ~0x3;
9295 if(file
->custdata_seg
.data
){
9296 file
->custdata_seg
.data
= realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9297 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9298 file
->custdata_seg
.len
+= len
;
9300 file
->custdata_seg
.len
= len
;
9301 data
= file
->custdata_seg
.data
= malloc(file
->custdata_seg
.len
);
9304 *((unsigned short *)data
) = V_VT(value
);
9305 *((unsigned int *)(data
+2)) = mb_len
;
9306 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], mb_len
, NULL
, NULL
);
9307 for (i
= 6 + mb_len
; i
< len
; i
++)
9310 /* TODO: Check if the encoded data is already present in custdata_seg */
9315 FIXME("Argument type not yet handled\n");
9320 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9322 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9324 DWORD offs
= file
->arraydesc_seg
.len
;
9328 /* TODO: we should check for duplicates, but that's harder because each
9329 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9330 * at the library-level) */
9332 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9333 file
->arraydesc_seg
.data
= realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9334 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9336 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9337 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9338 for(i
= 0; i
< desc
->cDims
; ++i
){
9339 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9340 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9346 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9352 VARTYPE vt
, subtype
;
9363 vt
= desc
->vt
& VT_TYPEMASK
;
9365 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9367 encoded
[1] = WMSFT_append_typedesc(desc
->lptdesc
, file
, &mix
, out_size
);
9368 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9370 *out_size
+= 2 * sizeof(DWORD
);
9371 }else if(vt
== VT_CARRAY
){
9372 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9373 encoded
[1] = WMSFT_append_arraydesc(desc
->lpadesc
, file
);
9375 }else if(vt
== VT_USERDEFINED
){
9376 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9377 encoded
[1] = desc
->hreftype
;
9378 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9380 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9398 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9401 data
= file
->typdesc_seg
.data
;
9402 while(offs
< file
->typdesc_seg
.len
){
9403 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9405 offs
+= sizeof(encoded
);
9408 file
->typdesc_seg
.len
+= sizeof(encoded
);
9409 data
= file
->typdesc_seg
.data
= realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9411 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9416 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9418 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9419 DWORD ret
= cdguids_seg
->len
, offs
;
9420 MSFT_CDGuid
*cdguid
;
9423 if(list_empty(custdata_list
))
9426 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9427 cdguids_seg
->data
= realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9428 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9430 offs
= ret
+ sizeof(MSFT_CDGuid
);
9431 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9432 cdguid
->GuidOffset
= cd
->guid
->offset
;
9433 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9434 cdguid
->next
= offs
;
9435 offs
+= sizeof(MSFT_CDGuid
);
9445 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9446 WMSFT_TLBFile
*file
)
9448 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9449 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9450 MSFT_VarRecord
*varrecord
;
9451 MSFT_FuncRecord
*funcrecord
;
9453 DWORD
*name
, *offsets
, offs
;
9455 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9456 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9458 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9460 /* optional fields */
9461 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9462 if(!list_empty(&desc
->custdata_list
))
9463 recorded_size
+= 7 * sizeof(INT
);
9464 else if(desc
->HelpStringContext
!= 0)
9465 recorded_size
+= 6 * sizeof(INT
);
9467 else if(desc
->Entry
)
9468 recorded_size
+= 3 * sizeof(INT
);
9469 else if(desc
->HelpString
)
9470 recorded_size
+= 2 * sizeof(INT
);
9471 else if(desc
->helpcontext
)
9472 recorded_size
+= sizeof(INT
);
9474 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9476 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9477 if(desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9478 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9483 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9486 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9487 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9489 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9491 /* optional fields */
9492 if(desc
->HelpStringContext
!= 0)
9493 recorded_size
+= 5 * sizeof(INT
);
9494 else if(!list_empty(&desc
->custdata_list
))
9495 recorded_size
+= 4 * sizeof(INT
);
9497 else if(desc
->HelpString
)
9498 recorded_size
+= 2 * sizeof(INT
);
9499 else if(desc
->HelpContext
!= 0)
9500 recorded_size
+= sizeof(INT
);
9502 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9505 if(!recorded_size
&& !extra_size
)
9508 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9510 aux_seg
->len
+= recorded_size
+ extra_size
;
9512 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9514 aux_seg
->data
= realloc(aux_seg
->data
, aux_seg
->len
);
9516 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9518 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9521 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9522 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9523 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9524 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9526 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9527 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9528 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9529 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9532 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9537 * ^has_param_defaults
9538 * ^oEntry_is_intresource
9540 funcrecord
->FKCCIC
=
9541 desc
->funcdesc
.funckind
|
9542 (desc
->funcdesc
.invkind
<< 3) |
9543 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9544 (desc
->funcdesc
.callconv
<< 8);
9546 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9547 funcrecord
->FKCCIC
|= 0x2000;
9549 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9550 if(desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9551 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9552 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9555 if(paramdefault_size
> 0)
9556 funcrecord
->FKCCIC
|= 0x1000;
9558 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9559 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9561 /* optional fields */
9563 if(!list_empty(&desc
->custdata_list
)){
9564 size
+= 7 * sizeof(INT
);
9565 funcrecord
->HelpContext
= desc
->helpcontext
;
9566 if(desc
->HelpString
)
9567 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9569 funcrecord
->oHelpString
= -1;
9571 funcrecord
->oEntry
= -1;
9572 else if(IS_INTRESOURCE(desc
->Entry
))
9573 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9575 funcrecord
->oEntry
= desc
->Entry
->offset
;
9576 funcrecord
->res9
= -1;
9577 funcrecord
->resA
= -1;
9578 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9579 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9580 }else if(desc
->HelpStringContext
!= 0){
9581 size
+= 6 * sizeof(INT
);
9582 funcrecord
->HelpContext
= desc
->helpcontext
;
9583 if(desc
->HelpString
)
9584 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9586 funcrecord
->oHelpString
= -1;
9588 funcrecord
->oEntry
= -1;
9589 else if(IS_INTRESOURCE(desc
->Entry
))
9590 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9592 funcrecord
->oEntry
= desc
->Entry
->offset
;
9593 funcrecord
->res9
= -1;
9594 funcrecord
->resA
= -1;
9595 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9596 }else if(desc
->Entry
){
9597 size
+= 3 * sizeof(INT
);
9598 funcrecord
->HelpContext
= desc
->helpcontext
;
9599 if(desc
->HelpString
)
9600 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9602 funcrecord
->oHelpString
= -1;
9604 funcrecord
->oEntry
= -1;
9605 else if(IS_INTRESOURCE(desc
->Entry
))
9606 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9608 funcrecord
->oEntry
= desc
->Entry
->offset
;
9609 }else if(desc
->HelpString
){
9610 size
+= 2 * sizeof(INT
);
9611 funcrecord
->HelpContext
= desc
->helpcontext
;
9612 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9613 }else if(desc
->helpcontext
){
9614 size
+= sizeof(INT
);
9615 funcrecord
->HelpContext
= desc
->helpcontext
;
9618 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9619 size
+= paramdefault_size
;
9621 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9622 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9624 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9625 if(desc
->pParamDesc
[j
].Name
)
9626 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9629 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
;
9631 if(paramdefault_size
){
9632 if(desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9633 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.pparamdescex
->varDefaultValue
, file
);
9634 else if(paramdefault_size
)
9639 size
+= sizeof(MSFT_ParameterInfo
);
9642 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9648 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9651 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9652 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9653 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9654 DWORD size
= 5 * sizeof(INT
);
9656 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9657 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9658 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9659 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9661 if(desc
->vardesc
.varkind
== VAR_CONST
){
9662 varrecord
->vardescsize
+= sizeof(VARIANT
);
9663 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.lpvarValue
, file
);
9665 varrecord
->OffsValue
= desc
->vardesc
.oInst
;
9668 if(desc
->HelpStringContext
!= 0){
9669 size
+= 5 * sizeof(INT
);
9670 varrecord
->HelpContext
= desc
->HelpContext
;
9671 if(desc
->HelpString
)
9672 varrecord
->HelpString
= desc
->HelpString
->offset
;
9674 varrecord
->HelpString
= -1;
9675 varrecord
->res9
= -1;
9676 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9677 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9678 }else if(!list_empty(&desc
->custdata_list
)){
9679 size
+= 4 * sizeof(INT
);
9680 varrecord
->HelpContext
= desc
->HelpContext
;
9681 if(desc
->HelpString
)
9682 varrecord
->HelpString
= desc
->HelpString
->offset
;
9684 varrecord
->HelpString
= -1;
9685 varrecord
->res9
= -1;
9686 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9687 }else if(desc
->HelpString
){
9688 size
+= 2 * sizeof(INT
);
9689 varrecord
->HelpContext
= desc
->HelpContext
;
9690 if(desc
->HelpString
)
9691 varrecord
->HelpString
= desc
->HelpString
->offset
;
9693 varrecord
->HelpString
= -1;
9694 }else if(desc
->HelpContext
!= 0){
9695 size
+= sizeof(INT
);
9696 varrecord
->HelpContext
= desc
->HelpContext
;
9699 varrecord
->Info
= size
| (i
<< 16);
9705 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9708 memid
= (MEMBERID
*)varrecord
;
9709 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9710 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9711 *memid
= desc
->funcdesc
.memid
;
9714 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9715 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9716 *memid
= desc
->vardesc
.memid
;
9720 name
= (DWORD
*)memid
;
9721 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9722 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9724 *name
= desc
->Name
->offset
;
9729 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9730 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9732 *name
= desc
->Name
->offset
;
9741 typedef struct tagWMSFT_RefChunk
{
9748 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9750 DWORD offs
= file
->ref_seg
.len
, i
;
9751 WMSFT_RefChunk
*chunk
;
9753 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9754 file
->ref_seg
.data
= realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9756 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9758 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9759 chunk
->href
= info
->impltypes
[i
].hRef
;
9760 chunk
->res04
= info
->impltypes
[i
].implflags
;
9762 if(i
< info
->typeattr
.cImplTypes
- 1)
9763 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9772 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9776 size
= sizeof(MSFT_TypeInfoBase
);
9779 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9780 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9781 base
->typekind
= TKIND_DISPATCH
;
9783 base
->typekind
= info
->typeattr
.typekind
;
9784 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9785 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9786 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9791 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9797 base
->posguid
= info
->guid
->offset
;
9800 base
->flags
= info
->typeattr
.wTypeFlags
;
9802 base
->NameOffset
= info
->Name
->offset
;
9804 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9805 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9807 base
->NameOffset
= -1;
9809 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9811 base
->docstringoffs
= info
->DocString
->offset
;
9813 base
->docstringoffs
= -1;
9814 base
->helpstringcontext
= info
->dwHelpStringContext
;
9815 base
->helpcontext
= info
->dwHelpContext
;
9816 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9817 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9818 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9819 base
->size
= info
->typeattr
.cbSizeInstance
;
9820 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9821 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9822 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9823 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9824 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9826 base
->datatype1
= info
->DllName
->offset
;
9828 base
->datatype1
= -1;
9830 if(info
->typeattr
.cImplTypes
> 0)
9831 base
->datatype1
= info
->impltypes
[0].hRef
;
9833 base
->datatype1
= -1;
9835 base
->datatype2
= index
; /* FIXME: i think there's more here */
9843 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9847 file
->typeinfo_seg
.len
= 0;
9848 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9849 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9850 *junk
= file
->typeinfo_seg
.len
;
9852 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9855 file
->typeinfo_seg
.data
= malloc(file
->typeinfo_seg
.len
);
9856 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9858 file
->aux_seg
.len
= 0;
9859 file
->aux_seg
.data
= NULL
;
9861 file
->typeinfo_seg
.len
= 0;
9862 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9863 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9864 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9865 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9869 typedef struct tagWMSFT_ImpFile
{
9875 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9878 WMSFT_ImpFile
*impfile
;
9880 DWORD last_offs
= 0;
9882 file
->impfile_seg
.len
= 0;
9883 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9887 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
9891 path
= implib
->name
;
9892 size
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
), NULL
, 0, NULL
, NULL
);
9894 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9897 size
+= sizeof(INT16
);
9899 size
= (size
+ 4) & ~0x3;
9903 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9906 data
= file
->impfile_seg
.data
= malloc(file
->impfile_seg
.len
);
9908 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9909 int strlen
= 0, size
;
9911 impfile
= (WMSFT_ImpFile
*)data
;
9912 impfile
->guid_offs
= implib
->guid
->offset
;
9913 impfile
->lcid
= implib
->lcid
;
9914 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9916 data
+= sizeof(WMSFT_ImpFile
);
9919 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
9923 path
= implib
->name
;
9924 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
),
9925 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9927 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9930 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9932 size
= strlen
+ sizeof(INT16
);
9934 size
= (size
+ 4) & ~0x3;
9937 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9940 implib
->offset
= last_offs
;
9941 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9945 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9948 TLBRefType
*ref_type
;
9951 WMSFT_compile_impfile(This
, file
);
9953 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9954 info
= file
->impinfo_seg
.data
= malloc(file
->impinfo_seg
.len
);
9956 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
9957 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
9958 if(ref_type
->index
== TLB_REF_USE_GUID
){
9959 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
9960 info
->oGuid
= ref_type
->guid
->offset
;
9962 info
->oGuid
= ref_type
->index
;
9963 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
9969 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9971 file
->guidhash_seg
.len
= 0x80;
9972 file
->guidhash_seg
.data
= malloc(file
->guidhash_seg
.len
);
9973 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
9976 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9978 file
->namehash_seg
.len
= 0x200;
9979 file
->namehash_seg
.data
= malloc(file
->namehash_seg
.len
);
9980 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
9983 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
9985 if(contents
&& contents
->len
){
9986 segdir
->offset
= *running_offset
;
9987 segdir
->length
= contents
->len
;
9988 *running_offset
+= segdir
->length
;
9990 segdir
->offset
= -1;
9994 /* TODO: do these ever change? */
9996 segdir
->res0c
= 0xf;
9999 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10003 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10006 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10010 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10012 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10013 base
->memoffset
+= file_len
;
10020 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10022 free(file
->typeinfo_seg
.data
);
10023 free(file
->guidhash_seg
.data
);
10024 free(file
->guid_seg
.data
);
10025 free(file
->ref_seg
.data
);
10026 free(file
->impinfo_seg
.data
);
10027 free(file
->impfile_seg
.data
);
10028 free(file
->namehash_seg
.data
);
10029 free(file
->name_seg
.data
);
10030 free(file
->string_seg
.data
);
10031 free(file
->typdesc_seg
.data
);
10032 free(file
->arraydesc_seg
.data
);
10033 free(file
->custdata_seg
.data
);
10034 free(file
->cdguids_seg
.data
);
10035 free(file
->aux_seg
.data
);
10038 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10040 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10041 WMSFT_TLBFile file
;
10042 DWORD written
, junk_size
, junk_offs
, running_offset
;
10049 TRACE("%p\n", This
);
10051 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10052 if(This
->typeinfos
[i
]->needs_layout
)
10053 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10055 memset(&file
, 0, sizeof(file
));
10057 file
.header
.magic1
= 0x5446534D;
10058 file
.header
.magic2
= 0x00010002;
10059 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10060 file
.header
.lcid2
= This
->set_lcid
;
10061 file
.header
.varflags
= 0x40 | This
->syskind
;
10062 if (This
->HelpFile
)
10063 file
.header
.varflags
|= 0x10;
10064 if (This
->HelpStringDll
)
10065 file
.header
.varflags
|= HELPDLLFLAG
;
10066 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10067 file
.header
.flags
= This
->libflags
;
10068 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10069 file
.header
.helpcontext
= This
->dwHelpContext
;
10070 file
.header
.res44
= 0x20;
10071 file
.header
.res48
= 0x80;
10072 file
.header
.dispatchpos
= This
->dispatch_href
;
10074 WMSFT_compile_namehash(This
, &file
);
10075 /* do name and string compilation to get offsets for other compilations */
10076 hres
= WMSFT_compile_names(This
, &file
);
10078 WMSFT_free_file(&file
);
10082 hres
= WMSFT_compile_strings(This
, &file
);
10084 WMSFT_free_file(&file
);
10088 WMSFT_compile_guidhash(This
, &file
);
10089 hres
= WMSFT_compile_guids(This
, &file
);
10091 WMSFT_free_file(&file
);
10096 file
.header
.helpfile
= This
->HelpFile
->offset
;
10098 file
.header
.helpfile
= -1;
10100 if(This
->DocString
)
10101 file
.header
.helpstring
= This
->DocString
->offset
;
10103 file
.header
.helpstring
= -1;
10105 /* do some more segment compilation */
10106 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10107 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10110 file
.header
.NameOffset
= This
->Name
->offset
;
10112 file
.header
.NameOffset
= -1;
10114 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10117 file
.header
.posguid
= This
->guid
->offset
;
10119 file
.header
.posguid
= -1;
10121 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10122 if(file
.header
.varflags
& HELPDLLFLAG
)
10123 junk_size
+= sizeof(DWORD
);
10125 junk
= calloc(1, junk_size
);
10126 if(file
.header
.varflags
& HELPDLLFLAG
){
10127 *junk
= This
->HelpStringDll
->offset
;
10136 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10137 WMSFT_compile_impinfo(This
, &file
);
10139 running_offset
= 0;
10141 TRACE("header at: 0x%lx\n", running_offset
);
10142 running_offset
+= sizeof(file
.header
);
10144 TRACE("junk at: 0x%lx\n", running_offset
);
10145 running_offset
+= junk_size
;
10147 TRACE("segdir at: 0x%lx\n", running_offset
);
10148 running_offset
+= sizeof(file
.segdir
);
10150 TRACE("typeinfo at: 0x%lx\n", running_offset
);
10151 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10153 TRACE("guidhashtab at: 0x%lx\n", running_offset
);
10154 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10156 TRACE("guidtab at: 0x%lx\n", running_offset
);
10157 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10159 TRACE("reftab at: 0x%lx\n", running_offset
);
10160 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10162 TRACE("impinfo at: 0x%lx\n", running_offset
);
10163 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10165 TRACE("impfiles at: 0x%lx\n", running_offset
);
10166 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10168 TRACE("namehashtab at: 0x%lx\n", running_offset
);
10169 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10171 TRACE("nametab at: 0x%lx\n", running_offset
);
10172 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10174 TRACE("stringtab at: 0x%lx\n", running_offset
);
10175 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10177 TRACE("typdesc at: 0x%lx\n", running_offset
);
10178 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10180 TRACE("arraydescriptions at: 0x%lx\n", running_offset
);
10181 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10183 TRACE("custdata at: 0x%lx\n", running_offset
);
10184 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10186 TRACE("cdguids at: 0x%lx\n", running_offset
);
10187 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10189 TRACE("res0e at: 0x%lx\n", running_offset
);
10190 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10192 TRACE("res0f at: 0x%lx\n", running_offset
);
10193 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10195 TRACE("aux_seg at: 0x%lx\n", running_offset
);
10197 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10199 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10200 FILE_ATTRIBUTE_NORMAL
, 0);
10201 if (outfile
== INVALID_HANDLE_VALUE
){
10202 WMSFT_free_file(&file
);
10204 return TYPE_E_IOERROR
;
10207 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10209 WMSFT_free_file(&file
);
10210 CloseHandle(outfile
);
10212 return TYPE_E_IOERROR
;
10215 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10218 WMSFT_free_file(&file
);
10219 CloseHandle(outfile
);
10220 return TYPE_E_IOERROR
;
10223 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10225 WMSFT_free_file(&file
);
10226 CloseHandle(outfile
);
10227 return TYPE_E_IOERROR
;
10230 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10231 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10232 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10233 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10234 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10235 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10236 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10237 WMSFT_write_segment(outfile
, &file
.name_seg
);
10238 WMSFT_write_segment(outfile
, &file
.string_seg
);
10239 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10240 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10241 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10242 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10243 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10245 WMSFT_free_file(&file
);
10247 CloseHandle(outfile
);
10252 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10255 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10256 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10260 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10261 REFGUID guid
, VARIANT
*varVal
)
10263 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10266 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10268 if (!guid
|| !varVal
)
10269 return E_INVALIDARG
;
10271 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10273 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10276 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10277 ULONG helpStringContext
)
10279 FIXME("%p, %lu - stub\n", iface
, helpStringContext
);
10283 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10286 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10287 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10290 return E_INVALIDARG
;
10292 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10297 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10298 ICreateTypeLib2_fnQueryInterface
,
10299 ICreateTypeLib2_fnAddRef
,
10300 ICreateTypeLib2_fnRelease
,
10301 ICreateTypeLib2_fnCreateTypeInfo
,
10302 ICreateTypeLib2_fnSetName
,
10303 ICreateTypeLib2_fnSetVersion
,
10304 ICreateTypeLib2_fnSetGuid
,
10305 ICreateTypeLib2_fnSetDocString
,
10306 ICreateTypeLib2_fnSetHelpFileName
,
10307 ICreateTypeLib2_fnSetHelpContext
,
10308 ICreateTypeLib2_fnSetLcid
,
10309 ICreateTypeLib2_fnSetLibFlags
,
10310 ICreateTypeLib2_fnSaveAllChanges
,
10311 ICreateTypeLib2_fnDeleteTypeInfo
,
10312 ICreateTypeLib2_fnSetCustData
,
10313 ICreateTypeLib2_fnSetHelpStringContext
,
10314 ICreateTypeLib2_fnSetHelpStringDll
10317 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10318 REFIID riid
, void **object
)
10320 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10322 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10325 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10327 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10329 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10332 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10334 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10336 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10339 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10342 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10344 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10346 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10351 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10354 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10358 TRACE("%p %x\n", This
, typeFlags
);
10360 if (typeFlags
& TYPEFLAG_FDUAL
) {
10362 ITypeInfo
*dispatch
;
10366 hres
= LoadTypeLib(L
"stdole2.tlb", &stdole
);
10370 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10371 ITypeLib_Release(stdole
);
10375 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10376 ITypeInfo_Release(dispatch
);
10381 old_flags
= This
->typeattr
.wTypeFlags
;
10382 This
->typeattr
.wTypeFlags
= typeFlags
;
10384 hres
= ICreateTypeInfo2_LayOut(iface
);
10385 if (FAILED(hres
)) {
10386 This
->typeattr
.wTypeFlags
= old_flags
;
10393 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10396 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10398 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10401 return E_INVALIDARG
;
10403 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10408 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10411 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10413 TRACE("%p, %ld.\n", iface
, helpContext
);
10415 This
->dwHelpContext
= helpContext
;
10420 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10421 WORD majorVerNum
, WORD minorVerNum
)
10423 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10425 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10427 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10428 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10433 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10434 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10436 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10438 ITypeLib
*container
;
10439 TLBRefType
*ref_type
;
10441 TYPEATTR
*typeattr
;
10445 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10447 if (!typeInfo
|| !refType
)
10448 return E_INVALIDARG
;
10450 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10454 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10455 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10457 ITypeLib_Release(container
);
10459 *refType
= target
->hreftype
;
10464 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10465 if (FAILED(hres
)) {
10466 ITypeLib_Release(container
);
10470 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10471 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10472 implib
->lcid
== libattr
->lcid
&&
10473 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10474 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10478 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10479 implib
= calloc(1, sizeof(TLBImpLib
));
10481 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10482 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10483 implib
->name
= SysAllocString(our_container
->path
);
10485 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10486 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10488 implib
->name
= NULL
;
10489 TRACE("QueryPathOfRegTypeLib failed, no name stored: %#lx.\n", hres
);
10493 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10494 implib
->lcid
= libattr
->lcid
;
10495 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10496 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10498 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10501 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10502 ITypeLib_Release(container
);
10504 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10509 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10510 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10511 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10512 ref_type
->tkind
== typeattr
->typekind
)
10517 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10518 ref_type
= calloc(1, sizeof(TLBRefType
));
10520 ref_type
->tkind
= typeattr
->typekind
;
10521 ref_type
->pImpTLInfo
= implib
;
10522 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10524 ref_type
->index
= TLB_REF_USE_GUID
;
10526 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10528 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10531 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10533 *refType
= ref_type
->reference
| 0x1;
10535 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10536 This
->pTypeLib
->dispatch_href
= *refType
;
10541 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10542 UINT index
, FUNCDESC
*funcDesc
)
10544 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10545 TLBFuncDesc tmp_func_desc
, *func_desc
;
10550 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10552 if (!funcDesc
|| funcDesc
->oVft
& 3)
10553 return E_INVALIDARG
;
10555 switch (This
->typeattr
.typekind
) {
10557 if (funcDesc
->funckind
!= FUNC_STATIC
)
10558 return TYPE_E_BADMODULEKIND
;
10560 case TKIND_DISPATCH
:
10561 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10562 return TYPE_E_BADMODULEKIND
;
10565 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10566 return TYPE_E_BADMODULEKIND
;
10569 if (index
> This
->typeattr
.cFuncs
)
10570 return TYPE_E_ELEMENTNOTFOUND
;
10572 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10573 !funcDesc
->cParams
)
10574 return TYPE_E_INCONSISTENTPROPFUNCS
;
10576 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10577 funcDesc
->oVft
% 8 != 0)
10578 return E_INVALIDARG
;
10580 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10581 TLBFuncDesc_Constructor(&tmp_func_desc
);
10583 tmp_func_desc
.funcdesc
= *funcDesc
;
10585 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10586 tmp_func_desc
.funcdesc
.oVft
|= 1;
10588 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10589 tmp_func_desc
.funcdesc
.lprgscode
= malloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10590 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10592 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10593 tmp_func_desc
.funcdesc
.cScodes
= 0;
10596 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10597 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10598 buf_size
+= sizeof(ELEMDESC
);
10599 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10601 tmp_func_desc
.funcdesc
.lprgelemdescParam
= malloc(buf_size
);
10602 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10604 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10605 if (FAILED(hres
)) {
10606 free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10607 free(tmp_func_desc
.funcdesc
.lprgscode
);
10611 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10612 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10613 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10614 if (FAILED(hres
)) {
10615 free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10616 free(tmp_func_desc
.funcdesc
.lprgscode
);
10619 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10620 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10621 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10622 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].paramdesc
.pparamdescex
->varDefaultValue
);
10623 if (FAILED(hres
)) {
10624 free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10625 free(tmp_func_desc
.funcdesc
.lprgscode
);
10631 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10633 if (This
->funcdescs
) {
10634 This
->funcdescs
= realloc(This
->funcdescs
, sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10636 if (index
< This
->typeattr
.cFuncs
) {
10637 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10638 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10639 func_desc
= This
->funcdescs
+ index
;
10641 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10643 /* move custdata lists to the new memory location */
10644 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10646 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
10649 func_desc
= This
->funcdescs
= malloc(sizeof(TLBFuncDesc
));
10651 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10652 list_init(&func_desc
->custdata_list
);
10654 ++This
->typeattr
.cFuncs
;
10656 This
->needs_layout
= TRUE
;
10661 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10662 UINT index
, HREFTYPE refType
)
10664 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10665 TLBImplType
*impl_type
;
10668 TRACE("%p, %u, %ld.\n", iface
, index
, refType
);
10670 switch(This
->typeattr
.typekind
){
10671 case TKIND_COCLASS
: {
10673 FIXME("Unhandled index: -1\n");
10677 if(index
!= This
->typeattr
.cImplTypes
)
10678 return TYPE_E_ELEMENTNOTFOUND
;
10682 case TKIND_INTERFACE
:
10683 case TKIND_DISPATCH
:
10684 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10685 return TYPE_E_ELEMENTNOTFOUND
;
10688 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10692 if (This
->impltypes
){
10695 This
->impltypes
= realloc(This
->impltypes
, sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10697 if (index
< This
->typeattr
.cImplTypes
) {
10698 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10699 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10700 impl_type
= This
->impltypes
+ index
;
10702 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10704 /* move custdata lists to the new memory location */
10705 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10707 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
10710 impl_type
= This
->impltypes
= malloc(sizeof(TLBImplType
));
10712 memset(impl_type
, 0, sizeof(TLBImplType
));
10713 TLBImplType_Constructor(impl_type
);
10714 impl_type
->hRef
= refType
;
10716 ++This
->typeattr
.cImplTypes
;
10718 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10719 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10721 hres
= ICreateTypeInfo2_LayOut(iface
);
10728 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10729 UINT index
, INT implTypeFlags
)
10731 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10732 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10734 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10736 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10737 return TYPE_E_BADMODULEKIND
;
10739 if (index
>= This
->typeattr
.cImplTypes
)
10740 return TYPE_E_ELEMENTNOTFOUND
;
10742 impl_type
->implflags
= implTypeFlags
;
10747 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10750 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10752 TRACE("%p %d\n", This
, alignment
);
10754 This
->typeattr
.cbAlignment
= alignment
;
10759 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10762 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10764 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10767 return E_INVALIDARG
;
10769 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10771 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10776 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10777 UINT index
, VARDESC
*varDesc
)
10779 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10780 TLBVarDesc
*var_desc
;
10783 TRACE("%p %u %p\n", This
, index
, varDesc
);
10785 if (This
->vardescs
){
10788 This
->vardescs
= realloc(This
->vardescs
, sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10790 if (index
< This
->typeattr
.cVars
) {
10791 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10792 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10793 var_desc
= This
->vardescs
+ index
;
10795 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10796 memset(var_desc
, 0, sizeof(TLBVarDesc
));
10799 /* move custdata lists to the new memory location */
10800 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10802 TLB_relink_custdata(&This
->vardescs
[i
].custdata_list
);
10805 var_desc
= This
->vardescs
= calloc(1, sizeof(TLBVarDesc
));
10807 TLBVarDesc_Constructor(var_desc
);
10808 hr
= TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10811 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10813 ++This
->typeattr
.cVars
;
10815 This
->needs_layout
= TRUE
;
10820 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10821 UINT index
, LPOLESTR
*names
, UINT numNames
)
10823 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10824 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10827 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10830 return E_INVALIDARG
;
10832 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10833 return TYPE_E_ELEMENTNOTFOUND
;
10835 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10836 if(numNames
> func_desc
->funcdesc
.cParams
)
10837 return TYPE_E_ELEMENTNOTFOUND
;
10839 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10840 return TYPE_E_ELEMENTNOTFOUND
;
10842 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10843 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10844 if (iter
->Name
&& !wcscmp(TLB_get_bstr(iter
->Name
), *names
)) {
10845 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10846 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10847 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10849 return TYPE_E_AMBIGUOUSNAME
;
10853 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10855 for (i
= 1; i
< numNames
; ++i
) {
10856 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10857 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10863 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10864 UINT index
, LPOLESTR name
)
10866 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10868 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10871 return E_INVALIDARG
;
10873 if(index
>= This
->typeattr
.cVars
)
10874 return TYPE_E_ELEMENTNOTFOUND
;
10876 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10880 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10881 TYPEDESC
*tdescAlias
)
10883 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10886 TRACE("%p %p\n", This
, tdescAlias
);
10889 return E_INVALIDARG
;
10891 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
10892 return TYPE_E_BADMODULEKIND
;
10894 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
10898 free(This
->tdescAlias
);
10899 This
->tdescAlias
= malloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10900 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10905 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10906 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10908 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10909 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10913 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10914 UINT index
, LPOLESTR docString
)
10916 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10917 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10919 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10922 return E_INVALIDARG
;
10924 if(index
>= This
->typeattr
.cFuncs
)
10925 return TYPE_E_ELEMENTNOTFOUND
;
10927 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10932 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
10933 UINT index
, LPOLESTR docString
)
10935 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10936 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10938 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10941 return E_INVALIDARG
;
10943 if(index
>= This
->typeattr
.cVars
)
10944 return TYPE_E_ELEMENTNOTFOUND
;
10946 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10951 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
10952 UINT index
, DWORD helpContext
)
10954 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10955 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10957 TRACE("%p, %u, %ld.\n", iface
, index
, helpContext
);
10959 if(index
>= This
->typeattr
.cFuncs
)
10960 return TYPE_E_ELEMENTNOTFOUND
;
10962 func_desc
->helpcontext
= helpContext
;
10967 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
10968 UINT index
, DWORD helpContext
)
10970 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10971 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
10973 TRACE("%p, %u, %ld.\n", iface
, index
, helpContext
);
10975 if(index
>= This
->typeattr
.cVars
)
10976 return TYPE_E_ELEMENTNOTFOUND
;
10978 var_desc
->HelpContext
= helpContext
;
10983 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
10984 UINT index
, BSTR bstrMops
)
10986 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10987 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
10991 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
10994 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10996 TRACE("%p %p\n", This
, idlDesc
);
10999 return E_INVALIDARG
;
11001 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11002 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11007 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11009 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11010 ITypeInfo2
*tinfo
= &This
->ITypeInfo2_iface
;
11011 TLBFuncDesc
*func_desc
;
11012 UINT user_vft
= 0, i
, depth
= 0;
11013 HRESULT hres
= S_OK
;
11015 TRACE("%p\n", This
);
11017 This
->needs_layout
= FALSE
;
11019 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11024 hres
= ITypeInfo2_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11026 if (SUCCEEDED(hres
)) {
11027 hres
= ITypeInfo2_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11029 if (SUCCEEDED(hres
)) {
11030 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11031 if (FAILED(hres
)) {
11032 ITypeInfo_Release(inh
);
11035 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11036 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11040 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11041 if(SUCCEEDED(hres
)){
11043 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11044 if(SUCCEEDED(hres
)){
11045 ITypeInfo_Release(inh
);
11049 }while(SUCCEEDED(hres
));
11052 ITypeInfo_Release(inh
);
11053 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11054 This
->typeattr
.cbSizeVft
= 0;
11058 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11059 This
->typeattr
.cbSizeVft
= 0;
11063 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11064 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11066 This
->typeattr
.cbSizeVft
= 0;
11068 func_desc
= This
->funcdescs
;
11070 while (i
< This
->typeattr
.cFuncs
) {
11071 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11072 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11074 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11075 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11077 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11079 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11082 BOOL reset
= FALSE
;
11084 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11086 iter
= This
->funcdescs
;
11087 while (j
< This
->typeattr
.cFuncs
) {
11088 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11090 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11093 ++func_desc
->funcdesc
.memid
;
11094 iter
= This
->funcdescs
;
11107 if (user_vft
> This
->typeattr
.cbSizeVft
)
11108 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11110 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11111 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11112 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11114 BOOL reset
= FALSE
;
11117 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11119 iter
= This
->vardescs
;
11120 while (j
< This
->typeattr
.cVars
) {
11121 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11123 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11126 ++var_desc
->vardesc
.memid
;
11127 iter
= This
->vardescs
;
11140 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11143 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11146 TRACE("%p %u\n", This
, index
);
11148 if (index
>= This
->typeattr
.cFuncs
)
11149 return TYPE_E_ELEMENTNOTFOUND
;
11151 typeinfo_release_funcdesc(&This
->funcdescs
[index
]);
11153 --This
->typeattr
.cFuncs
;
11154 if (index
!= This
->typeattr
.cFuncs
)
11156 memmove(This
->funcdescs
+ index
, This
->funcdescs
+ index
+ 1,
11157 sizeof(*This
->funcdescs
) * (This
->typeattr
.cFuncs
- index
));
11158 for (i
= index
; i
< This
->typeattr
.cFuncs
; ++i
)
11159 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
11162 This
->needs_layout
= TRUE
;
11167 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11168 MEMBERID memid
, INVOKEKIND invKind
)
11170 FIXME("%p, %#lx, %d - stub\n", iface
, memid
, invKind
);
11174 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11177 FIXME("%p, %u - stub\n", iface
, index
);
11181 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11184 FIXME("%p, %#lx - stub\n", iface
, memid
);
11188 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11191 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11194 TRACE("%p %u\n", This
, index
);
11196 if (index
>= This
->typeattr
.cImplTypes
)
11197 return TYPE_E_ELEMENTNOTFOUND
;
11199 TLB_FreeCustData(&This
->impltypes
[index
].custdata_list
);
11200 --This
->typeattr
.cImplTypes
;
11202 if (index
< This
->typeattr
.cImplTypes
)
11204 memmove(This
->impltypes
+ index
, This
->impltypes
+ index
+ 1, (This
->typeattr
.cImplTypes
- index
) *
11205 sizeof(*This
->impltypes
));
11206 for (i
= index
; i
< This
->typeattr
.cImplTypes
; ++i
)
11207 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
11213 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11214 REFGUID guid
, VARIANT
*varVal
)
11218 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11220 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11222 if (!guid
|| !varVal
)
11223 return E_INVALIDARG
;
11225 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11227 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11230 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11231 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11233 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11234 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11238 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11239 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11241 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11242 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11246 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11247 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11249 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11250 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11254 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11255 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11257 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11258 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11262 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11263 ULONG helpStringContext
)
11265 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11267 TRACE("%p, %lu.\n", iface
, helpStringContext
);
11269 This
->dwHelpStringContext
= helpStringContext
;
11274 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11275 UINT index
, ULONG helpStringContext
)
11277 FIXME("%p, %u, %lu - stub\n", iface
, index
, helpStringContext
);
11281 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11282 UINT index
, ULONG helpStringContext
)
11284 FIXME("%p, %u, %lu - stub\n", iface
, index
, helpStringContext
);
11288 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11290 FIXME("%p - stub\n", iface
);
11294 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11297 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11299 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11302 return E_INVALIDARG
;
11304 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11309 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11310 ICreateTypeInfo2_fnQueryInterface
,
11311 ICreateTypeInfo2_fnAddRef
,
11312 ICreateTypeInfo2_fnRelease
,
11313 ICreateTypeInfo2_fnSetGuid
,
11314 ICreateTypeInfo2_fnSetTypeFlags
,
11315 ICreateTypeInfo2_fnSetDocString
,
11316 ICreateTypeInfo2_fnSetHelpContext
,
11317 ICreateTypeInfo2_fnSetVersion
,
11318 ICreateTypeInfo2_fnAddRefTypeInfo
,
11319 ICreateTypeInfo2_fnAddFuncDesc
,
11320 ICreateTypeInfo2_fnAddImplType
,
11321 ICreateTypeInfo2_fnSetImplTypeFlags
,
11322 ICreateTypeInfo2_fnSetAlignment
,
11323 ICreateTypeInfo2_fnSetSchema
,
11324 ICreateTypeInfo2_fnAddVarDesc
,
11325 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11326 ICreateTypeInfo2_fnSetVarName
,
11327 ICreateTypeInfo2_fnSetTypeDescAlias
,
11328 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11329 ICreateTypeInfo2_fnSetFuncDocString
,
11330 ICreateTypeInfo2_fnSetVarDocString
,
11331 ICreateTypeInfo2_fnSetFuncHelpContext
,
11332 ICreateTypeInfo2_fnSetVarHelpContext
,
11333 ICreateTypeInfo2_fnSetMops
,
11334 ICreateTypeInfo2_fnSetTypeIdldesc
,
11335 ICreateTypeInfo2_fnLayOut
,
11336 ICreateTypeInfo2_fnDeleteFuncDesc
,
11337 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11338 ICreateTypeInfo2_fnDeleteVarDesc
,
11339 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11340 ICreateTypeInfo2_fnDeleteImplType
,
11341 ICreateTypeInfo2_fnSetCustData
,
11342 ICreateTypeInfo2_fnSetFuncCustData
,
11343 ICreateTypeInfo2_fnSetParamCustData
,
11344 ICreateTypeInfo2_fnSetVarCustData
,
11345 ICreateTypeInfo2_fnSetImplTypeCustData
,
11346 ICreateTypeInfo2_fnSetHelpStringContext
,
11347 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11348 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11349 ICreateTypeInfo2_fnInvalidate
,
11350 ICreateTypeInfo2_fnSetName
11353 /******************************************************************************
11354 * ClearCustData (OLEAUT32.171)
11356 * Clear a custom data type's data.
11359 * lpCust [I] The custom data type instance
11364 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11366 if (lpCust
&& lpCust
->cCustData
)
11368 if (lpCust
->prgCustData
)
11372 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11373 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11375 CoTaskMemFree(lpCust
->prgCustData
);
11376 lpCust
->prgCustData
= NULL
;
11378 lpCust
->cCustData
= 0;