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
57 #define NONAMELESSUNION
70 #include "wine/debug.h"
73 #include "wine/heap.h"
74 #include "wine/list.h"
76 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
77 WINE_DECLARE_DEBUG_CHANNEL(typelib
);
91 WORD type_id
; /* Type identifier */
92 WORD count
; /* Number of resources of this type */
93 DWORD resloader
; /* SetResourceHandler() */
99 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
);
100 static HRESULT
TLB_AllocAndInitVarDesc(const VARDESC
*src
, VARDESC
**dest_ptr
);
101 static void TLB_FreeVarDesc(VARDESC
*);
103 /****************************************************************************
106 * Takes p_iVal (which is in little endian) and returns it
107 * in the host machine's byte order.
109 #ifdef WORDS_BIGENDIAN
110 static WORD
FromLEWord(WORD p_iVal
)
112 return (((p_iVal
& 0x00FF) << 8) |
113 ((p_iVal
& 0xFF00) >> 8));
117 static DWORD
FromLEDWord(DWORD p_iVal
)
119 return (((p_iVal
& 0x000000FF) << 24) |
120 ((p_iVal
& 0x0000FF00) << 8) |
121 ((p_iVal
& 0x00FF0000) >> 8) |
122 ((p_iVal
& 0xFF000000) >> 24));
125 #define FromLEWord(X) (X)
126 #define FromLEDWord(X) (X)
129 #define DISPATCH_HREF_OFFSET 0x01000000
130 #define DISPATCH_HREF_MASK 0xff000000
132 /****************************************************************************
135 * Fix byte order in any structure if necessary
137 #ifdef WORDS_BIGENDIAN
138 static void FromLEWords(void *p_Val
, int p_iSize
)
142 p_iSize
/= sizeof(WORD
);
145 *Val
= FromLEWord(*Val
);
152 static void FromLEDWords(void *p_Val
, int p_iSize
)
156 p_iSize
/= sizeof(DWORD
);
159 *Val
= FromLEDWord(*Val
);
165 #define FromLEWords(X,Y) /*nothing*/
166 #define FromLEDWords(X,Y) /*nothing*/
170 * Find a typelib key which matches a requested maj.min version.
172 static BOOL
find_typelib_key( REFGUID guid
, WORD
*wMaj
, WORD
*wMin
)
174 static const WCHAR typelibW
[] = {'T','y','p','e','l','i','b','\\',0};
178 INT best_maj
= -1, best_min
= -1;
181 memcpy( buffer
, typelibW
, sizeof(typelibW
) );
182 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
184 if (RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
) != ERROR_SUCCESS
)
187 len
= sizeof(key_name
);
189 while (RegEnumKeyExA(hkey
, i
++, key_name
, &len
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
)
193 if (sscanf(key_name
, "%x.%x", &v_maj
, &v_min
) == 2)
195 TRACE("found %s: %x.%x\n", debugstr_w(buffer
), v_maj
, v_min
);
197 if (*wMaj
== 0xffff && *wMin
== 0xffff)
199 if (v_maj
> best_maj
) best_maj
= v_maj
;
200 if (v_min
> best_min
) best_min
= v_min
;
202 else if (*wMaj
== v_maj
)
209 break; /* exact match */
211 if (*wMin
!= 0xffff && v_min
> best_min
) best_min
= v_min
;
214 len
= sizeof(key_name
);
218 TRACE("found best_maj %d, best_min %d\n", best_maj
, best_min
);
220 if (*wMaj
== 0xffff && *wMin
== 0xffff)
222 if (best_maj
>= 0 && best_min
>= 0)
230 if (*wMaj
== best_maj
&& best_min
>= 0)
238 /* get the path of a typelib key, in the form "Typelib\\<guid>\\<maj>.<min>" */
239 /* buffer must be at least 60 characters long */
240 static WCHAR
*get_typelib_key( REFGUID guid
, WORD wMaj
, WORD wMin
, WCHAR
*buffer
)
242 static const WCHAR TypelibW
[] = {'T','y','p','e','l','i','b','\\',0};
243 static const WCHAR VersionFormatW
[] = {'\\','%','x','.','%','x',0};
245 memcpy( buffer
, TypelibW
, sizeof(TypelibW
) );
246 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
247 swprintf( buffer
+ lstrlenW(buffer
), 20, VersionFormatW
, wMaj
, wMin
);
251 /* get the path of an interface key, in the form "Interface\\<guid>" */
252 /* buffer must be at least 50 characters long */
253 static WCHAR
*get_interface_key( REFGUID guid
, WCHAR
*buffer
)
255 static const WCHAR InterfaceW
[] = {'I','n','t','e','r','f','a','c','e','\\',0};
257 memcpy( buffer
, InterfaceW
, sizeof(InterfaceW
) );
258 StringFromGUID2( guid
, buffer
+ lstrlenW(buffer
), 40 );
262 /* get the lcid subkey for a typelib, in the form "<lcid>\\<syskind>" */
263 /* buffer must be at least 16 characters long */
264 static WCHAR
*get_lcid_subkey( LCID lcid
, SYSKIND syskind
, WCHAR
*buffer
)
266 static const WCHAR LcidFormatW
[] = {'%','l','x','\\',0};
267 static const WCHAR win16W
[] = {'w','i','n','1','6',0};
268 static const WCHAR win32W
[] = {'w','i','n','3','2',0};
269 static const WCHAR win64W
[] = {'w','i','n','6','4',0};
271 swprintf( buffer
, 16, LcidFormatW
, lcid
);
274 case SYS_WIN16
: lstrcatW( buffer
, win16W
); break;
275 case SYS_WIN32
: lstrcatW( buffer
, win32W
); break;
276 case SYS_WIN64
: lstrcatW( buffer
, win64W
); break;
278 TRACE("Typelib is for unsupported syskind %i\n", syskind
);
284 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
);
286 struct tlibredirect_data
300 /* Get the path to a registered type library. Helper for QueryPathOfRegTypeLib. */
301 static HRESULT
query_typelib_path( REFGUID guid
, WORD wMaj
, WORD wMin
,
302 SYSKIND syskind
, LCID lcid
, BSTR
*path
, BOOL redir
)
304 HRESULT hr
= TYPE_E_LIBNOTREGISTERED
;
308 WCHAR Path
[MAX_PATH
];
311 TRACE_(typelib
)("(%s, %x.%x, 0x%x, %p)\n", debugstr_guid(guid
), wMaj
, wMin
, lcid
, path
);
315 ACTCTX_SECTION_KEYED_DATA data
;
317 data
.cbSize
= sizeof(data
);
318 if (FindActCtxSectionGuid( 0, NULL
, ACTIVATION_CONTEXT_SECTION_COM_TYPE_LIBRARY_REDIRECTION
, guid
, &data
))
320 struct tlibredirect_data
*tlib
= (struct tlibredirect_data
*)data
.lpData
;
324 if ((wMaj
!= 0xffff || wMin
!= 0xffff) && (tlib
->major_version
!= wMaj
|| tlib
->minor_version
< wMin
))
325 return TYPE_E_LIBNOTREGISTERED
;
327 nameW
= (WCHAR
*)((BYTE
*)data
.lpSectionBase
+ tlib
->name_offset
);
328 len
= SearchPathW( NULL
, nameW
, NULL
, ARRAY_SIZE( Path
), Path
, NULL
);
329 if (!len
) return TYPE_E_LIBNOTREGISTERED
;
331 TRACE_(typelib
)("got path from context %s\n", debugstr_w(Path
));
332 *path
= SysAllocString( Path
);
337 if (!find_typelib_key( guid
, &wMaj
, &wMin
)) return TYPE_E_LIBNOTREGISTERED
;
338 get_typelib_key( guid
, wMaj
, wMin
, buffer
);
340 res
= RegOpenKeyExW( HKEY_CLASSES_ROOT
, buffer
, 0, KEY_READ
, &hkey
);
341 if (res
== ERROR_FILE_NOT_FOUND
)
343 TRACE_(typelib
)("%s not found\n", debugstr_w(buffer
));
344 return TYPE_E_LIBNOTREGISTERED
;
346 else if (res
!= ERROR_SUCCESS
)
348 TRACE_(typelib
)("failed to open %s for read access\n", debugstr_w(buffer
));
349 return TYPE_E_REGISTRYACCESS
;
354 LONG dwPathLen
= sizeof(Path
);
356 get_lcid_subkey( myLCID
, syskind
, buffer
);
358 if (RegQueryValueW(hkey
, buffer
, Path
, &dwPathLen
))
362 else if (myLCID
== lcid
)
364 /* try with sub-langid */
365 myLCID
= SUBLANGID(lcid
);
367 else if ((myLCID
== SUBLANGID(lcid
)) && myLCID
)
369 /* try with system langid */
379 *path
= SysAllocString( Path
);
384 TRACE_(typelib
)("-- 0x%08x\n", hr
);
388 /****************************************************************************
389 * QueryPathOfRegTypeLib [OLEAUT32.164]
391 * Gets the path to a registered type library.
394 * guid [I] referenced guid
395 * wMaj [I] major version
396 * wMin [I] minor version
398 * path [O] path of typelib
402 * Failure: If the type library is not registered then TYPE_E_LIBNOTREGISTERED
403 * or TYPE_E_REGISTRYACCESS if the type library registration key couldn't be
406 HRESULT WINAPI
QueryPathOfRegTypeLib( REFGUID guid
, WORD wMaj
, WORD wMin
, LCID lcid
, LPBSTR path
)
410 HRESULT hres
= query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN64
, lcid
, path
, TRUE
);
415 return query_typelib_path( guid
, wMaj
, wMin
, SYS_WIN32
, lcid
, path
, redir
);
418 /******************************************************************************
419 * CreateTypeLib [OLEAUT32.160] creates a typelib
425 HRESULT WINAPI
CreateTypeLib(
426 SYSKIND syskind
, LPCOLESTR szFile
, ICreateTypeLib
** ppctlib
428 FIXME("(%d,%s,%p), stub!\n",syskind
,debugstr_w(szFile
),ppctlib
);
432 /******************************************************************************
433 * LoadTypeLib [OLEAUT32.161]
435 * Loads a type library
438 * szFile [I] Name of file to load from.
439 * pptLib [O] Pointer that receives ITypeLib object on success.
446 * LoadTypeLibEx, LoadRegTypeLib, CreateTypeLib.
448 HRESULT WINAPI
LoadTypeLib(const OLECHAR
*szFile
, ITypeLib
* *pptLib
)
450 TRACE("(%s,%p)\n",debugstr_w(szFile
), pptLib
);
451 return LoadTypeLibEx(szFile
, REGKIND_DEFAULT
, pptLib
);
454 /******************************************************************************
455 * LoadTypeLibEx [OLEAUT32.183]
457 * Loads and optionally registers a type library
463 HRESULT WINAPI
LoadTypeLibEx(
464 LPCOLESTR szFile
, /* [in] Name of file to load from */
465 REGKIND regkind
, /* [in] Specify kind of registration */
466 ITypeLib
**pptLib
) /* [out] Pointer to pointer to loaded type library */
468 WCHAR szPath
[MAX_PATH
+1];
471 TRACE("(%s,%d,%p)\n",debugstr_w(szFile
), regkind
, pptLib
);
473 if (!szFile
|| !pptLib
)
478 res
= TLB_ReadTypeLib(szFile
, szPath
, MAX_PATH
+ 1, (ITypeLib2
**)pptLib
);
483 case REGKIND_DEFAULT
:
484 /* don't register typelibs supplied with full path. Experimentation confirms the following */
485 if (((szFile
[0] == '\\') && (szFile
[1] == '\\')) ||
486 (szFile
[0] && (szFile
[1] == ':'))) break;
487 /* else fall-through */
489 case REGKIND_REGISTER
:
490 if (FAILED(res
= RegisterTypeLib(*pptLib
, szPath
, NULL
)))
492 ITypeLib_Release(*pptLib
);
500 TRACE(" returns %08x\n",res
);
504 /******************************************************************************
505 * LoadRegTypeLib [OLEAUT32.162]
507 * Loads a registered type library.
510 * rguid [I] GUID of the registered type library.
511 * wVerMajor [I] major version.
512 * wVerMinor [I] minor version.
513 * lcid [I] locale ID.
514 * ppTLib [O] pointer that receives an ITypeLib object on success.
518 * Failure: Any HRESULT code returned from QueryPathOfRegTypeLib or
521 HRESULT WINAPI
LoadRegTypeLib(
533 res
= QueryPathOfRegTypeLib( rguid
, wVerMajor
, wVerMinor
, lcid
, &bstr
);
537 res
= LoadTypeLib(bstr
, ppTLib
);
540 if ((wVerMajor
!=0xffff || wVerMinor
!=0xffff) && *ppTLib
)
544 res
= ITypeLib_GetLibAttr(*ppTLib
, &attr
);
547 BOOL mismatch
= attr
->wMajorVerNum
!= wVerMajor
|| attr
->wMinorVerNum
< wVerMinor
;
548 ITypeLib_ReleaseTLibAttr(*ppTLib
, attr
);
552 ITypeLib_Release(*ppTLib
);
554 res
= TYPE_E_LIBNOTREGISTERED
;
560 TRACE("(IID: %s) load %s (%p)\n",debugstr_guid(rguid
), SUCCEEDED(res
)? "SUCCESS":"FAILED", *ppTLib
);
566 /* some string constants shared between RegisterTypeLib and UnRegisterTypeLib */
567 static const WCHAR TypeLibW
[] = {'T','y','p','e','L','i','b',0};
568 static const WCHAR FLAGSW
[] = {'F','L','A','G','S',0};
569 static const WCHAR HELPDIRW
[] = {'H','E','L','P','D','I','R',0};
570 static const WCHAR ProxyStubClsidW
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d',0};
571 static const WCHAR ProxyStubClsid32W
[] = {'P','r','o','x','y','S','t','u','b','C','l','s','i','d','3','2',0};
573 static void TLB_register_interface(TLIBATTR
*libattr
, LPOLESTR name
, TYPEATTR
*tattr
, DWORD flag
)
578 static const WCHAR typelib_proxy_clsid
[] = {'{','0','0','0','2','0','4','2','4','-',
579 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
580 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
581 static const WCHAR dispatch_proxy_clsid
[] = {'{','0','0','0','2','0','4','2','0','-',
582 '0','0','0','0','-','0','0','0','0','-','C','0','0','0','-',
583 '0','0','0','0','0','0','0','0','0','0','4','6','}',0};
585 get_interface_key( &tattr
->guid
, keyName
);
586 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
587 KEY_WRITE
| flag
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
589 const WCHAR
*proxy_clsid
;
591 if (tattr
->typekind
== TKIND_INTERFACE
|| (tattr
->wTypeFlags
& TYPEFLAG_FDUAL
))
592 proxy_clsid
= typelib_proxy_clsid
;
594 proxy_clsid
= dispatch_proxy_clsid
;
597 RegSetValueExW(key
, NULL
, 0, REG_SZ
,
598 (BYTE
*)name
, (lstrlenW(name
)+1) * sizeof(OLECHAR
));
600 if (RegCreateKeyExW(key
, ProxyStubClsidW
, 0, NULL
, 0,
601 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
602 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
603 (const BYTE
*)proxy_clsid
, sizeof(typelib_proxy_clsid
));
607 if (RegCreateKeyExW(key
, ProxyStubClsid32W
, 0, NULL
, 0,
608 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
) {
609 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
610 (const BYTE
*)proxy_clsid
, sizeof(typelib_proxy_clsid
));
614 if (RegCreateKeyExW(key
, TypeLibW
, 0, NULL
, 0,
615 KEY_WRITE
| flag
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
618 static const WCHAR fmtver
[] = {'%','x','.','%','x',0 };
619 static const WCHAR VersionW
[] = {'V','e','r','s','i','o','n',0};
621 StringFromGUID2(&libattr
->guid
, buffer
, 40);
622 RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
623 (BYTE
*)buffer
, (lstrlenW(buffer
)+1) * sizeof(WCHAR
));
624 swprintf(buffer
, ARRAY_SIZE(buffer
), fmtver
, libattr
->wMajorVerNum
, libattr
->wMinorVerNum
);
625 RegSetValueExW(subKey
, VersionW
, 0, REG_SZ
,
626 (BYTE
*)buffer
, (lstrlenW(buffer
)+1) * sizeof(WCHAR
));
634 /******************************************************************************
635 * RegisterTypeLib [OLEAUT32.163]
636 * Adds information about a type library to the System Registry
638 * Docs: ITypeLib FAR * ptlib
639 * Docs: OLECHAR FAR* szFullPath
640 * Docs: OLECHAR FAR* szHelpDir
646 HRESULT WINAPI
RegisterTypeLib(
647 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
648 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
649 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
661 if (ptlib
== NULL
|| szFullPath
== NULL
)
664 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
668 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
671 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
674 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
675 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
679 /* Set the human-readable name of the typelib */
680 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
684 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
685 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
691 /* Make up the name of the typelib path subkey */
692 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
694 /* Create the typelib path subkey */
695 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
696 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
698 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
699 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
707 /* Create the flags subkey */
708 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
709 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
711 /* FIXME: is %u correct? */
712 static const WCHAR formatW
[] = {'%','u',0};
714 swprintf(buf
, ARRAY_SIZE(buf
), formatW
, attr
->wLibFlags
);
715 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
716 (BYTE
*)buf
, (lstrlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
724 /* create the helpdir subkey */
725 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
726 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
728 BOOL freeHelpDir
= FALSE
;
731 /* if we created a new key, and helpDir was null, set the helpdir
732 to the directory which contains the typelib. However,
733 if we just opened an existing key, we leave the helpdir alone */
734 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
735 szHelpDir
= SysAllocString(szFullPath
);
736 pIndexStr
= wcsrchr(szHelpDir
, '\\');
743 /* if we have an szHelpDir, set it! */
744 if (szHelpDir
!= NULL
) {
745 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
746 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
752 if (freeHelpDir
) SysFreeString(szHelpDir
);
764 /* register OLE Automation-compatible interfaces for this typelib */
765 types
= ITypeLib_GetTypeInfoCount(ptlib
);
766 for (tidx
=0; tidx
<types
; tidx
++) {
767 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
768 LPOLESTR name
= NULL
;
769 ITypeInfo
*tinfo
= NULL
;
771 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
774 case TKIND_INTERFACE
:
775 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
776 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
780 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
781 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
785 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
790 TYPEATTR
*tattr
= NULL
;
791 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
794 TRACE_(typelib
)("guid=%s, flags=%04x (",
795 debugstr_guid(&tattr
->guid
),
798 if (TRACE_ON(typelib
)) {
799 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
819 /* Register all dispinterfaces (which includes dual interfaces) and
820 oleautomation interfaces */
821 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
822 kind
== TKIND_DISPATCH
)
825 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
827 /* register interface<->typelib coupling */
828 TLB_register_interface(attr
, name
, tattr
, 0);
830 /* register TLBs into the opposite registry view, too */
831 if(opposite
== KEY_WOW64_32KEY
||
832 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
833 TLB_register_interface(attr
, name
, tattr
, opposite
);
836 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
839 ITypeInfo_Release(tinfo
);
846 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
851 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
853 WCHAR subKeyName
[50];
856 /* the path to the type */
857 get_interface_key( guid
, subKeyName
);
859 /* Delete its bits */
860 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
863 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
864 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
865 RegDeleteKeyW(subKey
, TypeLibW
);
867 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
870 /******************************************************************************
871 * UnRegisterTypeLib [OLEAUT32.186]
872 * Removes information about a type library from the System Registry
879 HRESULT WINAPI
UnRegisterTypeLib(
880 REFGUID libid
, /* [in] Guid of the library */
881 WORD wVerMajor
, /* [in] major version */
882 WORD wVerMinor
, /* [in] minor version */
883 LCID lcid
, /* [in] locale id */
886 BSTR tlibPath
= NULL
;
889 WCHAR subKeyName
[50];
892 BOOL deleteOtherStuff
;
894 TYPEATTR
* typeAttr
= NULL
;
896 ITypeInfo
* typeInfo
= NULL
;
897 ITypeLib
* typeLib
= NULL
;
900 TRACE("(IID: %s)\n",debugstr_guid(libid
));
902 /* Create the path to the key */
903 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
905 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
907 TRACE("Unsupported syskind %i\n", syskind
);
908 result
= E_INVALIDARG
;
912 /* get the path to the typelib on disk */
913 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
914 result
= E_INVALIDARG
;
918 /* Try and open the key to the type library. */
919 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
920 result
= E_INVALIDARG
;
924 /* Try and load the type library */
925 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
926 result
= TYPE_E_INVALIDSTATE
;
930 /* remove any types registered with this typelib */
931 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
932 for (i
=0; i
<numTypes
; i
++) {
933 /* get the kind of type */
934 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
938 /* skip non-interfaces, and get type info for the type */
939 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
942 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
945 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
949 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
950 kind
== TKIND_DISPATCH
)
953 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
955 TLB_unregister_interface(&typeAttr
->guid
, 0);
957 /* unregister TLBs into the opposite registry view, too */
958 if(opposite
== KEY_WOW64_32KEY
||
959 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
960 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
965 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
967 if (typeInfo
) ITypeInfo_Release(typeInfo
);
971 /* Now, delete the type library path subkey */
972 get_lcid_subkey( lcid
, syskind
, subKeyName
);
973 RegDeleteKeyW(key
, subKeyName
);
974 *wcsrchr( subKeyName
, '\\' ) = 0; /* remove last path component */
975 RegDeleteKeyW(key
, subKeyName
);
977 /* check if there is anything besides the FLAGS/HELPDIR keys.
978 If there is, we don't delete them */
979 tmpLength
= ARRAY_SIZE(subKeyName
);
980 deleteOtherStuff
= TRUE
;
982 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
983 tmpLength
= ARRAY_SIZE(subKeyName
);
985 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
986 if (!wcscmp(subKeyName
, FLAGSW
)) continue;
987 if (!wcscmp(subKeyName
, HELPDIRW
)) continue;
988 deleteOtherStuff
= FALSE
;
992 /* only delete the other parts of the key if we're absolutely sure */
993 if (deleteOtherStuff
) {
994 RegDeleteKeyW(key
, FLAGSW
);
995 RegDeleteKeyW(key
, HELPDIRW
);
999 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1000 *wcsrchr( keyName
, '\\' ) = 0; /* remove last path component */
1001 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1005 SysFreeString(tlibPath
);
1006 if (typeLib
) ITypeLib_Release(typeLib
);
1007 if (key
) RegCloseKey(key
);
1011 /******************************************************************************
1012 * RegisterTypeLibForUser [OLEAUT32.442]
1013 * Adds information about a type library to the user registry
1015 * Docs: ITypeLib FAR * ptlib
1016 * Docs: OLECHAR FAR* szFullPath
1017 * Docs: OLECHAR FAR* szHelpDir
1023 HRESULT WINAPI
RegisterTypeLibForUser(
1024 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1025 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1026 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1029 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1030 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1031 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1034 /******************************************************************************
1035 * UnRegisterTypeLibForUser [OLEAUT32.443]
1036 * Removes information about a type library from the user registry
1042 HRESULT WINAPI
UnRegisterTypeLibForUser(
1043 REFGUID libid
, /* [in] GUID of the library */
1044 WORD wVerMajor
, /* [in] major version */
1045 WORD wVerMinor
, /* [in] minor version */
1046 LCID lcid
, /* [in] locale id */
1049 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1050 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1051 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1054 /*======================= ITypeLib implementation =======================*/
1056 typedef struct tagTLBGuid
{
1063 typedef struct tagTLBCustData
1070 /* data structure for import typelibs */
1071 typedef struct tagTLBImpLib
1073 int offset
; /* offset in the file (MSFT)
1074 offset in nametable (SLTG)
1075 just used to identify library while reading
1077 TLBGuid
*guid
; /* libid */
1078 BSTR name
; /* name */
1080 LCID lcid
; /* lcid of imported typelib */
1082 WORD wVersionMajor
; /* major version number */
1083 WORD wVersionMinor
; /* minor version number */
1085 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1086 NULL if not yet loaded */
1090 typedef struct tagTLBString
{
1096 /* internal ITypeLib data */
1097 typedef struct tagITypeLibImpl
1099 ITypeLib2 ITypeLib2_iface
;
1100 ITypeComp ITypeComp_iface
;
1101 ICreateTypeLib2 ICreateTypeLib2_iface
;
1112 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1113 * exported to the application as a UNICODE string.
1115 struct list string_list
;
1116 struct list name_list
;
1117 struct list guid_list
;
1119 const TLBString
*Name
;
1120 const TLBString
*DocString
;
1121 const TLBString
*HelpFile
;
1122 const TLBString
*HelpStringDll
;
1123 DWORD dwHelpContext
;
1124 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1125 struct tagITypeInfoImpl
**typeinfos
;
1126 struct list custdata_list
;
1127 struct list implib_list
;
1128 int ctTypeDesc
; /* number of items in type desc array */
1129 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1130 library. Only used while reading MSFT
1132 struct list ref_list
; /* list of ref types in this typelib */
1133 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1136 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1142 static const ITypeLib2Vtbl tlbvt
;
1143 static const ITypeCompVtbl tlbtcvt
;
1144 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1146 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1148 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1151 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1153 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1156 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1158 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1161 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1163 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1166 /* ITypeLib methods */
1167 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1168 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1170 /*======================= ITypeInfo implementation =======================*/
1172 /* data for referenced types */
1173 typedef struct tagTLBRefType
1175 INT index
; /* Type index for internal ref or for external ref
1176 it the format is SLTG. -2 indicates to
1180 TLBGuid
*guid
; /* guid of the referenced type */
1181 /* if index == TLB_REF_USE_GUID */
1183 HREFTYPE reference
; /* The href of this ref */
1184 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1185 TLB_REF_INTERNAL for internal refs
1186 TLB_REF_NOT_FOUND for broken refs */
1191 #define TLB_REF_USE_GUID -2
1193 #define TLB_REF_INTERNAL (void*)-2
1194 #define TLB_REF_NOT_FOUND (void*)-1
1196 /* internal Parameter data */
1197 typedef struct tagTLBParDesc
1199 const TLBString
*Name
;
1200 struct list custdata_list
;
1203 /* internal Function data */
1204 typedef struct tagTLBFuncDesc
1206 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1207 const TLBString
*Name
; /* the name of this function */
1208 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1210 int HelpStringContext
;
1211 const TLBString
*HelpString
;
1212 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1213 struct list custdata_list
;
1216 /* internal Variable data */
1217 typedef struct tagTLBVarDesc
1219 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1220 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1221 const TLBString
*Name
; /* the name of this variable */
1223 int HelpStringContext
;
1224 const TLBString
*HelpString
;
1225 struct list custdata_list
;
1228 /* internal implemented interface data */
1229 typedef struct tagTLBImplType
1231 HREFTYPE hRef
; /* hRef of interface */
1232 int implflags
; /* IMPLFLAG_*s */
1233 struct list custdata_list
;
1236 /* internal TypeInfo data */
1237 typedef struct tagITypeInfoImpl
1239 ITypeInfo2 ITypeInfo2_iface
;
1240 ITypeComp ITypeComp_iface
;
1241 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1243 BOOL not_attached_to_typelib
;
1248 TYPEDESC
*tdescAlias
;
1250 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1251 int index
; /* index in this typelib; */
1252 HREFTYPE hreftype
; /* hreftype for app object binding */
1253 /* type libs seem to store the doc strings in ascii
1254 * so why should we do it in unicode?
1256 const TLBString
*Name
;
1257 const TLBString
*DocString
;
1258 const TLBString
*DllName
;
1259 const TLBString
*Schema
;
1260 DWORD dwHelpContext
;
1261 DWORD dwHelpStringContext
;
1264 TLBFuncDesc
*funcdescs
;
1267 TLBVarDesc
*vardescs
;
1269 /* Implemented Interfaces */
1270 TLBImplType
*impltypes
;
1272 struct list
*pcustdata_list
;
1273 struct list custdata_list
;
1276 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1278 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1281 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1283 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1286 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1288 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1291 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1293 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1296 static const ITypeInfo2Vtbl tinfvt
;
1297 static const ITypeCompVtbl tcompvt
;
1298 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1300 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1301 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1303 typedef struct tagTLBContext
1305 unsigned int oStart
; /* start of TLB in file */
1306 unsigned int pos
; /* current pos */
1307 unsigned int length
; /* total length */
1308 void *mapping
; /* memory mapping */
1309 MSFT_SegDir
* pTblDir
;
1310 ITypeLibImpl
* pLibInfo
;
1314 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1316 return str
!= NULL
? str
->str
: NULL
;
1319 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1323 return memcmp(left
, str
->str
, len
);
1326 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1328 return guid
!= NULL
? &guid
->guid
: NULL
;
1331 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1333 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1336 static int get_ptr_size(SYSKIND syskind
)
1346 WARN("Unhandled syskind: 0x%x\n", syskind
);
1353 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1354 if (pTD
->vt
& VT_RESERVED
)
1355 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1356 if (pTD
->vt
& VT_BYREF
)
1357 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1358 if (pTD
->vt
& VT_ARRAY
)
1359 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1360 if (pTD
->vt
& VT_VECTOR
)
1361 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1362 switch(pTD
->vt
& VT_TYPEMASK
) {
1363 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1364 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1365 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1366 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1367 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1368 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1369 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1370 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1371 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1372 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1373 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1374 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1375 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1376 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1377 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1378 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1379 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1380 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1381 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1382 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1383 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1384 pTD
->u
.hreftype
); break;
1385 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1386 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1387 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1388 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1390 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1391 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1393 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1394 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1395 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1398 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1402 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1404 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1405 dump_TypeDesc(&edesc
->tdesc
,buf
);
1406 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1407 MESSAGE("\t\tu.paramdesc.wParamFlags");
1408 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1409 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1410 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1411 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1412 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1413 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1414 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1415 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1416 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1418 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1420 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1421 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1422 MESSAGE("Param %d:\n",i
);
1423 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1425 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1426 switch (funcdesc
->funckind
) {
1427 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1428 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1429 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1430 case FUNC_STATIC
: MESSAGE("static");break;
1431 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1432 default: MESSAGE("unknown");break;
1434 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1435 switch (funcdesc
->invkind
) {
1436 case INVOKE_FUNC
: MESSAGE("func");break;
1437 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1438 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1439 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1441 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1442 switch (funcdesc
->callconv
) {
1443 case CC_CDECL
: MESSAGE("cdecl");break;
1444 case CC_PASCAL
: MESSAGE("pascal");break;
1445 case CC_STDCALL
: MESSAGE("stdcall");break;
1446 case CC_SYSCALL
: MESSAGE("syscall");break;
1449 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1450 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1451 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1453 MESSAGE("\telemdescFunc (return value type):\n");
1454 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1457 static const char * const typekind_desc
[] =
1470 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1473 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1474 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1475 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1478 dump_FUNCDESC(&(pfd
->funcdesc
));
1480 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1481 if(pfd
->Entry
== NULL
)
1482 MESSAGE("\tentry: (null)\n");
1483 else if(pfd
->Entry
== (void*)-1)
1484 MESSAGE("\tentry: invalid\n");
1485 else if(IS_INTRESOURCE(pfd
->Entry
))
1486 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1488 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1490 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1494 dump_TLBFuncDescOne(pfd
);
1499 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1503 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1509 static void dump_TLBImpLib(const TLBImpLib
*import
)
1511 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1512 debugstr_w(import
->name
));
1513 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1514 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1517 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1521 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1523 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1524 if(ref
->index
== -1)
1525 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1527 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1529 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1531 TRACE_(typelib
)("in lib\n");
1532 dump_TLBImpLib(ref
->pImpTLInfo
);
1537 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1542 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1543 impl
->hRef
, impl
->implflags
);
1549 static void dump_DispParms(const DISPPARAMS
* pdp
)
1553 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1555 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1557 TRACE("named args:\n");
1558 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1559 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1562 if (pdp
->cArgs
&& pdp
->rgvarg
)
1565 for (index
= 0; index
< pdp
->cArgs
; index
++)
1566 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1570 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1572 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1573 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1574 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1575 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1576 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1577 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1578 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1579 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1581 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1582 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1583 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1586 static void dump_VARDESC(const VARDESC
*v
)
1588 MESSAGE("memid %d\n",v
->memid
);
1589 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1590 MESSAGE("oInst %d\n",v
->u
.oInst
);
1591 dump_ELEMDESC(&(v
->elemdescVar
));
1592 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1593 MESSAGE("varkind %d\n",v
->varkind
);
1596 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1598 /* VT_LPWSTR is largest type that, may appear in type description */
1599 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1600 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1601 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1602 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1603 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1604 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1605 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1606 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1609 static void TLB_abort(void)
1614 /* returns the size required for a deep copy of a typedesc into a
1616 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1620 if (alloc_initial_space
)
1621 size
+= sizeof(TYPEDESC
);
1627 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1630 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1631 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1637 /* deep copy a typedesc into a flat buffer */
1638 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1643 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1652 dest
->u
.lptdesc
= buffer
;
1653 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1656 dest
->u
.lpadesc
= buffer
;
1657 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1658 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1659 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1665 /* free custom data allocated by MSFT_CustData */
1666 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1668 TLBCustData
*cd
, *cdn
;
1669 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1671 list_remove(&cd
->entry
);
1672 VariantClear(&cd
->data
);
1677 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1682 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1683 ret
= SysAllocStringLen(NULL
, len
- 1);
1684 if (!ret
) return ret
;
1685 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1689 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(TLBFuncDesc
*funcdescs
,
1690 UINT n
, MEMBERID memid
)
1693 if(funcdescs
->funcdesc
.memid
== memid
)
1701 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(TLBVarDesc
*vardescs
,
1702 UINT n
, MEMBERID memid
)
1705 if(vardescs
->vardesc
.memid
== memid
)
1713 static inline TLBVarDesc
*TLB_get_vardesc_by_name(TLBVarDesc
*vardescs
,
1714 UINT n
, const OLECHAR
*name
)
1717 if(!lstrcmpiW(TLB_get_bstr(vardescs
->Name
), name
))
1725 static inline TLBCustData
*TLB_get_custdata_by_guid(struct list
*custdata_list
, REFGUID guid
)
1727 TLBCustData
*cust_data
;
1728 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1729 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1734 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeInfoImpl
**typeinfos
,
1735 UINT n
, const OLECHAR
*name
)
1738 if(!lstrcmpiW(TLB_get_bstr((*typeinfos
)->Name
), name
))
1746 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1748 list_init(&var_desc
->custdata_list
);
1751 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1755 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1760 TLBVarDesc_Constructor(&ret
[n
-1]);
1767 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1771 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1776 list_init(&ret
[n
-1].custdata_list
);
1783 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1785 list_init(&func_desc
->custdata_list
);
1788 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1792 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1797 TLBFuncDesc_Constructor(&ret
[n
-1]);
1804 static void TLBImplType_Constructor(TLBImplType
*impl
)
1806 list_init(&impl
->custdata_list
);
1809 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1813 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1818 TLBImplType_Constructor(&ret
[n
-1]);
1825 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1826 const GUID
*new_guid
, HREFTYPE hreftype
)
1830 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1831 if (IsEqualGUID(&guid
->guid
, new_guid
))
1835 guid
= heap_alloc(sizeof(TLBGuid
));
1839 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1840 guid
->hreftype
= hreftype
;
1842 list_add_tail(guid_list
, &guid
->entry
);
1847 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1849 TLBCustData
*cust_data
;
1861 return DISP_E_BADVARTYPE
;
1864 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1867 cust_data
= heap_alloc(sizeof(TLBCustData
));
1869 return E_OUTOFMEMORY
;
1871 cust_data
->guid
= tlbguid
;
1872 VariantInit(&cust_data
->data
);
1874 list_add_tail(custdata_list
, &cust_data
->entry
);
1876 VariantClear(&cust_data
->data
);
1878 return VariantCopy(&cust_data
->data
, var
);
1881 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1888 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1889 if (wcscmp(str
->str
, new_str
) == 0)
1893 str
= heap_alloc(sizeof(TLBString
));
1897 str
->str
= SysAllocString(new_str
);
1903 list_add_tail(string_list
, &str
->entry
);
1908 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1909 ULONG
*size
, WORD
*align
)
1915 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1919 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1921 ITypeInfo_Release(other
);
1926 *size
= attr
->cbSizeInstance
;
1928 *align
= attr
->cbAlignment
;
1930 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1931 ITypeInfo_Release(other
);
1936 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1937 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1939 ULONG i
, sub
, ptr_size
;
1942 ptr_size
= get_ptr_size(sys
);
1981 *size
= sizeof(DATE
);
1984 *size
= sizeof(VARIANT
);
1986 if(sys
== SYS_WIN32
)
1987 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
1991 *size
= sizeof(DECIMAL
);
1998 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
1999 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2000 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2005 case VT_USERDEFINED
:
2006 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2008 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2022 /**********************************************************************
2024 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2027 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2029 if (where
!= DO_NOT_SEEK
)
2031 where
+= pcx
->oStart
;
2032 if (where
> pcx
->length
)
2035 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2043 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2045 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2046 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2048 MSFT_Seek(pcx
, where
);
2049 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2050 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2055 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2060 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2061 FromLEDWords(buffer
, ret
);
2066 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2071 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2072 FromLEWords(buffer
, ret
);
2077 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2080 MSFT_GuidEntry entry
;
2083 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2085 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2088 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2090 guid
= heap_alloc(sizeof(TLBGuid
));
2092 guid
->offset
= offs
;
2093 guid
->guid
= entry
.guid
;
2094 guid
->hreftype
= entry
.hreftype
;
2096 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2098 offs
+= sizeof(MSFT_GuidEntry
);
2102 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2106 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2107 if(ret
->offset
== offset
){
2108 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2116 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2118 MSFT_NameIntro niName
;
2122 ERR_(typelib
)("bad offset %d\n", offset
);
2126 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2127 pcx
->pTblDir
->pNametab
.offset
+offset
);
2129 return niName
.hreftype
;
2132 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2135 MSFT_NameIntro intro
;
2137 int offs
= 0, lengthInChars
;
2139 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2143 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2146 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2147 intro
.namelen
&= 0xFF;
2148 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2150 len_piece
= (len_piece
+ 4) & ~0x3;
2154 string
= heap_alloc(len_piece
+ 1);
2155 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2156 string
[intro
.namelen
] = '\0';
2158 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2159 string
, -1, NULL
, 0);
2160 if (!lengthInChars
) {
2162 return E_UNEXPECTED
;
2165 tlbstr
= heap_alloc(sizeof(TLBString
));
2167 tlbstr
->offset
= offs
;
2168 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2169 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2173 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2179 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2183 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2184 if (tlbstr
->offset
== offset
) {
2185 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2193 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2197 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2198 if (tlbstr
->offset
== offset
) {
2199 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2208 * read a value and fill a VARIANT structure
2210 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2214 TRACE_(typelib
)("\n");
2216 if(offset
<0) { /* data are packed in here */
2217 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2218 V_I4(pVar
) = offset
& 0x3ffffff;
2221 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2222 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2223 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2224 switch (V_VT(pVar
)){
2225 case VT_EMPTY
: /* FIXME: is this right? */
2226 case VT_NULL
: /* FIXME: is this right? */
2227 case VT_I2
: /* this should not happen */
2238 case VT_VOID
: /* FIXME: is this right? */
2246 case VT_DECIMAL
: /* FIXME: is this right? */
2249 /* pointer types with known behaviour */
2252 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2254 V_BSTR(pVar
) = NULL
;
2256 ptr
= heap_alloc_zero(size
);
2257 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2258 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2259 /* FIXME: do we need a AtoW conversion here? */
2260 V_UNION(pVar
, bstrVal
[size
])='\0';
2261 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2266 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2273 case VT_USERDEFINED
:
2279 case VT_STREAMED_OBJECT
:
2280 case VT_STORED_OBJECT
:
2281 case VT_BLOB_OBJECT
:
2286 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2290 if(size
>0) /* (big|small) endian correct? */
2291 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2295 * create a linked list with custom data
2297 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2303 TRACE_(typelib
)("\n");
2305 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2309 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2310 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2311 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2312 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2313 list_add_head(custdata_list
, &pNew
->entry
);
2314 offset
= entry
.next
;
2319 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2322 pTd
->vt
=type
& VT_TYPEMASK
;
2324 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2326 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2329 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2331 return (invkind
== INVOKE_PROPERTYGET
||
2332 invkind
== INVOKE_PROPERTYPUT
||
2333 invkind
== INVOKE_PROPERTYPUTREF
);
2337 MSFT_DoFuncs(TLBContext
* pcx
,
2342 TLBFuncDesc
** pptfd
)
2345 * member information is stored in a data structure at offset
2346 * indicated by the memoffset field of the typeinfo structure
2347 * There are several distinctive parts.
2348 * The first part starts with a field that holds the total length
2349 * of this (first) part excluding this field. Then follow the records,
2350 * for each member there is one record.
2352 * The first entry is always the length of the record (including this
2354 * The rest of the record depends on the type of the member. If there is
2355 * a field indicating the member type (function, variable, interface, etc)
2356 * I have not found it yet. At this time we depend on the information
2357 * in the type info and the usual order how things are stored.
2359 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2362 * Third is an equal sized array with file offsets to the name entry
2365 * The fourth and last (?) part is an array with offsets to the records
2366 * in the first part of this file segment.
2369 int infolen
, nameoffset
, reclength
, i
;
2370 int recoffset
= offset
+ sizeof(INT
);
2372 char *recbuf
= heap_alloc(0xffff);
2373 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2374 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2376 TRACE_(typelib
)("\n");
2378 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2380 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2382 for ( i
= 0; i
< cFuncs
; i
++ )
2386 /* name, eventually add to a hash table */
2387 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2388 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2390 /* read the function information record */
2391 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2393 reclength
&= 0xffff;
2395 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2397 /* size without argument data */
2398 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2399 if (pFuncRec
->FKCCIC
& 0x1000)
2400 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2402 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2403 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2405 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2406 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2408 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2410 if (pFuncRec
->FKCCIC
& 0x2000 )
2412 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2413 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2414 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2417 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2420 ptfd
->Entry
= (TLBString
*)-1;
2422 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2423 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2425 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2426 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2428 /* fill the FuncDesc Structure */
2429 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2430 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2432 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2433 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2434 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2435 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2436 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2437 ptfd
->funcdesc
.oVft
= (pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2438 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2440 /* nameoffset is sometimes -1 on the second half of a propget/propput
2441 * pair of functions */
2442 if ((nameoffset
== -1) && (i
> 0) &&
2443 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2444 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2445 ptfd
->Name
= ptfd_prev
->Name
;
2447 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2451 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2453 /* do the parameters/arguments */
2454 if(pFuncRec
->nrargs
)
2457 MSFT_ParameterInfo paraminfo
;
2459 ptfd
->funcdesc
.lprgelemdescParam
=
2460 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2462 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2464 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2465 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2467 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2469 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2475 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2478 if (paraminfo
.oName
!= -1)
2479 ptfd
->pParamDesc
[j
].Name
=
2480 MSFT_ReadName( pcx
, paraminfo
.oName
);
2481 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2484 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2485 (pFuncRec
->FKCCIC
& 0x1000) )
2487 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2489 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2491 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2493 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2494 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2496 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2500 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2503 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2504 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2505 pFuncRec
->FKCCIC
& 0x80 )
2508 pFuncRec
->oArgCustData
[j
],
2509 &ptfd
->pParamDesc
[j
].custdata_list
);
2512 /* SEEK value = jump to offset,
2513 * from there jump to the end of record,
2514 * go back by (j-1) arguments
2516 MSFT_ReadLEDWords( ¶minfo
,
2517 sizeof(MSFT_ParameterInfo
), pcx
,
2518 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2519 * sizeof(MSFT_ParameterInfo
)));
2523 /* scode is not used: archaic win16 stuff FIXME: right? */
2524 ptfd
->funcdesc
.cScodes
= 0 ;
2525 ptfd
->funcdesc
.lprgscode
= NULL
;
2529 recoffset
+= reclength
;
2534 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2535 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2537 int infolen
, nameoffset
, reclength
;
2539 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2544 TRACE_(typelib
)("\n");
2546 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2547 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2548 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2549 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2550 recoffset
+= offset
+sizeof(INT
);
2551 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2552 /* name, eventually add to a hash table */
2553 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2554 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2555 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2556 /* read the variable information record */
2557 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2559 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2562 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2563 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2565 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2566 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2568 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2569 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2571 /* fill the VarDesc Structure */
2572 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2573 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2574 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2575 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2576 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2577 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2578 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2579 if(pVarRec
->VarKind
== VAR_CONST
){
2580 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2581 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2582 pVarRec
->OffsValue
, pcx
);
2584 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2585 recoffset
+= reclength
;
2589 /* process Implemented Interfaces of a com class */
2590 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2594 MSFT_RefRecord refrec
;
2597 TRACE_(typelib
)("\n");
2599 pTI
->impltypes
= TLBImplType_Alloc(count
);
2600 pImpl
= pTI
->impltypes
;
2601 for(i
=0;i
<count
;i
++){
2602 if(offset
<0) break; /* paranoia */
2603 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2604 pImpl
->hRef
= refrec
.reftype
;
2605 pImpl
->implflags
=refrec
.flags
;
2606 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2607 offset
=refrec
.onext
;
2613 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2614 * and some structures, and fix the alignment */
2615 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2617 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2618 switch(info
->tdescAlias
->vt
){
2626 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2627 info
->typeattr
.cbAlignment
= sizeof(void*);
2630 case VT_USERDEFINED
:
2631 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2634 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2635 info
->typeattr
.cbAlignment
= 8;
2637 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2638 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2640 info
->typeattr
.cbAlignment
= sizeof(void*);
2643 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2644 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2645 info
->typeattr
.typekind
== TKIND_COCLASS
){
2646 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2647 info
->typeattr
.cbAlignment
= sizeof(void*);
2653 * process a typeinfo record
2655 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2658 ITypeLibImpl
* pLibInfo
)
2660 MSFT_TypeInfoBase tiBase
;
2661 ITypeInfoImpl
*ptiRet
;
2663 TRACE_(typelib
)("count=%u\n", count
);
2665 ptiRet
= ITypeInfoImpl_Constructor();
2666 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2667 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2669 /* this is where we are coming from */
2670 ptiRet
->pTypeLib
= pLibInfo
;
2671 ptiRet
->index
=count
;
2673 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2674 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2675 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2676 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2677 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2678 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2679 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2680 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2681 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2682 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2683 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2684 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2685 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2686 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2688 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2689 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2690 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2694 /* IDLDESC idldescType; *//* never saw this one != zero */
2696 /* name, eventually add to a hash table */
2697 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2698 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2699 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2701 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2702 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2703 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2705 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2706 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2708 /* note: InfoType's Help file and HelpStringDll come from the containing
2709 * library. Further HelpString and Docstring appear to be the same thing :(
2712 if(ptiRet
->typeattr
.cFuncs
>0 )
2713 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2714 ptiRet
->typeattr
.cVars
,
2715 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2717 if(ptiRet
->typeattr
.cVars
>0 )
2718 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2719 ptiRet
->typeattr
.cVars
,
2720 tiBase
.memoffset
, &ptiRet
->vardescs
);
2721 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2722 switch(ptiRet
->typeattr
.typekind
)
2725 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2728 case TKIND_DISPATCH
:
2729 /* This is not -1 when the interface is a non-base dual interface or
2730 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2731 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2735 if (tiBase
.datatype1
!= -1)
2737 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2738 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2742 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2743 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2747 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2749 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2750 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2751 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2752 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2753 if (TRACE_ON(typelib
))
2754 dump_TypeInfo(ptiRet
);
2759 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2762 INT16 len_str
, len_piece
;
2763 int offs
= 0, lengthInChars
;
2765 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2769 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2772 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2773 len_piece
= len_str
+ sizeof(INT16
);
2775 len_piece
= (len_piece
+ 4) & ~0x3;
2779 string
= heap_alloc(len_piece
+ 1);
2780 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2781 string
[len_str
] = '\0';
2783 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2784 string
, -1, NULL
, 0);
2785 if (!lengthInChars
) {
2787 return E_UNEXPECTED
;
2790 tlbstr
= heap_alloc(sizeof(TLBString
));
2792 tlbstr
->offset
= offs
;
2793 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2794 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2798 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2804 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2809 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2810 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2811 MSFT_ImpInfo impinfo
;
2814 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2816 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2817 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2819 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2820 if(pImpLib
->offset
==impinfo
.oImpFile
)
2823 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2824 ref
->reference
= offs
;
2825 ref
->pImpTLInfo
= pImpLib
;
2826 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2827 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2828 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2829 ref
->index
= TLB_REF_USE_GUID
;
2831 ref
->index
= impinfo
.oGuid
;
2833 ERR("Cannot find a reference\n");
2834 ref
->reference
= -1;
2835 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2838 offs
+= sizeof(impinfo
);
2844 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2845 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2846 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2849 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2850 static CRITICAL_SECTION cache_section
;
2851 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2853 0, 0, &cache_section
,
2854 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2855 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2857 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2860 typedef struct TLB_PEFile
2862 IUnknown IUnknown_iface
;
2865 HRSRC typelib_resource
;
2866 HGLOBAL typelib_global
;
2867 LPVOID typelib_base
;
2870 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2872 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2875 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2877 if (IsEqualIID(riid
, &IID_IUnknown
))
2880 IUnknown_AddRef(iface
);
2884 return E_NOINTERFACE
;
2887 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2889 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2890 return InterlockedIncrement(&This
->refs
);
2893 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2895 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2896 ULONG refs
= InterlockedDecrement(&This
->refs
);
2899 if (This
->typelib_global
)
2900 FreeResource(This
->typelib_global
);
2902 FreeLibrary(This
->dll
);
2908 static const IUnknownVtbl TLB_PEFile_Vtable
=
2910 TLB_PEFile_QueryInterface
,
2915 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2918 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2920 This
= heap_alloc(sizeof(TLB_PEFile
));
2922 return E_OUTOFMEMORY
;
2924 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2927 This
->typelib_resource
= NULL
;
2928 This
->typelib_global
= NULL
;
2929 This
->typelib_base
= NULL
;
2931 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2932 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2936 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2937 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2938 if (This
->typelib_resource
)
2940 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2941 if (This
->typelib_global
)
2943 This
->typelib_base
= LockResource(This
->typelib_global
);
2945 if (This
->typelib_base
)
2947 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2948 *ppBase
= This
->typelib_base
;
2949 *ppFile
= &This
->IUnknown_iface
;
2955 TRACE("No TYPELIB resource found\n");
2959 TLB_PEFile_Release(&This
->IUnknown_iface
);
2963 typedef struct TLB_NEFile
2965 IUnknown IUnknown_iface
;
2967 LPVOID typelib_base
;
2970 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2972 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2975 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2977 if (IsEqualIID(riid
, &IID_IUnknown
))
2980 IUnknown_AddRef(iface
);
2984 return E_NOINTERFACE
;
2987 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
2989 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2990 return InterlockedIncrement(&This
->refs
);
2993 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
2995 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
2996 ULONG refs
= InterlockedDecrement(&This
->refs
);
2999 heap_free(This
->typelib_base
);
3005 static const IUnknownVtbl TLB_NEFile_Vtable
=
3007 TLB_NEFile_QueryInterface
,
3012 /***********************************************************************
3013 * read_xx_header [internal]
3015 static int read_xx_header( HFILE lzfd
)
3017 IMAGE_DOS_HEADER mzh
;
3020 LZSeek( lzfd
, 0, SEEK_SET
);
3021 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3023 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3026 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3027 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3030 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3032 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3033 return IMAGE_OS2_SIGNATURE
;
3034 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3035 return IMAGE_NT_SIGNATURE
;
3038 WARN("Can't handle %s files.\n", magic
);
3043 /***********************************************************************
3044 * find_ne_resource [internal]
3046 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3047 DWORD
*resLen
, DWORD
*resOff
)
3049 IMAGE_OS2_HEADER nehd
;
3050 NE_TYPEINFO
*typeInfo
;
3051 NE_NAMEINFO
*nameInfo
;
3057 /* Read in NE header */
3058 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3059 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3061 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3064 TRACE("No resources in NE dll\n" );
3068 /* Read in resource table */
3069 resTab
= heap_alloc( resTabSize
);
3070 if ( !resTab
) return FALSE
;
3072 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3073 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3075 heap_free( resTab
);
3080 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3082 if (!IS_INTRESOURCE(typeid)) /* named type */
3084 BYTE len
= strlen( typeid );
3085 while (typeInfo
->type_id
)
3087 if (!(typeInfo
->type_id
& 0x8000))
3089 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3090 if ((*p
== len
) && !_strnicmp( (char*)p
+1, typeid, len
)) goto found_type
;
3092 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3093 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3096 else /* numeric type id */
3098 WORD id
= LOWORD(typeid) | 0x8000;
3099 while (typeInfo
->type_id
)
3101 if (typeInfo
->type_id
== id
) goto found_type
;
3102 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3103 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3106 TRACE("No typeid entry found for %p\n", typeid );
3107 heap_free( resTab
);
3111 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3113 if (!IS_INTRESOURCE(resid
)) /* named resource */
3115 BYTE len
= strlen( resid
);
3116 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3118 BYTE
*p
= resTab
+ nameInfo
->id
;
3119 if (nameInfo
->id
& 0x8000) continue;
3120 if ((*p
== len
) && !_strnicmp( (char*)p
+1, resid
, len
)) goto found_name
;
3123 else /* numeric resource id */
3125 WORD id
= LOWORD(resid
) | 0x8000;
3126 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3127 if (nameInfo
->id
== id
) goto found_name
;
3129 TRACE("No resid entry found for %p\n", typeid );
3130 heap_free( resTab
);
3134 /* Return resource data */
3135 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3136 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3138 heap_free( resTab
);
3142 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3146 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3149 This
= heap_alloc(sizeof(TLB_NEFile
));
3150 if (!This
) return E_OUTOFMEMORY
;
3152 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3154 This
->typelib_base
= NULL
;
3156 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3157 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3159 DWORD reslen
, offset
;
3160 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3162 This
->typelib_base
= heap_alloc(reslen
);
3163 if( !This
->typelib_base
)
3167 LZSeek( lzfd
, offset
, SEEK_SET
);
3168 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3170 *ppBase
= This
->typelib_base
;
3171 *pdwTLBLength
= reslen
;
3172 *ppFile
= &This
->IUnknown_iface
;
3178 if( lzfd
>= 0) LZClose( lzfd
);
3179 TLB_NEFile_Release(&This
->IUnknown_iface
);
3183 typedef struct TLB_Mapping
3185 IUnknown IUnknown_iface
;
3189 LPVOID typelib_base
;
3192 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3194 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3197 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3199 if (IsEqualIID(riid
, &IID_IUnknown
))
3202 IUnknown_AddRef(iface
);
3206 return E_NOINTERFACE
;
3209 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3211 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3212 return InterlockedIncrement(&This
->refs
);
3215 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3217 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3218 ULONG refs
= InterlockedDecrement(&This
->refs
);
3221 if (This
->typelib_base
)
3222 UnmapViewOfFile(This
->typelib_base
);
3224 CloseHandle(This
->mapping
);
3225 if (This
->file
!= INVALID_HANDLE_VALUE
)
3226 CloseHandle(This
->file
);
3232 static const IUnknownVtbl TLB_Mapping_Vtable
=
3234 TLB_Mapping_QueryInterface
,
3239 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3243 This
= heap_alloc(sizeof(TLB_Mapping
));
3245 return E_OUTOFMEMORY
;
3247 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3249 This
->file
= INVALID_HANDLE_VALUE
;
3250 This
->mapping
= NULL
;
3251 This
->typelib_base
= NULL
;
3253 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3254 if (INVALID_HANDLE_VALUE
!= This
->file
)
3256 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3259 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3260 if(This
->typelib_base
)
3262 /* retrieve file size */
3263 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3264 *ppBase
= This
->typelib_base
;
3265 *ppFile
= &This
->IUnknown_iface
;
3271 IUnknown_Release(&This
->IUnknown_iface
);
3272 return TYPE_E_CANTLOADLIBRARY
;
3275 /****************************************************************************
3278 * find the type of the typelib file and map the typelib resource into
3282 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3283 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3285 ITypeLibImpl
*entry
;
3288 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3289 LPVOID pBase
= NULL
;
3290 DWORD dwTLBLength
= 0;
3291 IUnknown
*pFile
= NULL
;
3296 index_str
= wcsrchr(pszFileName
, '\\');
3297 if(index_str
&& *++index_str
!= '\0')
3300 LONG idx
= wcstol(index_str
, &end_ptr
, 10);
3301 if(*end_ptr
== '\0')
3303 int str_len
= index_str
- pszFileName
- 1;
3305 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3306 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3311 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3313 if(wcschr(file
, '\\'))
3315 lstrcpyW(pszPath
, file
);
3319 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3320 pszPath
[len
] = '\\';
3321 memcpy(pszPath
+ len
+ 1, file
, (lstrlenW(file
) + 1) * sizeof(WCHAR
));
3325 if(file
!= pszFileName
) heap_free(file
);
3327 h
= CreateFileW(pszPath
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3328 if(h
!= INVALID_HANDLE_VALUE
){
3329 FILE_NAME_INFORMATION size_info
;
3332 /* GetFileInformationByHandleEx returns the path of the file without
3333 * WOW64 redirection */
3334 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, &size_info
, sizeof(size_info
));
3335 if(br
|| GetLastError() == ERROR_MORE_DATA
){
3336 FILE_NAME_INFORMATION
*info
;
3337 DWORD size
= sizeof(*info
) + size_info
.FileNameLength
+ sizeof(WCHAR
);
3339 info
= HeapAlloc(GetProcessHeap(), 0, size
);
3341 br
= GetFileInformationByHandleEx(h
, FileNameInfo
, info
, size
);
3343 info
->FileName
[info
->FileNameLength
/ sizeof(WCHAR
)] = 0;
3344 lstrcpynW(pszPath
+ 2, info
->FileName
, cchPath
- 2);
3347 HeapFree(GetProcessHeap(), 0, info
);
3353 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3355 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3356 EnterCriticalSection(&cache_section
);
3357 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3359 if (!wcsicmp(entry
->path
, pszPath
) && entry
->index
== index
)
3361 TRACE("cache hit\n");
3362 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3363 ITypeLib2_AddRef(*ppTypeLib
);
3364 LeaveCriticalSection(&cache_section
);
3368 LeaveCriticalSection(&cache_section
);
3370 /* now actually load and parse the typelib */
3372 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3373 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3374 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3375 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3376 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3379 if (dwTLBLength
>= 4)
3381 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3382 if (dwSignature
== MSFT_SIGNATURE
)
3383 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3384 else if (dwSignature
== SLTG_SIGNATURE
)
3385 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3388 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3389 ret
= TYPE_E_CANTLOADLIBRARY
;
3393 ret
= TYPE_E_CANTLOADLIBRARY
;
3394 IUnknown_Release(pFile
);
3398 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3400 TRACE("adding to cache\n");
3401 impl
->path
= heap_alloc((lstrlenW(pszPath
)+1) * sizeof(WCHAR
));
3402 lstrcpyW(impl
->path
, pszPath
);
3403 /* We should really canonicalise the path here. */
3404 impl
->index
= index
;
3406 /* FIXME: check if it has added already in the meantime */
3407 EnterCriticalSection(&cache_section
);
3408 list_add_head(&tlb_cache
, &impl
->entry
);
3409 LeaveCriticalSection(&cache_section
);
3415 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3417 ret
= TYPE_E_CANTLOADLIBRARY
;
3424 /*================== ITypeLib(2) Methods ===================================*/
3426 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3428 ITypeLibImpl
* pTypeLibImpl
;
3430 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3431 if (!pTypeLibImpl
) return NULL
;
3433 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3434 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3435 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3436 pTypeLibImpl
->ref
= 1;
3438 list_init(&pTypeLibImpl
->implib_list
);
3439 list_init(&pTypeLibImpl
->custdata_list
);
3440 list_init(&pTypeLibImpl
->name_list
);
3441 list_init(&pTypeLibImpl
->string_list
);
3442 list_init(&pTypeLibImpl
->guid_list
);
3443 list_init(&pTypeLibImpl
->ref_list
);
3444 pTypeLibImpl
->dispatch_href
= -1;
3446 return pTypeLibImpl
;
3449 /****************************************************************************
3450 * ITypeLib2_Constructor_MSFT
3452 * loading an MSFT typelib from an in-memory image
3454 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3458 MSFT_Header tlbHeader
;
3459 MSFT_SegDir tlbSegDir
;
3460 ITypeLibImpl
* pTypeLibImpl
;
3463 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3465 pTypeLibImpl
= TypeLibImpl_Constructor();
3466 if (!pTypeLibImpl
) return NULL
;
3468 /* get pointer to beginning of typelib data */
3472 cx
.pLibInfo
= pTypeLibImpl
;
3473 cx
.length
= dwTLBLength
;
3476 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3477 TRACE_(typelib
)("header:\n");
3478 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3479 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3480 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3483 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3485 /* there is a small amount of information here until the next important
3487 * the segment directory . Try to calculate the amount of data */
3488 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3490 /* now read the segment directory */
3491 TRACE("read segment directory (at %d)\n",lPSegDir
);
3492 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3493 cx
.pTblDir
= &tlbSegDir
;
3495 /* just check two entries */
3496 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3498 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3499 heap_free(pTypeLibImpl
);
3503 MSFT_ReadAllNames(&cx
);
3504 MSFT_ReadAllStrings(&cx
);
3505 MSFT_ReadAllGuids(&cx
);
3507 /* now fill our internal data */
3508 /* TLIBATTR fields */
3509 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3511 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3512 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3513 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3514 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3515 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3517 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3518 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3520 /* name, eventually add to a hash table */
3521 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3524 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3525 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3527 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3530 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3531 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3534 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3537 if(tlbHeader
.CustomDataOffset
>= 0)
3539 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3542 /* fill in type descriptions */
3543 if(tlbSegDir
.pTypdescTab
.length
> 0)
3545 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3547 pTypeLibImpl
->ctTypeDesc
= cTD
;
3548 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3549 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3552 /* FIXME: add several sanity checks here */
3553 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3554 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3556 /* FIXME: check safearray */
3558 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3560 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3562 else if(td
[0] == VT_CARRAY
)
3564 /* array descr table here */
3565 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3567 else if(td
[0] == VT_USERDEFINED
)
3569 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3571 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3574 /* second time around to fill the array subscript info */
3577 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3578 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3580 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3581 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3584 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3586 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3588 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3590 for(j
= 0; j
<td
[2]; j
++)
3592 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3593 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3594 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3595 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3600 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3601 ERR("didn't find array description data\n");
3606 /* imported type libs */
3607 if(tlbSegDir
.pImpFiles
.offset
>0)
3610 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3613 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3617 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3618 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3619 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3621 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3622 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3623 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3624 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3627 name
= heap_alloc_zero(size
+1);
3628 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3629 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3632 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3633 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3635 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3639 MSFT_ReadAllRefs(&cx
);
3641 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3644 if(tlbHeader
.nrtypeinfos
>= 0 )
3646 ITypeInfoImpl
**ppTI
;
3648 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3650 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3652 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3655 (pTypeLibImpl
->TypeInfoCount
)++;
3660 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3661 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3662 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3666 TRACE("(%p)\n", pTypeLibImpl
);
3667 return &pTypeLibImpl
->ITypeLib2_iface
;
3671 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3677 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3678 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3682 guid
->Data4
[0] = s
>> 8;
3683 guid
->Data4
[1] = s
& 0xff;
3686 for(i
= 0; i
< 6; i
++) {
3687 memcpy(b
, str
+ 24 + 2 * i
, 2);
3688 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3693 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3700 bytelen
= *(const WORD
*)ptr
;
3701 if(bytelen
== 0xffff) return 2;
3703 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3704 tmp_str
= SysAllocStringLen(NULL
, len
);
3706 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3707 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3708 SysFreeString(tmp_str
);
3713 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3718 bytelen
= *(const WORD
*)ptr
;
3719 if(bytelen
== 0xffff) return 2;
3720 *str
= heap_alloc(bytelen
+ 1);
3721 memcpy(*str
, ptr
+ 2, bytelen
);
3722 (*str
)[bytelen
] = '\0';
3726 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3731 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3732 if (tlbstr
->offset
== offset
)
3736 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3737 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3738 SysFreeString(tmp_str
);
3743 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3745 char *ptr
= pLibBlk
;
3748 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3749 FIXME("libblk magic = %04x\n", w
);
3754 if((w
= *(WORD
*)ptr
) != 0xffff) {
3755 FIXME("LibBlk.res06 = %04x. Assumung string and skipping\n", w
);
3760 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3762 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3764 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3767 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3768 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3771 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3772 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3774 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3777 ptr
+= 4; /* skip res12 */
3779 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3782 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3785 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3788 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3789 ptr
+= sizeof(GUID
);
3791 return ptr
- (char*)pLibBlk
;
3794 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3799 } sltg_ref_lookup_t
;
3801 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3802 HREFTYPE
*typelib_ref
)
3804 if(table
&& typeinfo_ref
< table
->num
)
3806 *typelib_ref
= table
->refs
[typeinfo_ref
];
3810 ERR_(typelib
)("Unable to find reference\n");
3815 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3820 if((*pType
& 0xe00) == 0xe00) {
3822 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3823 pTD
= pTD
->u
.lptdesc
;
3825 switch(*pType
& 0x3f) {
3828 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3829 pTD
= pTD
->u
.lptdesc
;
3832 case VT_USERDEFINED
:
3833 pTD
->vt
= VT_USERDEFINED
;
3834 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3840 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3843 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3845 pTD
->vt
= VT_CARRAY
;
3846 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3847 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3848 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3849 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3851 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3857 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3861 pTD
->vt
= VT_SAFEARRAY
;
3862 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3863 pTD
= pTD
->u
.lptdesc
;
3867 pTD
->vt
= *pType
& 0x3f;
3876 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3877 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3879 /* Handle [in/out] first */
3880 if((*pType
& 0xc000) == 0xc000)
3881 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3882 else if(*pType
& 0x8000)
3883 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3884 else if(*pType
& 0x4000)
3885 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3887 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3890 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3893 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3895 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3899 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3904 TLBRefType
*ref_type
;
3905 sltg_ref_lookup_t
*table
;
3906 HREFTYPE typelib_ref
;
3908 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3909 FIXME("Ref magic = %x\n", pRef
->magic
);
3912 name
= ( (char*)pRef
->names
+ pRef
->number
);
3914 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3915 table
->num
= pRef
->number
>> 3;
3917 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3919 /* We don't want the first href to be 0 */
3920 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3922 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3924 unsigned int lib_offs
, type_num
;
3926 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3928 name
+= SLTG_ReadStringA(name
, &refname
);
3929 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3930 FIXME_(typelib
)("Can't sscanf ref\n");
3931 if(lib_offs
!= 0xffff) {
3934 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3935 if(import
->offset
== lib_offs
)
3938 if(&import
->entry
== &pTL
->implib_list
) {
3939 char fname
[MAX_PATH
+1];
3943 import
= heap_alloc_zero(sizeof(*import
));
3944 import
->offset
= lib_offs
;
3945 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3946 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3947 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3948 &import
->wVersionMajor
,
3949 &import
->wVersionMinor
,
3950 &import
->lcid
, fname
) != 4) {
3951 FIXME_(typelib
)("can't sscanf ref %s\n",
3952 pNameTable
+ lib_offs
+ 40);
3954 len
= strlen(fname
);
3955 if(fname
[len
-1] != '#')
3956 FIXME("fname = %s\n", fname
);
3957 fname
[len
-1] = '\0';
3958 import
->name
= TLB_MultiByteToBSTR(fname
);
3959 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3961 ref_type
->pImpTLInfo
= import
;
3963 /* Store a reference to IDispatch */
3964 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3965 pTL
->dispatch_href
= typelib_ref
;
3967 } else { /* internal ref */
3968 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3970 ref_type
->reference
= typelib_ref
;
3971 ref_type
->index
= type_num
;
3974 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3976 table
->refs
[ref
] = typelib_ref
;
3979 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3980 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3981 dump_TLBRefType(pTL
);
3985 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3986 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3988 SLTG_ImplInfo
*info
;
3989 TLBImplType
*pImplType
;
3990 /* I don't really get this structure, usually it's 0x16 bytes
3991 long, but iuser.tlb contains some that are 0x18 bytes long.
3992 That's ok because we can use the next ptr to jump to the next
3993 one. But how do we know the length of the last one? The WORD
3994 at offs 0x8 might be the clue. For now I'm just assuming that
3995 the last one is the regular 0x16 bytes. */
3997 info
= (SLTG_ImplInfo
*)pBlk
;
3999 pTI
->typeattr
.cImplTypes
++;
4000 if(info
->next
== 0xffff)
4002 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4005 info
= (SLTG_ImplInfo
*)pBlk
;
4006 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
4007 pImplType
= pTI
->impltypes
;
4009 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4010 pImplType
->implflags
= info
->impltypeflags
;
4013 if(info
->next
== 0xffff)
4016 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4017 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4019 info
++; /* see comment at top of function */
4023 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4024 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4026 TLBVarDesc
*pVarDesc
;
4027 const TLBString
*prevName
= NULL
;
4028 SLTG_Variable
*pItem
;
4032 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4034 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4035 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4037 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4039 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4040 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4041 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4045 if (pItem
->name
== 0xfffe)
4046 pVarDesc
->Name
= prevName
;
4048 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4050 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4051 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4052 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4054 if(pItem
->flags
& 0x02)
4055 pType
= &pItem
->type
;
4057 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4059 if (pItem
->flags
& ~0xda)
4060 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4062 SLTG_DoElem(pType
, pBlk
,
4063 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4065 if (TRACE_ON(typelib
)) {
4067 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4068 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4071 if (pItem
->flags
& 0x40) {
4072 TRACE_(typelib
)("VAR_DISPATCH\n");
4073 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4075 else if (pItem
->flags
& 0x10) {
4076 TRACE_(typelib
)("VAR_CONST\n");
4077 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4078 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4079 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4080 if (pItem
->flags
& 0x08)
4081 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4083 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4089 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4091 TRACE_(typelib
)("len = %u\n", len
);
4092 if (len
== 0xffff) {
4095 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4096 str
= SysAllocStringLen(NULL
, alloc_len
);
4097 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4099 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4100 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4109 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4110 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4113 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4118 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4119 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4120 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4123 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4124 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4126 if (pItem
->flags
& 0x80)
4127 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4129 prevName
= pVarDesc
->Name
;
4131 pTI
->typeattr
.cVars
= cVars
;
4134 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4135 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4137 SLTG_Function
*pFunc
;
4139 TLBFuncDesc
*pFuncDesc
;
4141 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4143 pFuncDesc
= pTI
->funcdescs
;
4144 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4145 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4150 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4151 case SLTG_FUNCTION_MAGIC
:
4152 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4154 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4155 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4157 case SLTG_STATIC_FUNCTION_MAGIC
:
4158 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4161 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4164 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4166 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4167 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4168 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4169 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4170 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4171 pFuncDesc
->funcdesc
.oVft
= (pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4173 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4174 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4176 if(pFunc
->retnextopt
& 0x80)
4177 pType
= &pFunc
->rettype
;
4179 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4181 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4183 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4184 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4185 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4187 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4189 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4190 char *paramName
= pNameTable
+ *pArg
;
4192 /* If arg type follows then paramName points to the 2nd
4193 letter of the name, else the next WORD is an offset to
4194 the arg type and paramName points to the first letter.
4195 So let's take one char off paramName and see if we're
4196 pointing at an alpha-numeric char. However if *pArg is
4197 0xffff or 0xfffe then the param has no name, the former
4198 meaning that the next WORD is the type, the latter
4199 meaning that the next WORD is an offset to the type. */
4204 else if(*pArg
== 0xfffe) {
4208 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4213 if(HaveOffs
) { /* the next word is an offset to type */
4214 pType
= (WORD
*)(pBlk
+ *pArg
);
4215 SLTG_DoElem(pType
, pBlk
,
4216 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4221 pArg
= SLTG_DoElem(pArg
, pBlk
,
4222 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4225 /* Are we an optional param ? */
4226 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4227 pFuncDesc
->funcdesc
.cParamsOpt
)
4228 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4231 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4232 paramName
- pNameTable
, pTI
->pTypeLib
);
4234 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4238 pTI
->typeattr
.cFuncs
= cFuncs
;
4241 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4242 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4243 SLTG_TypeInfoTail
*pTITail
)
4246 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4248 if(pTIHeader
->href_table
!= 0xffffffff) {
4249 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4255 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4256 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4258 heap_free(ref_lookup
);
4262 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4263 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4264 const SLTG_TypeInfoTail
*pTITail
)
4267 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4269 if(pTIHeader
->href_table
!= 0xffffffff) {
4270 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4276 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4277 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4280 if (pTITail
->funcs_off
!= 0xffff)
4281 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4283 heap_free(ref_lookup
);
4285 if (TRACE_ON(typelib
))
4286 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4289 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4290 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4291 const SLTG_TypeInfoTail
*pTITail
)
4293 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4296 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4297 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4298 const SLTG_TypeInfoTail
*pTITail
)
4301 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4303 if (pTITail
->simple_alias
) {
4304 /* if simple alias, no more processing required */
4305 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4306 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4310 if(pTIHeader
->href_table
!= 0xffffffff) {
4311 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4315 /* otherwise it is an offset to a type */
4316 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4318 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4319 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4321 heap_free(ref_lookup
);
4324 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4325 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4326 const SLTG_TypeInfoTail
*pTITail
)
4328 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4329 if (pTIHeader
->href_table
!= 0xffffffff)
4330 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4333 if (pTITail
->vars_off
!= 0xffff)
4334 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4336 if (pTITail
->funcs_off
!= 0xffff)
4337 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4339 if (pTITail
->impls_off
!= 0xffff)
4340 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4342 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4343 * of dispinterface functions including the IDispatch ones, so
4344 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4345 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4347 heap_free(ref_lookup
);
4348 if (TRACE_ON(typelib
))
4349 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4352 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4353 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4354 const SLTG_TypeInfoTail
*pTITail
)
4356 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4359 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4360 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4361 const SLTG_TypeInfoTail
*pTITail
)
4363 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4364 if (pTIHeader
->href_table
!= 0xffffffff)
4365 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4368 if (pTITail
->vars_off
!= 0xffff)
4369 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4371 if (pTITail
->funcs_off
!= 0xffff)
4372 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4373 heap_free(ref_lookup
);
4374 if (TRACE_ON(typelib
))
4378 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4379 manageable copy of it into this */
4392 } SLTG_InternalOtherTypeInfo
;
4394 /****************************************************************************
4395 * ITypeLib2_Constructor_SLTG
4397 * loading a SLTG typelib from an in-memory image
4399 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4401 ITypeLibImpl
*pTypeLibImpl
;
4402 SLTG_Header
*pHeader
;
4403 SLTG_BlkEntry
*pBlkEntry
;
4407 LPVOID pBlk
, pFirstBlk
;
4408 SLTG_LibBlk
*pLibBlk
;
4409 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4410 char *pAfterOTIBlks
= NULL
;
4411 char *pNameTable
, *ptr
;
4414 ITypeInfoImpl
**ppTypeInfoImpl
;
4416 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4419 pTypeLibImpl
= TypeLibImpl_Constructor();
4420 if (!pTypeLibImpl
) return NULL
;
4424 TRACE_(typelib
)("header:\n");
4425 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4426 pHeader
->nrOfFileBlks
);
4427 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4428 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4429 pHeader
->SLTG_magic
);
4433 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4434 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4436 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4437 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4439 /* Next we have a magic block */
4440 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4442 /* Let's see if we're still in sync */
4443 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4444 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4445 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4448 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4449 sizeof(SLTG_DIR_MAGIC
))) {
4450 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4454 pIndex
= (SLTG_Index
*)(pMagic
+1);
4456 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4458 pFirstBlk
= pPad9
+ 1;
4460 /* We'll set up a ptr to the main library block, which is the last one. */
4462 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4463 pBlkEntry
[order
].next
!= 0;
4464 order
= pBlkEntry
[order
].next
- 1) {
4465 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4469 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4471 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4476 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4478 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4481 ptr
= (char*)pLibBlk
+ len
;
4483 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4487 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4489 w
= *(WORD
*)(ptr
+ 2);
4492 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4493 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4494 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4496 w
= *(WORD
*)(ptr
+ 4 + len
);
4498 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4500 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4501 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4502 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4504 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4505 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4506 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4508 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4509 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4512 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4513 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4514 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4515 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4516 len
+= sizeof(SLTG_OtherTypeInfo
);
4520 pAfterOTIBlks
= ptr
;
4522 /* Skip this WORD and get the next DWORD */
4523 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4525 /* Now add this to pLibBLk look at what we're pointing at and
4526 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4527 dust and we should be pointing at the beginning of the name
4530 pNameTable
= (char*)pLibBlk
+ len
;
4532 switch(*(WORD
*)pNameTable
) {
4539 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4543 pNameTable
+= 0x216;
4547 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4549 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4552 /* Hopefully we now have enough ptrs set up to actually read in
4553 some TypeInfos. It's not clear which order to do them in, so
4554 I'll just follow the links along the BlkEntry chain and read
4555 them in the order in which they are in the file */
4557 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4558 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4560 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4561 pBlkEntry
[order
].next
!= 0;
4562 order
= pBlkEntry
[order
].next
- 1, i
++) {
4564 SLTG_TypeInfoHeader
*pTIHeader
;
4565 SLTG_TypeInfoTail
*pTITail
;
4566 SLTG_MemberHeader
*pMemHeader
;
4568 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4569 FIXME_(typelib
)("Index strings don't match\n");
4570 heap_free(pOtherTypeInfoBlks
);
4575 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4576 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4577 heap_free(pOtherTypeInfoBlks
);
4580 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4581 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4582 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4584 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4585 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4586 (*ppTypeInfoImpl
)->index
= i
;
4587 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4588 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4589 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4590 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4591 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4592 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4593 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4594 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4596 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4597 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4599 if((pTIHeader
->typeflags1
& 7) != 2)
4600 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4601 if(pTIHeader
->typeflags3
!= 2)
4602 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4604 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4605 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4606 typekind_desc
[pTIHeader
->typekind
],
4607 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4608 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4610 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4612 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4614 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4615 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4616 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4618 switch(pTIHeader
->typekind
) {
4620 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4621 pTIHeader
, pTITail
);
4625 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4626 pTIHeader
, pTITail
);
4629 case TKIND_INTERFACE
:
4630 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4631 pTIHeader
, pTITail
);
4635 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4636 pTIHeader
, pTITail
);
4640 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4641 pTIHeader
, pTITail
);
4644 case TKIND_DISPATCH
:
4645 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4646 pTIHeader
, pTITail
);
4650 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4651 pTIHeader
, pTITail
);
4655 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4660 /* could get cFuncs, cVars and cImplTypes from here
4661 but we've already set those */
4662 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4678 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4681 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4682 FIXME("Somehow processed %d TypeInfos\n", i
);
4683 heap_free(pOtherTypeInfoBlks
);
4687 heap_free(pOtherTypeInfoBlks
);
4688 return &pTypeLibImpl
->ITypeLib2_iface
;
4691 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4693 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4695 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4697 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4698 IsEqualIID(riid
,&IID_ITypeLib
)||
4699 IsEqualIID(riid
,&IID_ITypeLib2
))
4701 *ppv
= &This
->ITypeLib2_iface
;
4703 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4704 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4706 *ppv
= &This
->ICreateTypeLib2_iface
;
4711 TRACE("-- Interface: E_NOINTERFACE\n");
4712 return E_NOINTERFACE
;
4715 IUnknown_AddRef((IUnknown
*)*ppv
);
4719 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4721 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4722 ULONG ref
= InterlockedIncrement(&This
->ref
);
4724 TRACE("(%p) ref=%u\n", This
, ref
);
4729 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4731 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4732 ULONG ref
= InterlockedDecrement(&This
->ref
);
4734 TRACE("(%p) ref=%u\n",This
, ref
);
4738 TLBImpLib
*pImpLib
, *pImpLibNext
;
4739 TLBRefType
*ref_type
, *ref_type_next
;
4740 TLBString
*tlbstr
, *tlbstr_next
;
4741 TLBGuid
*tlbguid
, *tlbguid_next
;
4744 /* remove cache entry */
4747 TRACE("removing from cache list\n");
4748 EnterCriticalSection(&cache_section
);
4749 if(This
->entry
.next
)
4750 list_remove(&This
->entry
);
4751 LeaveCriticalSection(&cache_section
);
4752 heap_free(This
->path
);
4754 TRACE(" destroying ITypeLib(%p)\n",This
);
4756 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4757 list_remove(&tlbstr
->entry
);
4758 SysFreeString(tlbstr
->str
);
4762 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4763 list_remove(&tlbstr
->entry
);
4764 SysFreeString(tlbstr
->str
);
4768 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4769 list_remove(&tlbguid
->entry
);
4773 TLB_FreeCustData(&This
->custdata_list
);
4775 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4776 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4777 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4779 heap_free(This
->pTypeDesc
);
4781 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4783 if (pImpLib
->pImpTypeLib
)
4784 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4785 SysFreeString(pImpLib
->name
);
4787 list_remove(&pImpLib
->entry
);
4791 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4793 list_remove(&ref_type
->entry
);
4794 heap_free(ref_type
);
4797 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4798 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4799 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4801 heap_free(This
->typeinfos
);
4809 /* ITypeLib::GetTypeInfoCount
4811 * Returns the number of type descriptions in the type library
4813 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4815 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4816 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4817 return This
->TypeInfoCount
;
4820 /* ITypeLib::GetTypeInfo
4822 * retrieves the specified type description in the library.
4824 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4827 ITypeInfo
**ppTInfo
)
4829 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4831 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4834 return E_INVALIDARG
;
4836 if(index
>= This
->TypeInfoCount
)
4837 return TYPE_E_ELEMENTNOTFOUND
;
4839 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4840 ITypeInfo_AddRef(*ppTInfo
);
4846 /* ITypeLibs::GetTypeInfoType
4848 * Retrieves the type of a type description.
4850 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4855 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4857 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4860 return E_INVALIDARG
;
4862 if(index
>= This
->TypeInfoCount
)
4863 return TYPE_E_ELEMENTNOTFOUND
;
4865 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4870 /* ITypeLib::GetTypeInfoOfGuid
4872 * Retrieves the type description that corresponds to the specified GUID.
4875 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4878 ITypeInfo
**ppTInfo
)
4880 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4883 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4885 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4886 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4887 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4888 ITypeInfo_AddRef(*ppTInfo
);
4893 return TYPE_E_ELEMENTNOTFOUND
;
4896 /* ITypeLib::GetLibAttr
4898 * Retrieves the structure that contains the library's attributes.
4901 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4905 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4907 TRACE("(%p, %p)\n", This
, attr
);
4909 if (!attr
) return E_INVALIDARG
;
4911 *attr
= heap_alloc(sizeof(**attr
));
4912 if (!*attr
) return E_OUTOFMEMORY
;
4914 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4915 (*attr
)->lcid
= This
->set_lcid
;
4916 (*attr
)->syskind
= This
->syskind
;
4917 (*attr
)->wMajorVerNum
= This
->ver_major
;
4918 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4919 (*attr
)->wLibFlags
= This
->libflags
;
4924 /* ITypeLib::GetTypeComp
4926 * Enables a client compiler to bind to a library's types, variables,
4927 * constants, and global functions.
4930 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4932 ITypeComp
**ppTComp
)
4934 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4936 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4937 *ppTComp
= &This
->ITypeComp_iface
;
4938 ITypeComp_AddRef(*ppTComp
);
4943 /* ITypeLib::GetDocumentation
4945 * Retrieves the library's documentation string, the complete Help file name
4946 * and path, and the context identifier for the library Help topic in the Help
4949 * On a successful return all non-null BSTR pointers will have been set,
4952 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4956 BSTR
*pBstrDocString
,
4957 DWORD
*pdwHelpContext
,
4958 BSTR
*pBstrHelpFile
)
4960 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4961 HRESULT result
= E_INVALIDARG
;
4964 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4966 pBstrName
, pBstrDocString
,
4967 pdwHelpContext
, pBstrHelpFile
);
4971 /* documentation for the typelib */
4976 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4984 if (This
->DocString
)
4986 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4990 *pBstrDocString
= NULL
;
4994 *pdwHelpContext
= This
->dwHelpContext
;
5000 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5004 *pBstrHelpFile
= NULL
;
5011 /* for a typeinfo */
5012 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5014 if(SUCCEEDED(result
))
5016 result
= ITypeInfo_GetDocumentation(pTInfo
,
5020 pdwHelpContext
, pBstrHelpFile
);
5022 ITypeInfo_Release(pTInfo
);
5027 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5029 if (pBstrName
) SysFreeString (*pBstrName
);
5031 return STG_E_INSUFFICIENTMEMORY
;
5036 * Indicates whether a passed-in string contains the name of a type or member
5037 * described in the library.
5040 static HRESULT WINAPI
ITypeLib2_fnIsName(
5046 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5048 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5050 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5054 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5055 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5056 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5057 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5058 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5060 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5061 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5062 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5063 goto ITypeLib2_fnIsName_exit
;
5066 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5067 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5068 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5074 ITypeLib2_fnIsName_exit
:
5075 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5076 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5081 /* ITypeLib::FindName
5083 * Finds occurrences of a type description in a type library. This may be used
5084 * to quickly verify that a name exists in a type library.
5087 static HRESULT WINAPI
ITypeLib2_fnFindName(
5091 ITypeInfo
**ppTInfo
,
5095 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5100 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5102 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5103 return E_INVALIDARG
;
5105 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5106 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5107 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5111 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5112 memid
[count
] = MEMBERID_NIL
;
5113 goto ITypeLib2_fnFindName_exit
;
5116 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5117 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5119 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5120 memid
[count
] = func
->funcdesc
.memid
;
5121 goto ITypeLib2_fnFindName_exit
;
5125 var
= TLB_get_vardesc_by_name(pTInfo
->vardescs
, pTInfo
->typeattr
.cVars
, name
);
5127 memid
[count
] = var
->vardesc
.memid
;
5128 goto ITypeLib2_fnFindName_exit
;
5132 ITypeLib2_fnFindName_exit
:
5133 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5134 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5137 TRACE("found %d typeinfos\n", count
);
5144 /* ITypeLib::ReleaseTLibAttr
5146 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5149 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5151 TLIBATTR
*pTLibAttr
)
5153 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5154 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5155 heap_free(pTLibAttr
);
5158 /* ITypeLib2::GetCustData
5160 * gets the custom data
5162 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5167 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5168 TLBCustData
*pCData
;
5170 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5172 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5174 return TYPE_E_ELEMENTNOTFOUND
;
5176 VariantInit(pVarVal
);
5177 VariantCopy(pVarVal
, &pCData
->data
);
5182 /* ITypeLib2::GetLibStatistics
5184 * Returns statistics about a type library that are required for efficient
5185 * sizing of hash tables.
5188 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5190 ULONG
*pcUniqueNames
,
5191 ULONG
*pcchUniqueNames
)
5193 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5195 FIXME("(%p): stub!\n", This
);
5197 if(pcUniqueNames
) *pcUniqueNames
=1;
5198 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5202 /* ITypeLib2::GetDocumentation2
5204 * Retrieves the library's documentation string, the complete Help file name
5205 * and path, the localization context to use, and the context ID for the
5206 * library Help topic in the Help file.
5209 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5213 BSTR
*pbstrHelpString
,
5214 DWORD
*pdwHelpStringContext
,
5215 BSTR
*pbstrHelpStringDll
)
5217 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5221 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5223 /* the help string should be obtained from the helpstringdll,
5224 * using the _DLLGetDocumentation function, based on the supplied
5225 * lcid. Nice to do sometime...
5229 /* documentation for the typelib */
5231 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5232 if(pdwHelpStringContext
)
5233 *pdwHelpStringContext
=This
->dwHelpContext
;
5234 if(pbstrHelpStringDll
)
5235 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5241 /* for a typeinfo */
5242 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5244 if(SUCCEEDED(result
))
5246 ITypeInfo2
* pTInfo2
;
5247 result
= ITypeInfo_QueryInterface(pTInfo
,
5249 (LPVOID
*) &pTInfo2
);
5251 if(SUCCEEDED(result
))
5253 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5257 pdwHelpStringContext
,
5258 pbstrHelpStringDll
);
5260 ITypeInfo2_Release(pTInfo2
);
5263 ITypeInfo_Release(pTInfo
);
5269 static HRESULT
TLB_copy_all_custdata(struct list
*custdata_list
, CUSTDATA
*pCustData
)
5271 TLBCustData
*pCData
;
5275 ct
= list_count(custdata_list
);
5277 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5278 if(!pCustData
->prgCustData
)
5279 return E_OUTOFMEMORY
;
5281 pCustData
->cCustData
= ct
;
5283 cdi
= pCustData
->prgCustData
;
5284 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5285 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5286 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5294 /* ITypeLib2::GetAllCustData
5296 * Gets all custom data items for the library.
5299 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5301 CUSTDATA
*pCustData
)
5303 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5304 TRACE("(%p)->(%p)\n", This
, pCustData
);
5305 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5308 static const ITypeLib2Vtbl tlbvt
= {
5309 ITypeLib2_fnQueryInterface
,
5311 ITypeLib2_fnRelease
,
5312 ITypeLib2_fnGetTypeInfoCount
,
5313 ITypeLib2_fnGetTypeInfo
,
5314 ITypeLib2_fnGetTypeInfoType
,
5315 ITypeLib2_fnGetTypeInfoOfGuid
,
5316 ITypeLib2_fnGetLibAttr
,
5317 ITypeLib2_fnGetTypeComp
,
5318 ITypeLib2_fnGetDocumentation
,
5320 ITypeLib2_fnFindName
,
5321 ITypeLib2_fnReleaseTLibAttr
,
5323 ITypeLib2_fnGetCustData
,
5324 ITypeLib2_fnGetLibStatistics
,
5325 ITypeLib2_fnGetDocumentation2
,
5326 ITypeLib2_fnGetAllCustData
5330 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5332 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5334 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5337 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5339 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5341 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5344 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5346 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5348 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5351 static HRESULT WINAPI
ITypeLibComp_fnBind(
5356 ITypeInfo
** ppTInfo
,
5357 DESCKIND
* pDescKind
,
5360 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5361 BOOL typemismatch
= FALSE
;
5364 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5366 *pDescKind
= DESCKIND_NONE
;
5367 pBindPtr
->lptcomp
= NULL
;
5370 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5371 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5372 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5374 /* FIXME: check wFlags here? */
5375 /* FIXME: we should use a hash table to look this info up using lHash
5376 * instead of an O(n) search */
5377 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5378 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5380 if (pTypeInfo
->Name
&& !wcscmp(pTypeInfo
->Name
->str
, szName
))
5382 *pDescKind
= DESCKIND_TYPECOMP
;
5383 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5384 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5385 TRACE("module or enum: %s\n", debugstr_w(szName
));
5390 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5391 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5393 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5396 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5397 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5399 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5402 else if (hr
== TYPE_E_TYPEMISMATCH
)
5403 typemismatch
= TRUE
;
5406 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5407 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5409 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5411 ITypeInfo
*subtypeinfo
;
5413 DESCKIND subdesckind
;
5415 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5416 &subtypeinfo
, &subdesckind
, &subbindptr
);
5417 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5419 TYPEDESC tdesc_appobject
;
5420 const VARDESC vardesc_appobject
=
5423 NULL
, /* lpstrSchema */
5438 VAR_STATIC
/* varkind */
5441 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5442 tdesc_appobject
.vt
= VT_USERDEFINED
;
5444 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5446 /* cleanup things filled in by Bind call so we can put our
5447 * application object data in there instead */
5448 switch (subdesckind
)
5450 case DESCKIND_FUNCDESC
:
5451 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5453 case DESCKIND_VARDESC
:
5454 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5459 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5461 if (pTypeInfo
->hreftype
== -1)
5462 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5464 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5468 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5469 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5470 ITypeInfo_AddRef(*ppTInfo
);
5473 else if (hr
== TYPE_E_TYPEMISMATCH
)
5474 typemismatch
= TRUE
;
5480 TRACE("type mismatch %s\n", debugstr_w(szName
));
5481 return TYPE_E_TYPEMISMATCH
;
5485 TRACE("name not found %s\n", debugstr_w(szName
));
5490 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5494 ITypeInfo
** ppTInfo
,
5495 ITypeComp
** ppTComp
)
5497 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5498 ITypeInfoImpl
*info
;
5500 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5502 if(!szName
|| !ppTInfo
|| !ppTComp
)
5503 return E_INVALIDARG
;
5505 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, szName
);
5512 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5513 ITypeInfo_AddRef(*ppTInfo
);
5514 *ppTComp
= &info
->ITypeComp_iface
;
5515 ITypeComp_AddRef(*ppTComp
);
5520 static const ITypeCompVtbl tlbtcvt
=
5523 ITypeLibComp_fnQueryInterface
,
5524 ITypeLibComp_fnAddRef
,
5525 ITypeLibComp_fnRelease
,
5527 ITypeLibComp_fnBind
,
5528 ITypeLibComp_fnBindType
5531 /*================== ITypeInfo(2) Methods ===================================*/
5532 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5534 ITypeInfoImpl
*pTypeInfoImpl
;
5536 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5539 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5540 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5541 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5542 pTypeInfoImpl
->ref
= 0;
5543 pTypeInfoImpl
->hreftype
= -1;
5544 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5545 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5546 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5547 list_init(pTypeInfoImpl
->pcustdata_list
);
5549 TRACE("(%p)\n", pTypeInfoImpl
);
5550 return pTypeInfoImpl
;
5553 /* ITypeInfo::QueryInterface
5555 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5560 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5562 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5565 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5566 IsEqualIID(riid
,&IID_ITypeInfo
)||
5567 IsEqualIID(riid
,&IID_ITypeInfo2
))
5568 *ppvObject
= &This
->ITypeInfo2_iface
;
5569 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5570 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5571 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5572 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5573 *ppvObject
= &This
->ITypeComp_iface
;
5576 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5577 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5580 TRACE("-- Interface: E_NOINTERFACE\n");
5581 return E_NOINTERFACE
;
5584 /* ITypeInfo::AddRef
5586 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5588 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5589 ULONG ref
= InterlockedIncrement(&This
->ref
);
5591 TRACE("(%p)->ref is %u\n",This
, ref
);
5593 if (ref
== 1 /* incremented from 0 */)
5594 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5599 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5603 TRACE("destroying ITypeInfo(%p)\n",This
);
5605 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5608 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5609 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5611 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5612 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5613 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5614 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5616 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5617 heap_free(pFInfo
->pParamDesc
);
5618 TLB_FreeCustData(&pFInfo
->custdata_list
);
5620 heap_free(This
->funcdescs
);
5622 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5624 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5625 if (pVInfo
->vardesc_create
) {
5626 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5627 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5628 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5629 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5631 TLB_FreeCustData(&pVInfo
->custdata_list
);
5633 heap_free(This
->vardescs
);
5635 if(This
->impltypes
){
5636 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5637 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5638 TLB_FreeCustData(&pImpl
->custdata_list
);
5640 heap_free(This
->impltypes
);
5643 TLB_FreeCustData(&This
->custdata_list
);
5648 /* ITypeInfo::Release
5650 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5652 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5653 ULONG ref
= InterlockedDecrement(&This
->ref
);
5655 TRACE("(%p)->(%u)\n",This
, ref
);
5659 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5660 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5661 if (not_attached_to_typelib
)
5663 /* otherwise This will be freed when typelib is freed */
5669 /* ITypeInfo::GetTypeAttr
5671 * Retrieves a TYPEATTR structure that contains the attributes of the type
5675 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5676 LPTYPEATTR
*ppTypeAttr
)
5678 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5681 TRACE("(%p)\n",This
);
5683 size
= sizeof(**ppTypeAttr
);
5684 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5685 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5687 *ppTypeAttr
= heap_alloc(size
);
5689 return E_OUTOFMEMORY
;
5691 **ppTypeAttr
= This
->typeattr
;
5692 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5694 if (This
->tdescAlias
)
5695 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5697 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5698 /* This should include all the inherited funcs */
5699 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5700 /* This is always the size of IDispatch's vtbl */
5701 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5702 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5707 /* ITypeInfo::GetTypeComp
5709 * Retrieves the ITypeComp interface for the type description, which enables a
5710 * client compiler to bind to the type description's members.
5713 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5714 ITypeComp
* *ppTComp
)
5716 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5718 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5720 *ppTComp
= &This
->ITypeComp_iface
;
5721 ITypeComp_AddRef(*ppTComp
);
5725 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5727 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5728 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5729 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5733 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5736 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5737 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5739 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5740 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5741 *buffer
+= sizeof(PARAMDESCEX
);
5742 *pparamdescex_dest
= *pparamdescex_src
;
5743 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5744 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5745 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5746 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5749 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5753 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5755 UINT len
= SysStringLen(str
), i
;
5756 for (i
= 0; i
< len
; ++i
)
5762 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5764 if (V_VT(var
) == VT_INT
)
5765 return VariantChangeType(var
, var
, 0, VT_I4
);
5766 else if (V_VT(var
) == VT_UINT
)
5767 return VariantChangeType(var
, var
, 0, VT_UI4
);
5768 else if (V_VT(var
) == VT_BSTR
)
5769 return TLB_SanitizeBSTR(V_BSTR(var
));
5774 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5776 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5777 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5780 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5784 SIZE_T size
= sizeof(*src
);
5788 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5789 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5790 for (i
= 0; i
< src
->cParams
; i
++)
5792 size
+= sizeof(ELEMDESC
);
5793 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5796 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5797 if (!dest
) return E_OUTOFMEMORY
;
5800 if (dispinterface
) /* overwrite funckind */
5801 dest
->funckind
= FUNC_DISPATCH
;
5802 buffer
= (char *)(dest
+ 1);
5804 dest
->oVft
= dest
->oVft
& 0xFFFC;
5806 if (dest
->cScodes
) {
5807 dest
->lprgscode
= (SCODE
*)buffer
;
5808 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5809 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5811 dest
->lprgscode
= NULL
;
5813 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5816 SysFreeString((BSTR
)dest
);
5820 if (dest
->cParams
) {
5821 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5822 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5823 for (i
= 0; i
< src
->cParams
; i
++)
5825 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5831 /* undo the above actions */
5832 for (i
= i
- 1; i
>= 0; i
--)
5833 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5834 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5835 SysFreeString((BSTR
)dest
);
5839 dest
->lprgelemdescParam
= NULL
;
5841 /* special treatment for dispinterfaces: this makes functions appear
5842 * to return their [retval] value when it is really returning an
5844 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5846 if (dest
->cParams
&&
5847 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5849 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5850 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5852 ERR("elemdesc should have started with VT_PTR instead of:\n");
5854 dump_ELEMDESC(elemdesc
);
5855 return E_UNEXPECTED
;
5858 /* copy last parameter to the return value. we are using a flat
5859 * buffer so there is no danger of leaking memory in
5861 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5863 /* remove the last parameter */
5867 /* otherwise this function is made to appear to have no return
5869 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5877 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5879 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5880 if (var_desc
->varkind
== VAR_CONST
)
5881 VariantClear(var_desc
->u
.lpvarValue
);
5882 SysFreeString((BSTR
)var_desc
);
5885 HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const FUNCDESC
**ppFuncDesc
)
5887 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5889 if (index
>= This
->typeattr
.cFuncs
)
5890 return TYPE_E_ELEMENTNOTFOUND
;
5892 *ppFuncDesc
= &This
->funcdescs
[index
].funcdesc
;
5896 /* internal function to make the inherited interfaces' methods appear
5897 * part of the interface */
5898 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5899 UINT index
, const FUNCDESC
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5901 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5903 UINT implemented_funcs
= 0;
5908 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5912 ITypeInfo
*pSubTypeInfo
;
5915 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5919 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5922 &sub_funcs
, hrefoffset
);
5923 implemented_funcs
+= sub_funcs
;
5924 ITypeInfo_Release(pSubTypeInfo
);
5927 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5931 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5935 if (index
< implemented_funcs
)
5936 return E_INVALIDARG
;
5937 return ITypeInfoImpl_GetInternalFuncDesc(iface
, index
- implemented_funcs
,
5941 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5943 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5946 switch (pTypeDesc
->vt
)
5948 case VT_USERDEFINED
:
5949 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5953 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5956 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5964 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5967 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5968 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5969 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5972 /* ITypeInfo::GetFuncDesc
5974 * Retrieves the FUNCDESC structure that contains information about a
5975 * specified function.
5978 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5979 LPFUNCDESC
*ppFuncDesc
)
5981 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5982 const FUNCDESC
*internal_funcdesc
;
5984 UINT hrefoffset
= 0;
5986 TRACE("(%p) index %d\n", This
, index
);
5989 return E_INVALIDARG
;
5991 if (This
->needs_layout
)
5992 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
5994 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5995 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc((ITypeInfo
*)iface
, index
,
5996 &internal_funcdesc
, NULL
,
5999 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6000 &internal_funcdesc
);
6003 WARN("description for function %d not found\n", index
);
6007 hr
= TLB_AllocAndInitFuncDesc(
6010 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6012 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
6013 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6015 TRACE("-- 0x%08x\n", hr
);
6019 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6023 SIZE_T size
= sizeof(*src
);
6026 if (src
->lpstrSchema
) size
+= (lstrlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6027 if (src
->varkind
== VAR_CONST
)
6028 size
+= sizeof(VARIANT
);
6029 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6031 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6032 if (!dest
) return E_OUTOFMEMORY
;
6035 buffer
= (char *)(dest
+ 1);
6036 if (src
->lpstrSchema
)
6039 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6040 len
= lstrlenW(src
->lpstrSchema
);
6041 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6042 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6045 if (src
->varkind
== VAR_CONST
)
6049 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6050 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6051 buffer
+= sizeof(VARIANT
);
6052 VariantInit(dest
->u
.lpvarValue
);
6053 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6056 SysFreeString((BSTR
)dest
);
6060 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6063 if (src
->varkind
== VAR_CONST
)
6064 VariantClear(dest
->u
.lpvarValue
);
6065 SysFreeString((BSTR
)dest
);
6072 /* ITypeInfo::GetVarDesc
6074 * Retrieves a VARDESC structure that describes the specified variable.
6077 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6078 LPVARDESC
*ppVarDesc
)
6080 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6081 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6083 TRACE("(%p) index %d\n", This
, index
);
6085 if(index
>= This
->typeattr
.cVars
)
6086 return TYPE_E_ELEMENTNOTFOUND
;
6088 if (This
->needs_layout
)
6089 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6091 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6094 /* ITypeInfo_GetNames
6096 * Retrieves the variable with the specified member ID (or the name of the
6097 * property or method and its parameters) that correspond to the specified
6100 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6101 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6103 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6104 const TLBFuncDesc
*pFDesc
;
6105 const TLBVarDesc
*pVDesc
;
6107 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6110 return E_INVALIDARG
;
6114 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
6117 if(!cMaxNames
|| !pFDesc
->Name
)
6120 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6123 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6124 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6126 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6132 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
6135 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6140 if(This
->impltypes
&&
6141 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
6142 /* recursive search */
6145 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6146 if(SUCCEEDED(result
))
6148 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6149 ITypeInfo_Release(pTInfo
);
6152 WARN("Could not search inherited interface!\n");
6156 WARN("no names found\n");
6159 return TYPE_E_ELEMENTNOTFOUND
;
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 = 0x%08x\n", *pRefType
);
6220 TRACE("FAILURE -- hresult = 0x%08x\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) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6269 /* init out parameters in case of failure */
6270 for (i
= 0; i
< cNames
; i
++)
6271 pMemId
[i
] = MEMBERID_NIL
;
6273 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6275 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6276 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6277 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6278 for(i
=1; i
< cNames
; i
++){
6279 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6280 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6282 if( j
<pFDesc
->funcdesc
.cParams
)
6285 ret
=DISP_E_UNKNOWNNAME
;
6287 TRACE("-- 0x%08x\n", ret
);
6291 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, *rgszNames
);
6294 *pMemId
= pVDesc
->vardesc
.memid
;
6297 /* not found, see if it can be found in an inherited interface */
6298 if(This
->impltypes
) {
6299 /* recursive search */
6301 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6303 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6304 ITypeInfo_Release(pTInfo
);
6307 WARN("Could not search inherited interface!\n");
6309 WARN("no names found\n");
6310 return DISP_E_UNKNOWNNAME
;
6316 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6317 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6318 __ASM_GLOBAL_FUNC( call_method
,
6320 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6321 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6322 "movl %esp,%ebp\n\t"
6323 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6325 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6327 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6328 "movl 12(%ebp),%edx\n\t"
6329 "movl %esp,%edi\n\t"
6332 "subl %edx,%edi\n\t"
6333 "andl $~15,%edi\n\t"
6334 "movl %edi,%esp\n\t"
6335 "movl 12(%ebp),%ecx\n\t"
6336 "movl 16(%ebp),%esi\n\t"
6339 "1:\tcall *8(%ebp)\n\t"
6340 "subl %esp,%edi\n\t"
6341 "movl 20(%ebp),%ecx\n\t"
6342 "movl %edi,(%ecx)\n\t"
6343 "leal -8(%ebp),%esp\n\t"
6345 __ASM_CFI(".cfi_same_value %edi\n\t")
6347 __ASM_CFI(".cfi_same_value %esi\n\t")
6349 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6350 __ASM_CFI(".cfi_same_value %ebp\n\t")
6352 __ASM_GLOBAL_FUNC( call_double_method
,
6353 "jmp " __ASM_NAME("call_method") )
6355 #elif defined(__x86_64__)
6357 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6358 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6359 __ASM_GLOBAL_FUNC( call_method
,
6361 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6362 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6363 "movq %rsp,%rbp\n\t"
6364 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6366 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6368 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6369 "movq %rcx,%rax\n\t"
6372 "cmovgq %rdx,%rcx\n\t"
6373 "leaq 0(,%rcx,8),%rdx\n\t"
6374 "subq %rdx,%rsp\n\t"
6375 "andq $~15,%rsp\n\t"
6376 "movq %rsp,%rdi\n\t"
6379 "movq 0(%rsp),%rcx\n\t"
6380 "movq 8(%rsp),%rdx\n\t"
6381 "movq 16(%rsp),%r8\n\t"
6382 "movq 24(%rsp),%r9\n\t"
6383 "movq 0(%rsp),%xmm0\n\t"
6384 "movq 8(%rsp),%xmm1\n\t"
6385 "movq 16(%rsp),%xmm2\n\t"
6386 "movq 24(%rsp),%xmm3\n\t"
6388 "leaq -16(%rbp),%rsp\n\t"
6390 __ASM_CFI(".cfi_same_value %rdi\n\t")
6392 __ASM_CFI(".cfi_same_value %rsi\n\t")
6393 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6395 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6396 __ASM_CFI(".cfi_same_value %rbp\n\t")
6398 __ASM_GLOBAL_FUNC( call_double_method
,
6399 "jmp " __ASM_NAME("call_method") )
6401 #elif defined(__arm__)
6403 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6404 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6405 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6406 __ASM_GLOBAL_FUNC( call_method
,
6409 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6410 * 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)
6413 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6414 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6416 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6417 "beq 1f\n\t" /* Skip allocation if no stack args */
6418 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6419 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6420 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6421 "subs r1, r1, #4\n\t" /* Decrement count */
6422 "bgt 2b\n\t" /* Loop till done */
6426 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6428 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6429 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6431 "blx ip\n\t" /* Call the target function */
6433 "mov sp, fp\n\t" /* Clean the stack using fp */
6434 "pop {fp, pc}\n\t" /* Restore fp and return */
6436 __ASM_GLOBAL_FUNC( call_float_method
,
6437 "b " __ASM_NAME("call_method") )
6438 __ASM_GLOBAL_FUNC( call_double_method
,
6439 "b " __ASM_NAME("call_method") )
6441 #endif /* __arm__ */
6443 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6446 ITypeInfo
*tinfo2
= NULL
;
6447 TYPEATTR
*tattr
= NULL
;
6449 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6452 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6454 tdesc
->u
.hreftype
, hr
);
6457 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6460 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6461 ITypeInfo_Release(tinfo2
);
6465 switch (tattr
->typekind
)
6472 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
6475 case TKIND_INTERFACE
:
6476 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
6482 case TKIND_DISPATCH
:
6491 FIXME("TKIND_RECORD unhandled.\n");
6496 FIXME("TKIND_UNION unhandled.\n");
6501 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
6505 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6506 ITypeInfo_Release(tinfo2
);
6510 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6514 /* enforce only one level of pointer indirection */
6515 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
6517 tdesc
= tdesc
->u
.lptdesc
;
6519 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
6520 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
6521 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
6522 if ((tdesc
->vt
== VT_USERDEFINED
) ||
6523 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
6525 VARTYPE vt_userdefined
= 0;
6526 const TYPEDESC
*tdesc_userdefined
= tdesc
;
6527 if (tdesc
->vt
== VT_PTR
)
6529 vt_userdefined
= VT_BYREF
;
6530 tdesc_userdefined
= tdesc
->u
.lptdesc
;
6532 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
6534 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
6535 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
6537 *vt
|= vt_userdefined
;
6549 case VT_USERDEFINED
:
6550 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
6557 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
6558 hr
= DISP_E_BADVARTYPE
;
6562 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
6577 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
6584 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
6588 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6590 ITypeInfo_Release(tinfo2
);
6594 switch(tattr
->typekind
) {
6596 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.u
.hreftype
, guid
);
6599 case TKIND_INTERFACE
:
6600 case TKIND_DISPATCH
:
6601 *guid
= tattr
->guid
;
6605 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
6607 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
6608 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
6612 if (i
== tattr
->cImplTypes
)
6615 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
6616 if (SUCCEEDED(hres
))
6617 hres
= get_iface_guid(tinfo2
, href
, guid
);
6621 ERR("Unexpected typekind %d\n", tattr
->typekind
);
6622 hres
= E_UNEXPECTED
;
6625 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
6626 ITypeInfo_Release(tinfo2
);
6630 /***********************************************************************
6631 * DispCallFunc (OLEAUT32.@)
6633 * Invokes a function of the specified calling convention, passing the
6634 * specified arguments and returns the result.
6637 * pvInstance [I] Optional pointer to the instance whose function to invoke.
6638 * oVft [I] The offset in the vtable. See notes.
6639 * cc [I] Calling convention of the function to call.
6640 * vtReturn [I] The return type of the function.
6641 * cActuals [I] Number of parameters.
6642 * prgvt [I] The types of the parameters to pass. This is used for sizing only.
6643 * prgpvarg [I] The arguments to pass.
6644 * pvargResult [O] The return value of the function. Can be NULL.
6648 * Failure: HRESULT code.
6651 * The HRESULT return value of this function is not affected by the return
6652 * value of the user supplied function, which is returned in pvargResult.
6654 * If pvInstance is NULL then a non-object function is to be called and oVft
6655 * is the address of the function to call.
6657 * The cc parameter can be one of the following values:
6670 void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
, UINT cActuals
,
6671 VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6674 int argspos
= 0, stack_offset
;
6679 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6680 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6681 pvargResult
, V_VT(pvargResult
));
6683 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6685 FIXME("unsupported calling convention %d\n",cc
);
6686 return E_INVALIDARG
;
6689 /* maximum size for an argument is sizeof(VARIANT) */
6690 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6694 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6695 func
= vtable
[oVft
/sizeof(void *)];
6696 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6698 else func
= (void *)oVft
;
6704 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6707 WARN("invalid return type %u\n", vtReturn
);
6709 return E_INVALIDARG
;
6714 for (i
= 0; i
< cActuals
; i
++)
6716 VARIANT
*arg
= prgpvarg
[i
];
6727 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6728 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6732 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6733 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6735 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6736 args
[argspos
++] = V_BOOL(arg
);
6739 args
[argspos
++] = V_UI4(arg
);
6742 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6750 call_method( func
, argspos
, args
, &stack_offset
);
6753 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6757 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6762 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6765 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6769 if (stack_offset
&& cc
== CC_STDCALL
)
6771 WARN( "stack pointer off by %d\n", stack_offset
);
6772 return DISP_E_BADCALLEE
;
6774 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6775 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6778 #elif defined(__x86_64__)
6784 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6785 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6786 pvargResult
, V_VT(pvargResult
));
6788 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6790 FIXME("unsupported calling convention %d\n",cc
);
6791 return E_INVALIDARG
;
6794 /* maximum size for an argument is sizeof(DWORD_PTR) */
6795 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6799 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6800 func
= vtable
[oVft
/sizeof(void *)];
6801 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6803 else func
= (void *)oVft
;
6809 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6812 WARN("invalid return type %u\n", vtReturn
);
6814 return E_INVALIDARG
;
6819 for (i
= 0; i
< cActuals
; i
++)
6821 VARIANT
*arg
= prgpvarg
[i
];
6827 args
[argspos
++] = (ULONG_PTR
)arg
;
6829 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6830 args
[argspos
++] = V_BOOL(arg
);
6833 args
[argspos
++] = V_UI8(arg
);
6836 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6842 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6846 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6850 call_method( func
, argspos
, args
);
6853 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6857 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6858 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6861 #elif defined(__arm__)
6875 int rcount
; /* 32-bit register index count */
6877 int scount
= 0; /* single-precision float register index count */
6878 int dcount
= 0; /* double-precision float register index count */
6881 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6882 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6884 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6886 FIXME("unsupported calling convention %d\n",cc
);
6887 return E_INVALIDARG
;
6895 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6896 func
= vtable
[oVft
/sizeof(void *)];
6897 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6899 else func
= (void *)oVft
;
6901 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6902 /* first as it will need to be in the 'r' registers: */
6907 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6910 WARN("invalid return type %u\n", vtReturn
);
6911 return E_INVALIDARG
;
6912 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6916 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6917 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6919 for (i
= 0; i
< cActuals
; i
++)
6921 VARIANT
*arg
= prgpvarg
[i
];
6922 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6923 int ntemp
; /* Used for counting words split between registers and stack */
6929 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6932 dcount
= max( (scount
+ 1) / 2, dcount
);
6935 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6939 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6940 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6941 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6945 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6950 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6951 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6952 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6956 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6957 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6958 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6959 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6962 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6964 /* 8-byte align 'r' and/or stack: */
6966 rcount
+= (rcount
% 2);
6970 argspos
+= (argspos
% 2);
6972 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6976 regs
.r
[rcount
++] = *pdwarg
++;
6978 args
[argspos
++] = *pdwarg
++;
6982 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6984 regs
.r
[rcount
++] = V_BOOL(arg
);
6986 args
[argspos
++] = V_BOOL(arg
);
6988 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6990 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6992 regs
.sd
.s
[scount
++] = V_R4(arg
);
6994 args
[argspos
++] = V_UI4(arg
);
6999 regs
.r
[rcount
++] = V_UI4(arg
);
7001 args
[argspos
++] = V_UI4(arg
);
7004 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
7007 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
7011 case VT_EMPTY
: /* EMPTY = no return value */
7012 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
7014 call_method( func
, argspos
, args
, (DWORD
*)®s
);
7017 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
7021 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
7026 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
7029 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
7033 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
7034 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
7038 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
7039 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
7044 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7046 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7049 #define INVBUF_ELEMENT_SIZE \
7050 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7051 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7052 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7053 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7054 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7055 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7056 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7057 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7059 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7064 DISPPARAMS
*pDispParams
,
7065 VARIANT
*pVarResult
,
7066 EXCEPINFO
*pExcepInfo
,
7069 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7071 unsigned int var_index
;
7074 const TLBFuncDesc
*pFuncInfo
;
7077 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7078 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
7081 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7082 return DISP_E_MEMBERNOTFOUND
;
7086 ERR("NULL pDispParams not allowed\n");
7087 return E_INVALIDARG
;
7090 dump_DispParms(pDispParams
);
7092 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7094 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7095 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7096 return E_INVALIDARG
;
7099 /* we do this instead of using GetFuncDesc since it will return a fake
7100 * FUNCDESC for dispinterfaces and we want the real function description */
7101 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7102 pFuncInfo
= &This
->funcdescs
[fdc
];
7103 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7104 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7105 !func_restricted( &pFuncInfo
->funcdesc
))
7109 if (fdc
< This
->typeattr
.cFuncs
) {
7110 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7114 TRACE("invoking:\n");
7115 dump_TLBFuncDescOne(pFuncInfo
);
7118 switch (func_desc
->funckind
) {
7119 case FUNC_PUREVIRTUAL
:
7120 case FUNC_VIRTUAL
: {
7121 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7123 VARIANT retval
; /* pointer for storing byref retvals in */
7124 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7125 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7126 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7127 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7128 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7129 UINT vargs_converted
=0;
7133 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7135 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7137 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7138 hres
= DISP_E_PARAMNOTFOUND
;
7143 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7145 ERR("functions with the vararg attribute do not support named arguments\n");
7146 hres
= DISP_E_NONAMEDARGS
;
7150 for (i
= 0; i
< func_desc
->cParams
; i
++)
7152 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7153 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7158 TRACE("changing args\n");
7159 for (i
= 0; i
< func_desc
->cParams
; i
++)
7161 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7162 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7163 VARIANTARG
*src_arg
;
7165 if (wParamFlags
& PARAMFLAG_FLCID
)
7168 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7170 V_I4(arg
) = This
->pTypeLib
->lcid
;
7179 for (j
= 0; j
< cNamedArgs
; j
++)
7180 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7182 src_arg
= &pDispParams
->rgvarg
[j
];
7187 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7189 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7193 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7195 /* under most conditions the caller is not allowed to
7196 * pass in a dispparam arg in the index of what would be
7197 * the retval parameter. however, there is an exception
7198 * where the extra parameter is used in an extra
7199 * IDispatch::Invoke below */
7200 if ((i
< pDispParams
->cArgs
) &&
7201 ((func_desc
->cParams
!= 1) || !pVarResult
||
7202 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7204 hres
= DISP_E_BADPARAMCOUNT
;
7208 /* note: this check is placed so that if the caller passes
7209 * in a VARIANTARG for the retval we just ignore it, like
7211 if (i
== func_desc
->cParams
- 1)
7214 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7215 memset(arg
, 0, sizeof(*arg
));
7216 V_VT(arg
) = rgvt
[i
];
7217 memset(&retval
, 0, sizeof(retval
));
7218 V_BYREF(arg
) = &retval
;
7222 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7223 hres
= E_UNEXPECTED
;
7227 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7228 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7230 TRACE("%s\n", debugstr_variant(src_arg
));
7232 if(rgvt
[i
]!=V_VT(src_arg
))
7234 if (rgvt
[i
] == VT_VARIANT
)
7235 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7236 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7238 if (rgvt
[i
] == V_VT(src_arg
))
7239 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7242 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7243 if (wParamFlags
& PARAMFLAG_FIN
)
7244 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7245 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7247 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7249 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7252 SAFEARRAYBOUND bound
;
7256 bound
.cElements
= pDispParams
->cArgs
-i
;
7257 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7259 ERR("SafeArrayCreate failed\n");
7262 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7265 ERR("SafeArrayAccessData failed with %x\n", hres
);
7266 SafeArrayDestroy(a
);
7269 for (j
= 0; j
< bound
.cElements
; j
++)
7270 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7271 hres
= SafeArrayUnaccessData(a
);
7274 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7275 SafeArrayDestroy(a
);
7278 if (rgvt
[i
] & VT_BYREF
)
7279 V_BYREF(&rgvarg
[i
]) = &a
;
7281 V_ARRAY(&rgvarg
[i
]) = a
;
7282 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7284 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7286 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7287 if (wParamFlags
& PARAMFLAG_FIN
)
7288 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7290 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7291 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7292 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7294 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7296 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7297 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7301 /* FIXME: this doesn't work for VT_BYREF arguments if
7302 * they are not the same type as in the paramdesc */
7303 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7304 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7305 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7310 ERR("failed to convert param %d to %s from %s\n", i
,
7311 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7314 prgpvarg
[i
] = &rgvarg
[i
];
7318 prgpvarg
[i
] = src_arg
;
7321 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7322 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7323 && V_UNKNOWN(prgpvarg
[i
])) {
7324 IUnknown
*userdefined_iface
;
7327 if (tdesc
->vt
== VT_PTR
)
7328 tdesc
= tdesc
->u
.lptdesc
;
7330 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->u
.hreftype
, &guid
);
7334 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7336 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7340 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7341 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7344 else if (wParamFlags
& PARAMFLAG_FOPT
)
7347 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7348 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7350 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7356 VARIANTARG
*missing_arg
;
7357 /* if the function wants a pointer to a variant then
7358 * set that up, otherwise just pass the VT_ERROR in
7359 * the argument by value */
7360 if (rgvt
[i
] & VT_BYREF
)
7362 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7363 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7364 V_VARIANTREF(arg
) = missing_arg
;
7368 V_VT(missing_arg
) = VT_ERROR
;
7369 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7374 hres
= DISP_E_BADPARAMCOUNT
;
7378 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7380 /* VT_VOID is a special case for return types, so it is not
7381 * handled in the general function */
7382 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7383 V_VT(&varresult
) = VT_EMPTY
;
7386 V_VT(&varresult
) = 0;
7387 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7388 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7391 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7392 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7393 prgpvarg
, &varresult
);
7395 vargs_converted
= 0;
7397 for (i
= 0; i
< func_desc
->cParams
; i
++)
7399 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7400 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7402 if (wParamFlags
& PARAMFLAG_FLCID
)
7404 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7406 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7410 VariantInit(pVarResult
);
7411 /* deref return value */
7412 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7415 VARIANT_ClearInd(prgpvarg
[i
]);
7417 else if (vargs_converted
< pDispParams
->cArgs
)
7419 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7420 if (wParamFlags
& PARAMFLAG_FOUT
)
7422 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7424 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7428 ERR("failed to convert param %d to vt %d\n", i
,
7429 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7434 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7435 func_desc
->cParamsOpt
< 0 &&
7436 i
== func_desc
->cParams
-1)
7438 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7441 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7444 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7447 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7450 ERR("SafeArrayAccessData failed with %x\n", hres
);
7453 for (j
= 0; j
<= ubound
; j
++)
7454 VariantClear(&v
[j
]);
7455 hres
= SafeArrayUnaccessData(a
);
7458 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7462 VariantClear(&rgvarg
[i
]);
7465 else if (wParamFlags
& PARAMFLAG_FOPT
)
7467 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7468 VariantClear(&rgvarg
[i
]);
7471 VariantClear(&missing_arg
[i
]);
7474 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7476 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7477 hres
= DISP_E_EXCEPTION
;
7480 IErrorInfo
*pErrorInfo
;
7481 pExcepInfo
->scode
= V_ERROR(&varresult
);
7482 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7484 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7485 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7486 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7487 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7489 IErrorInfo_Release(pErrorInfo
);
7493 if (V_VT(&varresult
) != VT_ERROR
)
7495 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7499 VariantClear(pVarResult
);
7500 *pVarResult
= varresult
;
7503 VariantClear(&varresult
);
7506 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7507 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7508 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7509 (pDispParams
->cArgs
!= 0))
7511 if (V_VT(pVarResult
) == VT_DISPATCH
)
7513 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7514 /* Note: not VariantClear; we still need the dispatch
7515 * pointer to be valid */
7516 VariantInit(pVarResult
);
7517 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7518 GetSystemDefaultLCID(), wFlags
,
7519 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7520 IDispatch_Release(pDispatch
);
7524 VariantClear(pVarResult
);
7525 hres
= DISP_E_NOTACOLLECTION
;
7533 case FUNC_DISPATCH
: {
7536 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7537 if (SUCCEEDED(hres
)) {
7538 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7539 hres
= IDispatch_Invoke(
7540 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7541 pVarResult
,pExcepInfo
,pArgErr
7544 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7545 IDispatch_Release(disp
);
7547 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7551 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7556 TRACE("-- 0x%08x\n", hres
);
7559 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7562 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7563 if(FAILED(hres
)) return hres
;
7565 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7566 dump_VARDESC(var_desc
);
7567 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7571 /* not found, look for it in inherited interfaces */
7572 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7573 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7574 if(This
->impltypes
) {
7575 /* recursive search */
7577 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7578 if(SUCCEEDED(hres
)){
7579 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7580 ITypeInfo_Release(pTInfo
);
7583 WARN("Could not search inherited interface!\n");
7586 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7587 return DISP_E_MEMBERNOTFOUND
;
7590 /* ITypeInfo::GetDocumentation
7592 * Retrieves the documentation string, the complete Help file name and path,
7593 * and the context ID for the Help topic for a specified type description.
7595 * (Can be tested by the Visual Basic Editor in Word for instance.)
7597 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7598 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7599 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7601 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7602 const TLBFuncDesc
*pFDesc
;
7603 const TLBVarDesc
*pVDesc
;
7604 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7605 " HelpContext(%p) HelpFile(%p)\n",
7606 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7607 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7609 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7611 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7613 *pdwHelpContext
=This
->dwHelpContext
;
7615 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7617 }else {/* for a member */
7618 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7621 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7623 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7625 *pdwHelpContext
=pFDesc
->helpcontext
;
7627 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7630 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
7633 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7635 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7637 *pdwHelpContext
=pVDesc
->HelpContext
;
7639 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7644 if(This
->impltypes
&&
7645 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7646 /* recursive search */
7649 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7650 if(SUCCEEDED(result
)) {
7651 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7652 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7653 ITypeInfo_Release(pTInfo
);
7656 WARN("Could not search inherited interface!\n");
7659 WARN("member %d not found\n", memid
);
7660 return TYPE_E_ELEMENTNOTFOUND
;
7663 /* ITypeInfo::GetDllEntry
7665 * Retrieves a description or specification of an entry point for a function
7668 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7669 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7672 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7673 const TLBFuncDesc
*pFDesc
;
7675 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7677 if (pBstrDllName
) *pBstrDllName
= NULL
;
7678 if (pBstrName
) *pBstrName
= NULL
;
7679 if (pwOrdinal
) *pwOrdinal
= 0;
7681 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7682 return TYPE_E_BADMODULEKIND
;
7684 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
7686 dump_TypeInfo(This
);
7688 dump_TLBFuncDescOne(pFDesc
);
7691 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7693 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7695 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7703 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7706 return TYPE_E_ELEMENTNOTFOUND
;
7709 /* internal function to make the inherited interfaces' methods appear
7710 * part of the interface */
7711 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7712 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7714 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7717 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7719 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7721 ITypeInfo
*pSubTypeInfo
;
7723 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7727 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7729 ITypeInfo_Release(pSubTypeInfo
);
7733 *hRefType
-= DISPATCH_HREF_OFFSET
;
7735 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7736 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7741 struct search_res_tlb_params
7747 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7749 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7750 static const WCHAR formatW
[] = {'\\','%','d',0};
7751 WCHAR szPath
[MAX_PATH
+1];
7752 ITypeLib
*pTLib
= NULL
;
7756 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7759 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7762 if (swprintf(szPath
+ len
, ARRAY_SIZE(szPath
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7765 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7768 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7769 if (IsEqualGUID(params
->guid
, impl
->guid
))
7771 params
->pTLib
= pTLib
;
7772 return FALSE
; /* stop enumeration */
7774 ITypeLib_Release(pTLib
);
7780 /* ITypeInfo::GetRefTypeInfo
7782 * If a type description references other type descriptions, it retrieves
7783 * the referenced type descriptions.
7785 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7788 ITypeInfo
**ppTInfo
)
7790 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7791 HRESULT result
= E_FAIL
;
7794 return E_INVALIDARG
;
7796 if ((INT
)hRefType
< 0) {
7797 ITypeInfoImpl
*pTypeInfoImpl
;
7799 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7800 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7801 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7802 return TYPE_E_ELEMENTNOTFOUND
;
7804 /* when we meet a DUAL typeinfo, we must create the alternate
7807 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7809 *pTypeInfoImpl
= *This
;
7810 pTypeInfoImpl
->ref
= 0;
7811 list_init(&pTypeInfoImpl
->custdata_list
);
7813 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7814 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7816 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7818 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7819 /* the AddRef implicitly adds a reference to the parent typelib, which
7820 * stops the copied data from being destroyed until the new typeinfo's
7821 * refcount goes to zero, but we need to signal to the new instance to
7822 * not free its data structures when it is destroyed */
7823 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7825 ITypeInfo_AddRef(*ppTInfo
);
7828 } else if ((hRefType
& DISPATCH_HREF_MASK
) &&
7829 (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7831 HREFTYPE href_dispatch
= hRefType
;
7832 result
= ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &href_dispatch
, ppTInfo
);
7834 TLBRefType
*ref_type
;
7835 ITypeLib
*pTLib
= NULL
;
7838 if(!(hRefType
& 0x1)){
7839 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7841 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7844 *ppTInfo
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7845 ITypeInfo_AddRef(*ppTInfo
);
7851 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7853 if(ref_type
->reference
== (hRefType
& (~0x3)))
7856 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7858 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7862 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7864 TRACE("internal reference\n");
7865 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7867 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7868 TRACE("typeinfo in imported typelib that is already loaded\n");
7869 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7870 ITypeLib_AddRef(pTLib
);
7873 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
7874 struct search_res_tlb_params params
;
7877 TRACE("typeinfo in imported typelib that isn't already loaded\n");
7879 /* Search in resource table */
7880 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
7881 params
.pTLib
= NULL
;
7882 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
7883 pTLib
= params
.pTLib
;
7888 /* Search on disk */
7889 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
7890 ref_type
->pImpTLInfo
->wVersionMajor
,
7891 ref_type
->pImpTLInfo
->wVersionMinor
,
7892 This
->pTypeLib
->syskind
,
7893 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
7895 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
7897 result
= LoadTypeLib(libnam
, &pTLib
);
7898 SysFreeString(libnam
);
7901 if(SUCCEEDED(result
)) {
7902 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
7903 ITypeLib_AddRef(pTLib
);
7907 if(SUCCEEDED(result
)) {
7908 if(ref_type
->index
== TLB_REF_USE_GUID
)
7909 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), ppTInfo
);
7911 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, ppTInfo
);
7914 ITypeLib_Release(pTLib
);
7918 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
7919 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
7923 /* ITypeInfo::AddressOfMember
7925 * Retrieves the addresses of static functions or variables, such as those
7928 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
7929 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
7931 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7937 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
7939 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
7943 module
= LoadLibraryW(dll
);
7946 ERR("couldn't load %s\n", debugstr_w(dll
));
7948 SysFreeString(entry
);
7949 return STG_E_FILENOTFOUND
;
7951 /* FIXME: store library somewhere where we can free it */
7956 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
7957 entryA
= heap_alloc(len
);
7958 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
7960 *ppv
= GetProcAddress(module
, entryA
);
7962 ERR("function not found %s\n", debugstr_a(entryA
));
7968 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
7970 ERR("function not found %d\n", ordinal
);
7974 SysFreeString(entry
);
7977 return TYPE_E_DLLFUNCTIONNOTFOUND
;
7982 /* ITypeInfo::CreateInstance
7984 * Creates a new instance of a type that describes a component object class
7987 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
7988 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
7990 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7994 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8000 WARN("Not able to aggregate\n");
8001 return CLASS_E_NOAGGREGATION
;
8004 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8005 if(FAILED(hr
)) return hr
;
8007 if(pTA
->typekind
!= TKIND_COCLASS
)
8009 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8015 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8018 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8019 TRACE("GetActiveObject rets %08x\n", hr
);
8022 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8023 IUnknown_Release(pUnk
);
8028 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8029 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8033 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8037 /* ITypeInfo::GetMops
8039 * Retrieves marshalling information.
8041 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
8044 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8045 FIXME("(%p %d) stub!\n", This
, memid
);
8050 /* ITypeInfo::GetContainingTypeLib
8052 * Retrieves the containing type library and the index of the type description
8053 * within that type library.
8055 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8056 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8058 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8060 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8062 *pIndex
=This
->index
;
8063 TRACE("returning pIndex=%d\n", *pIndex
);
8067 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8068 ITypeLib_AddRef(*ppTLib
);
8069 TRACE("returning ppTLib=%p\n", *ppTLib
);
8075 /* ITypeInfo::ReleaseTypeAttr
8077 * Releases a TYPEATTR previously returned by Get
8080 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8081 TYPEATTR
* pTypeAttr
)
8083 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8084 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8085 heap_free(pTypeAttr
);
8088 /* ITypeInfo::ReleaseFuncDesc
8090 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8092 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8094 FUNCDESC
*pFuncDesc
)
8096 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8099 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8101 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8102 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8103 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8105 SysFreeString((BSTR
)pFuncDesc
);
8108 /* ITypeInfo::ReleaseVarDesc
8110 * Releases a VARDESC previously returned by GetVarDesc.
8112 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8115 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8116 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8118 TLB_FreeVarDesc(pVarDesc
);
8121 /* ITypeInfo2::GetTypeKind
8123 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8126 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8127 TYPEKIND
*pTypeKind
)
8129 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8130 *pTypeKind
= This
->typeattr
.typekind
;
8131 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8135 /* ITypeInfo2::GetTypeFlags
8137 * Returns the type flags without any allocations. This returns a DWORD type
8138 * flag, which expands the type flags without growing the TYPEATTR (type
8142 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8144 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8145 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8146 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
8150 /* ITypeInfo2::GetFuncIndexOfMemId
8151 * Binds to a specific member based on a known DISPID, where the member name
8152 * is not known (for example, when binding to a default member).
8155 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8156 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8158 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8162 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8163 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8164 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8167 if(fdc
< This
->typeattr
.cFuncs
) {
8171 result
= TYPE_E_ELEMENTNOTFOUND
;
8173 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8174 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8178 /* TypeInfo2::GetVarIndexOfMemId
8180 * Binds to a specific member based on a known DISPID, where the member name
8181 * is not known (for example, when binding to a default member).
8184 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8185 MEMBERID memid
, UINT
*pVarIndex
)
8187 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8188 TLBVarDesc
*pVarInfo
;
8190 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8192 pVarInfo
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8194 return TYPE_E_ELEMENTNOTFOUND
;
8196 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8201 /* ITypeInfo2::GetCustData
8203 * Gets the custom data
8205 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8210 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8211 TLBCustData
*pCData
;
8213 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8215 if(!guid
|| !pVarVal
)
8216 return E_INVALIDARG
;
8218 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8220 VariantInit( pVarVal
);
8222 VariantCopy( pVarVal
, &pCData
->data
);
8224 VariantClear( pVarVal
);
8228 /* ITypeInfo2::GetFuncCustData
8230 * Gets the custom data
8232 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8238 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8239 TLBCustData
*pCData
;
8240 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8242 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8244 if(index
>= This
->typeattr
.cFuncs
)
8245 return TYPE_E_ELEMENTNOTFOUND
;
8247 pCData
= TLB_get_custdata_by_guid(&pFDesc
->custdata_list
, guid
);
8249 return TYPE_E_ELEMENTNOTFOUND
;
8251 VariantInit(pVarVal
);
8252 VariantCopy(pVarVal
, &pCData
->data
);
8257 /* ITypeInfo2::GetParamCustData
8259 * Gets the custom data
8261 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8268 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8269 TLBCustData
*pCData
;
8270 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8272 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8273 debugstr_guid(guid
), pVarVal
);
8275 if(indexFunc
>= This
->typeattr
.cFuncs
)
8276 return TYPE_E_ELEMENTNOTFOUND
;
8278 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8279 return TYPE_E_ELEMENTNOTFOUND
;
8281 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8283 return TYPE_E_ELEMENTNOTFOUND
;
8285 VariantInit(pVarVal
);
8286 VariantCopy(pVarVal
, &pCData
->data
);
8291 /* ITypeInfo2::GetVarCustData
8293 * Gets the custom data
8295 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8301 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8302 TLBCustData
*pCData
;
8303 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8305 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8307 if(index
>= This
->typeattr
.cVars
)
8308 return TYPE_E_ELEMENTNOTFOUND
;
8310 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8312 return TYPE_E_ELEMENTNOTFOUND
;
8314 VariantInit(pVarVal
);
8315 VariantCopy(pVarVal
, &pCData
->data
);
8320 /* ITypeInfo2::GetImplCustData
8322 * Gets the custom data
8324 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8330 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8331 TLBCustData
*pCData
;
8332 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8334 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8336 if(index
>= This
->typeattr
.cImplTypes
)
8337 return TYPE_E_ELEMENTNOTFOUND
;
8339 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8341 return TYPE_E_ELEMENTNOTFOUND
;
8343 VariantInit(pVarVal
);
8344 VariantCopy(pVarVal
, &pCData
->data
);
8349 /* ITypeInfo2::GetDocumentation2
8351 * Retrieves the documentation string, the complete Help file name and path,
8352 * the localization context to use, and the context ID for the library Help
8353 * topic in the Help file.
8356 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8360 BSTR
*pbstrHelpString
,
8361 DWORD
*pdwHelpStringContext
,
8362 BSTR
*pbstrHelpStringDll
)
8364 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8365 const TLBFuncDesc
*pFDesc
;
8366 const TLBVarDesc
*pVDesc
;
8367 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8368 "HelpStringContext(%p) HelpStringDll(%p)\n",
8369 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8370 pbstrHelpStringDll
);
8371 /* the help string should be obtained from the helpstringdll,
8372 * using the _DLLGetDocumentation function, based on the supplied
8373 * lcid. Nice to do sometime...
8375 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8377 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8378 if(pdwHelpStringContext
)
8379 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8380 if(pbstrHelpStringDll
)
8381 *pbstrHelpStringDll
=
8382 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8384 }else {/* for a member */
8385 pFDesc
= TLB_get_funcdesc_by_memberid(This
->funcdescs
, This
->typeattr
.cFuncs
, memid
);
8388 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8389 if(pdwHelpStringContext
)
8390 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8391 if(pbstrHelpStringDll
)
8392 *pbstrHelpStringDll
=
8393 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8396 pVDesc
= TLB_get_vardesc_by_memberid(This
->vardescs
, This
->typeattr
.cVars
, memid
);
8399 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8400 if(pdwHelpStringContext
)
8401 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8402 if(pbstrHelpStringDll
)
8403 *pbstrHelpStringDll
=
8404 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8408 return TYPE_E_ELEMENTNOTFOUND
;
8411 /* ITypeInfo2::GetAllCustData
8413 * Gets all custom data items for the Type info.
8416 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8418 CUSTDATA
*pCustData
)
8420 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8422 TRACE("%p %p\n", This
, pCustData
);
8424 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8427 /* ITypeInfo2::GetAllFuncCustData
8429 * Gets all custom data items for the specified Function
8432 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8435 CUSTDATA
*pCustData
)
8437 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8438 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[index
];
8440 TRACE("%p %u %p\n", This
, index
, pCustData
);
8442 if(index
>= This
->typeattr
.cFuncs
)
8443 return TYPE_E_ELEMENTNOTFOUND
;
8445 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8448 /* ITypeInfo2::GetAllParamCustData
8450 * Gets all custom data items for the Functions
8453 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8454 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8456 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8457 TLBFuncDesc
*pFDesc
= &This
->funcdescs
[indexFunc
];
8459 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8461 if(indexFunc
>= This
->typeattr
.cFuncs
)
8462 return TYPE_E_ELEMENTNOTFOUND
;
8464 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8465 return TYPE_E_ELEMENTNOTFOUND
;
8467 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8470 /* ITypeInfo2::GetAllVarCustData
8472 * Gets all custom data items for the specified Variable
8475 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8476 UINT index
, CUSTDATA
*pCustData
)
8478 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8479 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8481 TRACE("%p %u %p\n", This
, index
, pCustData
);
8483 if(index
>= This
->typeattr
.cVars
)
8484 return TYPE_E_ELEMENTNOTFOUND
;
8486 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8489 /* ITypeInfo2::GetAllImplCustData
8491 * Gets all custom data items for the specified implementation type
8494 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8497 CUSTDATA
*pCustData
)
8499 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8500 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8502 TRACE("%p %u %p\n", This
, index
, pCustData
);
8504 if(index
>= This
->typeattr
.cImplTypes
)
8505 return TYPE_E_ELEMENTNOTFOUND
;
8507 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8510 static const ITypeInfo2Vtbl tinfvt
=
8513 ITypeInfo_fnQueryInterface
,
8515 ITypeInfo_fnRelease
,
8517 ITypeInfo_fnGetTypeAttr
,
8518 ITypeInfo_fnGetTypeComp
,
8519 ITypeInfo_fnGetFuncDesc
,
8520 ITypeInfo_fnGetVarDesc
,
8521 ITypeInfo_fnGetNames
,
8522 ITypeInfo_fnGetRefTypeOfImplType
,
8523 ITypeInfo_fnGetImplTypeFlags
,
8524 ITypeInfo_fnGetIDsOfNames
,
8526 ITypeInfo_fnGetDocumentation
,
8527 ITypeInfo_fnGetDllEntry
,
8528 ITypeInfo_fnGetRefTypeInfo
,
8529 ITypeInfo_fnAddressOfMember
,
8530 ITypeInfo_fnCreateInstance
,
8531 ITypeInfo_fnGetMops
,
8532 ITypeInfo_fnGetContainingTypeLib
,
8533 ITypeInfo_fnReleaseTypeAttr
,
8534 ITypeInfo_fnReleaseFuncDesc
,
8535 ITypeInfo_fnReleaseVarDesc
,
8537 ITypeInfo2_fnGetTypeKind
,
8538 ITypeInfo2_fnGetTypeFlags
,
8539 ITypeInfo2_fnGetFuncIndexOfMemId
,
8540 ITypeInfo2_fnGetVarIndexOfMemId
,
8541 ITypeInfo2_fnGetCustData
,
8542 ITypeInfo2_fnGetFuncCustData
,
8543 ITypeInfo2_fnGetParamCustData
,
8544 ITypeInfo2_fnGetVarCustData
,
8545 ITypeInfo2_fnGetImplTypeCustData
,
8546 ITypeInfo2_fnGetDocumentation2
,
8547 ITypeInfo2_fnGetAllCustData
,
8548 ITypeInfo2_fnGetAllFuncCustData
,
8549 ITypeInfo2_fnGetAllParamCustData
,
8550 ITypeInfo2_fnGetAllVarCustData
,
8551 ITypeInfo2_fnGetAllImplTypeCustData
,
8554 /******************************************************************************
8555 * CreateDispTypeInfo [OLEAUT32.31]
8557 * Build type information for an object so it can be called through an
8558 * IDispatch interface.
8561 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8562 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8565 * This call allows an objects methods to be accessed through IDispatch, by
8566 * building an ITypeInfo object that IDispatch can use to call through.
8568 HRESULT WINAPI
CreateDispTypeInfo(
8569 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8570 LCID lcid
, /* [I] Locale Id */
8571 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8573 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8574 ITypeLibImpl
*pTypeLibImpl
;
8575 unsigned int param
, func
;
8576 TLBFuncDesc
*pFuncDesc
;
8580 pTypeLibImpl
= TypeLibImpl_Constructor();
8581 if (!pTypeLibImpl
) return E_FAIL
;
8583 pTypeLibImpl
->TypeInfoCount
= 2;
8584 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8586 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8587 pTIIface
->pTypeLib
= pTypeLibImpl
;
8588 pTIIface
->index
= 0;
8589 pTIIface
->Name
= NULL
;
8590 pTIIface
->dwHelpContext
= -1;
8591 pTIIface
->guid
= NULL
;
8592 pTIIface
->typeattr
.lcid
= lcid
;
8593 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8594 pTIIface
->typeattr
.wMajorVerNum
= 0;
8595 pTIIface
->typeattr
.wMinorVerNum
= 0;
8596 pTIIface
->typeattr
.cbAlignment
= 2;
8597 pTIIface
->typeattr
.cbSizeInstance
= -1;
8598 pTIIface
->typeattr
.cbSizeVft
= -1;
8599 pTIIface
->typeattr
.cFuncs
= 0;
8600 pTIIface
->typeattr
.cImplTypes
= 0;
8601 pTIIface
->typeattr
.cVars
= 0;
8602 pTIIface
->typeattr
.wTypeFlags
= 0;
8603 pTIIface
->hreftype
= 0;
8605 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8606 pFuncDesc
= pTIIface
->funcdescs
;
8607 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8608 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8609 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8610 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8611 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8612 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8613 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8614 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8615 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8616 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8617 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8618 pFuncDesc
->funcdesc
.cScodes
= 0;
8619 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8620 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8621 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8622 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8623 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8624 md
->cArgs
* sizeof(ELEMDESC
));
8625 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8626 for(param
= 0; param
< md
->cArgs
; param
++) {
8627 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8628 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8630 pFuncDesc
->helpcontext
= 0;
8631 pFuncDesc
->HelpStringContext
= 0;
8632 pFuncDesc
->HelpString
= NULL
;
8633 pFuncDesc
->Entry
= NULL
;
8634 list_init(&pFuncDesc
->custdata_list
);
8635 pTIIface
->typeattr
.cFuncs
++;
8639 dump_TypeInfo(pTIIface
);
8641 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8642 pTIClass
->pTypeLib
= pTypeLibImpl
;
8643 pTIClass
->index
= 1;
8644 pTIClass
->Name
= NULL
;
8645 pTIClass
->dwHelpContext
= -1;
8646 pTIClass
->guid
= NULL
;
8647 pTIClass
->typeattr
.lcid
= lcid
;
8648 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8649 pTIClass
->typeattr
.wMajorVerNum
= 0;
8650 pTIClass
->typeattr
.wMinorVerNum
= 0;
8651 pTIClass
->typeattr
.cbAlignment
= 2;
8652 pTIClass
->typeattr
.cbSizeInstance
= -1;
8653 pTIClass
->typeattr
.cbSizeVft
= -1;
8654 pTIClass
->typeattr
.cFuncs
= 0;
8655 pTIClass
->typeattr
.cImplTypes
= 1;
8656 pTIClass
->typeattr
.cVars
= 0;
8657 pTIClass
->typeattr
.wTypeFlags
= 0;
8658 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8660 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8662 ref
= heap_alloc_zero(sizeof(*ref
));
8663 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8664 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8666 dump_TypeInfo(pTIClass
);
8668 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8670 ITypeInfo_AddRef(*pptinfo
);
8671 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8677 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8679 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8681 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8684 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8686 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8688 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8691 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8693 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8695 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8698 static HRESULT WINAPI
ITypeComp_fnBind(
8703 ITypeInfo
** ppTInfo
,
8704 DESCKIND
* pDescKind
,
8707 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8708 const TLBFuncDesc
*pFDesc
;
8709 const TLBVarDesc
*pVDesc
;
8710 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8713 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8715 *pDescKind
= DESCKIND_NONE
;
8716 pBindPtr
->lpfuncdesc
= NULL
;
8719 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8720 pFDesc
= &This
->funcdescs
[fdc
];
8721 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8722 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8725 /* name found, but wrong flags */
8726 hr
= TYPE_E_TYPEMISMATCH
;
8730 if (fdc
< This
->typeattr
.cFuncs
)
8732 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8734 &pBindPtr
->lpfuncdesc
,
8735 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8738 *pDescKind
= DESCKIND_FUNCDESC
;
8739 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8740 ITypeInfo_AddRef(*ppTInfo
);
8743 pVDesc
= TLB_get_vardesc_by_name(This
->vardescs
, This
->typeattr
.cVars
, szName
);
8745 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8748 *pDescKind
= DESCKIND_VARDESC
;
8749 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8750 ITypeInfo_AddRef(*ppTInfo
);
8755 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8756 /* recursive search */
8760 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8763 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8764 ITypeInfo_Release(pTInfo
);
8768 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8769 ITypeComp_Release(pTComp
);
8770 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8771 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8773 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8774 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8775 SysFreeString((BSTR
)tmp
);
8779 WARN("Could not search inherited interface!\n");
8781 if (hr
== DISP_E_MEMBERNOTFOUND
)
8783 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8787 static HRESULT WINAPI
ITypeComp_fnBindType(
8791 ITypeInfo
** ppTInfo
,
8792 ITypeComp
** ppTComp
)
8794 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8796 /* strange behaviour (does nothing) but like the
8799 if (!ppTInfo
|| !ppTComp
)
8808 static const ITypeCompVtbl tcompvt
=
8811 ITypeComp_fnQueryInterface
,
8813 ITypeComp_fnRelease
,
8816 ITypeComp_fnBindType
8819 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8820 ICreateTypeLib2
** ppctlib
)
8825 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8827 if (!szFile
) return E_INVALIDARG
;
8829 This
= TypeLibImpl_Constructor();
8831 return E_OUTOFMEMORY
;
8833 This
->lcid
= GetSystemDefaultLCID();
8834 This
->syskind
= syskind
;
8835 This
->ptr_size
= get_ptr_size(syskind
);
8837 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
8839 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8840 return E_OUTOFMEMORY
;
8842 lstrcpyW(This
->path
, szFile
);
8844 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
8845 ITypeLib2_Release(&This
->ITypeLib2_iface
);
8849 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
8850 REFIID riid
, void **object
)
8852 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8854 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
8857 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
8859 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8861 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
8864 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
8866 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8868 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
8871 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
8872 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
8874 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8875 ITypeInfoImpl
*info
;
8878 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
8880 if (!ctinfo
|| !name
)
8881 return E_INVALIDARG
;
8883 info
= TLB_get_typeinfo_by_name(This
->typeinfos
, This
->TypeInfoCount
, name
);
8885 return TYPE_E_NAMECONFLICT
;
8887 if (This
->typeinfos
)
8888 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
8889 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
8891 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
8893 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
8895 info
->pTypeLib
= This
;
8896 info
->Name
= TLB_append_str(&This
->name_list
, name
);
8897 info
->index
= This
->TypeInfoCount
;
8898 info
->typeattr
.typekind
= kind
;
8899 info
->typeattr
.cbAlignment
= 4;
8901 switch (info
->typeattr
.typekind
) {
8903 case TKIND_INTERFACE
:
8904 case TKIND_DISPATCH
:
8906 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
8910 info
->typeattr
.cbSizeInstance
= 0;
8913 info
->typeattr
.cbSizeInstance
= 2;
8916 info
->typeattr
.cbSizeInstance
= -0x75;
8919 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
8920 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
8924 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
8925 &IID_ICreateTypeInfo
, (void **)ctinfo
);
8927 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
8931 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
8933 ++This
->TypeInfoCount
;
8938 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
8941 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8943 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
8946 return E_INVALIDARG
;
8948 This
->Name
= TLB_append_str(&This
->name_list
, name
);
8953 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
8954 WORD majorVerNum
, WORD minorVerNum
)
8956 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8958 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
8960 This
->ver_major
= majorVerNum
;
8961 This
->ver_minor
= minorVerNum
;
8966 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
8969 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8971 TRACE("%p %s\n", This
, debugstr_guid(guid
));
8973 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
8978 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
8981 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8983 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
8986 return E_INVALIDARG
;
8988 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
8993 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
8994 LPOLESTR helpFileName
)
8996 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
8998 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9001 return E_INVALIDARG
;
9003 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9008 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9011 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9013 TRACE("%p %d\n", This
, helpContext
);
9015 This
->dwHelpContext
= helpContext
;
9020 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9023 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9025 TRACE("%p %x\n", This
, lcid
);
9027 This
->set_lcid
= lcid
;
9032 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9035 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9037 TRACE("%p %x\n", This
, libFlags
);
9039 This
->libflags
= libFlags
;
9044 typedef struct tagWMSFT_SegContents
{
9047 } WMSFT_SegContents
;
9049 typedef struct tagWMSFT_TLBFile
{
9051 WMSFT_SegContents typeinfo_seg
;
9052 WMSFT_SegContents impfile_seg
;
9053 WMSFT_SegContents impinfo_seg
;
9054 WMSFT_SegContents ref_seg
;
9055 WMSFT_SegContents guidhash_seg
;
9056 WMSFT_SegContents guid_seg
;
9057 WMSFT_SegContents namehash_seg
;
9058 WMSFT_SegContents name_seg
;
9059 WMSFT_SegContents string_seg
;
9060 WMSFT_SegContents typdesc_seg
;
9061 WMSFT_SegContents arraydesc_seg
;
9062 WMSFT_SegContents custdata_seg
;
9063 WMSFT_SegContents cdguids_seg
;
9065 WMSFT_SegContents aux_seg
;
9068 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9069 WMSFT_TLBFile
*file
)
9075 file
->string_seg
.len
= 0;
9076 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9079 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9081 return E_UNEXPECTED
;
9083 size
+= sizeof(INT16
);
9085 size
= (size
+ 4) & ~0x3;
9089 file
->string_seg
.len
+= size
;
9091 /* temporarily use str->offset to store the length of the aligned,
9092 * converted string */
9096 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9099 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9102 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9103 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9105 heap_free(file
->string_seg
.data
);
9106 return E_UNEXPECTED
;
9109 *((INT16
*)data
) = size
;
9111 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9115 str
->offset
= last_offs
;
9122 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9123 WMSFT_TLBFile
*file
)
9128 MSFT_NameIntro
*last_intro
= NULL
;
9130 file
->header
.nametablecount
= 0;
9131 file
->header
.nametablechars
= 0;
9133 file
->name_seg
.len
= 0;
9134 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9137 size
= lstrlenW(str
->str
);
9138 file
->header
.nametablechars
+= size
;
9139 file
->header
.nametablecount
++;
9141 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9143 return E_UNEXPECTED
;
9145 size
+= sizeof(MSFT_NameIntro
);
9147 size
= (size
+ 4) & ~0x3;
9151 file
->name_seg
.len
+= size
;
9153 /* temporarily use str->offset to store the length of the aligned,
9154 * converted string */
9158 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9159 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9162 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9164 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9166 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9167 data
+ sizeof(MSFT_NameIntro
),
9168 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9170 heap_free(file
->name_seg
.data
);
9171 return E_UNEXPECTED
;
9173 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9175 intro
->hreftype
= -1; /* TODO? */
9176 intro
->namelen
= size
& 0xFF;
9177 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9178 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9179 intro
->namelen
|= hash
<< 16;
9180 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9181 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9183 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9184 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9186 /* update str->offset to actual value to use in other
9187 * compilation functions that require positions within
9188 * the string table */
9192 str
->offset
= last_offs
;
9197 last_intro
->hreftype
= 0; /* last one is 0? */
9202 static inline int hash_guid(GUID
*guid
)
9206 for (i
= 0; i
< 8; i
++)
9207 hash
^= ((const short *)guid
)[i
];
9212 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9215 MSFT_GuidEntry
*entry
;
9217 int hash_key
, *guidhashtab
;
9219 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9220 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9222 entry
= file
->guid_seg
.data
;
9224 guidhashtab
= file
->guidhash_seg
.data
;
9225 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9226 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9227 entry
->hreftype
= guid
->hreftype
;
9229 hash_key
= hash_guid(&guid
->guid
);
9230 entry
->next_hash
= guidhashtab
[hash_key
];
9231 guidhashtab
[hash_key
] = offs
;
9233 guid
->offset
= offs
;
9234 offs
+= sizeof(MSFT_GuidEntry
);
9241 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9244 VARTYPE arg_type
= V_VT(value
);
9247 DWORD ret
= file
->custdata_seg
.len
;
9249 if(arg_type
== VT_INT
)
9251 if(arg_type
== VT_UINT
)
9255 if(V_VT(value
) != arg_type
) {
9256 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9258 ERR("VariantChangeType failed: %08x\n", hres
);
9263 /* Check if default value can be stored in-place */
9268 if(V_UI4(&v
) > 0x3ffffff)
9281 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9284 /* have to allocate space in custdata_seg */
9293 /* Construct the data to be allocated */
9296 if(file
->custdata_seg
.data
){
9297 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9298 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9299 file
->custdata_seg
.len
+= sizeof(int) * 2;
9301 file
->custdata_seg
.len
= sizeof(int) * 2;
9302 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9305 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9306 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9308 /* TODO: Check if the encoded data is already present in custdata_seg */
9314 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9317 if(file
->custdata_seg
.data
){
9318 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9319 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9320 file
->custdata_seg
.len
+= len
;
9322 file
->custdata_seg
.len
= len
;
9323 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9326 *((unsigned short *)data
) = V_VT(value
);
9327 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9328 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9329 if(V_BSTR(&v
)[i
] <= 0x7f)
9330 data
[i
+6] = V_BSTR(&v
)[i
];
9334 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9335 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9338 /* TODO: Check if the encoded data is already present in custdata_seg */
9343 FIXME("Argument type not yet handled\n");
9348 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9350 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9352 DWORD offs
= file
->arraydesc_seg
.len
;
9356 /* TODO: we should check for duplicates, but that's harder because each
9357 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9358 * at the library-level) */
9360 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9361 if(!file
->arraydesc_seg
.data
)
9362 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9364 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9365 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9367 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9368 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9369 for(i
= 0; i
< desc
->cDims
; ++i
){
9370 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9371 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9377 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9383 VARTYPE vt
, subtype
;
9394 vt
= desc
->vt
& VT_TYPEMASK
;
9396 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9398 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9399 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9401 *out_size
+= 2 * sizeof(DWORD
);
9402 }else if(vt
== VT_CARRAY
){
9403 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9404 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9406 }else if(vt
== VT_USERDEFINED
){
9407 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9408 encoded
[1] = desc
->u
.hreftype
;
9409 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9411 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9429 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9432 data
= file
->typdesc_seg
.data
;
9433 while(offs
< file
->typdesc_seg
.len
){
9434 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9436 offs
+= sizeof(encoded
);
9439 file
->typdesc_seg
.len
+= sizeof(encoded
);
9440 if(!file
->typdesc_seg
.data
)
9441 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9443 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9445 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9450 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9452 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9453 DWORD ret
= cdguids_seg
->len
, offs
;
9454 MSFT_CDGuid
*cdguid
;
9457 if(list_empty(custdata_list
))
9460 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9461 if(!cdguids_seg
->data
){
9462 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9464 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9465 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9468 offs
= ret
+ sizeof(MSFT_CDGuid
);
9469 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9470 cdguid
->GuidOffset
= cd
->guid
->offset
;
9471 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9472 cdguid
->next
= offs
;
9473 offs
+= sizeof(MSFT_CDGuid
);
9483 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9484 WMSFT_TLBFile
*file
)
9486 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9487 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9488 MSFT_VarRecord
*varrecord
;
9489 MSFT_FuncRecord
*funcrecord
;
9491 DWORD
*name
, *offsets
, offs
;
9493 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9494 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9496 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9498 /* optional fields */
9499 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9500 if(!list_empty(&desc
->custdata_list
))
9501 recorded_size
+= 7 * sizeof(INT
);
9502 else if(desc
->HelpStringContext
!= 0)
9503 recorded_size
+= 6 * sizeof(INT
);
9505 else if(desc
->Entry
)
9506 recorded_size
+= 3 * sizeof(INT
);
9507 else if(desc
->HelpString
)
9508 recorded_size
+= 2 * sizeof(INT
);
9509 else if(desc
->helpcontext
)
9510 recorded_size
+= sizeof(INT
);
9512 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9514 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9515 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9516 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9521 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9524 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9525 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9527 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9529 /* optional fields */
9530 if(desc
->HelpStringContext
!= 0)
9531 recorded_size
+= 5 * sizeof(INT
);
9532 else if(!list_empty(&desc
->custdata_list
))
9533 recorded_size
+= 4 * sizeof(INT
);
9535 else if(desc
->HelpString
)
9536 recorded_size
+= 2 * sizeof(INT
);
9537 else if(desc
->HelpContext
!= 0)
9538 recorded_size
+= sizeof(INT
);
9540 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9543 if(!recorded_size
&& !extra_size
)
9546 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9548 aux_seg
->len
+= recorded_size
+ extra_size
;
9550 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9553 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9555 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9557 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9559 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9562 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9563 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9564 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9565 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9567 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9568 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9569 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9570 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9573 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9578 * ^has_param_defaults
9579 * ^oEntry_is_intresource
9581 funcrecord
->FKCCIC
=
9582 desc
->funcdesc
.funckind
|
9583 (desc
->funcdesc
.invkind
<< 3) |
9584 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9585 (desc
->funcdesc
.callconv
<< 8);
9587 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9588 funcrecord
->FKCCIC
|= 0x2000;
9590 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9591 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9592 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9593 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9596 if(paramdefault_size
> 0)
9597 funcrecord
->FKCCIC
|= 0x1000;
9599 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9600 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9602 /* optional fields */
9604 if(!list_empty(&desc
->custdata_list
)){
9605 size
+= 7 * sizeof(INT
);
9606 funcrecord
->HelpContext
= desc
->helpcontext
;
9607 if(desc
->HelpString
)
9608 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9610 funcrecord
->oHelpString
= -1;
9612 funcrecord
->oEntry
= -1;
9613 else if(IS_INTRESOURCE(desc
->Entry
))
9614 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9616 funcrecord
->oEntry
= desc
->Entry
->offset
;
9617 funcrecord
->res9
= -1;
9618 funcrecord
->resA
= -1;
9619 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9620 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9621 }else if(desc
->HelpStringContext
!= 0){
9622 size
+= 6 * sizeof(INT
);
9623 funcrecord
->HelpContext
= desc
->helpcontext
;
9624 if(desc
->HelpString
)
9625 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9627 funcrecord
->oHelpString
= -1;
9629 funcrecord
->oEntry
= -1;
9630 else if(IS_INTRESOURCE(desc
->Entry
))
9631 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9633 funcrecord
->oEntry
= desc
->Entry
->offset
;
9634 funcrecord
->res9
= -1;
9635 funcrecord
->resA
= -1;
9636 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9637 }else if(desc
->Entry
){
9638 size
+= 3 * sizeof(INT
);
9639 funcrecord
->HelpContext
= desc
->helpcontext
;
9640 if(desc
->HelpString
)
9641 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9643 funcrecord
->oHelpString
= -1;
9645 funcrecord
->oEntry
= -1;
9646 else if(IS_INTRESOURCE(desc
->Entry
))
9647 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9649 funcrecord
->oEntry
= desc
->Entry
->offset
;
9650 }else if(desc
->HelpString
){
9651 size
+= 2 * sizeof(INT
);
9652 funcrecord
->HelpContext
= desc
->helpcontext
;
9653 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9654 }else if(desc
->helpcontext
){
9655 size
+= sizeof(INT
);
9656 funcrecord
->HelpContext
= desc
->helpcontext
;
9659 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9660 size
+= paramdefault_size
;
9662 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9663 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9665 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9666 if(desc
->pParamDesc
[j
].Name
)
9667 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9670 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9672 if(paramdefault_size
){
9673 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9674 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9675 else if(paramdefault_size
)
9680 size
+= sizeof(MSFT_ParameterInfo
);
9683 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9689 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9692 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9693 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9694 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9695 DWORD size
= 5 * sizeof(INT
);
9697 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9698 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9699 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9700 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9702 if(desc
->vardesc
.varkind
== VAR_CONST
){
9703 varrecord
->vardescsize
+= sizeof(VARIANT
);
9704 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9706 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9709 if(desc
->HelpStringContext
!= 0){
9710 size
+= 5 * sizeof(INT
);
9711 varrecord
->HelpContext
= desc
->HelpContext
;
9712 if(desc
->HelpString
)
9713 varrecord
->HelpString
= desc
->HelpString
->offset
;
9715 varrecord
->HelpString
= -1;
9716 varrecord
->res9
= -1;
9717 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9718 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9719 }else if(!list_empty(&desc
->custdata_list
)){
9720 size
+= 4 * sizeof(INT
);
9721 varrecord
->HelpContext
= desc
->HelpContext
;
9722 if(desc
->HelpString
)
9723 varrecord
->HelpString
= desc
->HelpString
->offset
;
9725 varrecord
->HelpString
= -1;
9726 varrecord
->res9
= -1;
9727 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9728 }else if(desc
->HelpString
){
9729 size
+= 2 * sizeof(INT
);
9730 varrecord
->HelpContext
= desc
->HelpContext
;
9731 if(desc
->HelpString
)
9732 varrecord
->HelpString
= desc
->HelpString
->offset
;
9734 varrecord
->HelpString
= -1;
9735 }else if(desc
->HelpContext
!= 0){
9736 size
+= sizeof(INT
);
9737 varrecord
->HelpContext
= desc
->HelpContext
;
9740 varrecord
->Info
= size
| (i
<< 16);
9746 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9749 memid
= (MEMBERID
*)varrecord
;
9750 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9751 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9752 *memid
= desc
->funcdesc
.memid
;
9755 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9756 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9757 *memid
= desc
->vardesc
.memid
;
9761 name
= (UINT
*)memid
;
9762 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9763 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9765 *name
= desc
->Name
->offset
;
9770 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9771 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9773 *name
= desc
->Name
->offset
;
9782 typedef struct tagWMSFT_RefChunk
{
9789 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9791 DWORD offs
= file
->ref_seg
.len
, i
;
9792 WMSFT_RefChunk
*chunk
;
9794 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9795 if(!file
->ref_seg
.data
)
9796 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9798 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9800 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9802 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9803 chunk
->href
= info
->impltypes
[i
].hRef
;
9804 chunk
->res04
= info
->impltypes
[i
].implflags
;
9806 if(i
< info
->typeattr
.cImplTypes
- 1)
9807 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9816 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9820 size
= sizeof(MSFT_TypeInfoBase
);
9823 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9824 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9825 base
->typekind
= TKIND_DISPATCH
;
9827 base
->typekind
= info
->typeattr
.typekind
;
9828 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
9829 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
9830 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
9835 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
9841 base
->posguid
= info
->guid
->offset
;
9844 base
->flags
= info
->typeattr
.wTypeFlags
;
9846 base
->NameOffset
= info
->Name
->offset
;
9848 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
9849 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
9851 base
->NameOffset
= -1;
9853 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
9855 base
->docstringoffs
= info
->DocString
->offset
;
9857 base
->docstringoffs
= -1;
9858 base
->helpstringcontext
= info
->dwHelpStringContext
;
9859 base
->helpcontext
= info
->dwHelpContext
;
9860 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
9861 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
9862 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
9863 base
->size
= info
->typeattr
.cbSizeInstance
;
9864 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
9865 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
9866 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
9867 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
9868 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
9870 base
->datatype1
= info
->DllName
->offset
;
9872 base
->datatype1
= -1;
9874 if(info
->typeattr
.cImplTypes
> 0)
9875 base
->datatype1
= info
->impltypes
[0].hRef
;
9877 base
->datatype1
= -1;
9879 base
->datatype2
= index
; /* FIXME: i think there's more here */
9887 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
9891 file
->typeinfo_seg
.len
= 0;
9892 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9893 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9894 *junk
= file
->typeinfo_seg
.len
;
9896 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
9899 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
9900 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
9902 file
->aux_seg
.len
= 0;
9903 file
->aux_seg
.data
= NULL
;
9905 file
->typeinfo_seg
.len
= 0;
9906 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
9907 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
9908 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
9909 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
9913 typedef struct tagWMSFT_ImpFile
{
9919 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9922 WMSFT_ImpFile
*impfile
;
9924 DWORD last_offs
= 0;
9926 file
->impfile_seg
.len
= 0;
9927 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9931 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
9935 path
= implib
->name
;
9936 size
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
), NULL
, 0, NULL
, NULL
);
9938 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9941 size
+= sizeof(INT16
);
9943 size
= (size
+ 4) & ~0x3;
9947 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
9950 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
9952 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
9953 int strlen
= 0, size
;
9955 impfile
= (WMSFT_ImpFile
*)data
;
9956 impfile
->guid_offs
= implib
->guid
->offset
;
9957 impfile
->lcid
= implib
->lcid
;
9958 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
9960 data
+= sizeof(WMSFT_ImpFile
);
9963 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
9967 path
= implib
->name
;
9968 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
),
9969 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9971 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
9974 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
9976 size
= strlen
+ sizeof(INT16
);
9978 size
= (size
+ 4) & ~0x3;
9981 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
9984 implib
->offset
= last_offs
;
9985 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
9989 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9992 TLBRefType
*ref_type
;
9995 WMSFT_compile_impfile(This
, file
);
9997 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
9998 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
10000 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10001 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10002 if(ref_type
->index
== TLB_REF_USE_GUID
){
10003 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10004 info
->oGuid
= ref_type
->guid
->offset
;
10006 info
->oGuid
= ref_type
->index
;
10007 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10013 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10015 file
->guidhash_seg
.len
= 0x80;
10016 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10017 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10020 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10022 file
->namehash_seg
.len
= 0x200;
10023 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10024 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10027 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10029 if(contents
&& contents
->len
){
10030 segdir
->offset
= *running_offset
;
10031 segdir
->length
= contents
->len
;
10032 *running_offset
+= segdir
->length
;
10034 segdir
->offset
= -1;
10035 segdir
->length
= 0;
10038 /* TODO: do these ever change? */
10039 segdir
->res08
= -1;
10040 segdir
->res0c
= 0xf;
10043 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10047 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10050 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10054 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10056 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10057 base
->memoffset
+= file_len
;
10064 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10066 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10067 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10068 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10069 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10070 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10071 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10072 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10073 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10074 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10075 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10076 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10077 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10078 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10079 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10082 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10084 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10085 WMSFT_TLBFile file
;
10086 DWORD written
, junk_size
, junk_offs
, running_offset
;
10093 TRACE("%p\n", This
);
10095 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10096 if(This
->typeinfos
[i
]->needs_layout
)
10097 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10099 memset(&file
, 0, sizeof(file
));
10101 file
.header
.magic1
= 0x5446534D;
10102 file
.header
.magic2
= 0x00010002;
10103 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10104 file
.header
.lcid2
= This
->set_lcid
;
10105 file
.header
.varflags
= 0x40 | This
->syskind
;
10106 if (This
->HelpFile
)
10107 file
.header
.varflags
|= 0x10;
10108 if (This
->HelpStringDll
)
10109 file
.header
.varflags
|= HELPDLLFLAG
;
10110 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10111 file
.header
.flags
= This
->libflags
;
10112 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10113 file
.header
.helpcontext
= This
->dwHelpContext
;
10114 file
.header
.res44
= 0x20;
10115 file
.header
.res48
= 0x80;
10116 file
.header
.dispatchpos
= This
->dispatch_href
;
10118 WMSFT_compile_namehash(This
, &file
);
10119 /* do name and string compilation to get offsets for other compilations */
10120 hres
= WMSFT_compile_names(This
, &file
);
10122 WMSFT_free_file(&file
);
10126 hres
= WMSFT_compile_strings(This
, &file
);
10128 WMSFT_free_file(&file
);
10132 WMSFT_compile_guidhash(This
, &file
);
10133 hres
= WMSFT_compile_guids(This
, &file
);
10135 WMSFT_free_file(&file
);
10140 file
.header
.helpfile
= This
->HelpFile
->offset
;
10142 file
.header
.helpfile
= -1;
10144 if(This
->DocString
)
10145 file
.header
.helpstring
= This
->DocString
->offset
;
10147 file
.header
.helpstring
= -1;
10149 /* do some more segment compilation */
10150 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10151 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10154 file
.header
.NameOffset
= This
->Name
->offset
;
10156 file
.header
.NameOffset
= -1;
10158 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10161 file
.header
.posguid
= This
->guid
->offset
;
10163 file
.header
.posguid
= -1;
10165 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10166 if(file
.header
.varflags
& HELPDLLFLAG
)
10167 junk_size
+= sizeof(DWORD
);
10169 junk
= heap_alloc_zero(junk_size
);
10170 if(file
.header
.varflags
& HELPDLLFLAG
){
10171 *junk
= This
->HelpStringDll
->offset
;
10180 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10181 WMSFT_compile_impinfo(This
, &file
);
10183 running_offset
= 0;
10185 TRACE("header at: 0x%x\n", running_offset
);
10186 running_offset
+= sizeof(file
.header
);
10188 TRACE("junk at: 0x%x\n", running_offset
);
10189 running_offset
+= junk_size
;
10191 TRACE("segdir at: 0x%x\n", running_offset
);
10192 running_offset
+= sizeof(file
.segdir
);
10194 TRACE("typeinfo at: 0x%x\n", running_offset
);
10195 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10197 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10198 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10200 TRACE("guidtab at: 0x%x\n", running_offset
);
10201 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10203 TRACE("reftab at: 0x%x\n", running_offset
);
10204 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10206 TRACE("impinfo at: 0x%x\n", running_offset
);
10207 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10209 TRACE("impfiles at: 0x%x\n", running_offset
);
10210 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10212 TRACE("namehashtab at: 0x%x\n", running_offset
);
10213 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10215 TRACE("nametab at: 0x%x\n", running_offset
);
10216 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10218 TRACE("stringtab at: 0x%x\n", running_offset
);
10219 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10221 TRACE("typdesc at: 0x%x\n", running_offset
);
10222 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10224 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10225 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10227 TRACE("custdata at: 0x%x\n", running_offset
);
10228 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10230 TRACE("cdguids at: 0x%x\n", running_offset
);
10231 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10233 TRACE("res0e at: 0x%x\n", running_offset
);
10234 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10236 TRACE("res0f at: 0x%x\n", running_offset
);
10237 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10239 TRACE("aux_seg at: 0x%x\n", running_offset
);
10241 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10243 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10244 FILE_ATTRIBUTE_NORMAL
, 0);
10245 if (outfile
== INVALID_HANDLE_VALUE
){
10246 WMSFT_free_file(&file
);
10248 return TYPE_E_IOERROR
;
10251 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10253 WMSFT_free_file(&file
);
10254 CloseHandle(outfile
);
10256 return TYPE_E_IOERROR
;
10259 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10262 WMSFT_free_file(&file
);
10263 CloseHandle(outfile
);
10264 return TYPE_E_IOERROR
;
10267 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10269 WMSFT_free_file(&file
);
10270 CloseHandle(outfile
);
10271 return TYPE_E_IOERROR
;
10274 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10275 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10276 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10277 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10278 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10279 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10280 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10281 WMSFT_write_segment(outfile
, &file
.name_seg
);
10282 WMSFT_write_segment(outfile
, &file
.string_seg
);
10283 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10284 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10285 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10286 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10287 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10289 WMSFT_free_file(&file
);
10291 CloseHandle(outfile
);
10296 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10299 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10300 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10304 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10305 REFGUID guid
, VARIANT
*varVal
)
10307 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10310 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10312 if (!guid
|| !varVal
)
10313 return E_INVALIDARG
;
10315 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10317 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10320 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10321 ULONG helpStringContext
)
10323 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10324 FIXME("%p %u - stub\n", This
, helpStringContext
);
10328 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10331 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10332 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10335 return E_INVALIDARG
;
10337 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10342 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10343 ICreateTypeLib2_fnQueryInterface
,
10344 ICreateTypeLib2_fnAddRef
,
10345 ICreateTypeLib2_fnRelease
,
10346 ICreateTypeLib2_fnCreateTypeInfo
,
10347 ICreateTypeLib2_fnSetName
,
10348 ICreateTypeLib2_fnSetVersion
,
10349 ICreateTypeLib2_fnSetGuid
,
10350 ICreateTypeLib2_fnSetDocString
,
10351 ICreateTypeLib2_fnSetHelpFileName
,
10352 ICreateTypeLib2_fnSetHelpContext
,
10353 ICreateTypeLib2_fnSetLcid
,
10354 ICreateTypeLib2_fnSetLibFlags
,
10355 ICreateTypeLib2_fnSaveAllChanges
,
10356 ICreateTypeLib2_fnDeleteTypeInfo
,
10357 ICreateTypeLib2_fnSetCustData
,
10358 ICreateTypeLib2_fnSetHelpStringContext
,
10359 ICreateTypeLib2_fnSetHelpStringDll
10362 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10363 REFIID riid
, void **object
)
10365 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10367 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10370 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10372 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10374 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10377 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10379 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10381 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10384 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10387 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10389 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10391 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10396 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10399 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10403 TRACE("%p %x\n", This
, typeFlags
);
10405 if (typeFlags
& TYPEFLAG_FDUAL
) {
10406 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10408 ITypeInfo
*dispatch
;
10412 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10416 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10417 ITypeLib_Release(stdole
);
10421 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10422 ITypeInfo_Release(dispatch
);
10427 old_flags
= This
->typeattr
.wTypeFlags
;
10428 This
->typeattr
.wTypeFlags
= typeFlags
;
10430 hres
= ICreateTypeInfo2_LayOut(iface
);
10431 if (FAILED(hres
)) {
10432 This
->typeattr
.wTypeFlags
= old_flags
;
10439 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10442 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10444 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10447 return E_INVALIDARG
;
10449 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10454 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10457 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10459 TRACE("%p %d\n", This
, helpContext
);
10461 This
->dwHelpContext
= helpContext
;
10466 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10467 WORD majorVerNum
, WORD minorVerNum
)
10469 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10471 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10473 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10474 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10479 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10480 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10482 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10484 ITypeLib
*container
;
10485 TLBRefType
*ref_type
;
10487 TYPEATTR
*typeattr
;
10491 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10493 if (!typeInfo
|| !refType
)
10494 return E_INVALIDARG
;
10496 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10500 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10501 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10503 ITypeLib_Release(container
);
10505 *refType
= target
->hreftype
;
10510 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10511 if (FAILED(hres
)) {
10512 ITypeLib_Release(container
);
10516 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10517 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10518 implib
->lcid
== libattr
->lcid
&&
10519 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10520 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10524 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10525 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10527 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10528 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10529 implib
->name
= SysAllocString(our_container
->path
);
10531 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10532 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10534 implib
->name
= NULL
;
10535 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10539 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10540 implib
->lcid
= libattr
->lcid
;
10541 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10542 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10544 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10547 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10548 ITypeLib_Release(container
);
10550 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10555 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10556 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10557 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10558 ref_type
->tkind
== typeattr
->typekind
)
10563 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10564 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10566 ref_type
->tkind
= typeattr
->typekind
;
10567 ref_type
->pImpTLInfo
= implib
;
10568 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10570 ref_type
->index
= TLB_REF_USE_GUID
;
10572 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10574 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10577 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10579 *refType
= ref_type
->reference
| 0x1;
10581 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10582 This
->pTypeLib
->dispatch_href
= *refType
;
10587 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10588 UINT index
, FUNCDESC
*funcDesc
)
10590 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10591 TLBFuncDesc tmp_func_desc
, *func_desc
;
10596 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10598 if (!funcDesc
|| funcDesc
->oVft
& 3)
10599 return E_INVALIDARG
;
10601 switch (This
->typeattr
.typekind
) {
10603 if (funcDesc
->funckind
!= FUNC_STATIC
)
10604 return TYPE_E_BADMODULEKIND
;
10606 case TKIND_DISPATCH
:
10607 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10608 return TYPE_E_BADMODULEKIND
;
10611 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10612 return TYPE_E_BADMODULEKIND
;
10615 if (index
> This
->typeattr
.cFuncs
)
10616 return TYPE_E_ELEMENTNOTFOUND
;
10618 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10619 !funcDesc
->cParams
)
10620 return TYPE_E_INCONSISTENTPROPFUNCS
;
10623 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10624 funcDesc
->oVft
% 8 != 0)
10625 return E_INVALIDARG
;
10628 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10629 TLBFuncDesc_Constructor(&tmp_func_desc
);
10631 tmp_func_desc
.funcdesc
= *funcDesc
;
10633 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10634 tmp_func_desc
.funcdesc
.oVft
|= 1;
10636 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10637 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10638 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10640 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10641 tmp_func_desc
.funcdesc
.cScodes
= 0;
10644 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10645 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10646 buf_size
+= sizeof(ELEMDESC
);
10647 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10649 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10650 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10652 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10653 if (FAILED(hres
)) {
10654 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10655 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10659 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10660 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10661 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10662 if (FAILED(hres
)) {
10663 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10664 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10667 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10668 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10669 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10670 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10671 if (FAILED(hres
)) {
10672 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10673 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10679 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10681 if (This
->funcdescs
) {
10682 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10683 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10685 if (index
< This
->typeattr
.cFuncs
) {
10686 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10687 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10688 func_desc
= This
->funcdescs
+ index
;
10690 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10692 /* move custdata lists to the new memory location */
10693 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10695 TLBFuncDesc
*fd
= &This
->funcdescs
[i
];
10696 if(fd
->custdata_list
.prev
== fd
->custdata_list
.next
)
10697 list_init(&fd
->custdata_list
);
10699 fd
->custdata_list
.prev
->next
= &fd
->custdata_list
;
10700 fd
->custdata_list
.next
->prev
= &fd
->custdata_list
;
10705 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10707 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10708 list_init(&func_desc
->custdata_list
);
10710 ++This
->typeattr
.cFuncs
;
10712 This
->needs_layout
= TRUE
;
10717 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10718 UINT index
, HREFTYPE refType
)
10720 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10721 TLBImplType
*impl_type
;
10724 TRACE("%p %u %d\n", This
, index
, refType
);
10726 switch(This
->typeattr
.typekind
){
10727 case TKIND_COCLASS
: {
10729 FIXME("Unhandled index: -1\n");
10733 if(index
!= This
->typeattr
.cImplTypes
)
10734 return TYPE_E_ELEMENTNOTFOUND
;
10738 case TKIND_INTERFACE
:
10739 case TKIND_DISPATCH
:
10740 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10741 return TYPE_E_ELEMENTNOTFOUND
;
10744 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10748 if (This
->impltypes
){
10751 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10752 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10754 if (index
< This
->typeattr
.cImplTypes
) {
10755 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10756 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10757 impl_type
= This
->impltypes
+ index
;
10759 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10761 /* move custdata lists to the new memory location */
10762 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10764 TLBImplType
*it
= &This
->impltypes
[i
];
10765 if(it
->custdata_list
.prev
== it
->custdata_list
.next
)
10766 list_init(&it
->custdata_list
);
10768 it
->custdata_list
.prev
->next
= &it
->custdata_list
;
10769 it
->custdata_list
.next
->prev
= &it
->custdata_list
;
10774 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10776 memset(impl_type
, 0, sizeof(TLBImplType
));
10777 TLBImplType_Constructor(impl_type
);
10778 impl_type
->hRef
= refType
;
10780 ++This
->typeattr
.cImplTypes
;
10782 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10783 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10785 hres
= ICreateTypeInfo2_LayOut(iface
);
10792 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10793 UINT index
, INT implTypeFlags
)
10795 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10796 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10798 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10800 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10801 return TYPE_E_BADMODULEKIND
;
10803 if (index
>= This
->typeattr
.cImplTypes
)
10804 return TYPE_E_ELEMENTNOTFOUND
;
10806 impl_type
->implflags
= implTypeFlags
;
10811 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10814 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10816 TRACE("%p %d\n", This
, alignment
);
10818 This
->typeattr
.cbAlignment
= alignment
;
10823 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10826 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10828 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10831 return E_INVALIDARG
;
10833 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10835 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10840 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10841 UINT index
, VARDESC
*varDesc
)
10843 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10844 TLBVarDesc
*var_desc
;
10846 TRACE("%p %u %p\n", This
, index
, varDesc
);
10848 if (This
->vardescs
){
10851 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
10852 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
10854 if (index
< This
->typeattr
.cVars
) {
10855 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
10856 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
10857 var_desc
= This
->vardescs
+ index
;
10859 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
10861 /* move custdata lists to the new memory location */
10862 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
10864 TLBVarDesc
*var
= &This
->vardescs
[i
];
10865 if(var
->custdata_list
.prev
== var
->custdata_list
.next
)
10866 list_init(&var
->custdata_list
);
10868 var
->custdata_list
.prev
->next
= &var
->custdata_list
;
10869 var
->custdata_list
.next
->prev
= &var
->custdata_list
;
10874 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
10876 TLBVarDesc_Constructor(var_desc
);
10877 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
10878 var_desc
->vardesc
= *var_desc
->vardesc_create
;
10880 ++This
->typeattr
.cVars
;
10882 This
->needs_layout
= TRUE
;
10887 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
10888 UINT index
, LPOLESTR
*names
, UINT numNames
)
10890 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10891 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10894 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
10897 return E_INVALIDARG
;
10899 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
10900 return TYPE_E_ELEMENTNOTFOUND
;
10902 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
10903 if(numNames
> func_desc
->funcdesc
.cParams
)
10904 return TYPE_E_ELEMENTNOTFOUND
;
10906 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
10907 return TYPE_E_ELEMENTNOTFOUND
;
10909 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
10910 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
10911 if (iter
->Name
&& !wcscmp(TLB_get_bstr(iter
->Name
), *names
)) {
10912 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10913 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
10914 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
10916 return TYPE_E_AMBIGUOUSNAME
;
10920 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
10922 for (i
= 1; i
< numNames
; ++i
) {
10923 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
10924 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
10930 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
10931 UINT index
, LPOLESTR name
)
10933 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10935 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
10938 return E_INVALIDARG
;
10940 if(index
>= This
->typeattr
.cVars
)
10941 return TYPE_E_ELEMENTNOTFOUND
;
10943 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
10947 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
10948 TYPEDESC
*tdescAlias
)
10950 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10953 TRACE("%p %p\n", This
, tdescAlias
);
10956 return E_INVALIDARG
;
10958 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
10959 return TYPE_E_BADMODULEKIND
;
10961 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
10965 heap_free(This
->tdescAlias
);
10966 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
10967 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
10972 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
10973 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
10975 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10976 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
10980 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
10981 UINT index
, LPOLESTR docString
)
10983 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10984 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
10986 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
10989 return E_INVALIDARG
;
10991 if(index
>= This
->typeattr
.cFuncs
)
10992 return TYPE_E_ELEMENTNOTFOUND
;
10994 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
10999 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11000 UINT index
, LPOLESTR docString
)
11002 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11003 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11005 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11008 return E_INVALIDARG
;
11010 if(index
>= This
->typeattr
.cVars
)
11011 return TYPE_E_ELEMENTNOTFOUND
;
11013 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11018 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11019 UINT index
, DWORD helpContext
)
11021 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11022 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11024 TRACE("%p %u %d\n", This
, index
, helpContext
);
11026 if(index
>= This
->typeattr
.cFuncs
)
11027 return TYPE_E_ELEMENTNOTFOUND
;
11029 func_desc
->helpcontext
= helpContext
;
11034 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11035 UINT index
, DWORD helpContext
)
11037 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11038 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11040 TRACE("%p %u %d\n", This
, index
, helpContext
);
11042 if(index
>= This
->typeattr
.cVars
)
11043 return TYPE_E_ELEMENTNOTFOUND
;
11045 var_desc
->HelpContext
= helpContext
;
11050 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11051 UINT index
, BSTR bstrMops
)
11053 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11054 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11058 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11061 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11063 TRACE("%p %p\n", This
, idlDesc
);
11066 return E_INVALIDARG
;
11068 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11069 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11074 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11076 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11078 TLBFuncDesc
*func_desc
;
11079 UINT user_vft
= 0, i
, depth
= 0;
11080 HRESULT hres
= S_OK
;
11082 TRACE("%p\n", This
);
11084 This
->needs_layout
= FALSE
;
11086 hres
= ICreateTypeInfo2_QueryInterface(iface
, &IID_ITypeInfo
, (LPVOID
*)&tinfo
);
11090 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11095 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11097 if (SUCCEEDED(hres
)) {
11098 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11100 if (SUCCEEDED(hres
)) {
11101 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11102 if (FAILED(hres
)) {
11103 ITypeInfo_Release(inh
);
11104 ITypeInfo_Release(tinfo
);
11107 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11108 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11112 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11113 if(SUCCEEDED(hres
)){
11115 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11116 if(SUCCEEDED(hres
)){
11117 ITypeInfo_Release(inh
);
11121 }while(SUCCEEDED(hres
));
11124 ITypeInfo_Release(inh
);
11125 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11126 This
->typeattr
.cbSizeVft
= 0;
11129 ITypeInfo_Release(tinfo
);
11132 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11133 This
->typeattr
.cbSizeVft
= 0;
11136 ITypeInfo_Release(tinfo
);
11139 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11140 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11142 This
->typeattr
.cbSizeVft
= 0;
11144 func_desc
= This
->funcdescs
;
11146 while (i
< This
->typeattr
.cFuncs
) {
11147 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11148 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11150 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11151 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11153 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11155 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11158 BOOL reset
= FALSE
;
11160 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11162 iter
= This
->funcdescs
;
11163 while (j
< This
->typeattr
.cFuncs
) {
11164 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11166 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11169 ++func_desc
->funcdesc
.memid
;
11170 iter
= This
->funcdescs
;
11183 if (user_vft
> This
->typeattr
.cbSizeVft
)
11184 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11186 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11187 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11188 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11190 BOOL reset
= FALSE
;
11193 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11195 iter
= This
->vardescs
;
11196 while (j
< This
->typeattr
.cVars
) {
11197 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11199 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11202 ++var_desc
->vardesc
.memid
;
11203 iter
= This
->vardescs
;
11213 ITypeInfo_Release(tinfo
);
11217 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11220 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11221 FIXME("%p %u - stub\n", This
, index
);
11225 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11226 MEMBERID memid
, INVOKEKIND invKind
)
11228 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11229 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11233 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11236 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11237 FIXME("%p %u - stub\n", This
, index
);
11241 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11244 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11245 FIXME("%p %x - stub\n", This
, memid
);
11249 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11252 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11253 FIXME("%p %u - stub\n", This
, index
);
11257 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11258 REFGUID guid
, VARIANT
*varVal
)
11262 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11264 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11266 if (!guid
|| !varVal
)
11267 return E_INVALIDARG
;
11269 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11271 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11274 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11275 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11277 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11278 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11282 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11283 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11285 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11286 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11290 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11291 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11293 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11294 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11298 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11299 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11301 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11302 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11306 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11307 ULONG helpStringContext
)
11309 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11311 TRACE("%p %u\n", This
, helpStringContext
);
11313 This
->dwHelpStringContext
= helpStringContext
;
11318 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11319 UINT index
, ULONG helpStringContext
)
11321 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11322 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11326 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11327 UINT index
, ULONG helpStringContext
)
11329 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11330 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11334 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11336 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11337 FIXME("%p - stub\n", This
);
11341 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11344 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11346 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11349 return E_INVALIDARG
;
11351 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11356 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11357 ICreateTypeInfo2_fnQueryInterface
,
11358 ICreateTypeInfo2_fnAddRef
,
11359 ICreateTypeInfo2_fnRelease
,
11360 ICreateTypeInfo2_fnSetGuid
,
11361 ICreateTypeInfo2_fnSetTypeFlags
,
11362 ICreateTypeInfo2_fnSetDocString
,
11363 ICreateTypeInfo2_fnSetHelpContext
,
11364 ICreateTypeInfo2_fnSetVersion
,
11365 ICreateTypeInfo2_fnAddRefTypeInfo
,
11366 ICreateTypeInfo2_fnAddFuncDesc
,
11367 ICreateTypeInfo2_fnAddImplType
,
11368 ICreateTypeInfo2_fnSetImplTypeFlags
,
11369 ICreateTypeInfo2_fnSetAlignment
,
11370 ICreateTypeInfo2_fnSetSchema
,
11371 ICreateTypeInfo2_fnAddVarDesc
,
11372 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11373 ICreateTypeInfo2_fnSetVarName
,
11374 ICreateTypeInfo2_fnSetTypeDescAlias
,
11375 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11376 ICreateTypeInfo2_fnSetFuncDocString
,
11377 ICreateTypeInfo2_fnSetVarDocString
,
11378 ICreateTypeInfo2_fnSetFuncHelpContext
,
11379 ICreateTypeInfo2_fnSetVarHelpContext
,
11380 ICreateTypeInfo2_fnSetMops
,
11381 ICreateTypeInfo2_fnSetTypeIdldesc
,
11382 ICreateTypeInfo2_fnLayOut
,
11383 ICreateTypeInfo2_fnDeleteFuncDesc
,
11384 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11385 ICreateTypeInfo2_fnDeleteVarDesc
,
11386 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11387 ICreateTypeInfo2_fnDeleteImplType
,
11388 ICreateTypeInfo2_fnSetCustData
,
11389 ICreateTypeInfo2_fnSetFuncCustData
,
11390 ICreateTypeInfo2_fnSetParamCustData
,
11391 ICreateTypeInfo2_fnSetVarCustData
,
11392 ICreateTypeInfo2_fnSetImplTypeCustData
,
11393 ICreateTypeInfo2_fnSetHelpStringContext
,
11394 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11395 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11396 ICreateTypeInfo2_fnInvalidate
,
11397 ICreateTypeInfo2_fnSetName
11400 /******************************************************************************
11401 * ClearCustData (OLEAUT32.171)
11403 * Clear a custom data type's data.
11406 * lpCust [I] The custom data type instance
11411 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11413 if (lpCust
&& lpCust
->cCustData
)
11415 if (lpCust
->prgCustData
)
11419 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11420 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11422 CoTaskMemFree(lpCust
->prgCustData
);
11423 lpCust
->prgCustData
= NULL
;
11425 lpCust
->cCustData
= 0;