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
);
88 WORD type_id
; /* Type identifier */
89 WORD count
; /* Number of resources of this type */
90 DWORD resloader
; /* SetResourceHandler() */
96 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
97 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
98 static void TLB_FreeVarDesc(VARDESC
*);
100 /****************************************************************************
103 * Takes p_iVal (which is in little endian) and returns it
104 * in the host machine's byte order.
106 #ifdef WORDS_BIGENDIAN
107 static WORD
FromLEWord(WORD p_iVal
)
109 return (((p_iVal
& 0x00FF) << 8) |
110 ((p_iVal
& 0xFF00) >> 8));
114 static DWORD
FromLEDWord(DWORD p_iVal
)
116 return (((p_iVal
& 0x000000FF) << 24) |
117 ((p_iVal
& 0x0000FF00) << 8) |
118 ((p_iVal
& 0x00FF0000) >> 8) |
119 ((p_iVal
& 0xFF000000) >> 24));
122 #define FromLEWord(X) (X)
123 #define FromLEDWord(X) (X)
126 #define DISPATCH_HREF_OFFSET 0x01000000
127 #define DISPATCH_HREF_MASK 0xff000000
129 /****************************************************************************
132 * Fix byte order in any structure if necessary
134 #ifdef WORDS_BIGENDIAN
135 static void FromLEWords(void *p_Val
, int p_iSize
)
139 p_iSize
/= sizeof(WORD
);
142 *Val
= FromLEWord(*Val
);
149 static void FromLEDWords(void *p_Val
, int p_iSize
)
153 p_iSize
/= sizeof(DWORD
);
156 *Val
= FromLEDWord(*Val
);
162 #define FromLEWords(X,Y) /*nothing*/
163 #define FromLEDWords(X,Y) /*nothing*/
167 * Find a typelib key which matches a requested maj.min version.
169 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
174 INT best_maj
= -1, best_min
= -1;
177 lstrcpyW( buffer
, L
"Typelib\\" );
178 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
180 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
183 len
= sizeof(key_name
);
185 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
189 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
191 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
193 if (*wMaj
== 0xffff && *wMin
== 0xffff)
195 if (v_maj
> best_maj
) best_maj
= v_maj
;
196 if (v_min
> best_min
) best_min
= v_min
;
198 else if (*wMaj
== v_maj
)
205 break; /* exact match */
207 if (*wMin
!= 0xffff && v_min
>= *wMin
&& v_min
> best_min
) best_min
= v_min
;
210 len
= sizeof(key_name
);
214 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
216 if (*wMaj
== 0xffff && *wMin
== 0xffff)
218 if (best_maj
>= 0 && best_min
>= 0)
226 if (*wMaj
== best_maj
&& best_min
>= 0)
234 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
235 /* buffer must be at least 60 characters long */
236 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
238 lstrcpyW( buffer
, L
"Typelib\\" );
239 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
240 swprintf( buffer
+ lstrlenW(buffer
), 20, L
"\\%x.%x", wMaj
, wMin
);
244 /* get the path of an interface key, in the form "Interface\\<guid>" */
245 /* buffer must be at least 50 characters long */
246 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
248 lstrcpyW( buffer
, L
"Interface\\" );
249 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
253 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
254 /* buffer must be at least 16 characters long */
255 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
257 swprintf( buffer
, 16, L
"%lx\\", lcid
);
260 case SYS_WIN16
: lstrcatW( buffer
, L
"win16" ); break;
261 case SYS_WIN32
: lstrcatW( buffer
, L
"win32" ); break;
262 case SYS_WIN64
: lstrcatW( buffer
, L
"win64" ); break;
264 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
270 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
272 struct tlibredirect_data
286 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
287 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
288 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
290 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
294 WCHAR Path
[MAX_PATH
];
297 TRACE_(typelib
)("%s, %x.%x, %#lx, %p\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
301 ACTCTX_SECTION_KEYED_DATA data
;
303 data
.cbSize
= sizeof(data
);
304 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
306 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
310 if ((wMaj
!= 0xffff || wMin
!= 0xffff) && (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
))
311 return TYPE_E_LIBNOTREGISTERED
;
313 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
314 len
= SearchPathW( NULL
, nameW
, NULL
, ARRAY_SIZE( Path
), Path
, NULL
);
315 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
317 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
318 *path
= SysAllocString( Path
);
323 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
324 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
326 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
327 if (res
== ERROR_FILE_NOT_FOUND
)
329 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
330 return TYPE_E_LIBNOTREGISTERED
;
332 else if (res
!= ERROR_SUCCESS
)
334 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
335 return TYPE_E_REGISTRYACCESS
;
340 LONG dwPathLen
= sizeof(Path
);
342 get_lcid_subkey( myLCID
, syskind
, buffer
);
344 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
348 else if (myLCID
== lcid
)
350 /* try with sub-langid */
351 myLCID
= SUBLANGID(lcid
);
353 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
355 /* try with system langid */
365 *path
= SysAllocString( Path
);
370 TRACE_(typelib
)("-- %#lx\n", hr
);
374 /****************************************************************************
375 * QueryPathOfRegTypeLib [OLEAUT32.164]
377 * Gets the path to a registered type library.
380 * guid [I] referenced guid
381 * wMaj [I] major version
382 * wMin [I] minor version
384 * path [O] path of typelib
388 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
389 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
392 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
396 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
401 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, 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
);
1982 if(sys
== SYS_WIN32
)
1983 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1987 *size
= sizeof(DECIMAL
);
1994 for(i
= 0; i
< tdesc
->lpadesc
->cDims
; ++i
)
1995 *size
+= tdesc
->lpadesc
->rgbounds
[i
].cElements
;
1996 hr
= TLB_size_instance(info
, sys
, &tdesc
->lpadesc
->tdescElem
, &sub
, align
);
2001 case VT_USERDEFINED
:
2002 return TLB_get_size_from_hreftype(info
, tdesc
->hreftype
, size
, align
);
2004 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2018 /**********************************************************************
2020 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2023 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2025 if (where
!= DO_NOT_SEEK
)
2027 where
+= pcx
->oStart
;
2028 if (where
> pcx
->length
)
2031 ERR("seek beyond end (%ld/%d)\n", where
, pcx
->length
);
2039 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2041 TRACE_(typelib
)("pos=0x%08x len %#lx, %u, %u, %#lx\n",
2042 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2044 MSFT_Seek(pcx
, where
);
2045 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2046 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2051 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2056 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2057 FromLEDWords(buffer
, ret
);
2062 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2067 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2068 FromLEWords(buffer
, ret
);
2073 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2076 MSFT_GuidEntry entry
;
2079 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2081 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2084 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2086 guid
= malloc(sizeof(TLBGuid
));
2088 guid
->offset
= offs
;
2089 guid
->guid
= entry
.guid
;
2090 guid
->hreftype
= entry
.hreftype
;
2092 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2094 offs
+= sizeof(MSFT_GuidEntry
);
2098 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2102 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2103 if(ret
->offset
== offset
){
2104 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2112 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2114 MSFT_NameIntro niName
;
2118 ERR_(typelib
)("bad offset %d\n", offset
);
2122 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2123 pcx
->pTblDir
->pNametab
.offset
+offset
);
2125 return niName
.hreftype
;
2128 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2131 MSFT_NameIntro intro
;
2133 int offs
= 0, lengthInChars
;
2135 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2139 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2142 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2143 intro
.namelen
&= 0xFF;
2144 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2146 len_piece
= (len_piece
+ 4) & ~0x3;
2150 string
= malloc(len_piece
+ 1);
2151 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2152 string
[intro
.namelen
] = '\0';
2154 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2155 string
, -1, NULL
, 0);
2156 if (!lengthInChars
) {
2158 return E_UNEXPECTED
;
2161 tlbstr
= malloc(sizeof(TLBString
));
2163 tlbstr
->offset
= offs
;
2164 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2165 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2169 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2175 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2179 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2180 if (tlbstr
->offset
== offset
) {
2181 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2189 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2193 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2194 if (tlbstr
->offset
== offset
) {
2195 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2204 * read a value and fill a VARIANT structure
2206 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2210 TRACE_(typelib
)("\n");
2212 if(offset
<0) { /* data are packed in here */
2213 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2214 V_I4(pVar
) = offset
& 0x3ffffff;
2217 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2218 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2219 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2220 switch (V_VT(pVar
)){
2221 case VT_EMPTY
: /* FIXME: is this right? */
2222 case VT_NULL
: /* FIXME: is this right? */
2223 case VT_I2
: /* this should not happen */
2234 case VT_VOID
: /* FIXME: is this right? */
2242 case VT_DECIMAL
: /* FIXME: is this right? */
2245 /* pointer types with known behaviour */
2248 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2250 V_BSTR(pVar
) = NULL
;
2253 ptr
= calloc(1, size
);
2254 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2255 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, size
, NULL
, 0 );
2256 V_BSTR(pVar
)=SysAllocStringLen(NULL
,len
);
2257 MultiByteToWideChar(CP_ACP
, 0, ptr
, size
, V_BSTR(pVar
), len
);
2262 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2269 case VT_USERDEFINED
:
2275 case VT_STREAMED_OBJECT
:
2276 case VT_STORED_OBJECT
:
2277 case VT_BLOB_OBJECT
:
2282 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2286 if(size
>0) /* (big|small) endian correct? */
2287 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2291 * create a linked list with custom data
2293 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2299 TRACE_(typelib
)("\n");
2301 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2305 pNew
= calloc(1, sizeof(TLBCustData
));
2306 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2307 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2308 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2309 list_add_head(custdata_list
, &pNew
->entry
);
2310 offset
= entry
.next
;
2315 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2318 pTd
->vt
=type
& VT_TYPEMASK
;
2320 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2322 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2325 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2327 return (invkind
== INVOKE_PROPERTYGET
||
2328 invkind
== INVOKE_PROPERTYPUT
||
2329 invkind
== INVOKE_PROPERTYPUTREF
);
2333 MSFT_DoFuncs(TLBContext
* pcx
,
2338 TLBFuncDesc
** pptfd
)
2341 * member information is stored in a data structure at offset
2342 * indicated by the memoffset field of the typeinfo structure
2343 * There are several distinctive parts.
2344 * The first part starts with a field that holds the total length
2345 * of this (first) part excluding this field. Then follow the records,
2346 * for each member there is one record.
2348 * The first entry is always the length of the record (including this
2350 * The rest of the record depends on the type of the member. If there is
2351 * a field indicating the member type (function, variable, interface, etc)
2352 * I have not found it yet. At this time we depend on the information
2353 * in the type info and the usual order how things are stored.
2355 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2358 * Third is an equal sized array with file offsets to the name entry
2361 * The fourth and last (?) part is an array with offsets to the records
2362 * in the first part of this file segment.
2365 int infolen
, nameoffset
, reclength
, i
;
2366 int recoffset
= offset
+ sizeof(INT
);
2368 char *recbuf
= malloc(0xffff);
2369 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2370 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2372 TRACE_(typelib
)("\n");
2374 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2376 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2378 for ( i
= 0; i
< cFuncs
; i
++ )
2382 /* name, eventually add to a hash table */
2383 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2384 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2386 /* read the function information record */
2387 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2389 reclength
&= 0xffff;
2391 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2393 /* size without argument data */
2394 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2395 if (pFuncRec
->FKCCIC
& 0x1000)
2396 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2398 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2399 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2401 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2402 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2404 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2406 if (pFuncRec
->FKCCIC
& 0x2000 )
2408 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2409 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2410 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2413 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2416 ptfd
->Entry
= (TLBString
*)-1;
2418 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2419 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2421 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2422 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2424 /* fill the FuncDesc Structure */
2425 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2426 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2428 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2429 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2430 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2431 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2432 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2433 if (ptfd
->funcdesc
.funckind
== FUNC_DISPATCH
)
2434 ptfd
->funcdesc
.oVft
= 0;
2436 ptfd
->funcdesc
.oVft
= (pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2437 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2439 /* nameoffset is sometimes -1 on the second half of a propget/propput
2440 * pair of functions */
2441 if ((nameoffset
== -1) && (i
> 0) &&
2442 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2443 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2444 ptfd
->Name
= ptfd_prev
->Name
;
2446 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2450 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2452 /* do the parameters/arguments */
2453 if(pFuncRec
->nrargs
)
2456 MSFT_ParameterInfo paraminfo
;
2458 ptfd
->funcdesc
.lprgelemdescParam
=
2459 calloc(pFuncRec
->nrargs
, sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
));
2461 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2463 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2464 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2466 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2468 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2474 elemdesc
->paramdesc
.wParamFlags
= paraminfo
.Flags
;
2477 if (paraminfo
.oName
!= -1)
2478 ptfd
->pParamDesc
[j
].Name
=
2479 MSFT_ReadName( pcx
, paraminfo
.oName
);
2480 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2483 if ( (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2484 (pFuncRec
->FKCCIC
& 0x1000) )
2486 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2488 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2490 PARAMDESC
* pParamDesc
= &elemdesc
->paramdesc
;
2492 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2493 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2495 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2499 elemdesc
->paramdesc
.pparamdescex
= NULL
;
2502 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2503 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2504 pFuncRec
->FKCCIC
& 0x80 )
2507 pFuncRec
->oArgCustData
[j
],
2508 &ptfd
->pParamDesc
[j
].custdata_list
);
2511 /* SEEK value = jump to offset,
2512 * from there jump to the end of record,
2513 * go back by (j-1) arguments
2515 MSFT_ReadLEDWords( ¶minfo
,
2516 sizeof(MSFT_ParameterInfo
), pcx
,
2517 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2518 * sizeof(MSFT_ParameterInfo
)));
2522 /* scode is not used: archaic win16 stuff FIXME: right? */
2523 ptfd
->funcdesc
.cScodes
= 0 ;
2524 ptfd
->funcdesc
.lprgscode
= NULL
;
2528 recoffset
+= reclength
;
2533 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2534 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2536 int infolen
, nameoffset
, reclength
;
2538 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2543 TRACE_(typelib
)("\n");
2545 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2546 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2547 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2548 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2549 recoffset
+= offset
+sizeof(INT
);
2550 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2551 /* name, eventually add to a hash table */
2552 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2553 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2554 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2555 /* read the variable information record */
2556 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2558 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2561 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2562 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2564 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2565 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2567 if (reclength
> FIELD_OFFSET(MSFT_VarRecord
, oCustData
))
2568 MSFT_CustData(pcx
, pVarRec
->oCustData
, &ptvd
->custdata_list
);
2570 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2571 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2573 /* fill the VarDesc Structure */
2574 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2575 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2576 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2577 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2578 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2579 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2580 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2581 if(pVarRec
->VarKind
== VAR_CONST
){
2582 ptvd
->vardesc
.lpvarValue
= calloc(1, sizeof(VARIANT
));
2583 MSFT_ReadValue(ptvd
->vardesc
.lpvarValue
,
2584 pVarRec
->OffsValue
, pcx
);
2586 ptvd
->vardesc
.oInst
=pVarRec
->OffsValue
;
2587 recoffset
+= reclength
;
2591 /* process Implemented Interfaces of a com class */
2592 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2596 MSFT_RefRecord refrec
;
2599 TRACE_(typelib
)("\n");
2601 pTI
->impltypes
= TLBImplType_Alloc(count
);
2602 pImpl
= pTI
->impltypes
;
2603 for(i
=0;i
<count
;i
++){
2604 if(offset
<0) break; /* paranoia */
2605 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2606 pImpl
->hRef
= refrec
.reftype
;
2607 pImpl
->implflags
=refrec
.flags
;
2608 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2609 offset
=refrec
.onext
;
2615 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2616 * and some structures, and fix the alignment */
2617 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2619 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2620 switch(info
->tdescAlias
->vt
){
2628 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2629 info
->typeattr
.cbAlignment
= sizeof(void*);
2632 case VT_USERDEFINED
:
2633 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2636 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2637 info
->typeattr
.cbAlignment
= 8;
2639 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2640 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2642 info
->typeattr
.cbAlignment
= sizeof(void*);
2645 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2646 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2647 info
->typeattr
.typekind
== TKIND_COCLASS
){
2648 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2649 info
->typeattr
.cbAlignment
= sizeof(void*);
2655 * process a typeinfo record
2657 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2660 ITypeLibImpl
* pLibInfo
)
2662 MSFT_TypeInfoBase tiBase
;
2663 ITypeInfoImpl
*ptiRet
;
2665 TRACE_(typelib
)("count=%u\n", count
);
2667 ptiRet
= ITypeInfoImpl_Constructor();
2668 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2669 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2671 /* this is where we are coming from */
2672 ptiRet
->pTypeLib
= pLibInfo
;
2673 ptiRet
->index
=count
;
2675 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2676 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2677 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2678 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2679 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2680 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2681 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2682 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2683 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2684 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2685 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2686 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2687 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2688 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2690 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2691 ptiRet
->tdescAlias
= malloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2692 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2696 /* IDLDESC idldescType; *//* never saw this one != zero */
2698 /* name, eventually add to a hash table */
2699 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2700 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2701 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2703 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2704 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2705 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2707 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2708 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2710 /* note: InfoType's Help file and HelpStringDll come from the containing
2711 * library. Further HelpString and Docstring appear to be the same thing :(
2714 if(ptiRet
->typeattr
.cFuncs
>0 )
2715 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2716 ptiRet
->typeattr
.cVars
,
2717 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2719 if(ptiRet
->typeattr
.cVars
>0 )
2720 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2721 ptiRet
->typeattr
.cVars
,
2722 tiBase
.memoffset
, &ptiRet
->vardescs
);
2723 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2724 switch(ptiRet
->typeattr
.typekind
)
2727 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2730 case TKIND_DISPATCH
:
2731 /* This is not -1 when the interface is a non-base dual interface or
2732 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2733 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2737 if (tiBase
.datatype1
!= -1)
2739 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2740 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2744 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2745 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2749 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2751 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2752 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2753 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2754 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2755 if (TRACE_ON(typelib
))
2756 dump_TypeInfo(ptiRet
);
2761 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2764 INT16 len_str
, len_piece
;
2765 int offs
= 0, lengthInChars
;
2767 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2771 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2774 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2775 len_piece
= len_str
+ sizeof(INT16
);
2777 len_piece
= (len_piece
+ 4) & ~0x3;
2781 string
= malloc(len_piece
+ 1);
2782 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2783 string
[len_str
] = '\0';
2785 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2786 string
, -1, NULL
, 0);
2787 if (!lengthInChars
) {
2789 return E_UNEXPECTED
;
2792 tlbstr
= malloc(sizeof(TLBString
));
2794 tlbstr
->offset
= offs
;
2795 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2796 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2800 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2806 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2811 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2812 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2813 MSFT_ImpInfo impinfo
;
2816 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2818 ref
= calloc(1, sizeof(TLBRefType
));
2819 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2821 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2822 if(pImpLib
->offset
==impinfo
.oImpFile
)
2825 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2826 ref
->reference
= offs
;
2827 ref
->pImpTLInfo
= pImpLib
;
2828 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2829 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2830 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2831 ref
->index
= TLB_REF_USE_GUID
;
2833 ref
->index
= impinfo
.oGuid
;
2835 ERR("Cannot find a reference\n");
2836 ref
->reference
= -1;
2837 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2840 offs
+= sizeof(impinfo
);
2846 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2847 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2848 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2851 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2852 static CRITICAL_SECTION cache_section
;
2853 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2855 0, 0, &cache_section
,
2856 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2857 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2859 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2862 typedef struct TLB_PEFile
2864 IUnknown IUnknown_iface
;
2867 HRSRC typelib_resource
;
2868 HGLOBAL typelib_global
;
2869 LPVOID typelib_base
;
2872 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2874 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2877 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2879 if (IsEqualIID(riid
, &IID_IUnknown
))
2882 IUnknown_AddRef(iface
);
2886 return E_NOINTERFACE
;
2889 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2891 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2892 return InterlockedIncrement(&This
->refs
);
2895 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2897 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2898 ULONG refs
= InterlockedDecrement(&This
->refs
);
2901 if (This
->typelib_global
)
2902 FreeResource(This
->typelib_global
);
2904 FreeLibrary(This
->dll
);
2910 static const IUnknownVtbl TLB_PEFile_Vtable
=
2912 TLB_PEFile_QueryInterface
,
2917 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2920 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2922 This
= malloc(sizeof(TLB_PEFile
));
2924 return E_OUTOFMEMORY
;
2926 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2929 This
->typelib_resource
= NULL
;
2930 This
->typelib_global
= NULL
;
2931 This
->typelib_base
= NULL
;
2933 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2934 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2938 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), L
"TYPELIB");
2939 if (This
->typelib_resource
)
2941 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2942 if (This
->typelib_global
)
2944 This
->typelib_base
= LockResource(This
->typelib_global
);
2946 if (This
->typelib_base
)
2948 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2949 *ppBase
= This
->typelib_base
;
2950 *ppFile
= &This
->IUnknown_iface
;
2956 TRACE("No TYPELIB resource found\n");
2960 TLB_PEFile_Release(&This
->IUnknown_iface
);
2964 typedef struct TLB_NEFile
2966 IUnknown IUnknown_iface
;
2968 LPVOID typelib_base
;
2971 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2973 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2976 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2978 if (IsEqualIID(riid
, &IID_IUnknown
))
2981 IUnknown_AddRef(iface
);
2985 return E_NOINTERFACE
;
2988 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2990 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2991 return InterlockedIncrement(&This
->refs
);
2994 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2996 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2997 ULONG refs
= InterlockedDecrement(&This
->refs
);
3000 free(This
->typelib_base
);
3006 static const IUnknownVtbl TLB_NEFile_Vtable
=
3008 TLB_NEFile_QueryInterface
,
3013 /***********************************************************************
3014 * read_xx_header [internal]
3016 static int read_xx_header( HFILE lzfd
)
3018 IMAGE_DOS_HEADER mzh
;
3021 LZSeek( lzfd
, 0, SEEK_SET
);
3022 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3024 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3027 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3028 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3031 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3033 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3034 return IMAGE_OS2_SIGNATURE
;
3035 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3036 return IMAGE_NT_SIGNATURE
;
3039 WARN("Can't handle %s files.\n", magic
);
3044 /***********************************************************************
3045 * find_ne_resource [internal]
3047 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3048 DWORD
*resLen
, DWORD
*resOff
)
3050 IMAGE_OS2_HEADER nehd
;
3051 NE_TYPEINFO
*typeInfo
;
3052 NE_NAMEINFO
*nameInfo
;
3058 /* Read in NE header */
3059 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3060 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3062 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3065 TRACE("No resources in NE dll\n" );
3069 /* Read in resource table */
3070 resTab
= malloc( resTabSize
);
3071 if ( !resTab
) return FALSE
;
3073 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3074 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3081 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3083 if (!IS_INTRESOURCE(typeid)) /* named type */
3085 BYTE len
= strlen( typeid );
3086 while (typeInfo
->type_id
)
3088 if (!(typeInfo
->type_id
& 0x8000))
3090 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3091 if ((*p
== len
) && !_strnicmp( (char*)p
+1, typeid, len
)) goto found_type
;
3093 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3094 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3097 else /* numeric type id */
3099 WORD id
= LOWORD(typeid) | 0x8000;
3100 while (typeInfo
->type_id
)
3102 if (typeInfo
->type_id
== id
) goto found_type
;
3103 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3104 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3107 TRACE("No typeid entry found for %p\n", typeid );
3112 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3114 if (!IS_INTRESOURCE(resid
)) /* named resource */
3116 BYTE len
= strlen( resid
);
3117 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3119 BYTE
*p
= resTab
+ nameInfo
->id
;
3120 if (nameInfo
->id
& 0x8000) continue;
3121 if ((*p
== len
) && !_strnicmp( (char*)p
+1, resid
, len
)) goto found_name
;
3124 else /* numeric resource id */
3126 WORD id
= LOWORD(resid
) | 0x8000;
3127 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3128 if (nameInfo
->id
== id
) goto found_name
;
3130 TRACE("No resid entry found for %p\n", typeid );
3135 /* Return resource data */
3136 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3137 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3143 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3147 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3150 This
= malloc(sizeof(TLB_NEFile
));
3151 if (!This
) return E_OUTOFMEMORY
;
3153 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3155 This
->typelib_base
= NULL
;
3157 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3158 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3160 DWORD reslen
, offset
;
3161 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3163 This
->typelib_base
= malloc(reslen
);
3164 if( !This
->typelib_base
)
3168 LZSeek( lzfd
, offset
, SEEK_SET
);
3169 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3171 *ppBase
= This
->typelib_base
;
3172 *pdwTLBLength
= reslen
;
3173 *ppFile
= &This
->IUnknown_iface
;
3179 if( lzfd
>= 0) LZClose( lzfd
);
3180 TLB_NEFile_Release(&This
->IUnknown_iface
);
3184 typedef struct TLB_Mapping
3186 IUnknown IUnknown_iface
;
3190 LPVOID typelib_base
;
3193 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3195 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3198 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3200 if (IsEqualIID(riid
, &IID_IUnknown
))
3203 IUnknown_AddRef(iface
);
3207 return E_NOINTERFACE
;
3210 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3212 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3213 return InterlockedIncrement(&This
->refs
);
3216 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3218 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3219 ULONG refs
= InterlockedDecrement(&This
->refs
);
3222 if (This
->typelib_base
)
3223 UnmapViewOfFile(This
->typelib_base
);
3225 CloseHandle(This
->mapping
);
3226 if (This
->file
!= INVALID_HANDLE_VALUE
)
3227 CloseHandle(This
->file
);
3233 static const IUnknownVtbl TLB_Mapping_Vtable
=
3235 TLB_Mapping_QueryInterface
,
3240 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3244 This
= malloc(sizeof(TLB_Mapping
));
3246 return E_OUTOFMEMORY
;
3248 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3250 This
->file
= INVALID_HANDLE_VALUE
;
3251 This
->mapping
= NULL
;
3252 This
->typelib_base
= NULL
;
3254 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3255 if (INVALID_HANDLE_VALUE
!= This
->file
)
3257 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3260 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3261 if(This
->typelib_base
)
3263 /* retrieve file size */
3264 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3265 *ppBase
= This
->typelib_base
;
3266 *ppFile
= &This
->IUnknown_iface
;
3272 IUnknown_Release(&This
->IUnknown_iface
);
3273 return TYPE_E_CANTLOADLIBRARY
;
3276 /****************************************************************************
3279 * find the type of the typelib file and map the typelib resource into
3283 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3284 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3286 ITypeLibImpl
*entry
;
3289 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3290 LPVOID pBase
= NULL
;
3291 DWORD dwTLBLength
= 0;
3292 IUnknown
*pFile
= NULL
;
3297 index_str
= wcsrchr(pszFileName
, '\\');
3298 if(index_str
&& *++index_str
!= '\0')
3301 LONG idx
= wcstol(index_str
, &end_ptr
, 10);
3302 if(*end_ptr
== '\0')
3304 int str_len
= index_str
- pszFileName
- 1;
3306 file
= malloc((str_len
+ 1) * sizeof(WCHAR
));
3307 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3312 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3314 if(wcschr(file
, '\\'))
3316 lstrcpyW(pszPath
, file
);
3320 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3321 pszPath
[len
] = '\\';
3322 memcpy(pszPath
+ len
+ 1, file
, (lstrlenW(file
) + 1) * sizeof(WCHAR
));
3326 if(file
!= pszFileName
) free(file
);
3328 h
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3329 if(h
!= INVALID_HANDLE_VALUE
){
3330 GetFinalPathNameByHandleW(h
, pszPath
, cchPath
, FILE_NAME_NORMALIZED
| VOLUME_NAME_DOS
);
3334 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3336 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3337 EnterCriticalSection(&cache_section
);
3338 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3340 if (!wcsicmp(entry
->path
, pszPath
) && entry
->index
== index
)
3342 TRACE("cache hit\n");
3343 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3344 ITypeLib2_AddRef(*ppTypeLib
);
3345 LeaveCriticalSection(&cache_section
);
3349 LeaveCriticalSection(&cache_section
);
3351 /* now actually load and parse the typelib */
3353 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3354 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3355 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3356 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3357 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3360 if (dwTLBLength
>= 4)
3362 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3363 if (dwSignature
== MSFT_SIGNATURE
)
3364 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3365 else if (dwSignature
== SLTG_SIGNATURE
)
3366 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3369 FIXME("Header type magic %#lx not supported.\n", dwSignature
);
3370 ret
= TYPE_E_CANTLOADLIBRARY
;
3374 ret
= TYPE_E_CANTLOADLIBRARY
;
3375 IUnknown_Release(pFile
);
3379 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3381 TRACE("adding to cache\n");
3382 impl
->path
= wcsdup(pszPath
);
3383 /* We should really canonicalise the path here. */
3384 impl
->index
= index
;
3386 /* FIXME: check if it has added already in the meantime */
3387 EnterCriticalSection(&cache_section
);
3388 list_add_head(&tlb_cache
, &impl
->entry
);
3389 LeaveCriticalSection(&cache_section
);
3395 ERR("Loading of typelib %s failed with error %ld\n", debugstr_w(pszFileName
), GetLastError());
3397 ret
= TYPE_E_CANTLOADLIBRARY
;
3404 /*================== ITypeLib(2) Methods ===================================*/
3406 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3408 ITypeLibImpl
* pTypeLibImpl
;
3410 pTypeLibImpl
= calloc(1, sizeof(ITypeLibImpl
));
3411 if (!pTypeLibImpl
) return NULL
;
3413 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3414 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3415 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3416 pTypeLibImpl
->ref
= 1;
3418 list_init(&pTypeLibImpl
->implib_list
);
3419 list_init(&pTypeLibImpl
->custdata_list
);
3420 list_init(&pTypeLibImpl
->name_list
);
3421 list_init(&pTypeLibImpl
->string_list
);
3422 list_init(&pTypeLibImpl
->guid_list
);
3423 list_init(&pTypeLibImpl
->ref_list
);
3424 pTypeLibImpl
->dispatch_href
= -1;
3426 return pTypeLibImpl
;
3429 /****************************************************************************
3430 * ITypeLib2_Constructor_MSFT
3432 * loading an MSFT typelib from an in-memory image
3434 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3438 MSFT_Header tlbHeader
;
3439 MSFT_SegDir tlbSegDir
;
3440 ITypeLibImpl
* pTypeLibImpl
;
3443 TRACE("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
3445 pTypeLibImpl
= TypeLibImpl_Constructor();
3446 if (!pTypeLibImpl
) return NULL
;
3448 /* get pointer to beginning of typelib data */
3452 cx
.pLibInfo
= pTypeLibImpl
;
3453 cx
.length
= dwTLBLength
;
3456 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3457 TRACE_(typelib
)("header:\n");
3458 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3459 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3460 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3463 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3465 /* there is a small amount of information here until the next important
3467 * the segment directory . Try to calculate the amount of data */
3468 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3470 /* now read the segment directory */
3471 TRACE("read segment directory (at %ld)\n",lPSegDir
);
3472 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3473 cx
.pTblDir
= &tlbSegDir
;
3475 /* just check two entries */
3476 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3478 ERR("cannot find the table directory, ptr %#lx\n",lPSegDir
);
3483 MSFT_ReadAllNames(&cx
);
3484 MSFT_ReadAllStrings(&cx
);
3485 MSFT_ReadAllGuids(&cx
);
3487 /* now fill our internal data */
3488 /* TLIBATTR fields */
3489 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3491 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3492 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3493 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3494 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3495 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3497 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3498 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3500 /* name, eventually add to a hash table */
3501 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3504 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3505 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3507 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3510 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3511 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3514 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3517 if(tlbHeader
.CustomDataOffset
>= 0)
3519 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3522 /* fill in type descriptions */
3523 if(tlbSegDir
.pTypdescTab
.length
> 0)
3525 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3527 pTypeLibImpl
->ctTypeDesc
= cTD
;
3528 pTypeLibImpl
->pTypeDesc
= calloc(cTD
, sizeof(TYPEDESC
));
3529 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3532 /* FIXME: add several sanity checks here */
3533 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3534 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3536 /* FIXME: check safearray */
3538 pTypeLibImpl
->pTypeDesc
[i
].lptdesc
= &std_typedesc
[td
[2]];
3540 pTypeLibImpl
->pTypeDesc
[i
].lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3542 else if(td
[0] == VT_CARRAY
)
3544 /* array descr table here */
3545 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3547 else if(td
[0] == VT_USERDEFINED
)
3549 pTypeLibImpl
->pTypeDesc
[i
].hreftype
= MAKELONG(td
[2],td
[3]);
3551 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3554 /* second time around to fill the array subscript info */
3557 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3558 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3560 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].lpadesc
);
3561 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
= calloc(1, sizeof(ARRAYDESC
) + sizeof(SAFEARRAYBOUND
) * (td
[3] - 1));
3564 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3566 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3568 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->cDims
= td
[2];
3570 for(j
= 0; j
<td
[2]; j
++)
3572 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->rgbounds
[j
].cElements
,
3573 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3574 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].lpadesc
->rgbounds
[j
].lLbound
,
3575 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3580 pTypeLibImpl
->pTypeDesc
[i
].lpadesc
= NULL
;
3581 ERR("didn't find array description data\n");
3586 /* imported type libs */
3587 if(tlbSegDir
.pImpFiles
.offset
>0)
3590 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3593 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3597 pImpLib
= calloc(1, sizeof(TLBImpLib
));
3598 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3599 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3601 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3602 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3603 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3604 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3607 name
= calloc(1, size
+ 1);
3608 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3609 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3612 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3613 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3615 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3619 MSFT_ReadAllRefs(&cx
);
3621 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3624 if(tlbHeader
.nrtypeinfos
>= 0 )
3626 ITypeInfoImpl
**ppTI
;
3628 ppTI
= pTypeLibImpl
->typeinfos
= calloc(tlbHeader
.nrtypeinfos
, sizeof(ITypeInfoImpl
*));
3630 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3632 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3635 (pTypeLibImpl
->TypeInfoCount
)++;
3640 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3641 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3642 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3646 TRACE("(%p)\n", pTypeLibImpl
);
3647 return &pTypeLibImpl
->ITypeLib2_iface
;
3651 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3657 if(sscanf(str
, "%lx-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3658 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3662 guid
->Data4
[0] = s
>> 8;
3663 guid
->Data4
[1] = s
& 0xff;
3666 for(i
= 0; i
< 6; i
++) {
3667 memcpy(b
, str
+ 24 + 2 * i
, 2);
3668 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3673 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3680 bytelen
= *(const WORD
*)ptr
;
3681 if(bytelen
== 0xffff) return 2;
3683 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3684 tmp_str
= SysAllocStringLen(NULL
, len
);
3686 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3687 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3688 SysFreeString(tmp_str
);
3693 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3698 bytelen
= *(const WORD
*)ptr
;
3699 if(bytelen
== 0xffff) return 2;
3700 *str
= malloc(bytelen
+ 1);
3701 memcpy(*str
, ptr
+ 2, bytelen
);
3702 (*str
)[bytelen
] = '\0';
3706 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3711 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3712 if (tlbstr
->offset
== offset
)
3716 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3717 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3718 SysFreeString(tmp_str
);
3723 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3725 char *ptr
= pLibBlk
;
3728 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3729 FIXME("libblk magic = %04x\n", w
);
3734 if((w
= *(WORD
*)ptr
) != 0xffff) {
3735 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w
);
3740 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3742 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3744 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3747 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3748 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3751 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3752 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3754 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3757 ptr
+= 4; /* skip res12 */
3759 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3762 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3765 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3768 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3769 ptr
+= sizeof(GUID
);
3771 return ptr
- (char*)pLibBlk
;
3774 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3779 } sltg_ref_lookup_t
;
3781 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3782 HREFTYPE
*typelib_ref
)
3784 if(table
&& typeinfo_ref
< table
->num
)
3786 *typelib_ref
= table
->refs
[typeinfo_ref
];
3790 ERR_(typelib
)("Unable to find reference\n");
3795 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3800 if((*pType
& 0xe00) == 0xe00) {
3802 pTD
->lptdesc
= calloc(1, sizeof(TYPEDESC
));
3805 switch(*pType
& 0x3f) {
3808 pTD
->lptdesc
= calloc(1, sizeof(TYPEDESC
));
3812 case VT_USERDEFINED
:
3813 pTD
->vt
= VT_USERDEFINED
;
3814 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->hreftype
);
3820 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3823 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3825 pTD
->vt
= VT_CARRAY
;
3826 pTD
->lpadesc
= calloc(1, sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3827 pTD
->lpadesc
->cDims
= pSA
->cDims
;
3828 memcpy(pTD
->lpadesc
->rgbounds
, pSA
->rgsabound
,
3829 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3831 pTD
= &pTD
->lpadesc
->tdescElem
;
3837 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3841 pTD
->vt
= VT_SAFEARRAY
;
3842 pTD
->lptdesc
= calloc(1, sizeof(TYPEDESC
));
3847 pTD
->vt
= *pType
& 0x3f;
3856 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3857 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3859 /* Handle [in/out] first */
3860 if((*pType
& 0xc000) == 0xc000)
3861 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3862 else if(*pType
& 0x8000)
3863 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3864 else if(*pType
& 0x4000)
3865 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3867 pElem
->paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3870 pElem
->paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3873 pElem
->paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3875 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3879 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3884 TLBRefType
*ref_type
;
3885 sltg_ref_lookup_t
*table
;
3886 HREFTYPE typelib_ref
;
3888 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3889 FIXME("Ref magic = %x\n", pRef
->magic
);
3892 name
= ( (char*)pRef
->names
+ pRef
->number
);
3894 table
= malloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3895 table
->num
= pRef
->number
>> 3;
3897 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3899 /* We don't want the first href to be 0 */
3900 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3902 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3904 unsigned int lib_offs
, type_num
;
3906 ref_type
= calloc(1, sizeof(TLBRefType
));
3908 name
+= SLTG_ReadStringA(name
, &refname
);
3909 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3910 FIXME_(typelib
)("Can't sscanf ref\n");
3911 if(lib_offs
!= 0xffff) {
3914 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3915 if(import
->offset
== lib_offs
)
3918 if(&import
->entry
== &pTL
->implib_list
) {
3919 char fname
[MAX_PATH
+1];
3923 import
= calloc(1, sizeof(*import
));
3924 import
->offset
= lib_offs
;
3925 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3926 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3927 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%lx#%s",
3928 &import
->wVersionMajor
,
3929 &import
->wVersionMinor
,
3930 &import
->lcid
, fname
) != 4) {
3931 FIXME_(typelib
)("can't sscanf ref %s\n",
3932 pNameTable
+ lib_offs
+ 40);
3934 len
= strlen(fname
);
3935 if(fname
[len
-1] != '#')
3936 FIXME("fname = %s\n", fname
);
3937 fname
[len
-1] = '\0';
3938 import
->name
= TLB_MultiByteToBSTR(fname
);
3939 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3941 ref_type
->pImpTLInfo
= import
;
3943 /* Store a reference to IDispatch */
3944 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3945 pTL
->dispatch_href
= typelib_ref
;
3947 } else { /* internal ref */
3948 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3950 ref_type
->reference
= typelib_ref
;
3951 ref_type
->index
= type_num
;
3954 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3956 table
->refs
[ref
] = typelib_ref
;
3959 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3960 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3961 dump_TLBRefType(pTL
);
3965 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3966 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3968 SLTG_ImplInfo
*info
;
3969 TLBImplType
*pImplType
;
3970 /* I don't really get this structure, usually it's 0x16 bytes
3971 long, but iuser.tlb contains some that are 0x18 bytes long.
3972 That's ok because we can use the next ptr to jump to the next
3973 one. But how do we know the length of the last one? The WORD
3974 at offs 0x8 might be the clue. For now I'm just assuming that
3975 the last one is the regular 0x16 bytes. */
3977 info
= (SLTG_ImplInfo
*)pBlk
;
3979 pTI
->typeattr
.cImplTypes
++;
3980 if(info
->next
== 0xffff)
3982 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3985 info
= (SLTG_ImplInfo
*)pBlk
;
3986 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
3987 pImplType
= pTI
->impltypes
;
3989 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
3990 pImplType
->implflags
= info
->impltypeflags
;
3993 if(info
->next
== 0xffff)
3996 FIXME_(typelib
)("Interface inheriting more than one interface\n");
3997 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
3999 info
++; /* see comment at top of function */
4003 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4004 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4006 TLBVarDesc
*pVarDesc
;
4007 const TLBString
*prevName
= NULL
;
4008 SLTG_Variable
*pItem
;
4012 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4014 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4015 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4017 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4019 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4020 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4021 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4025 if (pItem
->name
== 0xfffe)
4026 pVarDesc
->Name
= prevName
;
4028 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4030 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4031 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4032 TRACE_(typelib
)("memid = %#lx\n", pItem
->memid
);
4034 if(pItem
->flags
& 0x02)
4035 pType
= &pItem
->type
;
4037 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4039 if (pItem
->flags
& ~0xda)
4040 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4042 SLTG_DoElem(pType
, pBlk
,
4043 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4045 if (TRACE_ON(typelib
)) {
4047 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4048 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4051 if (pItem
->flags
& 0x40) {
4052 TRACE_(typelib
)("VAR_DISPATCH\n");
4053 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4055 else if (pItem
->flags
& 0x10) {
4056 TRACE_(typelib
)("VAR_CONST\n");
4057 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4058 pVarDesc
->vardesc
.lpvarValue
= malloc(sizeof(VARIANT
));
4059 V_VT(pVarDesc
->vardesc
.lpvarValue
) = VT_INT
;
4060 if (pItem
->flags
& 0x08)
4061 V_INT(pVarDesc
->vardesc
.lpvarValue
) = pItem
->byte_offs
;
4063 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4069 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4071 TRACE_(typelib
)("len = %u\n", len
);
4072 if (len
== 0xffff) {
4075 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4076 str
= SysAllocStringLen(NULL
, alloc_len
);
4077 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4079 V_VT(pVarDesc
->vardesc
.lpvarValue
) = VT_BSTR
;
4080 V_BSTR(pVarDesc
->vardesc
.lpvarValue
) = str
;
4089 V_INT(pVarDesc
->vardesc
.lpvarValue
) =
4090 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4093 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4098 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4099 pVarDesc
->vardesc
.oInst
= pItem
->byte_offs
;
4100 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4103 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4104 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4106 if (pItem
->flags
& 0x80)
4107 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4109 prevName
= pVarDesc
->Name
;
4111 pTI
->typeattr
.cVars
= cVars
;
4114 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4115 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4117 SLTG_Function
*pFunc
;
4119 TLBFuncDesc
*pFuncDesc
;
4121 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4123 pFuncDesc
= pTI
->funcdescs
;
4124 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4125 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4130 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4131 case SLTG_FUNCTION_MAGIC
:
4132 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4134 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4135 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4137 case SLTG_STATIC_FUNCTION_MAGIC
:
4138 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4141 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4144 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4146 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4147 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4148 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4149 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4150 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4151 if (pFuncDesc
->funcdesc
.funckind
== FUNC_DISPATCH
)
4152 pFuncDesc
->funcdesc
.oVft
= 0;
4154 pFuncDesc
->funcdesc
.oVft
= (pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4156 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4157 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4159 if(pFunc
->retnextopt
& 0x80)
4160 pType
= &pFunc
->rettype
;
4162 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4164 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4166 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4167 calloc(pFuncDesc
->funcdesc
.cParams
, sizeof(ELEMDESC
));
4168 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4170 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4172 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4173 char *paramName
= pNameTable
+ *pArg
;
4175 /* If arg type follows then paramName points to the 2nd
4176 letter of the name, else the next WORD is an offset to
4177 the arg type and paramName points to the first letter.
4178 So let's take one char off paramName and see if we're
4179 pointing at an alphanumeric char. However if *pArg is
4180 0xffff or 0xfffe then the param has no name, the former
4181 meaning that the next WORD is the type, the latter
4182 meaning that the next WORD is an offset to the type. */
4187 else if(*pArg
== 0xfffe) {
4191 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4196 if(HaveOffs
) { /* the next word is an offset to type */
4197 pType
= (WORD
*)(pBlk
+ *pArg
);
4198 SLTG_DoElem(pType
, pBlk
,
4199 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4204 pArg
= SLTG_DoElem(pArg
, pBlk
,
4205 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4208 /* Are we an optional param ? */
4209 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4210 pFuncDesc
->funcdesc
.cParamsOpt
)
4211 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4214 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4215 paramName
- pNameTable
, pTI
->pTypeLib
);
4217 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4221 pTI
->typeattr
.cFuncs
= cFuncs
;
4224 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4225 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4226 SLTG_TypeInfoTail
*pTITail
)
4229 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4231 if(pTIHeader
->href_table
!= 0xffffffff) {
4232 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4238 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4239 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4245 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4246 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4247 const SLTG_TypeInfoTail
*pTITail
)
4250 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4252 if(pTIHeader
->href_table
!= 0xffffffff) {
4253 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4259 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4260 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4263 if (pTITail
->funcs_off
!= 0xffff)
4264 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4268 if (TRACE_ON(typelib
))
4269 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4272 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4273 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4274 const SLTG_TypeInfoTail
*pTITail
)
4276 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4279 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4280 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4281 const SLTG_TypeInfoTail
*pTITail
)
4284 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4286 if (pTITail
->simple_alias
) {
4287 /* if simple alias, no more processing required */
4288 pTI
->tdescAlias
= calloc(1, sizeof(TYPEDESC
));
4289 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4293 if(pTIHeader
->href_table
!= 0xffffffff) {
4294 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4298 /* otherwise it is an offset to a type */
4299 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4301 pTI
->tdescAlias
= malloc(sizeof(TYPEDESC
));
4302 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4307 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4308 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4309 const SLTG_TypeInfoTail
*pTITail
)
4311 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4312 if (pTIHeader
->href_table
!= 0xffffffff)
4313 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4316 if (pTITail
->vars_off
!= 0xffff)
4317 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4319 if (pTITail
->funcs_off
!= 0xffff)
4320 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4322 if (pTITail
->impls_off
!= 0xffff)
4323 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4325 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4326 * of dispinterface functions including the IDispatch ones, so
4327 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4328 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4331 if (TRACE_ON(typelib
))
4332 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4335 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4336 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4337 const SLTG_TypeInfoTail
*pTITail
)
4339 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4342 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4343 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4344 const SLTG_TypeInfoTail
*pTITail
)
4346 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4347 if (pTIHeader
->href_table
!= 0xffffffff)
4348 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4351 if (pTITail
->vars_off
!= 0xffff)
4352 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4354 if (pTITail
->funcs_off
!= 0xffff)
4355 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4357 if (TRACE_ON(typelib
))
4361 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4362 manageable copy of it into this */
4375 } SLTG_InternalOtherTypeInfo
;
4377 /****************************************************************************
4378 * ITypeLib2_Constructor_SLTG
4380 * loading a SLTG typelib from an in-memory image
4382 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4384 ITypeLibImpl
*pTypeLibImpl
;
4385 SLTG_Header
*pHeader
;
4386 SLTG_BlkEntry
*pBlkEntry
;
4390 LPVOID pBlk
, pFirstBlk
;
4391 SLTG_LibBlk
*pLibBlk
;
4392 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4393 char *pAfterOTIBlks
= NULL
;
4394 char *pNameTable
, *ptr
;
4397 ITypeInfoImpl
**ppTypeInfoImpl
;
4399 TRACE_(typelib
)("%p, TLB length = %ld\n", pLib
, dwTLBLength
);
4402 pTypeLibImpl
= TypeLibImpl_Constructor();
4403 if (!pTypeLibImpl
) return NULL
;
4407 TRACE_(typelib
)("header:\n");
4408 TRACE_(typelib
)("\tmagic %#lx, file blocks = %d\n", pHeader
->SLTG_magic
,
4409 pHeader
->nrOfFileBlks
);
4410 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
)
4412 FIXME_(typelib
)("Header type magic %#lx not supported.\n", pHeader
->SLTG_magic
);
4416 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4417 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4419 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4420 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4422 /* Next we have a magic block */
4423 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4425 /* Let's see if we're still in sync */
4426 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4427 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4428 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4431 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4432 sizeof(SLTG_DIR_MAGIC
))) {
4433 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4437 pIndex
= (SLTG_Index
*)(pMagic
+1);
4439 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4441 pFirstBlk
= pPad9
+ 1;
4443 /* We'll set up a ptr to the main library block, which is the last one. */
4445 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4446 pBlkEntry
[order
].next
!= 0;
4447 order
= pBlkEntry
[order
].next
- 1) {
4448 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4452 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4454 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4459 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4461 pOtherTypeInfoBlks
= calloc(pTypeLibImpl
->TypeInfoCount
, sizeof(*pOtherTypeInfoBlks
));
4464 ptr
= (char*)pLibBlk
+ len
;
4466 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4470 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4472 w
= *(WORD
*)(ptr
+ 2);
4475 pOtherTypeInfoBlks
[i
].index_name
= malloc(w
+ 1);
4476 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4477 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4479 w
= *(WORD
*)(ptr
+ 4 + len
);
4481 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4483 pOtherTypeInfoBlks
[i
].other_name
= malloc(w
+ 1);
4484 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4485 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4487 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4488 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4489 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4491 pOtherTypeInfoBlks
[i
].extra
= malloc(extra
);
4492 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4495 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4496 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4497 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4498 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4499 len
+= sizeof(SLTG_OtherTypeInfo
);
4503 pAfterOTIBlks
= ptr
;
4505 /* Skip this WORD and get the next DWORD */
4506 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4508 /* Now add this to pLibBLk look at what we're pointing at and
4509 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4510 dust and we should be pointing at the beginning of the name
4513 pNameTable
= (char*)pLibBlk
+ len
;
4515 switch(*(WORD
*)pNameTable
) {
4522 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4526 pNameTable
+= 0x216;
4530 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4532 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4535 /* Hopefully we now have enough ptrs set up to actually read in
4536 some TypeInfos. It's not clear which order to do them in, so
4537 I'll just follow the links along the BlkEntry chain and read
4538 them in the order in which they are in the file */
4540 pTypeLibImpl
->typeinfos
= calloc(pTypeLibImpl
->TypeInfoCount
, sizeof(ITypeInfoImpl
*));
4541 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4543 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4544 pBlkEntry
[order
].next
!= 0;
4545 order
= pBlkEntry
[order
].next
- 1, i
++) {
4547 SLTG_TypeInfoHeader
*pTIHeader
;
4548 SLTG_TypeInfoTail
*pTITail
;
4549 SLTG_MemberHeader
*pMemHeader
;
4551 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4552 FIXME_(typelib
)("Index strings don't match\n");
4553 free(pOtherTypeInfoBlks
);
4558 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4559 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4560 free(pOtherTypeInfoBlks
);
4563 TRACE_(typelib
)("pTIHeader->res06 = %lx, pTIHeader->res0e = %lx, "
4564 "pTIHeader->res16 = %lx, pTIHeader->res1e = %lx\n",
4565 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4567 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4568 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4569 (*ppTypeInfoImpl
)->index
= i
;
4570 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4571 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4572 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4573 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4574 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4575 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4576 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4577 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4579 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4580 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4582 if((pTIHeader
->typeflags1
& 7) != 2)
4583 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4584 if(pTIHeader
->typeflags3
!= 2)
4585 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4587 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4588 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4589 typekind_desc
[pTIHeader
->typekind
],
4590 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4591 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4593 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4595 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4597 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4598 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4599 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4601 switch(pTIHeader
->typekind
) {
4603 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4604 pTIHeader
, pTITail
);
4608 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4609 pTIHeader
, pTITail
);
4612 case TKIND_INTERFACE
:
4613 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4614 pTIHeader
, pTITail
);
4618 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4619 pTIHeader
, pTITail
);
4623 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4624 pTIHeader
, pTITail
);
4627 case TKIND_DISPATCH
:
4628 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4629 pTIHeader
, pTITail
);
4633 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4634 pTIHeader
, pTITail
);
4638 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4643 /* could get cFuncs, cVars and cImplTypes from here
4644 but we've already set those */
4645 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4661 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4664 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4665 FIXME("Somehow processed %d TypeInfos\n", i
);
4666 free(pOtherTypeInfoBlks
);
4670 free(pOtherTypeInfoBlks
);
4671 return &pTypeLibImpl
->ITypeLib2_iface
;
4674 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4676 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4678 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4680 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4681 IsEqualIID(riid
,&IID_ITypeLib
)||
4682 IsEqualIID(riid
,&IID_ITypeLib2
))
4684 *ppv
= &This
->ITypeLib2_iface
;
4686 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4687 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4689 *ppv
= &This
->ICreateTypeLib2_iface
;
4694 TRACE("-- Interface: E_NOINTERFACE\n");
4695 return E_NOINTERFACE
;
4698 IUnknown_AddRef((IUnknown
*)*ppv
);
4702 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4704 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4705 ULONG ref
= InterlockedIncrement(&This
->ref
);
4707 TRACE("%p, refcount %lu.\n", iface
, ref
);
4712 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4714 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4715 ULONG 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 EnterCriticalSection(&cache_section
);
4732 if(This
->entry
.next
)
4733 list_remove(&This
->entry
);
4734 LeaveCriticalSection(&cache_section
);
4737 TRACE(" destroying ITypeLib(%p)\n",This
);
4739 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4740 list_remove(&tlbstr
->entry
);
4741 SysFreeString(tlbstr
->str
);
4745 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4746 list_remove(&tlbstr
->entry
);
4747 SysFreeString(tlbstr
->str
);
4751 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4752 list_remove(&tlbguid
->entry
);
4756 TLB_FreeCustData(&This
->custdata_list
);
4758 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4759 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4760 free(This
->pTypeDesc
[i
].lpadesc
);
4762 free(This
->pTypeDesc
);
4764 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4766 if (pImpLib
->pImpTypeLib
)
4767 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4768 SysFreeString(pImpLib
->name
);
4770 list_remove(&pImpLib
->entry
);
4774 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4776 list_remove(&ref_type
->entry
);
4780 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4781 free(This
->typeinfos
[i
]->tdescAlias
);
4782 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4784 free(This
->typeinfos
);
4792 /* ITypeLib::GetTypeInfoCount
4794 * Returns the number of type descriptions in the type library
4796 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4798 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4799 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4800 return This
->TypeInfoCount
;
4803 /* ITypeLib::GetTypeInfo
4805 * retrieves the specified type description in the library.
4807 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4810 ITypeInfo
**ppTInfo
)
4812 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4814 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4817 return E_INVALIDARG
;
4819 if(index
>= This
->TypeInfoCount
)
4820 return TYPE_E_ELEMENTNOTFOUND
;
4822 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4823 ITypeInfo_AddRef(*ppTInfo
);
4829 /* ITypeLibs::GetTypeInfoType
4831 * Retrieves the type of a type description.
4833 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4838 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4840 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4843 return E_INVALIDARG
;
4845 if(index
>= This
->TypeInfoCount
)
4846 return TYPE_E_ELEMENTNOTFOUND
;
4848 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4853 /* ITypeLib::GetTypeInfoOfGuid
4855 * Retrieves the type description that corresponds to the specified GUID.
4858 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4861 ITypeInfo
**ppTInfo
)
4863 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4866 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4868 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4869 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4870 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4871 ITypeInfo_AddRef(*ppTInfo
);
4876 return TYPE_E_ELEMENTNOTFOUND
;
4879 /* ITypeLib::GetLibAttr
4881 * Retrieves the structure that contains the library's attributes.
4884 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4888 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4890 TRACE("(%p, %p)\n", This
, attr
);
4892 if (!attr
) return E_INVALIDARG
;
4894 *attr
= malloc(sizeof(**attr
));
4895 if (!*attr
) return E_OUTOFMEMORY
;
4897 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4898 (*attr
)->lcid
= This
->set_lcid
;
4899 (*attr
)->syskind
= This
->syskind
;
4900 (*attr
)->wMajorVerNum
= This
->ver_major
;
4901 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4902 (*attr
)->wLibFlags
= This
->libflags
;
4907 /* ITypeLib::GetTypeComp
4909 * Enables a client compiler to bind to a library's types, variables,
4910 * constants, and global functions.
4913 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4915 ITypeComp
**ppTComp
)
4917 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4919 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4920 *ppTComp
= &This
->ITypeComp_iface
;
4921 ITypeComp_AddRef(*ppTComp
);
4926 /* ITypeLib::GetDocumentation
4928 * Retrieves the library's documentation string, the complete Help file name
4929 * and path, and the context identifier for the library Help topic in the Help
4932 * On a successful return all non-null BSTR pointers will have been set,
4935 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4939 BSTR
*pBstrDocString
,
4940 DWORD
*pdwHelpContext
,
4941 BSTR
*pBstrHelpFile
)
4943 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4944 HRESULT result
= E_INVALIDARG
;
4947 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4949 pBstrName
, pBstrDocString
,
4950 pdwHelpContext
, pBstrHelpFile
);
4954 /* documentation for the typelib */
4959 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4967 if (This
->DocString
)
4969 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4973 *pBstrDocString
= NULL
;
4977 *pdwHelpContext
= This
->dwHelpContext
;
4983 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
4987 *pBstrHelpFile
= NULL
;
4994 /* for a typeinfo */
4995 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
4997 if(SUCCEEDED(result
))
4999 result
= ITypeInfo_GetDocumentation(pTInfo
,
5003 pdwHelpContext
, pBstrHelpFile
);
5005 ITypeInfo_Release(pTInfo
);
5010 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5012 if (pBstrName
) SysFreeString (*pBstrName
);
5014 return STG_E_INSUFFICIENTMEMORY
;
5019 * Indicates whether a passed-in string contains the name of a type or member
5020 * described in the library.
5023 static HRESULT WINAPI
ITypeLib2_fnIsName(
5029 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5031 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5033 TRACE("%p, %s, %#lx, %p.\n", iface
, debugstr_w(szNameBuf
), lHashVal
, pfName
);
5036 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5037 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5038 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5039 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5040 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5042 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5043 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5044 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5045 goto ITypeLib2_fnIsName_exit
;
5048 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5049 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5050 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5056 ITypeLib2_fnIsName_exit
:
5057 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5058 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5063 /* ITypeLib::FindName
5065 * Finds occurrences of a type description in a type library. This may be used
5066 * to quickly verify that a name exists in a type library.
5069 static HRESULT WINAPI
ITypeLib2_fnFindName(
5073 ITypeInfo
**ppTInfo
,
5077 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5082 TRACE("%p, %s %#lx, %p, %p, %p.\n", iface
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5084 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5085 return E_INVALIDARG
;
5087 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5088 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5089 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5093 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5094 memid
[count
] = MEMBERID_NIL
;
5095 goto ITypeLib2_fnFindName_exit
;
5098 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5099 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5101 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5102 memid
[count
] = func
->funcdesc
.memid
;
5103 goto ITypeLib2_fnFindName_exit
;
5107 var
= TLB_get_vardesc_by_name(pTInfo
, name
);
5109 memid
[count
] = var
->vardesc
.memid
;
5110 goto ITypeLib2_fnFindName_exit
;
5114 ITypeLib2_fnFindName_exit
:
5115 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5116 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5119 TRACE("found %d typeinfos\n", count
);
5126 /* ITypeLib::ReleaseTLibAttr
5128 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5131 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5133 TLIBATTR
*pTLibAttr
)
5135 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5136 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5140 /* ITypeLib2::GetCustData
5142 * gets the custom data
5144 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5149 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5150 TLBCustData
*pCData
;
5152 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5154 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5156 return TYPE_E_ELEMENTNOTFOUND
;
5158 VariantInit(pVarVal
);
5159 VariantCopy(pVarVal
, &pCData
->data
);
5164 /* ITypeLib2::GetLibStatistics
5166 * Returns statistics about a type library that are required for efficient
5167 * sizing of hash tables.
5170 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5172 ULONG
*pcUniqueNames
,
5173 ULONG
*pcchUniqueNames
)
5175 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5177 FIXME("(%p): stub!\n", This
);
5179 if(pcUniqueNames
) *pcUniqueNames
=1;
5180 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5184 /* ITypeLib2::GetDocumentation2
5186 * Retrieves the library's documentation string, the complete Help file name
5187 * and path, the localization context to use, and the context ID for the
5188 * library Help topic in the Help file.
5191 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5195 BSTR
*pbstrHelpString
,
5196 DWORD
*pdwHelpStringContext
,
5197 BSTR
*pbstrHelpStringDll
)
5199 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5203 FIXME("%p, %d, %#lx, partially implemented stub!\n", iface
, index
, lcid
);
5205 /* the help string should be obtained from the helpstringdll,
5206 * using the _DLLGetDocumentation function, based on the supplied
5207 * lcid. Nice to do sometime...
5211 /* documentation for the typelib */
5213 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5214 if(pdwHelpStringContext
)
5215 *pdwHelpStringContext
=This
->dwHelpContext
;
5216 if(pbstrHelpStringDll
)
5217 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5223 /* for a typeinfo */
5224 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5226 if(SUCCEEDED(result
))
5228 ITypeInfo2
* pTInfo2
;
5229 result
= ITypeInfo_QueryInterface(pTInfo
,
5231 (LPVOID
*) &pTInfo2
);
5233 if(SUCCEEDED(result
))
5235 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5239 pdwHelpStringContext
,
5240 pbstrHelpStringDll
);
5242 ITypeInfo2_Release(pTInfo2
);
5245 ITypeInfo_Release(pTInfo
);
5251 static HRESULT
TLB_copy_all_custdata(const struct list
*custdata_list
, CUSTDATA
*pCustData
)
5253 TLBCustData
*pCData
;
5258 ct
= list_count(custdata_list
);
5260 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5261 if(!pCustData
->prgCustData
)
5262 return E_OUTOFMEMORY
;
5264 pCustData
->cCustData
= ct
;
5266 cdi
= pCustData
->prgCustData
;
5267 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5268 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5269 VariantInit(&cdi
->varValue
);
5270 hr
= VariantCopy(&cdi
->varValue
, &pCData
->data
);
5271 if(FAILED(hr
)) break;
5279 /* ITypeLib2::GetAllCustData
5281 * Gets all custom data items for the library.
5284 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5286 CUSTDATA
*pCustData
)
5288 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5289 TRACE("(%p)->(%p)\n", This
, pCustData
);
5290 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5293 static const ITypeLib2Vtbl tlbvt
= {
5294 ITypeLib2_fnQueryInterface
,
5296 ITypeLib2_fnRelease
,
5297 ITypeLib2_fnGetTypeInfoCount
,
5298 ITypeLib2_fnGetTypeInfo
,
5299 ITypeLib2_fnGetTypeInfoType
,
5300 ITypeLib2_fnGetTypeInfoOfGuid
,
5301 ITypeLib2_fnGetLibAttr
,
5302 ITypeLib2_fnGetTypeComp
,
5303 ITypeLib2_fnGetDocumentation
,
5305 ITypeLib2_fnFindName
,
5306 ITypeLib2_fnReleaseTLibAttr
,
5308 ITypeLib2_fnGetCustData
,
5309 ITypeLib2_fnGetLibStatistics
,
5310 ITypeLib2_fnGetDocumentation2
,
5311 ITypeLib2_fnGetAllCustData
5315 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5317 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5319 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5322 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5324 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5326 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5329 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5331 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5333 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5336 static HRESULT WINAPI
ITypeLibComp_fnBind(
5341 ITypeInfo
** ppTInfo
,
5342 DESCKIND
* pDescKind
,
5345 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5346 BOOL typemismatch
= FALSE
;
5349 TRACE("%p, %s, %#lx, %#x, %p, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5351 *pDescKind
= DESCKIND_NONE
;
5352 pBindPtr
->lptcomp
= NULL
;
5355 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5356 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5357 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5359 /* FIXME: check wFlags here? */
5360 /* FIXME: we should use a hash table to look this info up using lHash
5361 * instead of an O(n) search */
5362 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5363 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5365 if (pTypeInfo
->Name
&& !wcscmp(pTypeInfo
->Name
->str
, szName
))
5367 *pDescKind
= DESCKIND_TYPECOMP
;
5368 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5369 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5370 TRACE("module or enum: %s\n", debugstr_w(szName
));
5375 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5376 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5378 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5381 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5382 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5384 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5387 else if (hr
== TYPE_E_TYPEMISMATCH
)
5388 typemismatch
= TRUE
;
5391 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5392 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5394 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5396 ITypeInfo
*subtypeinfo
;
5398 DESCKIND subdesckind
;
5400 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5401 &subtypeinfo
, &subdesckind
, &subbindptr
);
5402 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5404 TYPEDESC tdesc_appobject
;
5405 const VARDESC vardesc_appobject
=
5408 NULL
, /* lpstrSchema */
5423 VAR_STATIC
/* varkind */
5426 tdesc_appobject
.hreftype
= pTypeInfo
->hreftype
;
5427 tdesc_appobject
.vt
= VT_USERDEFINED
;
5429 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5431 /* cleanup things filled in by Bind call so we can put our
5432 * application object data in there instead */
5433 switch (subdesckind
)
5435 case DESCKIND_FUNCDESC
:
5436 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5438 case DESCKIND_VARDESC
:
5439 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5444 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5446 if (pTypeInfo
->hreftype
== -1)
5447 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5449 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5453 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5454 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5455 ITypeInfo_AddRef(*ppTInfo
);
5458 else if (hr
== TYPE_E_TYPEMISMATCH
)
5459 typemismatch
= TRUE
;
5465 TRACE("type mismatch %s\n", debugstr_w(szName
));
5466 return TYPE_E_TYPEMISMATCH
;
5470 TRACE("name not found %s\n", debugstr_w(szName
));
5475 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5479 ITypeInfo
** ppTInfo
,
5480 ITypeComp
** ppTComp
)
5482 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5483 ITypeInfoImpl
*info
;
5485 TRACE("%p, %s, %#lx, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5487 if(!szName
|| !ppTInfo
|| !ppTComp
)
5488 return E_INVALIDARG
;
5490 info
= TLB_get_typeinfo_by_name(This
, szName
);
5497 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5498 ITypeInfo_AddRef(*ppTInfo
);
5499 *ppTComp
= &info
->ITypeComp_iface
;
5500 ITypeComp_AddRef(*ppTComp
);
5505 static const ITypeCompVtbl tlbtcvt
=
5508 ITypeLibComp_fnQueryInterface
,
5509 ITypeLibComp_fnAddRef
,
5510 ITypeLibComp_fnRelease
,
5512 ITypeLibComp_fnBind
,
5513 ITypeLibComp_fnBindType
5516 /*================== ITypeInfo(2) Methods ===================================*/
5517 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5519 ITypeInfoImpl
*pTypeInfoImpl
;
5521 pTypeInfoImpl
= calloc(1, sizeof(ITypeInfoImpl
));
5524 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5525 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5526 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5527 pTypeInfoImpl
->ref
= 0;
5528 pTypeInfoImpl
->hreftype
= -1;
5529 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5530 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5531 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5532 list_init(pTypeInfoImpl
->pcustdata_list
);
5534 TRACE("(%p)\n", pTypeInfoImpl
);
5535 return pTypeInfoImpl
;
5538 /* ITypeInfo::QueryInterface
5540 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5545 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5547 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5550 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5551 IsEqualIID(riid
,&IID_ITypeInfo
)||
5552 IsEqualIID(riid
,&IID_ITypeInfo2
))
5553 *ppvObject
= &This
->ITypeInfo2_iface
;
5554 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5555 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5556 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5557 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5558 *ppvObject
= &This
->ITypeComp_iface
;
5561 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5562 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5565 TRACE("-- Interface: E_NOINTERFACE\n");
5566 return E_NOINTERFACE
;
5569 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5571 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5572 ULONG ref
= InterlockedIncrement(&This
->ref
);
5574 TRACE("%p, refcount %lu.\n", iface
, ref
);
5576 if (ref
== 1 /* incremented from 0 */)
5577 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5582 static void typeinfo_release_funcdesc(TLBFuncDesc
*func
)
5586 for (i
= 0; i
< func
->funcdesc
.cParams
; ++i
)
5588 ELEMDESC
*elemdesc
= &func
->funcdesc
.lprgelemdescParam
[i
];
5589 if (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5590 VariantClear(&elemdesc
->paramdesc
.pparamdescex
->varDefaultValue
);
5591 TLB_FreeCustData(&func
->pParamDesc
[i
].custdata_list
);
5593 free(func
->funcdesc
.lprgelemdescParam
);
5594 free(func
->pParamDesc
);
5595 TLB_FreeCustData(&func
->custdata_list
);
5598 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5602 TRACE("destroying ITypeInfo(%p)\n",This
);
5604 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5606 typeinfo_release_funcdesc(&This
->funcdescs
[i
]);
5608 free(This
->funcdescs
);
5610 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5612 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5613 if (pVInfo
->vardesc_create
) {
5614 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5615 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5616 VariantClear(pVInfo
->vardesc
.lpvarValue
);
5617 free(pVInfo
->vardesc
.lpvarValue
);
5619 TLB_FreeCustData(&pVInfo
->custdata_list
);
5621 free(This
->vardescs
);
5623 if(This
->impltypes
){
5624 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5625 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5626 TLB_FreeCustData(&pImpl
->custdata_list
);
5628 free(This
->impltypes
);
5631 TLB_FreeCustData(&This
->custdata_list
);
5636 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5638 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5639 ULONG ref
= InterlockedDecrement(&This
->ref
);
5641 TRACE("%p, refcount %lu.\n", iface
, ref
);
5645 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5646 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5647 if (not_attached_to_typelib
)
5649 /* otherwise This will be freed when typelib is freed */
5655 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5656 LPTYPEATTR
*ppTypeAttr
)
5658 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5661 TRACE("(%p)\n",This
);
5663 size
= sizeof(**ppTypeAttr
);
5664 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5665 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5667 *ppTypeAttr
= malloc(size
);
5669 return E_OUTOFMEMORY
;
5671 **ppTypeAttr
= This
->typeattr
;
5672 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5674 if (This
->tdescAlias
)
5675 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5677 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5678 /* This should include all the inherited funcs */
5679 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5680 /* This is always the size of IDispatch's vtbl */
5681 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5682 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5687 /* ITypeInfo::GetTypeComp
5689 * Retrieves the ITypeComp interface for the type description, which enables a
5690 * client compiler to bind to the type description's members.
5693 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5694 ITypeComp
* *ppTComp
)
5696 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5698 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5700 *ppTComp
= &This
->ITypeComp_iface
;
5701 ITypeComp_AddRef(*ppTComp
);
5705 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5707 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5708 if (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5709 size
+= sizeof(*elemdesc
->paramdesc
.pparamdescex
);
5713 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5716 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5717 if (src
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5719 const PARAMDESCEX
*pparamdescex_src
= src
->paramdesc
.pparamdescex
;
5720 PARAMDESCEX
*pparamdescex_dest
= dest
->paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5721 *buffer
+= sizeof(PARAMDESCEX
);
5722 *pparamdescex_dest
= *pparamdescex_src
;
5723 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5724 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5725 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5726 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5729 dest
->paramdesc
.pparamdescex
= NULL
;
5733 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5735 if (V_VT(var
) == VT_INT
)
5736 return VariantChangeType(var
, var
, 0, VT_I4
);
5737 else if (V_VT(var
) == VT_UINT
)
5738 return VariantChangeType(var
, var
, 0, VT_UI4
);
5743 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5745 if (elemdesc
->paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5746 VariantClear(&elemdesc
->paramdesc
.pparamdescex
->varDefaultValue
);
5749 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5753 SIZE_T size
= sizeof(*src
);
5757 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5758 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5759 for (i
= 0; i
< src
->cParams
; i
++)
5761 size
+= sizeof(ELEMDESC
);
5762 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5765 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5766 if (!dest
) return E_OUTOFMEMORY
;
5769 if (dispinterface
) /* overwrite funckind */
5770 dest
->funckind
= FUNC_DISPATCH
;
5771 buffer
= (char *)(dest
+ 1);
5773 dest
->oVft
= dest
->oVft
& 0xFFFC;
5775 if (dest
->cScodes
) {
5776 dest
->lprgscode
= (SCODE
*)buffer
;
5777 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5778 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5780 dest
->lprgscode
= NULL
;
5782 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5785 SysFreeString((BSTR
)dest
);
5789 if (dest
->cParams
) {
5790 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5791 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5792 for (i
= 0; i
< src
->cParams
; i
++)
5794 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5800 /* undo the above actions */
5801 for (i
= i
- 1; i
>= 0; i
--)
5802 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5803 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5804 SysFreeString((BSTR
)dest
);
5808 dest
->lprgelemdescParam
= NULL
;
5810 /* special treatment for dispinterface FUNCDESC based on an interface FUNCDESC.
5811 * This accounts for several arguments that are separate in the signature of
5812 * IDispatch::Invoke, rather than passed in DISPPARAMS::rgvarg[] */
5813 if (dispinterface
&& (src
->funckind
!= FUNC_DISPATCH
))
5815 /* functions that have a [retval] parameter return this value into pVarResult.
5816 * [retval] is always the last parameter (if present) */
5817 if (dest
->cParams
&&
5818 (dest
->lprgelemdescParam
[dest
->cParams
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5820 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5821 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5823 ERR("elemdesc should have started with VT_PTR instead of:\n");
5825 dump_ELEMDESC(elemdesc
);
5826 return E_UNEXPECTED
;
5829 /* the type pointed to by this [retval] becomes elemdescFunc,
5830 * i.e. the function signature's return type.
5831 * We are using a flat buffer so there is no danger of leaking memory */
5832 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.lptdesc
;
5834 /* remove the last parameter */
5837 else if (dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5838 /* Even if not otherwise replaced HRESULT is returned in pExcepInfo->scode,
5839 * not pVarResult. So the function signature should show no return value. */
5840 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5842 /* The now-last (except [retval], removed above) parameter might be labeled [lcid].
5843 * If so it will be supplied from Invoke(lcid), so also not via DISPPARAMS::rgvarg */
5844 if (dest
->cParams
&& (dest
->lprgelemdescParam
[dest
->cParams
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
5852 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5854 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5855 if (var_desc
->varkind
== VAR_CONST
)
5856 VariantClear(var_desc
->lpvarValue
);
5857 SysFreeString((BSTR
)var_desc
);
5860 /* internal function to make the inherited interfaces' methods appear
5861 * part of the interface */
5862 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5863 UINT index
, const TLBFuncDesc
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5865 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5867 UINT implemented_funcs
= 0;
5872 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5876 ITypeInfo
*pSubTypeInfo
;
5879 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5883 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5886 &sub_funcs
, hrefoffset
);
5887 implemented_funcs
+= sub_funcs
;
5888 ITypeInfo_Release(pSubTypeInfo
);
5891 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5895 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5899 if (index
< implemented_funcs
)
5900 return E_INVALIDARG
;
5901 index
-= implemented_funcs
;
5903 if (index
>= This
->typeattr
.cFuncs
)
5904 return TYPE_E_ELEMENTNOTFOUND
;
5906 *ppFuncDesc
= &This
->funcdescs
[index
];
5910 static HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const TLBFuncDesc
**func_desc
, UINT
*hrefoffset
)
5912 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5914 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5915 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface
, index
, func_desc
, NULL
, hrefoffset
);
5917 if (index
>= This
->typeattr
.cFuncs
)
5918 return TYPE_E_ELEMENTNOTFOUND
;
5920 *func_desc
= &This
->funcdescs
[index
];
5924 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5926 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5929 switch (pTypeDesc
->vt
)
5931 case VT_USERDEFINED
:
5932 pTypeDesc
->hreftype
+= hrefoffset
;
5936 pTypeDesc
= pTypeDesc
->lptdesc
;
5939 pTypeDesc
= &pTypeDesc
->lpadesc
->tdescElem
;
5947 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5950 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5951 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5952 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5955 /* ITypeInfo::GetFuncDesc
5957 * Retrieves the FUNCDESC structure that contains information about a
5958 * specified function.
5961 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5962 LPFUNCDESC
*ppFuncDesc
)
5964 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5965 const TLBFuncDesc
*internal_funcdesc
;
5967 UINT hrefoffset
= 0;
5969 TRACE("(%p) index %d\n", This
, index
);
5972 return E_INVALIDARG
;
5974 if (This
->needs_layout
)
5975 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5977 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
5978 &internal_funcdesc
, &hrefoffset
);
5981 WARN("description for function %d not found\n", index
);
5985 hr
= TLB_AllocAndInitFuncDesc(
5986 &internal_funcdesc
->funcdesc
,
5988 This
->typeattr
.typekind
== TKIND_DISPATCH
);
5990 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
5991 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
5993 TRACE("-- %#lx.\n", hr
);
5997 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6001 SIZE_T size
= sizeof(*src
);
6004 if (src
->lpstrSchema
) size
+= (lstrlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6005 if (src
->varkind
== VAR_CONST
)
6006 size
+= sizeof(VARIANT
);
6007 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6009 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6010 if (!dest
) return E_OUTOFMEMORY
;
6013 buffer
= (char *)(dest
+ 1);
6014 if (src
->lpstrSchema
)
6017 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6018 len
= lstrlenW(src
->lpstrSchema
);
6019 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6020 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6023 if (src
->varkind
== VAR_CONST
)
6027 dest
->lpvarValue
= (VARIANT
*)buffer
;
6028 *dest
->lpvarValue
= *src
->lpvarValue
;
6029 buffer
+= sizeof(VARIANT
);
6030 VariantInit(dest
->lpvarValue
);
6031 hr
= VariantCopy(dest
->lpvarValue
, src
->lpvarValue
);
6034 SysFreeString((BSTR
)dest
);
6038 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6041 if (src
->varkind
== VAR_CONST
)
6042 VariantClear(dest
->lpvarValue
);
6043 SysFreeString((BSTR
)dest
);
6050 /* ITypeInfo::GetVarDesc
6052 * Retrieves a VARDESC structure that describes the specified variable.
6055 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6056 LPVARDESC
*ppVarDesc
)
6058 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6059 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6061 TRACE("(%p) index %d\n", This
, index
);
6063 if(index
>= This
->typeattr
.cVars
)
6064 return TYPE_E_ELEMENTNOTFOUND
;
6066 if (This
->needs_layout
)
6067 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6069 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6072 /* internal function to make the inherited interfaces' methods appear
6073 * part of the interface, remembering if the top-level was dispinterface */
6074 static HRESULT
typeinfo_getnames( ITypeInfo
*iface
, MEMBERID memid
, BSTR
*names
,
6075 UINT max_names
, UINT
*num_names
, BOOL dispinterface
)
6077 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
6078 const TLBFuncDesc
*func_desc
;
6079 const TLBVarDesc
*var_desc
;
6084 func_desc
= TLB_get_funcdesc_by_memberid(This
, memid
);
6087 UINT params
= func_desc
->funcdesc
.cParams
;
6088 if (!max_names
|| !func_desc
->Name
)
6091 *names
= SysAllocString(TLB_get_bstr(func_desc
->Name
));
6094 if (dispinterface
&& (func_desc
->funcdesc
.funckind
!= FUNC_DISPATCH
))
6096 /* match the rewriting of special trailing parameters in TLB_AllocAndInitFuncDesc */
6097 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
6098 --params
; /* Invoke(pVarResult) supplies the [retval] parameter, so it's hidden from DISPPARAMS */
6099 if ((params
> 0) && (func_desc
->funcdesc
.lprgelemdescParam
[params
- 1].paramdesc
.wParamFlags
& PARAMFLAG_FLCID
))
6100 --params
; /* Invoke(lcid) supplies the [lcid] parameter, so it's hidden from DISPPARAMS */
6103 for (i
= 0; i
< params
; i
++)
6105 if (*num_names
>= max_names
|| !func_desc
->pParamDesc
[i
].Name
)
6107 names
[*num_names
] = SysAllocString(TLB_get_bstr(func_desc
->pParamDesc
[i
].Name
));
6113 var_desc
= TLB_get_vardesc_by_memberid(This
, memid
);
6116 *names
= SysAllocString(TLB_get_bstr(var_desc
->Name
));
6121 if (This
->impltypes
&&
6122 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
))
6124 /* recursive search */
6127 result
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &parent
);
6128 if (SUCCEEDED(result
))
6130 result
= typeinfo_getnames(parent
, memid
, names
, max_names
, num_names
, dispinterface
);
6131 ITypeInfo_Release(parent
);
6134 WARN("Could not search inherited interface!\n");
6138 WARN("no names found\n");
6141 return TYPE_E_ELEMENTNOTFOUND
;
6146 /* ITypeInfo_GetNames
6148 * Retrieves the variable with the specified member ID (or the name of the
6149 * property or method and its parameters) that correspond to the specified
6152 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6153 BSTR
*names
, UINT max_names
, UINT
*num_names
)
6155 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6157 TRACE("%p, %#lx, %p, %d, %p\n", iface
, memid
, names
, max_names
, num_names
);
6159 if (!names
) return E_INVALIDARG
;
6161 return typeinfo_getnames((ITypeInfo
*)iface
, memid
, names
, max_names
, num_names
,
6162 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6165 /* ITypeInfo::GetRefTypeOfImplType
6167 * If a type description describes a COM class, it retrieves the type
6168 * description of the implemented interface types. For an interface,
6169 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6173 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6178 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6181 TRACE("(%p) index %d\n", This
, index
);
6182 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6186 /* only valid on dual interfaces;
6187 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6190 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6196 hr
= TYPE_E_ELEMENTNOTFOUND
;
6199 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6201 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6202 *pRefType
= This
->pTypeLib
->dispatch_href
;
6206 if(index
>= This
->typeattr
.cImplTypes
)
6207 hr
= TYPE_E_ELEMENTNOTFOUND
;
6209 *pRefType
= This
->impltypes
[index
].hRef
;
6210 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6218 TRACE("SUCCESS -- hRef %#lx.\n", *pRefType
);
6220 TRACE("FAILURE -- hresult %#lx.\n", hr
);
6226 /* ITypeInfo::GetImplTypeFlags
6228 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6229 * or base interface in a type description.
6231 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6232 UINT index
, INT
*pImplTypeFlags
)
6234 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6236 TRACE("(%p) index %d\n", This
, index
);
6239 return E_INVALIDARG
;
6241 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6242 *pImplTypeFlags
= 0;
6246 if(index
>= This
->typeattr
.cImplTypes
)
6247 return TYPE_E_ELEMENTNOTFOUND
;
6249 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6255 * Maps between member names and member IDs, and parameter names and
6258 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6259 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6261 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6262 const TLBVarDesc
*pVDesc
;
6266 TRACE("%p, %s, %d.\n", iface
, debugstr_w(*rgszNames
), cNames
);
6268 /* init out parameters in case of failure */
6269 for (i
= 0; i
< cNames
; i
++)
6270 pMemId
[i
] = MEMBERID_NIL
;
6272 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6274 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6275 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6276 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6277 for(i
=1; i
< cNames
; i
++){
6278 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6279 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6281 if( j
<pFDesc
->funcdesc
.cParams
)
6284 ret
=DISP_E_UNKNOWNNAME
;
6286 TRACE("-- %#lx.\n", ret
);
6290 pVDesc
= TLB_get_vardesc_by_name(This
, *rgszNames
);
6293 *pMemId
= pVDesc
->vardesc
.memid
;
6296 /* not found, see if it can be found in an inherited interface */
6297 if(This
->impltypes
) {
6298 /* recursive search */
6300 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6302 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6303 ITypeInfo_Release(pTInfo
);
6306 WARN("Could not search inherited interface!\n");
6308 WARN("no names found\n");
6309 return DISP_E_UNKNOWNNAME
;
6315 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6316 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6317 __ASM_GLOBAL_FUNC( call_method
,
6319 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6320 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6321 "movl %esp,%ebp\n\t"
6322 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6324 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6326 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6327 "movl 12(%ebp),%edx\n\t"
6328 "movl %esp,%edi\n\t"
6331 "subl %edx,%edi\n\t"
6332 "andl $~15,%edi\n\t"
6333 "movl %edi,%esp\n\t"
6334 "movl 12(%ebp),%ecx\n\t"
6335 "movl 16(%ebp),%esi\n\t"
6338 "1:\tcall *8(%ebp)\n\t"
6339 "subl %esp,%edi\n\t"
6340 "movl 20(%ebp),%ecx\n\t"
6341 "movl %edi,(%ecx)\n\t"
6342 "leal -8(%ebp),%esp\n\t"
6344 __ASM_CFI(".cfi_same_value %edi\n\t")
6346 __ASM_CFI(".cfi_same_value %esi\n\t")
6348 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6349 __ASM_CFI(".cfi_same_value %ebp\n\t")
6351 __ASM_GLOBAL_FUNC( call_double_method
,
6352 "jmp " __ASM_NAME("call_method") )
6354 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6355 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6357 int argspos
= 0, stack_offset
;
6362 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6363 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6364 pvargResult
, V_VT(pvargResult
));
6366 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6368 FIXME("unsupported calling convention %d\n",cc
);
6369 return E_INVALIDARG
;
6372 /* maximum size for an argument is sizeof(VARIANT) */
6373 args
= malloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6377 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6378 func
= vtable
[oVft
/sizeof(void *)];
6379 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6381 else func
= (void *)oVft
;
6387 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6390 WARN("invalid return type %u\n", vtReturn
);
6392 return E_INVALIDARG
;
6397 for (i
= 0; i
< cActuals
; i
++)
6399 VARIANT
*arg
= prgpvarg
[i
];
6410 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6411 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6415 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6416 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6418 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6419 args
[argspos
++] = V_BOOL(arg
);
6422 args
[argspos
++] = V_UI4(arg
);
6425 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6433 call_method( func
, argspos
, args
, &stack_offset
);
6436 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6440 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6445 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6448 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6452 if (stack_offset
&& cc
== CC_STDCALL
)
6454 WARN( "stack pointer off by %d\n", stack_offset
);
6455 return DISP_E_BADCALLEE
;
6457 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6458 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6462 #elif defined(__x86_64__)
6464 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6465 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6466 __ASM_GLOBAL_FUNC( call_method
,
6468 __ASM_SEH(".seh_pushreg %rbp\n\t")
6469 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6470 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6471 "movq %rsp,%rbp\n\t"
6472 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6473 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6475 __ASM_SEH(".seh_pushreg %rsi\n\t")
6476 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6478 __ASM_SEH(".seh_pushreg %rdi\n\t")
6479 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6480 __ASM_SEH(".seh_endprologue\n\t")
6481 "movq %rcx,%rax\n\t"
6484 "cmovgq %rdx,%rcx\n\t"
6485 "leaq 0(,%rcx,8),%rdx\n\t"
6486 "subq %rdx,%rsp\n\t"
6487 "andq $~15,%rsp\n\t"
6488 "movq %rsp,%rdi\n\t"
6491 "movq 0(%rsp),%rcx\n\t"
6492 "movq 8(%rsp),%rdx\n\t"
6493 "movq 16(%rsp),%r8\n\t"
6494 "movq 24(%rsp),%r9\n\t"
6495 "movq 0(%rsp),%xmm0\n\t"
6496 "movq 8(%rsp),%xmm1\n\t"
6497 "movq 16(%rsp),%xmm2\n\t"
6498 "movq 24(%rsp),%xmm3\n\t"
6500 "leaq -16(%rbp),%rsp\n\t"
6502 __ASM_CFI(".cfi_same_value %rdi\n\t")
6504 __ASM_CFI(".cfi_same_value %rsi\n\t")
6505 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6507 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6508 __ASM_CFI(".cfi_same_value %rbp\n\t")
6510 __ASM_GLOBAL_FUNC( call_double_method
,
6511 "jmp " __ASM_NAME("call_method") )
6513 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6514 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6521 TRACE("%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d).\n",
6522 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6523 pvargResult
, V_VT(pvargResult
));
6525 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6527 FIXME("unsupported calling convention %d\n",cc
);
6528 return E_INVALIDARG
;
6531 /* maximum size for an argument is sizeof(DWORD_PTR) */
6532 args
= malloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6536 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6537 func
= vtable
[oVft
/sizeof(void *)];
6538 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6540 else func
= (void *)oVft
;
6546 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6549 WARN("invalid return type %u\n", vtReturn
);
6551 return E_INVALIDARG
;
6556 for (i
= 0; i
< cActuals
; i
++)
6558 VARIANT
*arg
= prgpvarg
[i
];
6564 args
[argspos
++] = (ULONG_PTR
)arg
;
6566 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6567 args
[argspos
++] = V_BOOL(arg
);
6570 args
[argspos
++] = V_UI8(arg
);
6573 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6579 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6583 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6587 call_method( func
, argspos
, args
);
6590 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6594 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6595 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6599 #elif defined(__arm__)
6601 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6602 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6603 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6604 __ASM_GLOBAL_FUNC( call_method
,
6607 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6608 * r3 = *reg_args (pointer to 8, 64-bit d0-d7 (double) values OR as 16, 32-bit s0-s15 (float) values, followed by 4, 32-bit (DWORD) r0-r3 values)
6611 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6612 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6614 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6615 "beq 1f\n\t" /* Skip allocation if no stack args */
6616 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6617 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6618 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6619 "subs r1, r1, #4\n\t" /* Decrement count */
6620 "bgt 2b\n\t" /* Loop till done */
6624 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6626 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6627 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6629 "blx ip\n\t" /* Call the target function */
6631 "mov sp, fp\n\t" /* Clean the stack using fp */
6632 "pop {fp, pc}\n\t" /* Restore fp and return */
6634 __ASM_GLOBAL_FUNC( call_float_method
,
6635 "b " __ASM_NAME("call_method") )
6636 __ASM_GLOBAL_FUNC( call_double_method
,
6637 "b " __ASM_NAME("call_method") )
6639 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6640 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6655 int rcount
; /* 32-bit register index count */
6657 int scount
= 0; /* single-precision float register index count */
6658 int dcount
= 0; /* double-precision float register index count */
6661 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6662 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6664 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6666 FIXME("unsupported calling convention %d\n",cc
);
6667 return E_INVALIDARG
;
6675 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6676 func
= vtable
[oVft
/sizeof(void *)];
6677 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6679 else func
= (void *)oVft
;
6681 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6682 /* first as it will need to be in the 'r' registers: */
6687 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6690 WARN("invalid return type %u\n", vtReturn
);
6691 return E_INVALIDARG
;
6692 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6696 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6697 args
= malloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6699 for (i
= 0; i
< cActuals
; i
++)
6701 VARIANT
*arg
= prgpvarg
[i
];
6702 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6703 int ntemp
; /* Used for counting words split between registers and stack */
6709 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6712 dcount
= max( (scount
+ 1) / 2, dcount
);
6715 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6719 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6720 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6721 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6725 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6730 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6731 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6732 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6736 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6737 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6738 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6739 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6742 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6744 /* 8-byte align 'r' and/or stack: */
6746 rcount
+= (rcount
% 2);
6750 argspos
+= (argspos
% 2);
6752 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6756 regs
.r
[rcount
++] = *pdwarg
++;
6758 args
[argspos
++] = *pdwarg
++;
6762 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6764 regs
.r
[rcount
++] = V_BOOL(arg
);
6766 args
[argspos
++] = V_BOOL(arg
);
6768 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6770 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6772 regs
.sd
.s
[scount
++] = V_R4(arg
);
6774 args
[argspos
++] = V_UI4(arg
);
6779 regs
.r
[rcount
++] = V_UI4(arg
);
6781 args
[argspos
++] = V_UI4(arg
);
6784 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6787 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
6791 case VT_EMPTY
: /* EMPTY = no return value */
6792 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6794 call_method( func
, argspos
, args
, (DWORD
*)®s
);
6797 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
6801 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
6806 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6809 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6813 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6814 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6818 #elif defined(__aarch64__)
6820 extern DWORD_PTR CDECL
call_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6821 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6822 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6823 __ASM_GLOBAL_FUNC( call_method
,
6824 "stp x29, x30, [sp, #-16]!\n\t"
6825 __ASM_SEH(".seh_save_fplr_x 16\n\t")
6827 __ASM_SEH(".seh_set_fp\n\t")
6828 __ASM_SEH(".seh_endprologue\n\t")
6829 "sub sp, sp, x1, lsl #3\n\t"
6831 "1:\tsub x1, x1, #1\n\t"
6832 "ldr x4, [x2, x1, lsl #3]\n\t"
6833 "str x4, [sp, x1, lsl #3]\n\t"
6835 "2:\tmov x16, x0\n\t"
6837 "ldp d0, d1, [x9]\n\t"
6838 "ldp d2, d3, [x9, #0x10]\n\t"
6839 "ldp d4, d5, [x9, #0x20]\n\t"
6840 "ldp d6, d7, [x9, #0x30]\n\t"
6841 "ldp x0, x1, [x9, #0x40]\n\t"
6842 "ldp x2, x3, [x9, #0x50]\n\t"
6843 "ldp x4, x5, [x9, #0x60]\n\t"
6844 "ldp x6, x7, [x9, #0x70]\n\t"
6845 "ldr x8, [x9, #0x80]\n\t"
6848 "ldp x29, x30, [sp], #16\n\t"
6850 __ASM_GLOBAL_FUNC( call_float_method
,
6851 "b " __ASM_NAME("call_method") )
6852 __ASM_GLOBAL_FUNC( call_double_method
,
6853 "b " __ASM_NAME("call_method") )
6855 HRESULT WINAPI
DispCallFunc( void *instance
, ULONG_PTR offset
, CALLCONV cc
, VARTYPE ret_type
, UINT count
,
6856 VARTYPE
*types
, VARIANTARG
**vargs
, VARIANT
*result
)
6871 int rcount
; /* 64-bit register index count */
6872 int fpcount
= 0; /* float register index count */
6874 TRACE("(%p, %Id, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6875 instance
, offset
, cc
, ret_type
, count
, types
, vargs
, result
, V_VT(result
));
6877 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6879 FIXME("unsupported calling convention %d\n",cc
);
6880 return E_INVALIDARG
;
6888 const FARPROC
*vtable
= *(FARPROC
**)instance
;
6889 func
= vtable
[offset
/sizeof(void *)];
6890 regs
.x
[rcount
++] = (DWORD_PTR
)instance
; /* the This pointer is always the first parameter */
6892 else func
= (void *)offset
;
6894 /* maximum size for an argument is 16 */
6895 args
= malloc( 16 * count
);
6897 for (i
= 0; i
< count
; i
++)
6899 VARIANT
*arg
= vargs
[i
];
6904 if (fpcount
< 8) regs
.fp
[fpcount
++].f
= V_R4(arg
);
6905 else *(float *)&args
[argspos
++] = V_R4(arg
);
6909 if (fpcount
< 8) regs
.fp
[fpcount
++].d
= V_R8(arg
);
6910 else *(double *)&args
[argspos
++] = V_R8(arg
);
6915 memcpy( ®s
.x
[rcount
], arg
, sizeof(*arg
) );
6920 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6925 if (rcount
< 8) regs
.x
[rcount
++] = (DWORD_PTR
)arg
;
6926 else args
[argspos
++] = (DWORD_PTR
)arg
;
6928 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6929 if (rcount
< 8) regs
.x
[rcount
++] = V_BOOL(arg
);
6930 else args
[argspos
++] = V_BOOL(arg
);
6933 if (rcount
< 8) regs
.x
[rcount
++] = V_UI8(arg
);
6934 else args
[argspos
++] = V_UI8(arg
);
6937 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(types
[i
]), debugstr_variant(arg
));
6940 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 16-byte */
6946 return E_INVALIDARG
;
6949 regs
.x
[8] = (DWORD_PTR
)result
; /* x8 is a pointer to the result */
6950 call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6953 V_R4(result
) = call_float_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6957 V_R8(result
) = call_double_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6960 V_UI8(result
) = call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6964 if (ret_type
!= VT_VARIANT
) V_VT(result
) = ret_type
;
6965 TRACE("retval: %s\n", debugstr_variant(result
));
6969 #else /* __aarch64__ */
6971 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6972 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6974 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6975 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6981 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6984 ITypeInfo
*tinfo2
= NULL
;
6985 TYPEATTR
*tattr
= NULL
;
6987 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->hreftype
, &tinfo2
);
6990 ERR("Could not get typeinfo of hreftype %lx for VT_USERDEFINED, hr %#lx.\n", tdesc
->hreftype
, hr
);
6993 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6996 ERR("ITypeInfo_GetTypeAttr failed, hr %#lx.\n", hr
);
6997 ITypeInfo_Release(tinfo2
);
7001 switch (tattr
->typekind
)
7008 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
7011 case TKIND_INTERFACE
:
7012 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
7018 case TKIND_DISPATCH
:
7027 FIXME("TKIND_RECORD unhandled.\n");
7032 FIXME("TKIND_UNION unhandled.\n");
7037 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
7041 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7042 ITypeInfo_Release(tinfo2
);
7046 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
7050 /* enforce only one level of pointer indirection */
7051 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
7053 tdesc
= tdesc
->lptdesc
;
7055 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7056 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7057 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7058 if ((tdesc
->vt
== VT_USERDEFINED
) ||
7059 ((tdesc
->vt
== VT_PTR
) && (tdesc
->lptdesc
->vt
== VT_USERDEFINED
)))
7061 VARTYPE vt_userdefined
= 0;
7062 const TYPEDESC
*tdesc_userdefined
= tdesc
;
7063 if (tdesc
->vt
== VT_PTR
)
7065 vt_userdefined
= VT_BYREF
;
7066 tdesc_userdefined
= tdesc
->lptdesc
;
7068 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
7070 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
7071 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
7073 *vt
|= vt_userdefined
;
7085 case VT_USERDEFINED
:
7086 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
7093 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
7094 hr
= DISP_E_BADVARTYPE
;
7098 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->lptdesc
, vt
);
7113 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
7120 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
7124 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7126 ITypeInfo_Release(tinfo2
);
7130 switch(tattr
->typekind
) {
7132 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.hreftype
, guid
);
7135 case TKIND_INTERFACE
:
7136 case TKIND_DISPATCH
:
7137 *guid
= tattr
->guid
;
7141 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
7143 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
7144 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
7148 if (i
== tattr
->cImplTypes
)
7151 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
7152 if (SUCCEEDED(hres
))
7153 hres
= get_iface_guid(tinfo2
, href
, guid
);
7157 ERR("Unexpected typekind %d\n", tattr
->typekind
);
7158 hres
= E_UNEXPECTED
;
7161 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7162 ITypeInfo_Release(tinfo2
);
7166 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7168 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7171 #define INVBUF_ELEMENT_SIZE \
7172 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7173 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7174 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7175 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7176 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7177 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7178 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7179 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7181 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7186 DISPPARAMS
*pDispParams
,
7187 VARIANT
*pVarResult
,
7188 EXCEPINFO
*pExcepInfo
,
7191 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7193 unsigned int var_index
;
7196 const TLBFuncDesc
*pFuncInfo
;
7199 TRACE("%p, %p, %ld, %#x, %p, %p, %p, %p.\n", iface
, pIUnk
, memid
, wFlags
, pDispParams
,
7200 pVarResult
, pExcepInfo
, pArgErr
);
7202 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7203 return DISP_E_MEMBERNOTFOUND
;
7207 ERR("NULL pDispParams not allowed\n");
7208 return E_INVALIDARG
;
7211 dump_DispParms(pDispParams
);
7213 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7215 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7216 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7217 return E_INVALIDARG
;
7220 /* we do this instead of using GetFuncDesc since it will return a fake
7221 * FUNCDESC for dispinterfaces and we want the real function description */
7222 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7223 pFuncInfo
= &This
->funcdescs
[fdc
];
7224 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7225 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7226 !func_restricted( &pFuncInfo
->funcdesc
))
7230 if (fdc
< This
->typeattr
.cFuncs
) {
7231 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7235 TRACE("invoking:\n");
7236 dump_TLBFuncDescOne(pFuncInfo
);
7239 switch (func_desc
->funckind
) {
7240 case FUNC_PUREVIRTUAL
:
7241 case FUNC_VIRTUAL
: {
7242 void *buffer
= calloc(func_desc
->cParams
, INVBUF_ELEMENT_SIZE
);
7244 VARIANT retval
= {{{0}}}; /* pointer for storing byref retvals in */
7245 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7246 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7247 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7248 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7249 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7250 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7251 UINT vargs_converted
=0;
7256 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7258 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7260 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7261 hres
= DISP_E_PARAMNOTFOUND
;
7266 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7268 ERR("functions with the vararg attribute do not support named arguments\n");
7269 hres
= DISP_E_NONAMEDARGS
;
7273 for (i
= 0; i
< func_desc
->cParams
; i
++)
7275 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7276 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7281 TRACE("changing args\n");
7282 for (i
= 0; i
< func_desc
->cParams
; i
++)
7284 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
;
7285 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7286 VARIANTARG
*src_arg
;
7288 if (wParamFlags
& PARAMFLAG_FLCID
)
7290 prgpvarg
[i
] = &rgvarg
[i
];
7291 V_VT(prgpvarg
[i
]) = VT_I4
;
7292 V_I4(prgpvarg
[i
]) = This
->pTypeLib
->lcid
;
7298 for (j
= 0; j
< cNamedArgs
; j
++)
7300 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7302 src_arg
= &pDispParams
->rgvarg
[j
];
7307 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7309 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7313 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7315 /* under most conditions the caller is not allowed to
7316 * pass in a dispparam arg in the index of what would be
7317 * the retval parameter. however, there is an exception
7318 * where the extra parameter is used in an extra
7319 * IDispatch::Invoke below */
7320 if ((i
< pDispParams
->cArgs
) &&
7321 ((func_desc
->cParams
!= 1) || !pVarResult
||
7322 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7324 hres
= DISP_E_BADPARAMCOUNT
;
7328 /* note: this check is placed so that if the caller passes
7329 * in a VARIANTARG for the retval we just ignore it, like
7331 if (i
== func_desc
->cParams
- 1)
7333 prgpvarg
[i
] = &rgvarg
[i
];
7334 V_BYREF(prgpvarg
[i
]) = &retval
;
7335 V_VT(prgpvarg
[i
]) = rgvt
[i
];
7339 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7340 hres
= E_UNEXPECTED
;
7344 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7345 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7347 TRACE("%s\n", debugstr_variant(src_arg
));
7349 if(rgvt
[i
]!=V_VT(src_arg
))
7351 if (rgvt
[i
] == VT_VARIANT
)
7352 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7353 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7355 if (rgvt
[i
] == V_VT(src_arg
))
7356 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7359 if (wParamFlags
& PARAMFLAG_FIN
)
7360 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7361 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7363 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7365 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7367 SAFEARRAYBOUND bound
;
7371 bound
.cElements
= pDispParams
->cArgs
-i
;
7372 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7374 ERR("SafeArrayCreate failed\n");
7377 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7380 ERR("SafeArrayAccessData failed with %#lx.\n", hres
);
7381 SafeArrayDestroy(a
);
7384 for (j
= 0; j
< bound
.cElements
; j
++)
7385 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7386 hres
= SafeArrayUnaccessData(a
);
7389 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres
);
7390 SafeArrayDestroy(a
);
7393 if (rgvt
[i
] & VT_BYREF
)
7394 V_BYREF(&rgvarg
[i
]) = &a
;
7396 V_ARRAY(&rgvarg
[i
]) = a
;
7397 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7399 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7401 if (wParamFlags
& PARAMFLAG_FIN
)
7402 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7404 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7405 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7406 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7408 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7410 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7411 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7415 /* FIXME: this doesn't work for VT_BYREF arguments if
7416 * they are not the same type as in the paramdesc */
7417 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7418 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7419 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7424 ERR("failed to convert param %d to %s from %s\n", i
,
7425 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7428 prgpvarg
[i
] = &rgvarg
[i
];
7432 prgpvarg
[i
] = src_arg
;
7435 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->lptdesc
->vt
== VT_USERDEFINED
))
7436 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7437 && V_UNKNOWN(prgpvarg
[i
])) {
7438 IUnknown
*userdefined_iface
;
7441 if (tdesc
->vt
== VT_PTR
)
7442 tdesc
= tdesc
->lptdesc
;
7444 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->hreftype
, &guid
);
7448 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7450 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7454 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7455 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7458 else if (wParamFlags
& PARAMFLAG_FOPT
)
7461 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7462 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7464 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].paramdesc
.pparamdescex
->varDefaultValue
);
7470 /* if the function wants a pointer to a variant then
7471 * set that up, otherwise just pass the VT_ERROR in
7472 * the argument by value */
7473 if (rgvt
[i
] & VT_BYREF
)
7475 V_VT(&missing_arg
[i
]) = VT_ERROR
;
7476 V_ERROR(&missing_arg
[i
]) = DISP_E_PARAMNOTFOUND
;
7478 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7479 V_VARIANTREF(arg
) = &missing_arg
[i
];
7483 V_VT(arg
) = VT_ERROR
;
7484 V_ERROR(arg
) = DISP_E_PARAMNOTFOUND
;
7490 hres
= DISP_E_BADPARAMCOUNT
;
7494 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7496 /* VT_VOID is a special case for return types, so it is not
7497 * handled in the general function */
7498 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7499 V_VT(&varresult
) = VT_EMPTY
;
7502 V_VT(&varresult
) = 0;
7503 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7504 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7507 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7508 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7509 prgpvarg
, &varresult
);
7511 vargs_converted
= 0;
7513 for (i
= 0; i
< func_desc
->cParams
; i
++)
7515 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].paramdesc
.wParamFlags
;
7517 if (wParamFlags
& PARAMFLAG_FLCID
)
7519 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7521 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7525 VariantInit(pVarResult
);
7526 /* deref return value */
7527 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7530 VARIANT_ClearInd(prgpvarg
[i
]);
7532 else if (vargs_converted
< pDispParams
->cArgs
)
7534 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7535 if (wParamFlags
& PARAMFLAG_FOUT
)
7537 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7539 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7543 ERR("failed to convert param %d to vt %d\n", i
,
7544 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7549 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7550 func_desc
->cParamsOpt
< 0 &&
7551 i
== func_desc
->cParams
-1)
7553 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7556 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7559 ERR("SafeArrayGetUBound failed with %#lx.\n", hres
);
7562 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7565 ERR("SafeArrayAccessData failed with %#lx.\n", hres
);
7568 for (j
= 0; j
<= ubound
; j
++)
7569 VariantClear(&v
[j
]);
7570 hres
= SafeArrayUnaccessData(a
);
7573 ERR("SafeArrayUnaccessData failed with %#lx.\n", hres
);
7577 VariantClear(&rgvarg
[i
]);
7580 else if (wParamFlags
& PARAMFLAG_FOPT
)
7582 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7583 VariantClear(&rgvarg
[i
]);
7586 VariantClear(&missing_arg
[i
]);
7589 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7591 WARN("invoked function failed with error %#lx.\n", V_ERROR(&varresult
));
7592 hres
= DISP_E_EXCEPTION
;
7595 IErrorInfo
*pErrorInfo
;
7596 pExcepInfo
->scode
= V_ERROR(&varresult
);
7597 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7599 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7600 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7601 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7602 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7604 IErrorInfo_Release(pErrorInfo
);
7608 if (V_VT(&varresult
) != VT_ERROR
)
7610 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7614 VariantClear(pVarResult
);
7615 *pVarResult
= varresult
;
7618 VariantClear(&varresult
);
7621 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7622 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7623 (func_desc
->lprgelemdescParam
[0].paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7624 (pDispParams
->cArgs
!= 0))
7626 if (V_VT(pVarResult
) == VT_DISPATCH
)
7628 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7629 /* Note: not VariantClear; we still need the dispatch
7630 * pointer to be valid */
7631 VariantInit(pVarResult
);
7632 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7633 GetSystemDefaultLCID(), wFlags
,
7634 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7635 IDispatch_Release(pDispatch
);
7639 VariantClear(pVarResult
);
7640 hres
= DISP_E_NOTACOLLECTION
;
7648 case FUNC_DISPATCH
: {
7651 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7652 if (SUCCEEDED(hres
)) {
7653 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7654 hres
= IDispatch_Invoke(
7655 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7656 pVarResult
,pExcepInfo
,pArgErr
7659 FIXME("IDispatch::Invoke failed with %#lx. (Could be not a real error?)\n", hres
);
7660 IDispatch_Release(disp
);
7662 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7666 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7671 TRACE("-- %#lx\n", hres
);
7674 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7677 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7678 if(FAILED(hres
)) return hres
;
7680 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7681 dump_VARDESC(var_desc
);
7682 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7686 /* not found, look for it in inherited interfaces */
7687 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7688 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7689 if(This
->impltypes
) {
7690 /* recursive search */
7692 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7693 if(SUCCEEDED(hres
)){
7694 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7695 ITypeInfo_Release(pTInfo
);
7698 WARN("Could not search inherited interface!\n");
7701 WARN("did not find member id %ld, flags 0x%x!\n", memid
, wFlags
);
7702 return DISP_E_MEMBERNOTFOUND
;
7705 /* ITypeInfo::GetDocumentation
7707 * Retrieves the documentation string, the complete Help file name and path,
7708 * and the context ID for the Help topic for a specified type description.
7710 * (Can be tested by the Visual Basic Editor in Word for instance.)
7712 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7713 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7714 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7716 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7717 const TLBFuncDesc
*pFDesc
;
7718 const TLBVarDesc
*pVDesc
;
7719 TRACE("%p, %ld, %p, %p, %p, %p.\n",
7720 iface
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7721 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7723 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7725 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7727 *pdwHelpContext
=This
->dwHelpContext
;
7729 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7731 }else {/* for a member */
7732 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
7735 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7737 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7739 *pdwHelpContext
=pFDesc
->helpcontext
;
7741 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7744 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
7747 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7749 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7751 *pdwHelpContext
=pVDesc
->HelpContext
;
7753 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7758 if(This
->impltypes
&&
7759 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7760 /* recursive search */
7763 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7764 if(SUCCEEDED(result
)) {
7765 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7766 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7767 ITypeInfo_Release(pTInfo
);
7770 WARN("Could not search inherited interface!\n");
7773 WARN("member %ld not found\n", memid
);
7774 return TYPE_E_ELEMENTNOTFOUND
;
7777 /* ITypeInfo::GetDllEntry
7779 * Retrieves a description or specification of an entry point for a function
7782 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7783 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7786 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7787 const TLBFuncDesc
*pFDesc
;
7789 TRACE("%p, %#lx, %d, %p, %p, %p.\n", iface
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7791 if (pBstrDllName
) *pBstrDllName
= NULL
;
7792 if (pBstrName
) *pBstrName
= NULL
;
7793 if (pwOrdinal
) *pwOrdinal
= 0;
7795 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7796 return TYPE_E_BADMODULEKIND
;
7798 pFDesc
= TLB_get_funcdesc_by_memberid_invkind(This
, memid
, invKind
);
7799 if (!pFDesc
) return TYPE_E_ELEMENTNOTFOUND
;
7801 dump_TypeInfo(This
);
7802 if (TRACE_ON(ole
)) dump_TLBFuncDescOne(pFDesc
);
7804 if (pBstrDllName
) *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7806 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1))
7808 if (pBstrName
) *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7809 if (pwOrdinal
) *pwOrdinal
= -1;
7813 if (pBstrName
) *pBstrName
= NULL
;
7814 if (pwOrdinal
) *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7819 /* internal function to make the inherited interfaces' methods appear
7820 * part of the interface */
7821 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7822 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7824 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7827 TRACE("%p, %#lx.\n", iface
, *hRefType
);
7829 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7831 ITypeInfo
*pSubTypeInfo
;
7833 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7837 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7839 ITypeInfo_Release(pSubTypeInfo
);
7843 *hRefType
-= DISPATCH_HREF_OFFSET
;
7845 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7846 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7851 /* ITypeInfo::GetRefTypeInfo
7853 * If a type description references other type descriptions, it retrieves
7854 * the referenced type descriptions.
7856 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7859 ITypeInfo
**ppTInfo
)
7861 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7862 ITypeInfo
*type_info
= NULL
;
7863 HRESULT result
= E_FAIL
;
7864 TLBRefType
*ref_type
;
7868 return E_INVALIDARG
;
7870 if ((INT
)hRefType
< 0) {
7871 ITypeInfoImpl
*pTypeInfoImpl
;
7873 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7874 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7875 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7876 return TYPE_E_ELEMENTNOTFOUND
;
7878 /* when we meet a DUAL typeinfo, we must create the alternate
7881 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7883 *pTypeInfoImpl
= *This
;
7884 pTypeInfoImpl
->ref
= 0;
7885 list_init(&pTypeInfoImpl
->custdata_list
);
7887 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7888 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7890 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7892 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7893 /* the AddRef implicitly adds a reference to the parent typelib, which
7894 * stops the copied data from being destroyed until the new typeinfo's
7895 * refcount goes to zero, but we need to signal to the new instance to
7896 * not free its data structures when it is destroyed */
7897 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7898 ITypeInfo_AddRef(*ppTInfo
);
7900 TRACE("got dual interface %p\n", *ppTInfo
);
7904 if ((hRefType
& DISPATCH_HREF_MASK
) && (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7905 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &hRefType
, ppTInfo
);
7907 if(!(hRefType
& 0x1))
7909 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7911 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7914 type_info
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7915 ITypeInfo_AddRef(type_info
);
7923 ITypeLib
*pTLib
= NULL
;
7925 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7927 if(ref_type
->reference
== (hRefType
& (~0x3)))
7930 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7932 FIXME("Can't find pRefType for ref %lx\n", hRefType
);
7936 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7938 TRACE("internal reference\n");
7939 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7941 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7942 TRACE("typeinfo in imported typelib that is already loaded\n");
7943 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7944 ITypeLib_AddRef(pTLib
);
7947 /* Search in cached typelibs */
7948 ITypeLibImpl
*entry
;
7950 EnterCriticalSection(&cache_section
);
7951 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
7954 && IsEqualIID(&entry
->guid
->guid
, TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
))
7955 && entry
->ver_major
== ref_type
->pImpTLInfo
->wVersionMajor
7956 && entry
->ver_minor
== ref_type
->pImpTLInfo
->wVersionMinor
7957 && entry
->set_lcid
== ref_type
->pImpTLInfo
->lcid
7958 && entry
->syskind
== This
->pTypeLib
->syskind
)
7960 TRACE("got cached %p\n", entry
);
7961 pTLib
= (ITypeLib
*)&entry
->ITypeLib2_iface
;
7962 ITypeLib_AddRef(pTLib
);
7967 LeaveCriticalSection(&cache_section
);
7973 /* Search on disk */
7974 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7975 ref_type
->pImpTLInfo
->wVersionMajor
,
7976 ref_type
->pImpTLInfo
->wVersionMinor
,
7977 This
->pTypeLib
->syskind
,
7978 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7980 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7982 result
= LoadTypeLib(libnam
, &pTLib
);
7983 SysFreeString(libnam
);
7986 if(SUCCEEDED(result
)) {
7987 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7988 ITypeLib_AddRef(pTLib
);
7992 if(SUCCEEDED(result
)) {
7993 if(ref_type
->index
== TLB_REF_USE_GUID
)
7994 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), &type_info
);
7996 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, &type_info
);
7999 ITypeLib_Release(pTLib
);
8002 WARN("(%p) failed hreftype %#lx.\n", iface
, hRefType
);
8007 if ((hRefType
& 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info
, -2, ppTInfo
)))
8008 ITypeInfo_Release(type_info
);
8009 else *ppTInfo
= type_info
;
8011 TRACE("%p, hreftype %#lx, loaded %s (%p)\n", iface
, hRefType
,
8012 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
8016 /* ITypeInfo::AddressOfMember
8018 * Retrieves the addresses of static functions or variables, such as those
8021 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
8022 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
8029 TRACE("%p, %lx, %#x, %p.\n", iface
, memid
, invKind
, ppv
);
8031 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
8035 module
= LoadLibraryW(dll
);
8038 ERR("couldn't load %s\n", debugstr_w(dll
));
8040 SysFreeString(entry
);
8041 return STG_E_FILENOTFOUND
;
8043 /* FIXME: store library somewhere where we can free it */
8048 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
8049 entryA
= malloc(len
);
8050 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
8052 *ppv
= GetProcAddress(module
, entryA
);
8054 ERR("function not found %s\n", debugstr_a(entryA
));
8060 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
8062 ERR("function not found %d\n", ordinal
);
8066 SysFreeString(entry
);
8069 return TYPE_E_DLLFUNCTIONNOTFOUND
;
8074 /* ITypeInfo::CreateInstance
8076 * Creates a new instance of a type that describes a component object class
8079 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
8080 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
8082 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8086 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8092 WARN("Not able to aggregate\n");
8093 return CLASS_E_NOAGGREGATION
;
8096 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8097 if(FAILED(hr
)) return hr
;
8099 if(pTA
->typekind
!= TKIND_COCLASS
)
8101 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8107 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8110 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8111 TRACE("GetActiveObject rets %#lx.\n", hr
);
8114 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8115 IUnknown_Release(pUnk
);
8120 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8121 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8125 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8129 /* ITypeInfo::GetMops
8131 * Retrieves marshalling information.
8133 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
, BSTR
*pBstrMops
)
8135 FIXME("%p, %ld stub!\n", iface
, memid
);
8140 /* ITypeInfo::GetContainingTypeLib
8142 * Retrieves the containing type library and the index of the type description
8143 * within that type library.
8145 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8146 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8148 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8150 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8152 *pIndex
=This
->index
;
8153 TRACE("returning pIndex=%d\n", *pIndex
);
8157 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8158 ITypeLib_AddRef(*ppTLib
);
8159 TRACE("returning ppTLib=%p\n", *ppTLib
);
8165 /* ITypeInfo::ReleaseTypeAttr
8167 * Releases a TYPEATTR previously returned by Get
8170 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8171 TYPEATTR
* pTypeAttr
)
8173 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8174 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8178 /* ITypeInfo::ReleaseFuncDesc
8180 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8182 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8184 FUNCDESC
*pFuncDesc
)
8186 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8189 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8191 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8192 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8193 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8195 SysFreeString((BSTR
)pFuncDesc
);
8198 /* ITypeInfo::ReleaseVarDesc
8200 * Releases a VARDESC previously returned by GetVarDesc.
8202 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8205 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8206 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8208 TLB_FreeVarDesc(pVarDesc
);
8211 /* ITypeInfo2::GetTypeKind
8213 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8216 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8217 TYPEKIND
*pTypeKind
)
8219 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8220 *pTypeKind
= This
->typeattr
.typekind
;
8221 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8225 /* ITypeInfo2::GetTypeFlags
8227 * Returns the type flags without any allocations. This returns a DWORD type
8228 * flag, which expands the type flags without growing the TYPEATTR (type
8232 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8234 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8235 TRACE("%p, %p.\n", iface
, pTypeFlags
);
8236 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8240 /* ITypeInfo2::GetFuncIndexOfMemId
8241 * Binds to a specific member based on a known DISPID, where the member name
8242 * is not known (for example, when binding to a default member).
8245 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8246 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8248 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8252 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8253 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8254 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8257 if(fdc
< This
->typeattr
.cFuncs
) {
8261 result
= TYPE_E_ELEMENTNOTFOUND
;
8263 TRACE("%p, %#lx, %#x, hr %#lx.\n", iface
, memid
, invKind
, result
);
8267 /* TypeInfo2::GetVarIndexOfMemId
8269 * Binds to a specific member based on a known DISPID, where the member name
8270 * is not known (for example, when binding to a default member).
8273 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8274 MEMBERID memid
, UINT
*pVarIndex
)
8276 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8277 TLBVarDesc
*pVarInfo
;
8279 TRACE("%p, %ld, %p.\n", iface
, memid
, pVarIndex
);
8281 pVarInfo
= TLB_get_vardesc_by_memberid(This
, memid
);
8283 return TYPE_E_ELEMENTNOTFOUND
;
8285 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8290 /* ITypeInfo2::GetCustData
8292 * Gets the custom data
8294 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8299 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8300 TLBCustData
*pCData
;
8302 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8304 if(!guid
|| !pVarVal
)
8305 return E_INVALIDARG
;
8307 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8309 VariantInit( pVarVal
);
8311 VariantCopy( pVarVal
, &pCData
->data
);
8313 VariantClear( pVarVal
);
8317 /* ITypeInfo2::GetFuncCustData
8319 * Gets the custom data
8321 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8327 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8328 const TLBFuncDesc
*desc
;
8333 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8335 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &desc
, &hrefoffset
);
8338 WARN("description for function %d not found\n", index
);
8342 VariantInit(pVarVal
);
8343 data
= TLB_get_custdata_by_guid(&desc
->custdata_list
, guid
);
8344 return data
? VariantCopy(pVarVal
, &data
->data
) : S_OK
;
8347 /* ITypeInfo2::GetParamCustData
8349 * Gets the custom data
8351 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8358 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8359 const TLBFuncDesc
*pFDesc
;
8360 TLBCustData
*pCData
;
8364 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8365 debugstr_guid(guid
), pVarVal
);
8367 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8371 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8372 return TYPE_E_ELEMENTNOTFOUND
;
8374 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8376 return TYPE_E_ELEMENTNOTFOUND
;
8378 VariantInit(pVarVal
);
8379 VariantCopy(pVarVal
, &pCData
->data
);
8384 /* ITypeInfo2::GetVarCustData
8386 * Gets the custom data
8388 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8394 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8395 TLBCustData
*pCData
;
8396 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8398 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8400 if(index
>= This
->typeattr
.cVars
)
8401 return TYPE_E_ELEMENTNOTFOUND
;
8403 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8405 return TYPE_E_ELEMENTNOTFOUND
;
8407 VariantInit(pVarVal
);
8408 VariantCopy(pVarVal
, &pCData
->data
);
8413 /* ITypeInfo2::GetImplCustData
8415 * Gets the custom data
8417 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8423 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8424 TLBCustData
*pCData
;
8425 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8427 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8429 if(index
>= This
->typeattr
.cImplTypes
)
8430 return TYPE_E_ELEMENTNOTFOUND
;
8432 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8434 return TYPE_E_ELEMENTNOTFOUND
;
8436 VariantInit(pVarVal
);
8437 VariantCopy(pVarVal
, &pCData
->data
);
8442 /* ITypeInfo2::GetDocumentation2
8444 * Retrieves the documentation string, the complete Help file name and path,
8445 * the localization context to use, and the context ID for the library Help
8446 * topic in the Help file.
8449 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8453 BSTR
*pbstrHelpString
,
8454 DWORD
*pdwHelpStringContext
,
8455 BSTR
*pbstrHelpStringDll
)
8457 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8458 const TLBFuncDesc
*pFDesc
;
8459 const TLBVarDesc
*pVDesc
;
8460 TRACE("%p, %ld, %#lx, %p, %p, %p.\n",
8461 iface
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8462 pbstrHelpStringDll
);
8463 /* the help string should be obtained from the helpstringdll,
8464 * using the _DLLGetDocumentation function, based on the supplied
8465 * lcid. Nice to do sometime...
8467 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8469 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8470 if(pdwHelpStringContext
)
8471 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8472 if(pbstrHelpStringDll
)
8473 *pbstrHelpStringDll
=
8474 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8476 }else {/* for a member */
8477 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
8480 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8481 if(pdwHelpStringContext
)
8482 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8483 if(pbstrHelpStringDll
)
8484 *pbstrHelpStringDll
=
8485 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8488 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
8491 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8492 if(pdwHelpStringContext
)
8493 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8494 if(pbstrHelpStringDll
)
8495 *pbstrHelpStringDll
=
8496 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8500 return TYPE_E_ELEMENTNOTFOUND
;
8503 /* ITypeInfo2::GetAllCustData
8505 * Gets all custom data items for the Type info.
8508 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8510 CUSTDATA
*pCustData
)
8512 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8514 TRACE("%p %p\n", This
, pCustData
);
8516 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8519 /* ITypeInfo2::GetAllFuncCustData
8521 * Gets all custom data items for the specified Function
8524 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8527 CUSTDATA
*pCustData
)
8529 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8530 const TLBFuncDesc
*pFDesc
;
8534 TRACE("%p %u %p\n", This
, index
, pCustData
);
8536 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &pFDesc
, &hrefoffset
);
8540 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8543 /* ITypeInfo2::GetAllParamCustData
8545 * Gets all custom data items for the Functions
8548 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8549 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8551 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8552 const TLBFuncDesc
*pFDesc
;
8556 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8558 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8562 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8563 return TYPE_E_ELEMENTNOTFOUND
;
8565 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8568 /* ITypeInfo2::GetAllVarCustData
8570 * Gets all custom data items for the specified Variable
8573 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8574 UINT index
, CUSTDATA
*pCustData
)
8576 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8577 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8579 TRACE("%p %u %p\n", This
, index
, pCustData
);
8581 if(index
>= This
->typeattr
.cVars
)
8582 return TYPE_E_ELEMENTNOTFOUND
;
8584 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8587 /* ITypeInfo2::GetAllImplCustData
8589 * Gets all custom data items for the specified implementation type
8592 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8595 CUSTDATA
*pCustData
)
8597 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8598 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8600 TRACE("%p %u %p\n", This
, index
, pCustData
);
8602 if(index
>= This
->typeattr
.cImplTypes
)
8603 return TYPE_E_ELEMENTNOTFOUND
;
8605 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8608 static const ITypeInfo2Vtbl tinfvt
=
8611 ITypeInfo_fnQueryInterface
,
8613 ITypeInfo_fnRelease
,
8615 ITypeInfo_fnGetTypeAttr
,
8616 ITypeInfo_fnGetTypeComp
,
8617 ITypeInfo_fnGetFuncDesc
,
8618 ITypeInfo_fnGetVarDesc
,
8619 ITypeInfo_fnGetNames
,
8620 ITypeInfo_fnGetRefTypeOfImplType
,
8621 ITypeInfo_fnGetImplTypeFlags
,
8622 ITypeInfo_fnGetIDsOfNames
,
8624 ITypeInfo_fnGetDocumentation
,
8625 ITypeInfo_fnGetDllEntry
,
8626 ITypeInfo_fnGetRefTypeInfo
,
8627 ITypeInfo_fnAddressOfMember
,
8628 ITypeInfo_fnCreateInstance
,
8629 ITypeInfo_fnGetMops
,
8630 ITypeInfo_fnGetContainingTypeLib
,
8631 ITypeInfo_fnReleaseTypeAttr
,
8632 ITypeInfo_fnReleaseFuncDesc
,
8633 ITypeInfo_fnReleaseVarDesc
,
8635 ITypeInfo2_fnGetTypeKind
,
8636 ITypeInfo2_fnGetTypeFlags
,
8637 ITypeInfo2_fnGetFuncIndexOfMemId
,
8638 ITypeInfo2_fnGetVarIndexOfMemId
,
8639 ITypeInfo2_fnGetCustData
,
8640 ITypeInfo2_fnGetFuncCustData
,
8641 ITypeInfo2_fnGetParamCustData
,
8642 ITypeInfo2_fnGetVarCustData
,
8643 ITypeInfo2_fnGetImplTypeCustData
,
8644 ITypeInfo2_fnGetDocumentation2
,
8645 ITypeInfo2_fnGetAllCustData
,
8646 ITypeInfo2_fnGetAllFuncCustData
,
8647 ITypeInfo2_fnGetAllParamCustData
,
8648 ITypeInfo2_fnGetAllVarCustData
,
8649 ITypeInfo2_fnGetAllImplTypeCustData
,
8652 /******************************************************************************
8653 * CreateDispTypeInfo [OLEAUT32.31]
8655 * Build type information for an object so it can be called through an
8656 * IDispatch interface.
8659 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8660 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8663 * This call allows an objects methods to be accessed through IDispatch, by
8664 * building an ITypeInfo object that IDispatch can use to call through.
8666 HRESULT WINAPI
CreateDispTypeInfo(
8667 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8668 LCID lcid
, /* [I] Locale Id */
8669 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8671 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8672 ITypeLibImpl
*pTypeLibImpl
;
8673 unsigned int param
, func
;
8674 TLBFuncDesc
*pFuncDesc
;
8678 pTypeLibImpl
= TypeLibImpl_Constructor();
8679 if (!pTypeLibImpl
) return E_FAIL
;
8681 pTypeLibImpl
->TypeInfoCount
= 2;
8682 pTypeLibImpl
->typeinfos
= calloc(pTypeLibImpl
->TypeInfoCount
, sizeof(ITypeInfoImpl
*));
8684 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8685 pTIIface
->pTypeLib
= pTypeLibImpl
;
8686 pTIIface
->index
= 0;
8687 pTIIface
->Name
= NULL
;
8688 pTIIface
->dwHelpContext
= -1;
8689 pTIIface
->guid
= NULL
;
8690 pTIIface
->typeattr
.lcid
= lcid
;
8691 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8692 pTIIface
->typeattr
.wMajorVerNum
= 0;
8693 pTIIface
->typeattr
.wMinorVerNum
= 0;
8694 pTIIface
->typeattr
.cbAlignment
= 2;
8695 pTIIface
->typeattr
.cbSizeInstance
= -1;
8696 pTIIface
->typeattr
.cbSizeVft
= -1;
8697 pTIIface
->typeattr
.cFuncs
= 0;
8698 pTIIface
->typeattr
.cImplTypes
= 0;
8699 pTIIface
->typeattr
.cVars
= 0;
8700 pTIIface
->typeattr
.wTypeFlags
= 0;
8701 pTIIface
->hreftype
= 0;
8703 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8704 pFuncDesc
= pTIIface
->funcdescs
;
8705 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8706 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8707 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8708 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8709 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8710 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8711 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8712 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8713 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8714 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8715 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8716 pFuncDesc
->funcdesc
.cScodes
= 0;
8717 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8718 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8719 pFuncDesc
->funcdesc
.elemdescFunc
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8720 pFuncDesc
->funcdesc
.elemdescFunc
.paramdesc
.pparamdescex
= NULL
;
8721 pFuncDesc
->funcdesc
.lprgelemdescParam
= calloc(md
->cArgs
, sizeof(ELEMDESC
));
8722 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8723 for(param
= 0; param
< md
->cArgs
; param
++) {
8724 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8725 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8727 pFuncDesc
->helpcontext
= 0;
8728 pFuncDesc
->HelpStringContext
= 0;
8729 pFuncDesc
->HelpString
= NULL
;
8730 pFuncDesc
->Entry
= NULL
;
8731 list_init(&pFuncDesc
->custdata_list
);
8732 pTIIface
->typeattr
.cFuncs
++;
8736 dump_TypeInfo(pTIIface
);
8738 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8739 pTIClass
->pTypeLib
= pTypeLibImpl
;
8740 pTIClass
->index
= 1;
8741 pTIClass
->Name
= NULL
;
8742 pTIClass
->dwHelpContext
= -1;
8743 pTIClass
->guid
= NULL
;
8744 pTIClass
->typeattr
.lcid
= lcid
;
8745 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8746 pTIClass
->typeattr
.wMajorVerNum
= 0;
8747 pTIClass
->typeattr
.wMinorVerNum
= 0;
8748 pTIClass
->typeattr
.cbAlignment
= 2;
8749 pTIClass
->typeattr
.cbSizeInstance
= -1;
8750 pTIClass
->typeattr
.cbSizeVft
= -1;
8751 pTIClass
->typeattr
.cFuncs
= 0;
8752 pTIClass
->typeattr
.cImplTypes
= 1;
8753 pTIClass
->typeattr
.cVars
= 0;
8754 pTIClass
->typeattr
.wTypeFlags
= 0;
8755 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8757 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8759 ref
= calloc(1, sizeof(*ref
));
8760 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8761 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8763 dump_TypeInfo(pTIClass
);
8765 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8767 ITypeInfo_AddRef(*pptinfo
);
8768 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8774 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8776 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8778 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8781 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8783 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8785 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8788 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8790 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8792 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8795 static HRESULT WINAPI
ITypeComp_fnBind(
8800 ITypeInfo
** ppTInfo
,
8801 DESCKIND
* pDescKind
,
8804 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8805 const TLBFuncDesc
*pFDesc
;
8806 const TLBVarDesc
*pVDesc
;
8807 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8810 TRACE("%p, %s, %#lx, 0x%x, %p, %p, %p.\n", iface
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8812 *pDescKind
= DESCKIND_NONE
;
8813 pBindPtr
->lpfuncdesc
= NULL
;
8816 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8817 pFDesc
= &This
->funcdescs
[fdc
];
8818 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8819 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8822 /* name found, but wrong flags */
8823 hr
= TYPE_E_TYPEMISMATCH
;
8827 if (fdc
< This
->typeattr
.cFuncs
)
8829 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8831 &pBindPtr
->lpfuncdesc
,
8832 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8835 *pDescKind
= DESCKIND_FUNCDESC
;
8836 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8837 ITypeInfo_AddRef(*ppTInfo
);
8840 pVDesc
= TLB_get_vardesc_by_name(This
, szName
);
8842 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8845 *pDescKind
= DESCKIND_VARDESC
;
8846 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8847 ITypeInfo_AddRef(*ppTInfo
);
8852 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8853 /* recursive search */
8857 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8860 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8861 ITypeInfo_Release(pTInfo
);
8865 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8866 ITypeComp_Release(pTComp
);
8867 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8868 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8870 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8871 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8872 SysFreeString((BSTR
)tmp
);
8876 WARN("Could not search inherited interface!\n");
8878 if (hr
== DISP_E_MEMBERNOTFOUND
)
8880 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8884 static HRESULT WINAPI
ITypeComp_fnBindType(
8888 ITypeInfo
** ppTInfo
,
8889 ITypeComp
** ppTComp
)
8891 TRACE("%s, %#lx, %p, %p.\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8893 /* strange behaviour (does nothing) but like the
8896 if (!ppTInfo
|| !ppTComp
)
8905 static const ITypeCompVtbl tcompvt
=
8908 ITypeComp_fnQueryInterface
,
8910 ITypeComp_fnRelease
,
8913 ITypeComp_fnBindType
8916 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8917 ICreateTypeLib2
** ppctlib
)
8922 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8924 if (!szFile
) return E_INVALIDARG
;
8926 This
= TypeLibImpl_Constructor();
8928 return E_OUTOFMEMORY
;
8930 This
->lcid
= GetSystemDefaultLCID();
8931 This
->syskind
= syskind
;
8932 This
->ptr_size
= get_ptr_size(syskind
);
8934 This
->path
= wcsdup(szFile
);
8936 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8937 return E_OUTOFMEMORY
;
8940 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8941 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8945 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8946 REFIID riid
, void **object
)
8948 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8950 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8953 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8955 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8957 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8960 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8962 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8964 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8967 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8968 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8970 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8971 ITypeInfoImpl
*info
;
8974 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8976 if (!ctinfo
|| !name
)
8977 return E_INVALIDARG
;
8979 info
= TLB_get_typeinfo_by_name(This
, name
);
8981 return TYPE_E_NAMECONFLICT
;
8983 This
->typeinfos
= realloc(This
->typeinfos
, sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8985 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8987 info
->pTypeLib
= This
;
8988 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8989 info
->index
= This
->TypeInfoCount
;
8990 info
->typeattr
.typekind
= kind
;
8991 info
->typeattr
.cbAlignment
= 4;
8993 switch (info
->typeattr
.typekind
) {
8995 case TKIND_INTERFACE
:
8996 case TKIND_DISPATCH
:
8998 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
9002 info
->typeattr
.cbSizeInstance
= 0;
9005 info
->typeattr
.cbSizeInstance
= 2;
9008 info
->typeattr
.cbSizeInstance
= -0x75;
9011 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
9012 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
9016 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
9017 &IID_ICreateTypeInfo
, (void **)ctinfo
);
9019 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
9023 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
9025 ++This
->TypeInfoCount
;
9030 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
9033 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9035 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
9038 return E_INVALIDARG
;
9040 This
->Name
= TLB_append_str(&This
->name_list
, name
);
9045 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
9046 WORD majorVerNum
, WORD minorVerNum
)
9048 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9050 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
9052 This
->ver_major
= majorVerNum
;
9053 This
->ver_minor
= minorVerNum
;
9058 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
9061 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9063 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9065 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
9070 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
9073 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9075 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9078 return E_INVALIDARG
;
9080 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
9085 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
9086 LPOLESTR helpFileName
)
9088 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9090 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9093 return E_INVALIDARG
;
9095 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9100 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9103 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9105 TRACE("%p, %ld.\n", iface
, helpContext
);
9107 This
->dwHelpContext
= helpContext
;
9112 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9115 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9117 TRACE("%p, %#lx.\n", iface
, lcid
);
9119 This
->set_lcid
= lcid
;
9124 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9127 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9129 TRACE("%p %x\n", This
, libFlags
);
9131 This
->libflags
= libFlags
;
9136 typedef struct tagWMSFT_SegContents
{
9139 } WMSFT_SegContents
;
9141 typedef struct tagWMSFT_TLBFile
{
9143 WMSFT_SegContents typeinfo_seg
;
9144 WMSFT_SegContents impfile_seg
;
9145 WMSFT_SegContents impinfo_seg
;
9146 WMSFT_SegContents ref_seg
;
9147 WMSFT_SegContents guidhash_seg
;
9148 WMSFT_SegContents guid_seg
;
9149 WMSFT_SegContents namehash_seg
;
9150 WMSFT_SegContents name_seg
;
9151 WMSFT_SegContents string_seg
;
9152 WMSFT_SegContents typdesc_seg
;
9153 WMSFT_SegContents arraydesc_seg
;
9154 WMSFT_SegContents custdata_seg
;
9155 WMSFT_SegContents cdguids_seg
;
9157 WMSFT_SegContents aux_seg
;
9160 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9161 WMSFT_TLBFile
*file
)
9167 file
->string_seg
.len
= 0;
9168 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9171 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9173 return E_UNEXPECTED
;
9175 size
+= sizeof(INT16
);
9177 size
= (size
+ 4) & ~0x3;
9181 file
->string_seg
.len
+= size
;
9183 /* temporarily use str->offset to store the length of the aligned,
9184 * converted string */
9188 file
->string_seg
.data
= data
= malloc(file
->string_seg
.len
);
9191 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9194 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9195 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9197 free(file
->string_seg
.data
);
9198 return E_UNEXPECTED
;
9201 *((INT16
*)data
) = size
;
9203 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9207 str
->offset
= last_offs
;
9214 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9215 WMSFT_TLBFile
*file
)
9220 MSFT_NameIntro
*last_intro
= NULL
;
9222 file
->header
.nametablecount
= 0;
9223 file
->header
.nametablechars
= 0;
9225 file
->name_seg
.len
= 0;
9226 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9229 size
= lstrlenW(str
->str
);
9230 file
->header
.nametablechars
+= size
;
9231 file
->header
.nametablecount
++;
9233 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9235 return E_UNEXPECTED
;
9237 size
+= sizeof(MSFT_NameIntro
);
9239 size
= (size
+ 4) & ~0x3;
9243 file
->name_seg
.len
+= size
;
9245 /* temporarily use str->offset to store the length of the aligned,
9246 * converted string */
9250 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9251 file
->name_seg
.data
= data
= malloc(file
->name_seg
.len
+ 1);
9254 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9256 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9258 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9259 data
+ sizeof(MSFT_NameIntro
),
9260 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9262 free(file
->name_seg
.data
);
9263 return E_UNEXPECTED
;
9265 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9267 intro
->hreftype
= -1; /* TODO? */
9268 intro
->namelen
= size
& 0xFF;
9269 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9270 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9271 intro
->namelen
|= hash
<< 16;
9272 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9273 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9275 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9276 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9278 /* update str->offset to actual value to use in other
9279 * compilation functions that require positions within
9280 * the string table */
9284 str
->offset
= last_offs
;
9289 last_intro
->hreftype
= 0; /* last one is 0? */
9294 static inline int hash_guid(GUID
*guid
)
9298 for (i
= 0; i
< 8; i
++)
9299 hash
^= ((const short *)guid
)[i
];
9304 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9307 MSFT_GuidEntry
*entry
;
9309 int hash_key
, *guidhashtab
;
9311 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9312 file
->guid_seg
.data
= malloc(file
->guid_seg
.len
);
9314 entry
= file
->guid_seg
.data
;
9316 guidhashtab
= file
->guidhash_seg
.data
;
9317 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9318 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9319 entry
->hreftype
= guid
->hreftype
;
9321 hash_key
= hash_guid(&guid
->guid
);
9322 entry
->next_hash
= guidhashtab
[hash_key
];
9323 guidhashtab
[hash_key
] = offs
;
9325 guid
->offset
= offs
;
9326 offs
+= sizeof(MSFT_GuidEntry
);
9333 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9336 VARTYPE arg_type
= V_VT(value
);
9339 DWORD ret
= file
->custdata_seg
.len
;
9341 if(arg_type
== VT_INT
)
9343 if(arg_type
== VT_UINT
)
9347 if(V_VT(value
) != arg_type
) {
9348 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9350 ERR("VariantChangeType failed: %#lx.\n", hres
);
9355 /* Check if default value can be stored in-place */
9360 if(V_UI4(&v
) > 0x3ffffff)
9373 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9376 /* have to allocate space in custdata_seg */
9385 /* Construct the data to be allocated */
9388 if(file
->custdata_seg
.data
){
9389 file
->custdata_seg
.data
= realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9390 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9391 file
->custdata_seg
.len
+= sizeof(int) * 2;
9393 file
->custdata_seg
.len
= sizeof(int) * 2;
9394 data
= file
->custdata_seg
.data
= malloc(file
->custdata_seg
.len
);
9397 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9398 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9400 /* TODO: Check if the encoded data is already present in custdata_seg */
9406 int mb_len
= WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), NULL
, 0, NULL
, NULL
);
9407 int i
, len
= (6 + mb_len
+ 3) & ~0x3;
9410 if(file
->custdata_seg
.data
){
9411 file
->custdata_seg
.data
= realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9412 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9413 file
->custdata_seg
.len
+= len
;
9415 file
->custdata_seg
.len
= len
;
9416 data
= file
->custdata_seg
.data
= malloc(file
->custdata_seg
.len
);
9419 *((unsigned short *)data
) = V_VT(value
);
9420 *((unsigned int *)(data
+2)) = mb_len
;
9421 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], mb_len
, NULL
, NULL
);
9422 for (i
= 6 + mb_len
; i
< len
; i
++)
9425 /* TODO: Check if the encoded data is already present in custdata_seg */
9430 FIXME("Argument type not yet handled\n");
9435 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9437 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9439 DWORD offs
= file
->arraydesc_seg
.len
;
9443 /* TODO: we should check for duplicates, but that's harder because each
9444 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9445 * at the library-level) */
9447 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9448 file
->arraydesc_seg
.data
= realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9449 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9451 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9452 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9453 for(i
= 0; i
< desc
->cDims
; ++i
){
9454 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9455 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9461 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9467 VARTYPE vt
, subtype
;
9478 vt
= desc
->vt
& VT_TYPEMASK
;
9480 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9482 encoded
[1] = WMSFT_append_typedesc(desc
->lptdesc
, file
, &mix
, out_size
);
9483 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9485 *out_size
+= 2 * sizeof(DWORD
);
9486 }else if(vt
== VT_CARRAY
){
9487 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9488 encoded
[1] = WMSFT_append_arraydesc(desc
->lpadesc
, file
);
9490 }else if(vt
== VT_USERDEFINED
){
9491 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9492 encoded
[1] = desc
->hreftype
;
9493 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9495 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9513 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9516 data
= file
->typdesc_seg
.data
;
9517 while(offs
< file
->typdesc_seg
.len
){
9518 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9520 offs
+= sizeof(encoded
);
9523 file
->typdesc_seg
.len
+= sizeof(encoded
);
9524 data
= file
->typdesc_seg
.data
= realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9526 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9531 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9533 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9534 DWORD ret
= cdguids_seg
->len
, offs
;
9535 MSFT_CDGuid
*cdguid
;
9538 if(list_empty(custdata_list
))
9541 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9542 cdguids_seg
->data
= realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9543 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9545 offs
= ret
+ sizeof(MSFT_CDGuid
);
9546 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9547 cdguid
->GuidOffset
= cd
->guid
->offset
;
9548 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9549 cdguid
->next
= offs
;
9550 offs
+= sizeof(MSFT_CDGuid
);
9560 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9561 WMSFT_TLBFile
*file
)
9563 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9564 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9565 MSFT_VarRecord
*varrecord
;
9566 MSFT_FuncRecord
*funcrecord
;
9568 DWORD
*name
, *offsets
, offs
;
9570 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9571 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9573 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9575 /* optional fields */
9576 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9577 if(!list_empty(&desc
->custdata_list
))
9578 recorded_size
+= 7 * sizeof(INT
);
9579 else if(desc
->HelpStringContext
!= 0)
9580 recorded_size
+= 6 * sizeof(INT
);
9582 else if(desc
->Entry
)
9583 recorded_size
+= 3 * sizeof(INT
);
9584 else if(desc
->HelpString
)
9585 recorded_size
+= 2 * sizeof(INT
);
9586 else if(desc
->helpcontext
)
9587 recorded_size
+= sizeof(INT
);
9589 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9591 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9592 if(desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9593 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9598 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9601 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9602 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9604 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9606 /* optional fields */
9607 if(desc
->HelpStringContext
!= 0)
9608 recorded_size
+= 5 * sizeof(INT
);
9609 else if(!list_empty(&desc
->custdata_list
))
9610 recorded_size
+= 4 * sizeof(INT
);
9612 else if(desc
->HelpString
)
9613 recorded_size
+= 2 * sizeof(INT
);
9614 else if(desc
->HelpContext
!= 0)
9615 recorded_size
+= sizeof(INT
);
9617 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9620 if(!recorded_size
&& !extra_size
)
9623 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9625 aux_seg
->len
+= recorded_size
+ extra_size
;
9627 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9629 aux_seg
->data
= realloc(aux_seg
->data
, aux_seg
->len
);
9631 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9633 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9636 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9637 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9638 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9639 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9641 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9642 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9643 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9644 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9647 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9652 * ^has_param_defaults
9653 * ^oEntry_is_intresource
9655 funcrecord
->FKCCIC
=
9656 desc
->funcdesc
.funckind
|
9657 (desc
->funcdesc
.invkind
<< 3) |
9658 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9659 (desc
->funcdesc
.callconv
<< 8);
9661 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9662 funcrecord
->FKCCIC
|= 0x2000;
9664 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9665 if(desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9666 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9667 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9670 if(paramdefault_size
> 0)
9671 funcrecord
->FKCCIC
|= 0x1000;
9673 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9674 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9676 /* optional fields */
9678 if(!list_empty(&desc
->custdata_list
)){
9679 size
+= 7 * sizeof(INT
);
9680 funcrecord
->HelpContext
= desc
->helpcontext
;
9681 if(desc
->HelpString
)
9682 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9684 funcrecord
->oHelpString
= -1;
9686 funcrecord
->oEntry
= -1;
9687 else if(IS_INTRESOURCE(desc
->Entry
))
9688 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9690 funcrecord
->oEntry
= desc
->Entry
->offset
;
9691 funcrecord
->res9
= -1;
9692 funcrecord
->resA
= -1;
9693 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9694 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9695 }else if(desc
->HelpStringContext
!= 0){
9696 size
+= 6 * sizeof(INT
);
9697 funcrecord
->HelpContext
= desc
->helpcontext
;
9698 if(desc
->HelpString
)
9699 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9701 funcrecord
->oHelpString
= -1;
9703 funcrecord
->oEntry
= -1;
9704 else if(IS_INTRESOURCE(desc
->Entry
))
9705 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9707 funcrecord
->oEntry
= desc
->Entry
->offset
;
9708 funcrecord
->res9
= -1;
9709 funcrecord
->resA
= -1;
9710 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9711 }else if(desc
->Entry
){
9712 size
+= 3 * sizeof(INT
);
9713 funcrecord
->HelpContext
= desc
->helpcontext
;
9714 if(desc
->HelpString
)
9715 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9717 funcrecord
->oHelpString
= -1;
9719 funcrecord
->oEntry
= -1;
9720 else if(IS_INTRESOURCE(desc
->Entry
))
9721 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9723 funcrecord
->oEntry
= desc
->Entry
->offset
;
9724 }else if(desc
->HelpString
){
9725 size
+= 2 * sizeof(INT
);
9726 funcrecord
->HelpContext
= desc
->helpcontext
;
9727 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9728 }else if(desc
->helpcontext
){
9729 size
+= sizeof(INT
);
9730 funcrecord
->HelpContext
= desc
->helpcontext
;
9733 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9734 size
+= paramdefault_size
;
9736 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9737 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9739 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9740 if(desc
->pParamDesc
[j
].Name
)
9741 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9744 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
;
9746 if(paramdefault_size
){
9747 if(desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9748 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].paramdesc
.pparamdescex
->varDefaultValue
, file
);
9749 else if(paramdefault_size
)
9754 size
+= sizeof(MSFT_ParameterInfo
);
9757 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9763 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9766 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9767 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9768 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9769 DWORD size
= 5 * sizeof(INT
);
9771 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9772 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9773 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9774 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9776 if(desc
->vardesc
.varkind
== VAR_CONST
){
9777 varrecord
->vardescsize
+= sizeof(VARIANT
);
9778 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.lpvarValue
, file
);
9780 varrecord
->OffsValue
= desc
->vardesc
.oInst
;
9783 if(desc
->HelpStringContext
!= 0){
9784 size
+= 5 * sizeof(INT
);
9785 varrecord
->HelpContext
= desc
->HelpContext
;
9786 if(desc
->HelpString
)
9787 varrecord
->HelpString
= desc
->HelpString
->offset
;
9789 varrecord
->HelpString
= -1;
9790 varrecord
->res9
= -1;
9791 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9792 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9793 }else if(!list_empty(&desc
->custdata_list
)){
9794 size
+= 4 * sizeof(INT
);
9795 varrecord
->HelpContext
= desc
->HelpContext
;
9796 if(desc
->HelpString
)
9797 varrecord
->HelpString
= desc
->HelpString
->offset
;
9799 varrecord
->HelpString
= -1;
9800 varrecord
->res9
= -1;
9801 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9802 }else if(desc
->HelpString
){
9803 size
+= 2 * sizeof(INT
);
9804 varrecord
->HelpContext
= desc
->HelpContext
;
9805 if(desc
->HelpString
)
9806 varrecord
->HelpString
= desc
->HelpString
->offset
;
9808 varrecord
->HelpString
= -1;
9809 }else if(desc
->HelpContext
!= 0){
9810 size
+= sizeof(INT
);
9811 varrecord
->HelpContext
= desc
->HelpContext
;
9814 varrecord
->Info
= size
| (i
<< 16);
9820 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9823 memid
= (MEMBERID
*)varrecord
;
9824 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9825 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9826 *memid
= desc
->funcdesc
.memid
;
9829 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9830 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9831 *memid
= desc
->vardesc
.memid
;
9835 name
= (DWORD
*)memid
;
9836 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9837 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9839 *name
= desc
->Name
->offset
;
9844 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9845 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9847 *name
= desc
->Name
->offset
;
9856 typedef struct tagWMSFT_RefChunk
{
9863 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9865 DWORD offs
= file
->ref_seg
.len
, i
;
9866 WMSFT_RefChunk
*chunk
;
9868 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9869 file
->ref_seg
.data
= realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9871 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9873 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9874 chunk
->href
= info
->impltypes
[i
].hRef
;
9875 chunk
->res04
= info
->impltypes
[i
].implflags
;
9877 if(i
< info
->typeattr
.cImplTypes
- 1)
9878 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9887 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9891 size
= sizeof(MSFT_TypeInfoBase
);
9894 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9895 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9896 base
->typekind
= TKIND_DISPATCH
;
9898 base
->typekind
= info
->typeattr
.typekind
;
9899 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9900 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9901 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9906 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9912 base
->posguid
= info
->guid
->offset
;
9915 base
->flags
= info
->typeattr
.wTypeFlags
;
9917 base
->NameOffset
= info
->Name
->offset
;
9919 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9920 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9922 base
->NameOffset
= -1;
9924 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9926 base
->docstringoffs
= info
->DocString
->offset
;
9928 base
->docstringoffs
= -1;
9929 base
->helpstringcontext
= info
->dwHelpStringContext
;
9930 base
->helpcontext
= info
->dwHelpContext
;
9931 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9932 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9933 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9934 base
->size
= info
->typeattr
.cbSizeInstance
;
9935 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9936 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9937 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9938 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9939 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9941 base
->datatype1
= info
->DllName
->offset
;
9943 base
->datatype1
= -1;
9945 if(info
->typeattr
.cImplTypes
> 0)
9946 base
->datatype1
= info
->impltypes
[0].hRef
;
9948 base
->datatype1
= -1;
9950 base
->datatype2
= index
; /* FIXME: i think there's more here */
9958 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9962 file
->typeinfo_seg
.len
= 0;
9963 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9964 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9965 *junk
= file
->typeinfo_seg
.len
;
9967 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9970 file
->typeinfo_seg
.data
= malloc(file
->typeinfo_seg
.len
);
9971 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9973 file
->aux_seg
.len
= 0;
9974 file
->aux_seg
.data
= NULL
;
9976 file
->typeinfo_seg
.len
= 0;
9977 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9978 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9979 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9980 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9984 typedef struct tagWMSFT_ImpFile
{
9990 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9993 WMSFT_ImpFile
*impfile
;
9995 DWORD last_offs
= 0;
9997 file
->impfile_seg
.len
= 0;
9998 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10002 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10006 path
= implib
->name
;
10007 size
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
), NULL
, 0, NULL
, NULL
);
10009 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10012 size
+= sizeof(INT16
);
10014 size
= (size
+ 4) & ~0x3;
10018 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
10021 data
= file
->impfile_seg
.data
= malloc(file
->impfile_seg
.len
);
10023 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10024 int strlen
= 0, size
;
10026 impfile
= (WMSFT_ImpFile
*)data
;
10027 impfile
->guid_offs
= implib
->guid
->offset
;
10028 impfile
->lcid
= implib
->lcid
;
10029 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
10031 data
+= sizeof(WMSFT_ImpFile
);
10034 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10038 path
= implib
->name
;
10039 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
),
10040 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
10042 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10045 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
10047 size
= strlen
+ sizeof(INT16
);
10049 size
= (size
+ 4) & ~0x3;
10052 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
10055 implib
->offset
= last_offs
;
10056 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
10060 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10062 MSFT_ImpInfo
*info
;
10063 TLBRefType
*ref_type
;
10066 WMSFT_compile_impfile(This
, file
);
10068 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
10069 info
= file
->impinfo_seg
.data
= malloc(file
->impinfo_seg
.len
);
10071 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10072 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10073 if(ref_type
->index
== TLB_REF_USE_GUID
){
10074 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10075 info
->oGuid
= ref_type
->guid
->offset
;
10077 info
->oGuid
= ref_type
->index
;
10078 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10084 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10086 file
->guidhash_seg
.len
= 0x80;
10087 file
->guidhash_seg
.data
= malloc(file
->guidhash_seg
.len
);
10088 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10091 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10093 file
->namehash_seg
.len
= 0x200;
10094 file
->namehash_seg
.data
= malloc(file
->namehash_seg
.len
);
10095 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10098 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10100 if(contents
&& contents
->len
){
10101 segdir
->offset
= *running_offset
;
10102 segdir
->length
= contents
->len
;
10103 *running_offset
+= segdir
->length
;
10105 segdir
->offset
= -1;
10106 segdir
->length
= 0;
10109 /* TODO: do these ever change? */
10110 segdir
->res08
= -1;
10111 segdir
->res0c
= 0xf;
10114 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10118 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10121 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10125 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10127 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10128 base
->memoffset
+= file_len
;
10135 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10137 free(file
->typeinfo_seg
.data
);
10138 free(file
->guidhash_seg
.data
);
10139 free(file
->guid_seg
.data
);
10140 free(file
->ref_seg
.data
);
10141 free(file
->impinfo_seg
.data
);
10142 free(file
->impfile_seg
.data
);
10143 free(file
->namehash_seg
.data
);
10144 free(file
->name_seg
.data
);
10145 free(file
->string_seg
.data
);
10146 free(file
->typdesc_seg
.data
);
10147 free(file
->arraydesc_seg
.data
);
10148 free(file
->custdata_seg
.data
);
10149 free(file
->cdguids_seg
.data
);
10150 free(file
->aux_seg
.data
);
10153 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10155 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10156 WMSFT_TLBFile file
;
10157 DWORD written
, junk_size
, junk_offs
, running_offset
;
10164 TRACE("%p\n", This
);
10166 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10167 if(This
->typeinfos
[i
]->needs_layout
)
10168 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10170 memset(&file
, 0, sizeof(file
));
10172 file
.header
.magic1
= 0x5446534D;
10173 file
.header
.magic2
= 0x00010002;
10174 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10175 file
.header
.lcid2
= This
->set_lcid
;
10176 file
.header
.varflags
= 0x40 | This
->syskind
;
10177 if (This
->HelpFile
)
10178 file
.header
.varflags
|= 0x10;
10179 if (This
->HelpStringDll
)
10180 file
.header
.varflags
|= HELPDLLFLAG
;
10181 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10182 file
.header
.flags
= This
->libflags
;
10183 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10184 file
.header
.helpcontext
= This
->dwHelpContext
;
10185 file
.header
.res44
= 0x20;
10186 file
.header
.res48
= 0x80;
10187 file
.header
.dispatchpos
= This
->dispatch_href
;
10189 WMSFT_compile_namehash(This
, &file
);
10190 /* do name and string compilation to get offsets for other compilations */
10191 hres
= WMSFT_compile_names(This
, &file
);
10193 WMSFT_free_file(&file
);
10197 hres
= WMSFT_compile_strings(This
, &file
);
10199 WMSFT_free_file(&file
);
10203 WMSFT_compile_guidhash(This
, &file
);
10204 hres
= WMSFT_compile_guids(This
, &file
);
10206 WMSFT_free_file(&file
);
10211 file
.header
.helpfile
= This
->HelpFile
->offset
;
10213 file
.header
.helpfile
= -1;
10215 if(This
->DocString
)
10216 file
.header
.helpstring
= This
->DocString
->offset
;
10218 file
.header
.helpstring
= -1;
10220 /* do some more segment compilation */
10221 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10222 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10225 file
.header
.NameOffset
= This
->Name
->offset
;
10227 file
.header
.NameOffset
= -1;
10229 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10232 file
.header
.posguid
= This
->guid
->offset
;
10234 file
.header
.posguid
= -1;
10236 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10237 if(file
.header
.varflags
& HELPDLLFLAG
)
10238 junk_size
+= sizeof(DWORD
);
10240 junk
= calloc(1, junk_size
);
10241 if(file
.header
.varflags
& HELPDLLFLAG
){
10242 *junk
= This
->HelpStringDll
->offset
;
10251 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10252 WMSFT_compile_impinfo(This
, &file
);
10254 running_offset
= 0;
10256 TRACE("header at: 0x%lx\n", running_offset
);
10257 running_offset
+= sizeof(file
.header
);
10259 TRACE("junk at: 0x%lx\n", running_offset
);
10260 running_offset
+= junk_size
;
10262 TRACE("segdir at: 0x%lx\n", running_offset
);
10263 running_offset
+= sizeof(file
.segdir
);
10265 TRACE("typeinfo at: 0x%lx\n", running_offset
);
10266 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10268 TRACE("guidhashtab at: 0x%lx\n", running_offset
);
10269 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10271 TRACE("guidtab at: 0x%lx\n", running_offset
);
10272 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10274 TRACE("reftab at: 0x%lx\n", running_offset
);
10275 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10277 TRACE("impinfo at: 0x%lx\n", running_offset
);
10278 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10280 TRACE("impfiles at: 0x%lx\n", running_offset
);
10281 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10283 TRACE("namehashtab at: 0x%lx\n", running_offset
);
10284 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10286 TRACE("nametab at: 0x%lx\n", running_offset
);
10287 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10289 TRACE("stringtab at: 0x%lx\n", running_offset
);
10290 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10292 TRACE("typdesc at: 0x%lx\n", running_offset
);
10293 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10295 TRACE("arraydescriptions at: 0x%lx\n", running_offset
);
10296 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10298 TRACE("custdata at: 0x%lx\n", running_offset
);
10299 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10301 TRACE("cdguids at: 0x%lx\n", running_offset
);
10302 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10304 TRACE("res0e at: 0x%lx\n", running_offset
);
10305 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10307 TRACE("res0f at: 0x%lx\n", running_offset
);
10308 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10310 TRACE("aux_seg at: 0x%lx\n", running_offset
);
10312 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10314 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10315 FILE_ATTRIBUTE_NORMAL
, 0);
10316 if (outfile
== INVALID_HANDLE_VALUE
){
10317 WMSFT_free_file(&file
);
10319 return TYPE_E_IOERROR
;
10322 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10324 WMSFT_free_file(&file
);
10325 CloseHandle(outfile
);
10327 return TYPE_E_IOERROR
;
10330 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10333 WMSFT_free_file(&file
);
10334 CloseHandle(outfile
);
10335 return TYPE_E_IOERROR
;
10338 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10340 WMSFT_free_file(&file
);
10341 CloseHandle(outfile
);
10342 return TYPE_E_IOERROR
;
10345 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10346 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10347 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10348 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10349 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10350 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10351 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10352 WMSFT_write_segment(outfile
, &file
.name_seg
);
10353 WMSFT_write_segment(outfile
, &file
.string_seg
);
10354 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10355 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10356 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10357 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10358 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10360 WMSFT_free_file(&file
);
10362 CloseHandle(outfile
);
10367 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10370 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10371 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10375 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10376 REFGUID guid
, VARIANT
*varVal
)
10378 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10381 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10383 if (!guid
|| !varVal
)
10384 return E_INVALIDARG
;
10386 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10388 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10391 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10392 ULONG helpStringContext
)
10394 FIXME("%p, %lu - stub\n", iface
, helpStringContext
);
10398 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10401 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10402 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10405 return E_INVALIDARG
;
10407 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10412 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10413 ICreateTypeLib2_fnQueryInterface
,
10414 ICreateTypeLib2_fnAddRef
,
10415 ICreateTypeLib2_fnRelease
,
10416 ICreateTypeLib2_fnCreateTypeInfo
,
10417 ICreateTypeLib2_fnSetName
,
10418 ICreateTypeLib2_fnSetVersion
,
10419 ICreateTypeLib2_fnSetGuid
,
10420 ICreateTypeLib2_fnSetDocString
,
10421 ICreateTypeLib2_fnSetHelpFileName
,
10422 ICreateTypeLib2_fnSetHelpContext
,
10423 ICreateTypeLib2_fnSetLcid
,
10424 ICreateTypeLib2_fnSetLibFlags
,
10425 ICreateTypeLib2_fnSaveAllChanges
,
10426 ICreateTypeLib2_fnDeleteTypeInfo
,
10427 ICreateTypeLib2_fnSetCustData
,
10428 ICreateTypeLib2_fnSetHelpStringContext
,
10429 ICreateTypeLib2_fnSetHelpStringDll
10432 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10433 REFIID riid
, void **object
)
10435 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10437 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10440 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10442 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10444 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10447 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10449 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10451 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10454 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10457 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10459 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10461 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10466 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10469 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10473 TRACE("%p %x\n", This
, typeFlags
);
10475 if (typeFlags
& TYPEFLAG_FDUAL
) {
10477 ITypeInfo
*dispatch
;
10481 hres
= LoadTypeLib(L
"stdole2.tlb", &stdole
);
10485 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10486 ITypeLib_Release(stdole
);
10490 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10491 ITypeInfo_Release(dispatch
);
10496 old_flags
= This
->typeattr
.wTypeFlags
;
10497 This
->typeattr
.wTypeFlags
= typeFlags
;
10499 hres
= ICreateTypeInfo2_LayOut(iface
);
10500 if (FAILED(hres
)) {
10501 This
->typeattr
.wTypeFlags
= old_flags
;
10508 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10511 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10513 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10516 return E_INVALIDARG
;
10518 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10523 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10526 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10528 TRACE("%p, %ld.\n", iface
, helpContext
);
10530 This
->dwHelpContext
= helpContext
;
10535 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10536 WORD majorVerNum
, WORD minorVerNum
)
10538 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10540 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10542 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10543 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10548 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10549 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10551 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10553 ITypeLib
*container
;
10554 TLBRefType
*ref_type
;
10556 TYPEATTR
*typeattr
;
10560 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10562 if (!typeInfo
|| !refType
)
10563 return E_INVALIDARG
;
10565 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10569 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10570 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10572 ITypeLib_Release(container
);
10574 *refType
= target
->hreftype
;
10579 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10580 if (FAILED(hres
)) {
10581 ITypeLib_Release(container
);
10585 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10586 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10587 implib
->lcid
== libattr
->lcid
&&
10588 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10589 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10593 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10594 implib
= calloc(1, sizeof(TLBImpLib
));
10596 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10597 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10598 implib
->name
= SysAllocString(our_container
->path
);
10600 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10601 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10603 implib
->name
= NULL
;
10604 TRACE("QueryPathOfRegTypeLib failed, no name stored: %#lx.\n", hres
);
10608 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10609 implib
->lcid
= libattr
->lcid
;
10610 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10611 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10613 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10616 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10617 ITypeLib_Release(container
);
10619 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10624 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10625 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10626 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10627 ref_type
->tkind
== typeattr
->typekind
)
10632 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10633 ref_type
= calloc(1, sizeof(TLBRefType
));
10635 ref_type
->tkind
= typeattr
->typekind
;
10636 ref_type
->pImpTLInfo
= implib
;
10637 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10639 ref_type
->index
= TLB_REF_USE_GUID
;
10641 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10643 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10646 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10648 *refType
= ref_type
->reference
| 0x1;
10650 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10651 This
->pTypeLib
->dispatch_href
= *refType
;
10656 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10657 UINT index
, FUNCDESC
*funcDesc
)
10659 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10660 TLBFuncDesc tmp_func_desc
, *func_desc
;
10665 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10667 if (!funcDesc
|| funcDesc
->oVft
& 3)
10668 return E_INVALIDARG
;
10670 switch (This
->typeattr
.typekind
) {
10672 if (funcDesc
->funckind
!= FUNC_STATIC
)
10673 return TYPE_E_BADMODULEKIND
;
10675 case TKIND_DISPATCH
:
10676 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10677 return TYPE_E_BADMODULEKIND
;
10680 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10681 return TYPE_E_BADMODULEKIND
;
10684 if (index
> This
->typeattr
.cFuncs
)
10685 return TYPE_E_ELEMENTNOTFOUND
;
10687 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10688 !funcDesc
->cParams
)
10689 return TYPE_E_INCONSISTENTPROPFUNCS
;
10692 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10693 funcDesc
->oVft
% 8 != 0)
10694 return E_INVALIDARG
;
10697 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10698 TLBFuncDesc_Constructor(&tmp_func_desc
);
10700 tmp_func_desc
.funcdesc
= *funcDesc
;
10702 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10703 tmp_func_desc
.funcdesc
.oVft
|= 1;
10705 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10706 tmp_func_desc
.funcdesc
.lprgscode
= malloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10707 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10709 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10710 tmp_func_desc
.funcdesc
.cScodes
= 0;
10713 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10714 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10715 buf_size
+= sizeof(ELEMDESC
);
10716 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10718 tmp_func_desc
.funcdesc
.lprgelemdescParam
= malloc(buf_size
);
10719 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10721 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10722 if (FAILED(hres
)) {
10723 free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10724 free(tmp_func_desc
.funcdesc
.lprgscode
);
10728 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10729 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10730 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10731 if (FAILED(hres
)) {
10732 free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10733 free(tmp_func_desc
.funcdesc
.lprgscode
);
10736 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10737 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10738 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10739 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].paramdesc
.pparamdescex
->varDefaultValue
);
10740 if (FAILED(hres
)) {
10741 free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10742 free(tmp_func_desc
.funcdesc
.lprgscode
);
10748 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10750 if (This
->funcdescs
) {
10751 This
->funcdescs
= realloc(This
->funcdescs
, sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10753 if (index
< This
->typeattr
.cFuncs
) {
10754 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10755 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10756 func_desc
= This
->funcdescs
+ index
;
10758 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10760 /* move custdata lists to the new memory location */
10761 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10763 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
10766 func_desc
= This
->funcdescs
= malloc(sizeof(TLBFuncDesc
));
10768 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10769 list_init(&func_desc
->custdata_list
);
10771 ++This
->typeattr
.cFuncs
;
10773 This
->needs_layout
= TRUE
;
10778 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10779 UINT index
, HREFTYPE refType
)
10781 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10782 TLBImplType
*impl_type
;
10785 TRACE("%p, %u, %ld.\n", iface
, index
, refType
);
10787 switch(This
->typeattr
.typekind
){
10788 case TKIND_COCLASS
: {
10790 FIXME("Unhandled index: -1\n");
10794 if(index
!= This
->typeattr
.cImplTypes
)
10795 return TYPE_E_ELEMENTNOTFOUND
;
10799 case TKIND_INTERFACE
:
10800 case TKIND_DISPATCH
:
10801 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10802 return TYPE_E_ELEMENTNOTFOUND
;
10805 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10809 if (This
->impltypes
){
10812 This
->impltypes
= realloc(This
->impltypes
, sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10814 if (index
< This
->typeattr
.cImplTypes
) {
10815 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10816 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10817 impl_type
= This
->impltypes
+ index
;
10819 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10821 /* move custdata lists to the new memory location */
10822 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10824 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
10827 impl_type
= This
->impltypes
= malloc(sizeof(TLBImplType
));
10829 memset(impl_type
, 0, sizeof(TLBImplType
));
10830 TLBImplType_Constructor(impl_type
);
10831 impl_type
->hRef
= refType
;
10833 ++This
->typeattr
.cImplTypes
;
10835 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10836 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10838 hres
= ICreateTypeInfo2_LayOut(iface
);
10845 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10846 UINT index
, INT implTypeFlags
)
10848 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10849 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10851 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10853 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10854 return TYPE_E_BADMODULEKIND
;
10856 if (index
>= This
->typeattr
.cImplTypes
)
10857 return TYPE_E_ELEMENTNOTFOUND
;
10859 impl_type
->implflags
= implTypeFlags
;
10864 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10867 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10869 TRACE("%p %d\n", This
, alignment
);
10871 This
->typeattr
.cbAlignment
= alignment
;
10876 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10879 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10881 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10884 return E_INVALIDARG
;
10886 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10888 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10893 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10894 UINT index
, VARDESC
*varDesc
)
10896 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10897 TLBVarDesc
*var_desc
;
10900 TRACE("%p %u %p\n", This
, index
, varDesc
);
10902 if (This
->vardescs
){
10905 This
->vardescs
= realloc(This
->vardescs
, sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10907 if (index
< This
->typeattr
.cVars
) {
10908 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10909 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10910 var_desc
= This
->vardescs
+ index
;
10912 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10913 memset(var_desc
, 0, sizeof(TLBVarDesc
));
10916 /* move custdata lists to the new memory location */
10917 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10919 TLB_relink_custdata(&This
->vardescs
[i
].custdata_list
);
10922 var_desc
= This
->vardescs
= calloc(1, sizeof(TLBVarDesc
));
10924 TLBVarDesc_Constructor(var_desc
);
10925 hr
= TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10928 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10930 ++This
->typeattr
.cVars
;
10932 This
->needs_layout
= TRUE
;
10937 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10938 UINT index
, LPOLESTR
*names
, UINT numNames
)
10940 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10941 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10944 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10947 return E_INVALIDARG
;
10949 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10950 return TYPE_E_ELEMENTNOTFOUND
;
10952 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10953 if(numNames
> func_desc
->funcdesc
.cParams
)
10954 return TYPE_E_ELEMENTNOTFOUND
;
10956 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10957 return TYPE_E_ELEMENTNOTFOUND
;
10959 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10960 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10961 if (iter
->Name
&& !wcscmp(TLB_get_bstr(iter
->Name
), *names
)) {
10962 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10963 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10964 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10966 return TYPE_E_AMBIGUOUSNAME
;
10970 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10972 for (i
= 1; i
< numNames
; ++i
) {
10973 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10974 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10980 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10981 UINT index
, LPOLESTR name
)
10983 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10985 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10988 return E_INVALIDARG
;
10990 if(index
>= This
->typeattr
.cVars
)
10991 return TYPE_E_ELEMENTNOTFOUND
;
10993 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10997 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10998 TYPEDESC
*tdescAlias
)
11000 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11003 TRACE("%p %p\n", This
, tdescAlias
);
11006 return E_INVALIDARG
;
11008 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
11009 return TYPE_E_BADMODULEKIND
;
11011 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
11015 free(This
->tdescAlias
);
11016 This
->tdescAlias
= malloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
11017 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
11022 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
11023 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
11025 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11026 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
11030 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
11031 UINT index
, LPOLESTR docString
)
11033 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11034 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11036 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11039 return E_INVALIDARG
;
11041 if(index
>= This
->typeattr
.cFuncs
)
11042 return TYPE_E_ELEMENTNOTFOUND
;
11044 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11049 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11050 UINT index
, LPOLESTR docString
)
11052 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11053 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11055 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11058 return E_INVALIDARG
;
11060 if(index
>= This
->typeattr
.cVars
)
11061 return TYPE_E_ELEMENTNOTFOUND
;
11063 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11068 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11069 UINT index
, DWORD helpContext
)
11071 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11072 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11074 TRACE("%p, %u, %ld.\n", iface
, index
, helpContext
);
11076 if(index
>= This
->typeattr
.cFuncs
)
11077 return TYPE_E_ELEMENTNOTFOUND
;
11079 func_desc
->helpcontext
= helpContext
;
11084 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11085 UINT index
, DWORD helpContext
)
11087 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11088 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11090 TRACE("%p, %u, %ld.\n", iface
, index
, helpContext
);
11092 if(index
>= This
->typeattr
.cVars
)
11093 return TYPE_E_ELEMENTNOTFOUND
;
11095 var_desc
->HelpContext
= helpContext
;
11100 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11101 UINT index
, BSTR bstrMops
)
11103 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11104 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11108 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11111 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11113 TRACE("%p %p\n", This
, idlDesc
);
11116 return E_INVALIDARG
;
11118 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11119 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11124 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11126 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11127 ITypeInfo2
*tinfo
= &This
->ITypeInfo2_iface
;
11128 TLBFuncDesc
*func_desc
;
11129 UINT user_vft
= 0, i
, depth
= 0;
11130 HRESULT hres
= S_OK
;
11132 TRACE("%p\n", This
);
11134 This
->needs_layout
= FALSE
;
11136 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11141 hres
= ITypeInfo2_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11143 if (SUCCEEDED(hres
)) {
11144 hres
= ITypeInfo2_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11146 if (SUCCEEDED(hres
)) {
11147 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11148 if (FAILED(hres
)) {
11149 ITypeInfo_Release(inh
);
11152 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11153 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11157 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11158 if(SUCCEEDED(hres
)){
11160 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11161 if(SUCCEEDED(hres
)){
11162 ITypeInfo_Release(inh
);
11166 }while(SUCCEEDED(hres
));
11169 ITypeInfo_Release(inh
);
11170 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11171 This
->typeattr
.cbSizeVft
= 0;
11175 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11176 This
->typeattr
.cbSizeVft
= 0;
11180 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11181 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11183 This
->typeattr
.cbSizeVft
= 0;
11185 func_desc
= This
->funcdescs
;
11187 while (i
< This
->typeattr
.cFuncs
) {
11188 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11189 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11191 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11192 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11194 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11196 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11199 BOOL reset
= FALSE
;
11201 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11203 iter
= This
->funcdescs
;
11204 while (j
< This
->typeattr
.cFuncs
) {
11205 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11207 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11210 ++func_desc
->funcdesc
.memid
;
11211 iter
= This
->funcdescs
;
11224 if (user_vft
> This
->typeattr
.cbSizeVft
)
11225 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11227 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11228 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11229 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11231 BOOL reset
= FALSE
;
11234 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11236 iter
= This
->vardescs
;
11237 while (j
< This
->typeattr
.cVars
) {
11238 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11240 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11243 ++var_desc
->vardesc
.memid
;
11244 iter
= This
->vardescs
;
11257 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11260 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11263 TRACE("%p %u\n", This
, index
);
11265 if (index
>= This
->typeattr
.cFuncs
)
11266 return TYPE_E_ELEMENTNOTFOUND
;
11268 typeinfo_release_funcdesc(&This
->funcdescs
[index
]);
11270 --This
->typeattr
.cFuncs
;
11271 if (index
!= This
->typeattr
.cFuncs
)
11273 memmove(This
->funcdescs
+ index
, This
->funcdescs
+ index
+ 1,
11274 sizeof(*This
->funcdescs
) * (This
->typeattr
.cFuncs
- index
));
11275 for (i
= index
; i
< This
->typeattr
.cFuncs
; ++i
)
11276 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
11279 This
->needs_layout
= TRUE
;
11284 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11285 MEMBERID memid
, INVOKEKIND invKind
)
11287 FIXME("%p, %#lx, %d - stub\n", iface
, memid
, invKind
);
11291 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11294 FIXME("%p, %u - stub\n", iface
, index
);
11298 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11301 FIXME("%p, %#lx - stub\n", iface
, memid
);
11305 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11308 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11311 TRACE("%p %u\n", This
, index
);
11313 if (index
>= This
->typeattr
.cImplTypes
)
11314 return TYPE_E_ELEMENTNOTFOUND
;
11316 TLB_FreeCustData(&This
->impltypes
[index
].custdata_list
);
11317 --This
->typeattr
.cImplTypes
;
11319 if (index
< This
->typeattr
.cImplTypes
)
11321 memmove(This
->impltypes
+ index
, This
->impltypes
+ index
+ 1, (This
->typeattr
.cImplTypes
- index
) *
11322 sizeof(*This
->impltypes
));
11323 for (i
= index
; i
< This
->typeattr
.cImplTypes
; ++i
)
11324 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
11330 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11331 REFGUID guid
, VARIANT
*varVal
)
11335 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11337 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11339 if (!guid
|| !varVal
)
11340 return E_INVALIDARG
;
11342 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11344 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11347 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11348 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11350 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11351 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11355 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11356 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11358 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11359 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11363 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11364 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11366 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11367 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11371 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11372 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11374 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11375 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11379 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11380 ULONG helpStringContext
)
11382 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11384 TRACE("%p, %lu.\n", iface
, helpStringContext
);
11386 This
->dwHelpStringContext
= helpStringContext
;
11391 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11392 UINT index
, ULONG helpStringContext
)
11394 FIXME("%p, %u, %lu - stub\n", iface
, index
, helpStringContext
);
11398 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11399 UINT index
, ULONG helpStringContext
)
11401 FIXME("%p, %u, %lu - stub\n", iface
, index
, helpStringContext
);
11405 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11407 FIXME("%p - stub\n", iface
);
11411 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11414 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11416 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11419 return E_INVALIDARG
;
11421 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11426 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11427 ICreateTypeInfo2_fnQueryInterface
,
11428 ICreateTypeInfo2_fnAddRef
,
11429 ICreateTypeInfo2_fnRelease
,
11430 ICreateTypeInfo2_fnSetGuid
,
11431 ICreateTypeInfo2_fnSetTypeFlags
,
11432 ICreateTypeInfo2_fnSetDocString
,
11433 ICreateTypeInfo2_fnSetHelpContext
,
11434 ICreateTypeInfo2_fnSetVersion
,
11435 ICreateTypeInfo2_fnAddRefTypeInfo
,
11436 ICreateTypeInfo2_fnAddFuncDesc
,
11437 ICreateTypeInfo2_fnAddImplType
,
11438 ICreateTypeInfo2_fnSetImplTypeFlags
,
11439 ICreateTypeInfo2_fnSetAlignment
,
11440 ICreateTypeInfo2_fnSetSchema
,
11441 ICreateTypeInfo2_fnAddVarDesc
,
11442 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11443 ICreateTypeInfo2_fnSetVarName
,
11444 ICreateTypeInfo2_fnSetTypeDescAlias
,
11445 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11446 ICreateTypeInfo2_fnSetFuncDocString
,
11447 ICreateTypeInfo2_fnSetVarDocString
,
11448 ICreateTypeInfo2_fnSetFuncHelpContext
,
11449 ICreateTypeInfo2_fnSetVarHelpContext
,
11450 ICreateTypeInfo2_fnSetMops
,
11451 ICreateTypeInfo2_fnSetTypeIdldesc
,
11452 ICreateTypeInfo2_fnLayOut
,
11453 ICreateTypeInfo2_fnDeleteFuncDesc
,
11454 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11455 ICreateTypeInfo2_fnDeleteVarDesc
,
11456 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11457 ICreateTypeInfo2_fnDeleteImplType
,
11458 ICreateTypeInfo2_fnSetCustData
,
11459 ICreateTypeInfo2_fnSetFuncCustData
,
11460 ICreateTypeInfo2_fnSetParamCustData
,
11461 ICreateTypeInfo2_fnSetVarCustData
,
11462 ICreateTypeInfo2_fnSetImplTypeCustData
,
11463 ICreateTypeInfo2_fnSetHelpStringContext
,
11464 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11465 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11466 ICreateTypeInfo2_fnInvalidate
,
11467 ICreateTypeInfo2_fnSetName
11470 /******************************************************************************
11471 * ClearCustData (OLEAUT32.171)
11473 * Clear a custom data type's data.
11476 * lpCust [I] The custom data type instance
11481 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11483 if (lpCust
&& lpCust
->cCustData
)
11485 if (lpCust
->prgCustData
)
11489 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11490 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11492 CoTaskMemFree(lpCust
->prgCustData
);
11493 lpCust
->prgCustData
= NULL
;
11495 lpCust
->cCustData
= 0;