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(ITypeLib
*ptlib
, const WCHAR
*szFullPath
, const WCHAR
*szHelpDir
)
657 if (ptlib
== NULL
|| szFullPath
== NULL
)
660 if (FAILED(ITypeLib_GetLibAttr(ptlib
, &attr
)))
664 if (attr
->syskind
== SYS_WIN64
) return TYPE_E_BADMODULEKIND
;
667 get_typelib_key( &attr
->guid
, attr
->wMajorVerNum
, attr
->wMinorVerNum
, keyName
);
670 if (RegCreateKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, NULL
, 0,
671 KEY_WRITE
, NULL
, &key
, NULL
) == ERROR_SUCCESS
)
675 /* Set the human-readable name of the typelib */
676 if (FAILED(ITypeLib_GetDocumentation(ptlib
, -1, NULL
, &doc
, NULL
, NULL
)))
680 if (RegSetValueExW(key
, NULL
, 0, REG_SZ
,
681 (BYTE
*)doc
, (lstrlenW(doc
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
687 /* Make up the name of the typelib path subkey */
688 if (!get_lcid_subkey( attr
->lcid
, attr
->syskind
, tmp
)) res
= E_FAIL
;
690 /* Create the typelib path subkey */
691 if (res
== S_OK
&& RegCreateKeyExW(key
, tmp
, 0, NULL
, 0,
692 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
694 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
695 (BYTE
*)szFullPath
, (lstrlenW(szFullPath
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
)
703 /* Create the flags subkey */
704 if (res
== S_OK
&& RegCreateKeyExW(key
, FLAGSW
, 0, NULL
, 0,
705 KEY_WRITE
, NULL
, &subKey
, NULL
) == ERROR_SUCCESS
)
707 /* FIXME: is %u correct? */
708 static const WCHAR formatW
[] = {'%','u',0};
710 swprintf(buf
, ARRAY_SIZE(buf
), formatW
, attr
->wLibFlags
);
711 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
712 (BYTE
*)buf
, (lstrlenW(buf
) + 1)*sizeof(WCHAR
) ) != ERROR_SUCCESS
)
720 /* create the helpdir subkey */
721 if (res
== S_OK
&& RegCreateKeyExW(key
, HELPDIRW
, 0, NULL
, 0,
722 KEY_WRITE
, NULL
, &subKey
, &disposition
) == ERROR_SUCCESS
)
724 BSTR freeHelpDir
= NULL
;
727 /* if we created a new key, and helpDir was null, set the helpdir
728 to the directory which contains the typelib. However,
729 if we just opened an existing key, we leave the helpdir alone */
730 if ((disposition
== REG_CREATED_NEW_KEY
) && (szHelpDir
== NULL
)) {
731 szHelpDir
= freeHelpDir
= SysAllocString(szFullPath
);
732 file_name
= wcsrchr(szHelpDir
, '\\');
733 if (file_name
&& file_name
[0]) {
734 /* possible remove a numeric \index (resource-id) */
735 WCHAR
*end_ptr
= file_name
+ 1;
736 while ('0' <= *end_ptr
&& *end_ptr
<= '9') end_ptr
++;
740 file_name
= wcsrchr(szHelpDir
, '\\');
747 /* if we have an szHelpDir, set it! */
748 if (szHelpDir
!= NULL
) {
749 if (RegSetValueExW(subKey
, NULL
, 0, REG_SZ
,
750 (BYTE
*)szHelpDir
, (lstrlenW(szHelpDir
)+1) * sizeof(OLECHAR
)) != ERROR_SUCCESS
) {
755 SysFreeString(freeHelpDir
);
766 /* register OLE Automation-compatible interfaces for this typelib */
767 types
= ITypeLib_GetTypeInfoCount(ptlib
);
768 for (tidx
=0; tidx
<types
; tidx
++) {
769 if (SUCCEEDED(ITypeLib_GetTypeInfoType(ptlib
, tidx
, &kind
))) {
770 LPOLESTR name
= NULL
;
771 ITypeInfo
*tinfo
= NULL
;
773 ITypeLib_GetDocumentation(ptlib
, tidx
, &name
, NULL
, NULL
, NULL
);
776 case TKIND_INTERFACE
:
777 TRACE_(typelib
)("%d: interface %s\n", tidx
, debugstr_w(name
));
778 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
782 TRACE_(typelib
)("%d: dispinterface %s\n", tidx
, debugstr_w(name
));
783 ITypeLib_GetTypeInfo(ptlib
, tidx
, &tinfo
);
787 TRACE_(typelib
)("%d: %s\n", tidx
, debugstr_w(name
));
792 TYPEATTR
*tattr
= NULL
;
793 ITypeInfo_GetTypeAttr(tinfo
, &tattr
);
796 TRACE_(typelib
)("guid=%s, flags=%04x (",
797 debugstr_guid(&tattr
->guid
),
800 if (TRACE_ON(typelib
)) {
801 #define XX(x) if (TYPEFLAG_##x & tattr->wTypeFlags) MESSAGE(#x"|");
821 /* Register all dispinterfaces (which includes dual interfaces) and
822 oleautomation interfaces */
823 if ((kind
== TKIND_INTERFACE
&& (tattr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
824 kind
== TKIND_DISPATCH
)
827 DWORD opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
829 /* register interface<->typelib coupling */
830 TLB_register_interface(attr
, name
, tattr
, 0);
832 /* register TLBs into the opposite registry view, too */
833 if(opposite
== KEY_WOW64_32KEY
||
834 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
))
835 TLB_register_interface(attr
, name
, tattr
, opposite
);
838 ITypeInfo_ReleaseTypeAttr(tinfo
, tattr
);
841 ITypeInfo_Release(tinfo
);
848 ITypeLib_ReleaseTLibAttr(ptlib
, attr
);
853 static void TLB_unregister_interface(GUID
*guid
, REGSAM flag
)
855 WCHAR subKeyName
[50];
858 /* the path to the type */
859 get_interface_key( guid
, subKeyName
);
861 /* Delete its bits */
862 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, 0, KEY_WRITE
| flag
, &subKey
) != ERROR_SUCCESS
)
865 RegDeleteKeyW(subKey
, ProxyStubClsidW
);
866 RegDeleteKeyW(subKey
, ProxyStubClsid32W
);
867 RegDeleteKeyW(subKey
, TypeLibW
);
869 RegDeleteKeyExW(HKEY_CLASSES_ROOT
, subKeyName
, flag
, 0);
872 /******************************************************************************
873 * UnRegisterTypeLib [OLEAUT32.186]
874 * Removes information about a type library from the System Registry
881 HRESULT WINAPI
UnRegisterTypeLib(
882 REFGUID libid
, /* [in] Guid of the library */
883 WORD wVerMajor
, /* [in] major version */
884 WORD wVerMinor
, /* [in] minor version */
885 LCID lcid
, /* [in] locale id */
888 BSTR tlibPath
= NULL
;
891 WCHAR subKeyName
[50];
894 BOOL deleteOtherStuff
;
896 TYPEATTR
* typeAttr
= NULL
;
898 ITypeInfo
* typeInfo
= NULL
;
899 ITypeLib
* typeLib
= NULL
;
902 TRACE("(IID: %s)\n",debugstr_guid(libid
));
904 /* Create the path to the key */
905 get_typelib_key( libid
, wVerMajor
, wVerMinor
, keyName
);
907 if (syskind
!= SYS_WIN16
&& syskind
!= SYS_WIN32
&& syskind
!= SYS_WIN64
)
909 TRACE("Unsupported syskind %i\n", syskind
);
910 result
= E_INVALIDARG
;
914 /* get the path to the typelib on disk */
915 if (query_typelib_path(libid
, wVerMajor
, wVerMinor
, syskind
, lcid
, &tlibPath
, FALSE
) != S_OK
) {
916 result
= E_INVALIDARG
;
920 /* Try and open the key to the type library. */
921 if (RegOpenKeyExW(HKEY_CLASSES_ROOT
, keyName
, 0, KEY_READ
| KEY_WRITE
, &key
) != ERROR_SUCCESS
) {
922 result
= E_INVALIDARG
;
926 /* Try and load the type library */
927 if (LoadTypeLibEx(tlibPath
, REGKIND_NONE
, &typeLib
) != S_OK
) {
928 result
= TYPE_E_INVALIDSTATE
;
932 /* remove any types registered with this typelib */
933 numTypes
= ITypeLib_GetTypeInfoCount(typeLib
);
934 for (i
=0; i
<numTypes
; i
++) {
935 /* get the kind of type */
936 if (ITypeLib_GetTypeInfoType(typeLib
, i
, &kind
) != S_OK
) {
940 /* skip non-interfaces, and get type info for the type */
941 if ((kind
!= TKIND_INTERFACE
) && (kind
!= TKIND_DISPATCH
)) {
944 if (ITypeLib_GetTypeInfo(typeLib
, i
, &typeInfo
) != S_OK
) {
947 if (ITypeInfo_GetTypeAttr(typeInfo
, &typeAttr
) != S_OK
) {
951 if ((kind
== TKIND_INTERFACE
&& (typeAttr
->wTypeFlags
& TYPEFLAG_FOLEAUTOMATION
)) ||
952 kind
== TKIND_DISPATCH
)
955 REGSAM opposite
= (sizeof(void*) == 8 ? KEY_WOW64_32KEY
: KEY_WOW64_64KEY
);
957 TLB_unregister_interface(&typeAttr
->guid
, 0);
959 /* unregister TLBs into the opposite registry view, too */
960 if(opposite
== KEY_WOW64_32KEY
||
961 (IsWow64Process(GetCurrentProcess(), &is_wow64
) && is_wow64
)) {
962 TLB_unregister_interface(&typeAttr
->guid
, opposite
);
967 if (typeAttr
) ITypeInfo_ReleaseTypeAttr(typeInfo
, typeAttr
);
969 if (typeInfo
) ITypeInfo_Release(typeInfo
);
973 /* Now, delete the type library path subkey */
974 get_lcid_subkey( lcid
, syskind
, subKeyName
);
975 RegDeleteKeyW(key
, subKeyName
);
976 *wcsrchr( subKeyName
, '\\' ) = 0; /* remove last path component */
977 RegDeleteKeyW(key
, subKeyName
);
979 /* check if there is anything besides the FLAGS/HELPDIR keys.
980 If there is, we don't delete them */
981 tmpLength
= ARRAY_SIZE(subKeyName
);
982 deleteOtherStuff
= TRUE
;
984 while(RegEnumKeyExW(key
, i
++, subKeyName
, &tmpLength
, NULL
, NULL
, NULL
, NULL
) == ERROR_SUCCESS
) {
985 tmpLength
= ARRAY_SIZE(subKeyName
);
987 /* if its not FLAGS or HELPDIR, then we must keep the rest of the key */
988 if (!wcscmp(subKeyName
, FLAGSW
)) continue;
989 if (!wcscmp(subKeyName
, HELPDIRW
)) continue;
990 deleteOtherStuff
= FALSE
;
994 /* only delete the other parts of the key if we're absolutely sure */
995 if (deleteOtherStuff
) {
996 RegDeleteKeyW(key
, FLAGSW
);
997 RegDeleteKeyW(key
, HELPDIRW
);
1001 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1002 *wcsrchr( keyName
, '\\' ) = 0; /* remove last path component */
1003 RegDeleteKeyW(HKEY_CLASSES_ROOT
, keyName
);
1007 SysFreeString(tlibPath
);
1008 if (typeLib
) ITypeLib_Release(typeLib
);
1009 if (key
) RegCloseKey(key
);
1013 /******************************************************************************
1014 * RegisterTypeLibForUser [OLEAUT32.442]
1015 * Adds information about a type library to the user registry
1017 * Docs: ITypeLib FAR * ptlib
1018 * Docs: OLECHAR FAR* szFullPath
1019 * Docs: OLECHAR FAR* szHelpDir
1025 HRESULT WINAPI
RegisterTypeLibForUser(
1026 ITypeLib
* ptlib
, /* [in] Pointer to the library*/
1027 OLECHAR
* szFullPath
, /* [in] full Path of the library*/
1028 OLECHAR
* szHelpDir
) /* [in] dir to the helpfile for the library,
1031 FIXME("(%p, %s, %s) registering the typelib system-wide\n", ptlib
,
1032 debugstr_w(szFullPath
), debugstr_w(szHelpDir
));
1033 return RegisterTypeLib(ptlib
, szFullPath
, szHelpDir
);
1036 /******************************************************************************
1037 * UnRegisterTypeLibForUser [OLEAUT32.443]
1038 * Removes information about a type library from the user registry
1044 HRESULT WINAPI
UnRegisterTypeLibForUser(
1045 REFGUID libid
, /* [in] GUID of the library */
1046 WORD wVerMajor
, /* [in] major version */
1047 WORD wVerMinor
, /* [in] minor version */
1048 LCID lcid
, /* [in] locale id */
1051 FIXME("(%s, %u, %u, %u, %u) unregistering the typelib system-wide\n",
1052 debugstr_guid(libid
), wVerMajor
, wVerMinor
, lcid
, syskind
);
1053 return UnRegisterTypeLib(libid
, wVerMajor
, wVerMinor
, lcid
, syskind
);
1056 /*======================= ITypeLib implementation =======================*/
1058 typedef struct tagTLBGuid
{
1065 typedef struct tagTLBCustData
1072 /* data structure for import typelibs */
1073 typedef struct tagTLBImpLib
1075 int offset
; /* offset in the file (MSFT)
1076 offset in nametable (SLTG)
1077 just used to identify library while reading
1079 TLBGuid
*guid
; /* libid */
1080 BSTR name
; /* name */
1082 LCID lcid
; /* lcid of imported typelib */
1084 WORD wVersionMajor
; /* major version number */
1085 WORD wVersionMinor
; /* minor version number */
1087 struct tagITypeLibImpl
*pImpTypeLib
; /* pointer to loaded typelib, or
1088 NULL if not yet loaded */
1092 typedef struct tagTLBString
{
1098 /* internal ITypeLib data */
1099 typedef struct tagITypeLibImpl
1101 ITypeLib2 ITypeLib2_iface
;
1102 ITypeComp ITypeComp_iface
;
1103 ICreateTypeLib2 ICreateTypeLib2_iface
;
1114 /* strings can be stored in tlb as multibyte strings BUT they are *always*
1115 * exported to the application as a UNICODE string.
1117 struct list string_list
;
1118 struct list name_list
;
1119 struct list guid_list
;
1121 const TLBString
*Name
;
1122 const TLBString
*DocString
;
1123 const TLBString
*HelpFile
;
1124 const TLBString
*HelpStringDll
;
1125 DWORD dwHelpContext
;
1126 int TypeInfoCount
; /* nr of typeinfo's in librarry */
1127 struct tagITypeInfoImpl
**typeinfos
;
1128 struct list custdata_list
;
1129 struct list implib_list
;
1130 int ctTypeDesc
; /* number of items in type desc array */
1131 TYPEDESC
* pTypeDesc
; /* array of TypeDescriptions found in the
1132 library. Only used while reading MSFT
1134 struct list ref_list
; /* list of ref types in this typelib */
1135 HREFTYPE dispatch_href
; /* reference to IDispatch, -1 if unused */
1138 /* typelibs are cached, keyed by path and index, so store the linked list info within them */
1144 static const ITypeLib2Vtbl tlbvt
;
1145 static const ITypeCompVtbl tlbtcvt
;
1146 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
;
1148 static inline ITypeLibImpl
*impl_from_ITypeLib2(ITypeLib2
*iface
)
1150 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeLib2_iface
);
1153 static inline ITypeLibImpl
*impl_from_ITypeLib(ITypeLib
*iface
)
1155 return impl_from_ITypeLib2((ITypeLib2
*)iface
);
1158 static inline ITypeLibImpl
*impl_from_ITypeComp( ITypeComp
*iface
)
1160 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ITypeComp_iface
);
1163 static inline ITypeLibImpl
*impl_from_ICreateTypeLib2( ICreateTypeLib2
*iface
)
1165 return CONTAINING_RECORD(iface
, ITypeLibImpl
, ICreateTypeLib2_iface
);
1168 /* ITypeLib methods */
1169 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
);
1170 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
);
1172 /*======================= ITypeInfo implementation =======================*/
1174 /* data for referenced types */
1175 typedef struct tagTLBRefType
1177 INT index
; /* Type index for internal ref or for external ref
1178 it the format is SLTG. -2 indicates to
1182 TLBGuid
*guid
; /* guid of the referenced type */
1183 /* if index == TLB_REF_USE_GUID */
1185 HREFTYPE reference
; /* The href of this ref */
1186 TLBImpLib
*pImpTLInfo
; /* If ref is external ptr to library data
1187 TLB_REF_INTERNAL for internal refs
1188 TLB_REF_NOT_FOUND for broken refs */
1193 #define TLB_REF_USE_GUID -2
1195 #define TLB_REF_INTERNAL (void*)-2
1196 #define TLB_REF_NOT_FOUND (void*)-1
1198 /* internal Parameter data */
1199 typedef struct tagTLBParDesc
1201 const TLBString
*Name
;
1202 struct list custdata_list
;
1205 /* internal Function data */
1206 typedef struct tagTLBFuncDesc
1208 FUNCDESC funcdesc
; /* lots of info on the function and its attributes. */
1209 const TLBString
*Name
; /* the name of this function */
1210 TLBParDesc
*pParamDesc
; /* array with param names and custom data */
1212 int HelpStringContext
;
1213 const TLBString
*HelpString
;
1214 const TLBString
*Entry
; /* if IS_INTRESOURCE true, it's numeric; if -1 it isn't present */
1215 struct list custdata_list
;
1218 /* internal Variable data */
1219 typedef struct tagTLBVarDesc
1221 VARDESC vardesc
; /* lots of info on the variable and its attributes. */
1222 VARDESC
*vardesc_create
; /* additional data needed for storing VARDESC */
1223 const TLBString
*Name
; /* the name of this variable */
1225 int HelpStringContext
;
1226 const TLBString
*HelpString
;
1227 struct list custdata_list
;
1230 /* internal implemented interface data */
1231 typedef struct tagTLBImplType
1233 HREFTYPE hRef
; /* hRef of interface */
1234 int implflags
; /* IMPLFLAG_*s */
1235 struct list custdata_list
;
1238 /* internal TypeInfo data */
1239 typedef struct tagITypeInfoImpl
1241 ITypeInfo2 ITypeInfo2_iface
;
1242 ITypeComp ITypeComp_iface
;
1243 ICreateTypeInfo2 ICreateTypeInfo2_iface
;
1245 BOOL not_attached_to_typelib
;
1250 TYPEDESC
*tdescAlias
;
1252 ITypeLibImpl
* pTypeLib
; /* back pointer to typelib */
1253 int index
; /* index in this typelib; */
1254 HREFTYPE hreftype
; /* hreftype for app object binding */
1255 /* type libs seem to store the doc strings in ascii
1256 * so why should we do it in unicode?
1258 const TLBString
*Name
;
1259 const TLBString
*DocString
;
1260 const TLBString
*DllName
;
1261 const TLBString
*Schema
;
1262 DWORD dwHelpContext
;
1263 DWORD dwHelpStringContext
;
1266 TLBFuncDesc
*funcdescs
;
1269 TLBVarDesc
*vardescs
;
1271 /* Implemented Interfaces */
1272 TLBImplType
*impltypes
;
1274 struct list
*pcustdata_list
;
1275 struct list custdata_list
;
1278 static inline ITypeInfoImpl
*info_impl_from_ITypeComp( ITypeComp
*iface
)
1280 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeComp_iface
);
1283 static inline ITypeInfoImpl
*impl_from_ITypeInfo2( ITypeInfo2
*iface
)
1285 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ITypeInfo2_iface
);
1288 static inline ITypeInfoImpl
*impl_from_ITypeInfo( ITypeInfo
*iface
)
1290 return impl_from_ITypeInfo2((ITypeInfo2
*)iface
);
1293 static inline ITypeInfoImpl
*info_impl_from_ICreateTypeInfo2( ICreateTypeInfo2
*iface
)
1295 return CONTAINING_RECORD(iface
, ITypeInfoImpl
, ICreateTypeInfo2_iface
);
1298 static const ITypeInfo2Vtbl tinfvt
;
1299 static const ITypeCompVtbl tcompvt
;
1300 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
;
1302 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void);
1303 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
);
1305 typedef struct tagTLBContext
1307 unsigned int oStart
; /* start of TLB in file */
1308 unsigned int pos
; /* current pos */
1309 unsigned int length
; /* total length */
1310 void *mapping
; /* memory mapping */
1311 MSFT_SegDir
* pTblDir
;
1312 ITypeLibImpl
* pLibInfo
;
1316 static inline BSTR
TLB_get_bstr(const TLBString
*str
)
1318 return str
!= NULL
? str
->str
: NULL
;
1321 static inline int TLB_str_memcmp(void *left
, const TLBString
*str
, DWORD len
)
1325 return memcmp(left
, str
->str
, len
);
1328 static inline const GUID
*TLB_get_guidref(const TLBGuid
*guid
)
1330 return guid
!= NULL
? &guid
->guid
: NULL
;
1333 static inline const GUID
*TLB_get_guid_null(const TLBGuid
*guid
)
1335 return guid
!= NULL
? &guid
->guid
: &GUID_NULL
;
1338 static int get_ptr_size(SYSKIND syskind
)
1348 WARN("Unhandled syskind: 0x%x\n", syskind
);
1355 static void dump_TypeDesc(const TYPEDESC
*pTD
,char *szVarType
) {
1356 if (pTD
->vt
& VT_RESERVED
)
1357 szVarType
+= strlen(strcpy(szVarType
, "reserved | "));
1358 if (pTD
->vt
& VT_BYREF
)
1359 szVarType
+= strlen(strcpy(szVarType
, "ref to "));
1360 if (pTD
->vt
& VT_ARRAY
)
1361 szVarType
+= strlen(strcpy(szVarType
, "array of "));
1362 if (pTD
->vt
& VT_VECTOR
)
1363 szVarType
+= strlen(strcpy(szVarType
, "vector of "));
1364 switch(pTD
->vt
& VT_TYPEMASK
) {
1365 case VT_UI1
: sprintf(szVarType
, "VT_UI1"); break;
1366 case VT_I2
: sprintf(szVarType
, "VT_I2"); break;
1367 case VT_I4
: sprintf(szVarType
, "VT_I4"); break;
1368 case VT_R4
: sprintf(szVarType
, "VT_R4"); break;
1369 case VT_R8
: sprintf(szVarType
, "VT_R8"); break;
1370 case VT_BOOL
: sprintf(szVarType
, "VT_BOOL"); break;
1371 case VT_ERROR
: sprintf(szVarType
, "VT_ERROR"); break;
1372 case VT_CY
: sprintf(szVarType
, "VT_CY"); break;
1373 case VT_DATE
: sprintf(szVarType
, "VT_DATE"); break;
1374 case VT_BSTR
: sprintf(szVarType
, "VT_BSTR"); break;
1375 case VT_UNKNOWN
: sprintf(szVarType
, "VT_UNKNOWN"); break;
1376 case VT_DISPATCH
: sprintf(szVarType
, "VT_DISPATCH"); break;
1377 case VT_I1
: sprintf(szVarType
, "VT_I1"); break;
1378 case VT_UI2
: sprintf(szVarType
, "VT_UI2"); break;
1379 case VT_UI4
: sprintf(szVarType
, "VT_UI4"); break;
1380 case VT_INT
: sprintf(szVarType
, "VT_INT"); break;
1381 case VT_UINT
: sprintf(szVarType
, "VT_UINT"); break;
1382 case VT_VARIANT
: sprintf(szVarType
, "VT_VARIANT"); break;
1383 case VT_VOID
: sprintf(szVarType
, "VT_VOID"); break;
1384 case VT_HRESULT
: sprintf(szVarType
, "VT_HRESULT"); break;
1385 case VT_USERDEFINED
: sprintf(szVarType
, "VT_USERDEFINED ref = %x",
1386 pTD
->u
.hreftype
); break;
1387 case VT_LPSTR
: sprintf(szVarType
, "VT_LPSTR"); break;
1388 case VT_LPWSTR
: sprintf(szVarType
, "VT_LPWSTR"); break;
1389 case VT_PTR
: sprintf(szVarType
, "ptr to ");
1390 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 7);
1392 case VT_SAFEARRAY
: sprintf(szVarType
, "safearray of ");
1393 dump_TypeDesc(pTD
->u
.lptdesc
, szVarType
+ 13);
1395 case VT_CARRAY
: sprintf(szVarType
, "%d dim array of ",
1396 pTD
->u
.lpadesc
->cDims
); /* FIXME print out sizes */
1397 dump_TypeDesc(&pTD
->u
.lpadesc
->tdescElem
, szVarType
+ strlen(szVarType
));
1400 default: sprintf(szVarType
, "unknown(%d)", pTD
->vt
& VT_TYPEMASK
); break;
1404 static void dump_ELEMDESC(const ELEMDESC
*edesc
) {
1406 USHORT flags
= edesc
->u
.paramdesc
.wParamFlags
;
1407 dump_TypeDesc(&edesc
->tdesc
,buf
);
1408 MESSAGE("\t\ttdesc.vartype %d (%s)\n",edesc
->tdesc
.vt
,buf
);
1409 MESSAGE("\t\tu.paramdesc.wParamFlags");
1410 if (!flags
) MESSAGE(" PARAMFLAGS_NONE");
1411 if (flags
& PARAMFLAG_FIN
) MESSAGE(" PARAMFLAG_FIN");
1412 if (flags
& PARAMFLAG_FOUT
) MESSAGE(" PARAMFLAG_FOUT");
1413 if (flags
& PARAMFLAG_FLCID
) MESSAGE(" PARAMFLAG_FLCID");
1414 if (flags
& PARAMFLAG_FRETVAL
) MESSAGE(" PARAMFLAG_FRETVAL");
1415 if (flags
& PARAMFLAG_FOPT
) MESSAGE(" PARAMFLAG_FOPT");
1416 if (flags
& PARAMFLAG_FHASDEFAULT
) MESSAGE(" PARAMFLAG_FHASDEFAULT");
1417 if (flags
& PARAMFLAG_FHASCUSTDATA
) MESSAGE(" PARAMFLAG_FHASCUSTDATA");
1418 MESSAGE("\n\t\tu.paramdesc.lpex %p\n",edesc
->u
.paramdesc
.pparamdescex
);
1420 static void dump_FUNCDESC(const FUNCDESC
*funcdesc
) {
1422 MESSAGE("memid is %08x\n",funcdesc
->memid
);
1423 for (i
=0;i
<funcdesc
->cParams
;i
++) {
1424 MESSAGE("Param %d:\n",i
);
1425 dump_ELEMDESC(funcdesc
->lprgelemdescParam
+i
);
1427 MESSAGE("\tfunckind: %d (",funcdesc
->funckind
);
1428 switch (funcdesc
->funckind
) {
1429 case FUNC_VIRTUAL
: MESSAGE("virtual");break;
1430 case FUNC_PUREVIRTUAL
: MESSAGE("pure virtual");break;
1431 case FUNC_NONVIRTUAL
: MESSAGE("nonvirtual");break;
1432 case FUNC_STATIC
: MESSAGE("static");break;
1433 case FUNC_DISPATCH
: MESSAGE("dispatch");break;
1434 default: MESSAGE("unknown");break;
1436 MESSAGE(")\n\tinvkind: %d (",funcdesc
->invkind
);
1437 switch (funcdesc
->invkind
) {
1438 case INVOKE_FUNC
: MESSAGE("func");break;
1439 case INVOKE_PROPERTYGET
: MESSAGE("property get");break;
1440 case INVOKE_PROPERTYPUT
: MESSAGE("property put");break;
1441 case INVOKE_PROPERTYPUTREF
: MESSAGE("property put ref");break;
1443 MESSAGE(")\n\tcallconv: %d (",funcdesc
->callconv
);
1444 switch (funcdesc
->callconv
) {
1445 case CC_CDECL
: MESSAGE("cdecl");break;
1446 case CC_PASCAL
: MESSAGE("pascal");break;
1447 case CC_STDCALL
: MESSAGE("stdcall");break;
1448 case CC_SYSCALL
: MESSAGE("syscall");break;
1451 MESSAGE(")\n\toVft: %d\n", funcdesc
->oVft
);
1452 MESSAGE("\tcParamsOpt: %d\n", funcdesc
->cParamsOpt
);
1453 MESSAGE("\twFlags: %x\n", funcdesc
->wFuncFlags
);
1455 MESSAGE("\telemdescFunc (return value type):\n");
1456 dump_ELEMDESC(&funcdesc
->elemdescFunc
);
1459 static const char * const typekind_desc
[] =
1472 static void dump_TLBFuncDescOne(const TLBFuncDesc
* pfd
)
1475 MESSAGE("%s(%u)\n", debugstr_w(TLB_get_bstr(pfd
->Name
)), pfd
->funcdesc
.cParams
);
1476 for (i
=0;i
<pfd
->funcdesc
.cParams
;i
++)
1477 MESSAGE("\tparm%d: %s\n",i
,debugstr_w(TLB_get_bstr(pfd
->pParamDesc
[i
].Name
)));
1480 dump_FUNCDESC(&(pfd
->funcdesc
));
1482 MESSAGE("\thelpstring: %s\n", debugstr_w(TLB_get_bstr(pfd
->HelpString
)));
1483 if(pfd
->Entry
== NULL
)
1484 MESSAGE("\tentry: (null)\n");
1485 else if(pfd
->Entry
== (void*)-1)
1486 MESSAGE("\tentry: invalid\n");
1487 else if(IS_INTRESOURCE(pfd
->Entry
))
1488 MESSAGE("\tentry: %p\n", pfd
->Entry
);
1490 MESSAGE("\tentry: %s\n", debugstr_w(TLB_get_bstr(pfd
->Entry
)));
1492 static void dump_TLBFuncDesc(const TLBFuncDesc
* pfd
, UINT n
)
1496 dump_TLBFuncDescOne(pfd
);
1501 static void dump_TLBVarDesc(const TLBVarDesc
* pvd
, UINT n
)
1505 TRACE_(typelib
)("%s\n", debugstr_w(TLB_get_bstr(pvd
->Name
)));
1511 static void dump_TLBImpLib(const TLBImpLib
*import
)
1513 TRACE_(typelib
)("%s %s\n", debugstr_guid(TLB_get_guidref(import
->guid
)),
1514 debugstr_w(import
->name
));
1515 TRACE_(typelib
)("v%d.%d lcid=%x offset=%x\n", import
->wVersionMajor
,
1516 import
->wVersionMinor
, import
->lcid
, import
->offset
);
1519 static void dump_TLBRefType(const ITypeLibImpl
*pTL
)
1523 LIST_FOR_EACH_ENTRY(ref
, &pTL
->ref_list
, TLBRefType
, entry
)
1525 TRACE_(typelib
)("href:0x%08x\n", ref
->reference
);
1526 if(ref
->index
== -1)
1527 TRACE_(typelib
)("%s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
1529 TRACE_(typelib
)("type no: %d\n", ref
->index
);
1531 if(ref
->pImpTLInfo
!= TLB_REF_INTERNAL
&& ref
->pImpTLInfo
!= TLB_REF_NOT_FOUND
)
1533 TRACE_(typelib
)("in lib\n");
1534 dump_TLBImpLib(ref
->pImpTLInfo
);
1539 static void dump_TLBImplType(const TLBImplType
* impl
, UINT n
)
1544 TRACE_(typelib
)("implementing/inheriting interface hRef = %x implflags %x\n",
1545 impl
->hRef
, impl
->implflags
);
1551 static void dump_DispParms(const DISPPARAMS
* pdp
)
1555 TRACE("args=%u named args=%u\n", pdp
->cArgs
, pdp
->cNamedArgs
);
1557 if (pdp
->cNamedArgs
&& pdp
->rgdispidNamedArgs
)
1559 TRACE("named args:\n");
1560 for (index
= 0; index
< pdp
->cNamedArgs
; index
++)
1561 TRACE( "\t0x%x\n", pdp
->rgdispidNamedArgs
[index
] );
1564 if (pdp
->cArgs
&& pdp
->rgvarg
)
1567 for (index
= 0; index
< pdp
->cArgs
; index
++)
1568 TRACE(" [%d] %s\n", index
, debugstr_variant(pdp
->rgvarg
+index
));
1572 static void dump_TypeInfo(const ITypeInfoImpl
* pty
)
1574 TRACE("%p ref=%u\n", pty
, pty
->ref
);
1575 TRACE("%s %s\n", debugstr_w(TLB_get_bstr(pty
->Name
)), debugstr_w(TLB_get_bstr(pty
->DocString
)));
1576 TRACE("attr:%s\n", debugstr_guid(TLB_get_guidref(pty
->guid
)));
1577 TRACE("kind:%s\n", typekind_desc
[pty
->typeattr
.typekind
]);
1578 TRACE("fct:%u var:%u impl:%u\n", pty
->typeattr
.cFuncs
, pty
->typeattr
.cVars
, pty
->typeattr
.cImplTypes
);
1579 TRACE("wTypeFlags: 0x%04x\n", pty
->typeattr
.wTypeFlags
);
1580 TRACE("parent tlb:%p index in TLB:%u\n",pty
->pTypeLib
, pty
->index
);
1581 if (pty
->typeattr
.typekind
== TKIND_MODULE
) TRACE("dllname:%s\n", debugstr_w(TLB_get_bstr(pty
->DllName
)));
1583 dump_TLBFuncDesc(pty
->funcdescs
, pty
->typeattr
.cFuncs
);
1584 dump_TLBVarDesc(pty
->vardescs
, pty
->typeattr
.cVars
);
1585 dump_TLBImplType(pty
->impltypes
, pty
->typeattr
.cImplTypes
);
1588 static void dump_VARDESC(const VARDESC
*v
)
1590 MESSAGE("memid %d\n",v
->memid
);
1591 MESSAGE("lpstrSchema %s\n",debugstr_w(v
->lpstrSchema
));
1592 MESSAGE("oInst %d\n",v
->u
.oInst
);
1593 dump_ELEMDESC(&(v
->elemdescVar
));
1594 MESSAGE("wVarFlags %x\n",v
->wVarFlags
);
1595 MESSAGE("varkind %d\n",v
->varkind
);
1598 static TYPEDESC std_typedesc
[VT_LPWSTR
+1] =
1600 /* VT_LPWSTR is largest type that, may appear in type description */
1601 {{0}, VT_EMPTY
}, {{0}, VT_NULL
}, {{0}, VT_I2
}, {{0}, VT_I4
},
1602 {{0}, VT_R4
}, {{0}, VT_R8
}, {{0}, VT_CY
}, {{0}, VT_DATE
},
1603 {{0}, VT_BSTR
}, {{0}, VT_DISPATCH
}, {{0}, VT_ERROR
}, {{0}, VT_BOOL
},
1604 {{0}, VT_VARIANT
},{{0}, VT_UNKNOWN
}, {{0}, VT_DECIMAL
}, {{0}, 15}, /* unused in VARENUM */
1605 {{0}, VT_I1
}, {{0}, VT_UI1
}, {{0}, VT_UI2
}, {{0}, VT_UI4
},
1606 {{0}, VT_I8
}, {{0}, VT_UI8
}, {{0}, VT_INT
}, {{0}, VT_UINT
},
1607 {{0}, VT_VOID
}, {{0}, VT_HRESULT
}, {{0}, VT_PTR
}, {{0}, VT_SAFEARRAY
},
1608 {{0}, VT_CARRAY
}, {{0}, VT_USERDEFINED
}, {{0}, VT_LPSTR
}, {{0}, VT_LPWSTR
}
1611 static void TLB_abort(void)
1616 /* returns the size required for a deep copy of a typedesc into a
1618 static SIZE_T
TLB_SizeTypeDesc( const TYPEDESC
*tdesc
, BOOL alloc_initial_space
)
1622 if (alloc_initial_space
)
1623 size
+= sizeof(TYPEDESC
);
1629 size
+= TLB_SizeTypeDesc(tdesc
->u
.lptdesc
, TRUE
);
1632 size
+= FIELD_OFFSET(ARRAYDESC
, rgbounds
[tdesc
->u
.lpadesc
->cDims
]);
1633 size
+= TLB_SizeTypeDesc(&tdesc
->u
.lpadesc
->tdescElem
, FALSE
);
1639 /* deep copy a typedesc into a flat buffer */
1640 static void *TLB_CopyTypeDesc( TYPEDESC
*dest
, const TYPEDESC
*src
, void *buffer
)
1645 buffer
= (char *)buffer
+ sizeof(TYPEDESC
);
1654 dest
->u
.lptdesc
= buffer
;
1655 buffer
= TLB_CopyTypeDesc(NULL
, src
->u
.lptdesc
, buffer
);
1658 dest
->u
.lpadesc
= buffer
;
1659 memcpy(dest
->u
.lpadesc
, src
->u
.lpadesc
, FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]));
1660 buffer
= (char *)buffer
+ FIELD_OFFSET(ARRAYDESC
, rgbounds
[src
->u
.lpadesc
->cDims
]);
1661 buffer
= TLB_CopyTypeDesc(&dest
->u
.lpadesc
->tdescElem
, &src
->u
.lpadesc
->tdescElem
, buffer
);
1667 /* free custom data allocated by MSFT_CustData */
1668 static inline void TLB_FreeCustData(struct list
*custdata_list
)
1670 TLBCustData
*cd
, *cdn
;
1671 LIST_FOR_EACH_ENTRY_SAFE(cd
, cdn
, custdata_list
, TLBCustData
, entry
)
1673 list_remove(&cd
->entry
);
1674 VariantClear(&cd
->data
);
1679 static BSTR
TLB_MultiByteToBSTR(const char *ptr
)
1684 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, NULL
, 0);
1685 ret
= SysAllocStringLen(NULL
, len
- 1);
1686 if (!ret
) return ret
;
1687 MultiByteToWideChar(CP_ACP
, 0, ptr
, -1, ret
, len
);
1691 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1695 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1697 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
)
1698 return &typeinfo
->funcdescs
[i
];
1704 static inline TLBFuncDesc
*TLB_get_funcdesc_by_memberid_invkind(ITypeInfoImpl
*typeinfo
, MEMBERID memid
, INVOKEKIND invkind
)
1708 for (i
= 0; i
< typeinfo
->typeattr
.cFuncs
; ++i
)
1710 if (typeinfo
->funcdescs
[i
].funcdesc
.memid
== memid
&& typeinfo
->funcdescs
[i
].funcdesc
.invkind
== invkind
)
1711 return &typeinfo
->funcdescs
[i
];
1717 static inline TLBVarDesc
*TLB_get_vardesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1721 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1723 if (typeinfo
->vardescs
[i
].vardesc
.memid
== memid
)
1724 return &typeinfo
->vardescs
[i
];
1730 static inline TLBVarDesc
*TLB_get_vardesc_by_name(ITypeInfoImpl
*typeinfo
, const OLECHAR
*name
)
1734 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1736 if (!lstrcmpiW(TLB_get_bstr(typeinfo
->vardescs
[i
].Name
), name
))
1737 return &typeinfo
->vardescs
[i
];
1743 static inline TLBCustData
*TLB_get_custdata_by_guid(const struct list
*custdata_list
, REFGUID guid
)
1745 TLBCustData
*cust_data
;
1746 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1747 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1752 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeLibImpl
*typelib
, const OLECHAR
*name
)
1756 for (i
= 0; i
< typelib
->TypeInfoCount
; ++i
)
1758 if (!lstrcmpiW(TLB_get_bstr(typelib
->typeinfos
[i
]->Name
), name
))
1759 return typelib
->typeinfos
[i
];
1765 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1767 list_init(&var_desc
->custdata_list
);
1770 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1774 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1779 TLBVarDesc_Constructor(&ret
[n
-1]);
1786 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1790 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1795 list_init(&ret
[n
-1].custdata_list
);
1802 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1804 list_init(&func_desc
->custdata_list
);
1807 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1811 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1816 TLBFuncDesc_Constructor(&ret
[n
-1]);
1823 static void TLBImplType_Constructor(TLBImplType
*impl
)
1825 list_init(&impl
->custdata_list
);
1828 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1832 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1837 TLBImplType_Constructor(&ret
[n
-1]);
1844 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1845 const GUID
*new_guid
, HREFTYPE hreftype
)
1849 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1850 if (IsEqualGUID(&guid
->guid
, new_guid
))
1854 guid
= heap_alloc(sizeof(TLBGuid
));
1858 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1859 guid
->hreftype
= hreftype
;
1861 list_add_tail(guid_list
, &guid
->entry
);
1866 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1868 TLBCustData
*cust_data
;
1880 return DISP_E_BADVARTYPE
;
1883 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1886 cust_data
= heap_alloc(sizeof(TLBCustData
));
1888 return E_OUTOFMEMORY
;
1890 cust_data
->guid
= tlbguid
;
1891 VariantInit(&cust_data
->data
);
1893 list_add_tail(custdata_list
, &cust_data
->entry
);
1895 VariantClear(&cust_data
->data
);
1897 return VariantCopy(&cust_data
->data
, var
);
1900 /* Used to update list pointers after list itself was moved. */
1901 static void TLB_relink_custdata(struct list
*custdata_list
)
1903 if (custdata_list
->prev
== custdata_list
->next
)
1904 list_init(custdata_list
);
1907 custdata_list
->prev
->next
= custdata_list
;
1908 custdata_list
->next
->prev
= custdata_list
;
1912 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1919 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1920 if (wcscmp(str
->str
, new_str
) == 0)
1924 str
= heap_alloc(sizeof(TLBString
));
1928 str
->str
= SysAllocString(new_str
);
1934 list_add_tail(string_list
, &str
->entry
);
1939 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1940 ULONG
*size
, WORD
*align
)
1946 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1950 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1952 ITypeInfo_Release(other
);
1957 *size
= attr
->cbSizeInstance
;
1959 *align
= attr
->cbAlignment
;
1961 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1962 ITypeInfo_Release(other
);
1967 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1968 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1970 ULONG i
, sub
, ptr_size
;
1973 ptr_size
= get_ptr_size(sys
);
2012 *size
= sizeof(DATE
);
2015 *size
= sizeof(VARIANT
);
2017 if(sys
== SYS_WIN32
)
2018 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2022 *size
= sizeof(DECIMAL
);
2029 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2030 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2031 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2036 case VT_USERDEFINED
:
2037 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2039 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2053 /**********************************************************************
2055 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2058 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2060 if (where
!= DO_NOT_SEEK
)
2062 where
+= pcx
->oStart
;
2063 if (where
> pcx
->length
)
2066 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2074 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2076 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2077 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2079 MSFT_Seek(pcx
, where
);
2080 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2081 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2086 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2091 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2092 FromLEDWords(buffer
, ret
);
2097 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2102 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2103 FromLEWords(buffer
, ret
);
2108 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2111 MSFT_GuidEntry entry
;
2114 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2116 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2119 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2121 guid
= heap_alloc(sizeof(TLBGuid
));
2123 guid
->offset
= offs
;
2124 guid
->guid
= entry
.guid
;
2125 guid
->hreftype
= entry
.hreftype
;
2127 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2129 offs
+= sizeof(MSFT_GuidEntry
);
2133 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2137 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2138 if(ret
->offset
== offset
){
2139 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2147 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2149 MSFT_NameIntro niName
;
2153 ERR_(typelib
)("bad offset %d\n", offset
);
2157 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2158 pcx
->pTblDir
->pNametab
.offset
+offset
);
2160 return niName
.hreftype
;
2163 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2166 MSFT_NameIntro intro
;
2168 int offs
= 0, lengthInChars
;
2170 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2174 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2177 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2178 intro
.namelen
&= 0xFF;
2179 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2181 len_piece
= (len_piece
+ 4) & ~0x3;
2185 string
= heap_alloc(len_piece
+ 1);
2186 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2187 string
[intro
.namelen
] = '\0';
2189 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2190 string
, -1, NULL
, 0);
2191 if (!lengthInChars
) {
2193 return E_UNEXPECTED
;
2196 tlbstr
= heap_alloc(sizeof(TLBString
));
2198 tlbstr
->offset
= offs
;
2199 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2200 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2204 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2210 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2214 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2215 if (tlbstr
->offset
== offset
) {
2216 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2224 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2228 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2229 if (tlbstr
->offset
== offset
) {
2230 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2239 * read a value and fill a VARIANT structure
2241 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2245 TRACE_(typelib
)("\n");
2247 if(offset
<0) { /* data are packed in here */
2248 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2249 V_I4(pVar
) = offset
& 0x3ffffff;
2252 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2253 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2254 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2255 switch (V_VT(pVar
)){
2256 case VT_EMPTY
: /* FIXME: is this right? */
2257 case VT_NULL
: /* FIXME: is this right? */
2258 case VT_I2
: /* this should not happen */
2269 case VT_VOID
: /* FIXME: is this right? */
2277 case VT_DECIMAL
: /* FIXME: is this right? */
2280 /* pointer types with known behaviour */
2283 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2285 V_BSTR(pVar
) = NULL
;
2287 ptr
= heap_alloc_zero(size
);
2288 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2289 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2290 /* FIXME: do we need a AtoW conversion here? */
2291 V_UNION(pVar
, bstrVal
[size
])='\0';
2292 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2297 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2304 case VT_USERDEFINED
:
2310 case VT_STREAMED_OBJECT
:
2311 case VT_STORED_OBJECT
:
2312 case VT_BLOB_OBJECT
:
2317 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2321 if(size
>0) /* (big|small) endian correct? */
2322 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2326 * create a linked list with custom data
2328 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2334 TRACE_(typelib
)("\n");
2336 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2340 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2341 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2342 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2343 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2344 list_add_head(custdata_list
, &pNew
->entry
);
2345 offset
= entry
.next
;
2350 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2353 pTd
->vt
=type
& VT_TYPEMASK
;
2355 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2357 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2360 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2362 return (invkind
== INVOKE_PROPERTYGET
||
2363 invkind
== INVOKE_PROPERTYPUT
||
2364 invkind
== INVOKE_PROPERTYPUTREF
);
2368 MSFT_DoFuncs(TLBContext
* pcx
,
2373 TLBFuncDesc
** pptfd
)
2376 * member information is stored in a data structure at offset
2377 * indicated by the memoffset field of the typeinfo structure
2378 * There are several distinctive parts.
2379 * The first part starts with a field that holds the total length
2380 * of this (first) part excluding this field. Then follow the records,
2381 * for each member there is one record.
2383 * The first entry is always the length of the record (including this
2385 * The rest of the record depends on the type of the member. If there is
2386 * a field indicating the member type (function, variable, interface, etc)
2387 * I have not found it yet. At this time we depend on the information
2388 * in the type info and the usual order how things are stored.
2390 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2393 * Third is an equal sized array with file offsets to the name entry
2396 * The fourth and last (?) part is an array with offsets to the records
2397 * in the first part of this file segment.
2400 int infolen
, nameoffset
, reclength
, i
;
2401 int recoffset
= offset
+ sizeof(INT
);
2403 char *recbuf
= heap_alloc(0xffff);
2404 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2405 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2407 TRACE_(typelib
)("\n");
2409 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2411 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2413 for ( i
= 0; i
< cFuncs
; i
++ )
2417 /* name, eventually add to a hash table */
2418 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2419 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2421 /* read the function information record */
2422 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2424 reclength
&= 0xffff;
2426 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2428 /* size without argument data */
2429 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2430 if (pFuncRec
->FKCCIC
& 0x1000)
2431 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2433 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2434 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2436 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2437 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2439 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2441 if (pFuncRec
->FKCCIC
& 0x2000 )
2443 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2444 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2445 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2448 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2451 ptfd
->Entry
= (TLBString
*)-1;
2453 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2454 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2456 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2457 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2459 /* fill the FuncDesc Structure */
2460 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2461 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2463 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2464 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2465 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2466 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2467 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2468 ptfd
->funcdesc
.oVft
= (pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2469 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2471 /* nameoffset is sometimes -1 on the second half of a propget/propput
2472 * pair of functions */
2473 if ((nameoffset
== -1) && (i
> 0) &&
2474 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2475 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2476 ptfd
->Name
= ptfd_prev
->Name
;
2478 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2482 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2484 /* do the parameters/arguments */
2485 if(pFuncRec
->nrargs
)
2488 MSFT_ParameterInfo paraminfo
;
2490 ptfd
->funcdesc
.lprgelemdescParam
=
2491 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2493 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2495 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2496 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2498 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2500 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2506 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2509 if (paraminfo
.oName
!= -1)
2510 ptfd
->pParamDesc
[j
].Name
=
2511 MSFT_ReadName( pcx
, paraminfo
.oName
);
2512 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2515 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2516 (pFuncRec
->FKCCIC
& 0x1000) )
2518 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2520 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2522 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2524 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2525 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2527 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2531 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2534 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2535 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2536 pFuncRec
->FKCCIC
& 0x80 )
2539 pFuncRec
->oArgCustData
[j
],
2540 &ptfd
->pParamDesc
[j
].custdata_list
);
2543 /* SEEK value = jump to offset,
2544 * from there jump to the end of record,
2545 * go back by (j-1) arguments
2547 MSFT_ReadLEDWords( ¶minfo
,
2548 sizeof(MSFT_ParameterInfo
), pcx
,
2549 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2550 * sizeof(MSFT_ParameterInfo
)));
2554 /* scode is not used: archaic win16 stuff FIXME: right? */
2555 ptfd
->funcdesc
.cScodes
= 0 ;
2556 ptfd
->funcdesc
.lprgscode
= NULL
;
2560 recoffset
+= reclength
;
2565 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2566 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2568 int infolen
, nameoffset
, reclength
;
2570 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2575 TRACE_(typelib
)("\n");
2577 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2578 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2579 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2580 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2581 recoffset
+= offset
+sizeof(INT
);
2582 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2583 /* name, eventually add to a hash table */
2584 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2585 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2586 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2587 /* read the variable information record */
2588 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2590 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2593 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2594 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2596 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2597 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2599 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2600 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2602 /* fill the VarDesc Structure */
2603 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2604 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2605 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2606 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2607 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2608 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2609 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2610 if(pVarRec
->VarKind
== VAR_CONST
){
2611 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2612 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2613 pVarRec
->OffsValue
, pcx
);
2615 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2616 recoffset
+= reclength
;
2620 /* process Implemented Interfaces of a com class */
2621 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2625 MSFT_RefRecord refrec
;
2628 TRACE_(typelib
)("\n");
2630 pTI
->impltypes
= TLBImplType_Alloc(count
);
2631 pImpl
= pTI
->impltypes
;
2632 for(i
=0;i
<count
;i
++){
2633 if(offset
<0) break; /* paranoia */
2634 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2635 pImpl
->hRef
= refrec
.reftype
;
2636 pImpl
->implflags
=refrec
.flags
;
2637 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2638 offset
=refrec
.onext
;
2644 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2645 * and some structures, and fix the alignment */
2646 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2648 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2649 switch(info
->tdescAlias
->vt
){
2657 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2658 info
->typeattr
.cbAlignment
= sizeof(void*);
2661 case VT_USERDEFINED
:
2662 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2665 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2666 info
->typeattr
.cbAlignment
= 8;
2668 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2669 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2671 info
->typeattr
.cbAlignment
= sizeof(void*);
2674 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2675 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2676 info
->typeattr
.typekind
== TKIND_COCLASS
){
2677 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2678 info
->typeattr
.cbAlignment
= sizeof(void*);
2684 * process a typeinfo record
2686 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2689 ITypeLibImpl
* pLibInfo
)
2691 MSFT_TypeInfoBase tiBase
;
2692 ITypeInfoImpl
*ptiRet
;
2694 TRACE_(typelib
)("count=%u\n", count
);
2696 ptiRet
= ITypeInfoImpl_Constructor();
2697 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2698 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2700 /* this is where we are coming from */
2701 ptiRet
->pTypeLib
= pLibInfo
;
2702 ptiRet
->index
=count
;
2704 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2705 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2706 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2707 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2708 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2709 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2710 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2711 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2712 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2713 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2714 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2715 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2716 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2717 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2719 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2720 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2721 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2725 /* IDLDESC idldescType; *//* never saw this one != zero */
2727 /* name, eventually add to a hash table */
2728 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2729 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2730 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2732 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2733 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2734 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2736 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2737 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2739 /* note: InfoType's Help file and HelpStringDll come from the containing
2740 * library. Further HelpString and Docstring appear to be the same thing :(
2743 if(ptiRet
->typeattr
.cFuncs
>0 )
2744 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2745 ptiRet
->typeattr
.cVars
,
2746 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2748 if(ptiRet
->typeattr
.cVars
>0 )
2749 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2750 ptiRet
->typeattr
.cVars
,
2751 tiBase
.memoffset
, &ptiRet
->vardescs
);
2752 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2753 switch(ptiRet
->typeattr
.typekind
)
2756 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2759 case TKIND_DISPATCH
:
2760 /* This is not -1 when the interface is a non-base dual interface or
2761 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2762 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2766 if (tiBase
.datatype1
!= -1)
2768 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2769 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2773 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2774 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2778 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2780 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2781 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2782 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2783 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2784 if (TRACE_ON(typelib
))
2785 dump_TypeInfo(ptiRet
);
2790 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2793 INT16 len_str
, len_piece
;
2794 int offs
= 0, lengthInChars
;
2796 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2800 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2803 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2804 len_piece
= len_str
+ sizeof(INT16
);
2806 len_piece
= (len_piece
+ 4) & ~0x3;
2810 string
= heap_alloc(len_piece
+ 1);
2811 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2812 string
[len_str
] = '\0';
2814 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2815 string
, -1, NULL
, 0);
2816 if (!lengthInChars
) {
2818 return E_UNEXPECTED
;
2821 tlbstr
= heap_alloc(sizeof(TLBString
));
2823 tlbstr
->offset
= offs
;
2824 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2825 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2829 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2835 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2840 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2841 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2842 MSFT_ImpInfo impinfo
;
2845 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2847 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2848 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2850 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2851 if(pImpLib
->offset
==impinfo
.oImpFile
)
2854 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2855 ref
->reference
= offs
;
2856 ref
->pImpTLInfo
= pImpLib
;
2857 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2858 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2859 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2860 ref
->index
= TLB_REF_USE_GUID
;
2862 ref
->index
= impinfo
.oGuid
;
2864 ERR("Cannot find a reference\n");
2865 ref
->reference
= -1;
2866 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2869 offs
+= sizeof(impinfo
);
2875 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2876 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2877 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2880 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2881 static CRITICAL_SECTION cache_section
;
2882 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2884 0, 0, &cache_section
,
2885 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2886 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2888 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2891 typedef struct TLB_PEFile
2893 IUnknown IUnknown_iface
;
2896 HRSRC typelib_resource
;
2897 HGLOBAL typelib_global
;
2898 LPVOID typelib_base
;
2901 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2903 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2906 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2908 if (IsEqualIID(riid
, &IID_IUnknown
))
2911 IUnknown_AddRef(iface
);
2915 return E_NOINTERFACE
;
2918 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2920 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2921 return InterlockedIncrement(&This
->refs
);
2924 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2926 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2927 ULONG refs
= InterlockedDecrement(&This
->refs
);
2930 if (This
->typelib_global
)
2931 FreeResource(This
->typelib_global
);
2933 FreeLibrary(This
->dll
);
2939 static const IUnknownVtbl TLB_PEFile_Vtable
=
2941 TLB_PEFile_QueryInterface
,
2946 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2949 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2951 This
= heap_alloc(sizeof(TLB_PEFile
));
2953 return E_OUTOFMEMORY
;
2955 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2958 This
->typelib_resource
= NULL
;
2959 This
->typelib_global
= NULL
;
2960 This
->typelib_base
= NULL
;
2962 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2963 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2967 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2968 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2969 if (This
->typelib_resource
)
2971 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2972 if (This
->typelib_global
)
2974 This
->typelib_base
= LockResource(This
->typelib_global
);
2976 if (This
->typelib_base
)
2978 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2979 *ppBase
= This
->typelib_base
;
2980 *ppFile
= &This
->IUnknown_iface
;
2986 TRACE("No TYPELIB resource found\n");
2990 TLB_PEFile_Release(&This
->IUnknown_iface
);
2994 typedef struct TLB_NEFile
2996 IUnknown IUnknown_iface
;
2998 LPVOID typelib_base
;
3001 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
3003 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
3006 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3008 if (IsEqualIID(riid
, &IID_IUnknown
))
3011 IUnknown_AddRef(iface
);
3015 return E_NOINTERFACE
;
3018 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3020 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3021 return InterlockedIncrement(&This
->refs
);
3024 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3026 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3027 ULONG refs
= InterlockedDecrement(&This
->refs
);
3030 heap_free(This
->typelib_base
);
3036 static const IUnknownVtbl TLB_NEFile_Vtable
=
3038 TLB_NEFile_QueryInterface
,
3043 /***********************************************************************
3044 * read_xx_header [internal]
3046 static int read_xx_header( HFILE lzfd
)
3048 IMAGE_DOS_HEADER mzh
;
3051 LZSeek( lzfd
, 0, SEEK_SET
);
3052 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3054 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3057 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3058 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3061 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3063 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3064 return IMAGE_OS2_SIGNATURE
;
3065 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3066 return IMAGE_NT_SIGNATURE
;
3069 WARN("Can't handle %s files.\n", magic
);
3074 /***********************************************************************
3075 * find_ne_resource [internal]
3077 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3078 DWORD
*resLen
, DWORD
*resOff
)
3080 IMAGE_OS2_HEADER nehd
;
3081 NE_TYPEINFO
*typeInfo
;
3082 NE_NAMEINFO
*nameInfo
;
3088 /* Read in NE header */
3089 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3090 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3092 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3095 TRACE("No resources in NE dll\n" );
3099 /* Read in resource table */
3100 resTab
= heap_alloc( resTabSize
);
3101 if ( !resTab
) return FALSE
;
3103 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3104 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3106 heap_free( resTab
);
3111 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3113 if (!IS_INTRESOURCE(typeid)) /* named type */
3115 BYTE len
= strlen( typeid );
3116 while (typeInfo
->type_id
)
3118 if (!(typeInfo
->type_id
& 0x8000))
3120 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3121 if ((*p
== len
) && !_strnicmp( (char*)p
+1, typeid, len
)) goto found_type
;
3123 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3124 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3127 else /* numeric type id */
3129 WORD id
= LOWORD(typeid) | 0x8000;
3130 while (typeInfo
->type_id
)
3132 if (typeInfo
->type_id
== id
) goto found_type
;
3133 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3134 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3137 TRACE("No typeid entry found for %p\n", typeid );
3138 heap_free( resTab
);
3142 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3144 if (!IS_INTRESOURCE(resid
)) /* named resource */
3146 BYTE len
= strlen( resid
);
3147 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3149 BYTE
*p
= resTab
+ nameInfo
->id
;
3150 if (nameInfo
->id
& 0x8000) continue;
3151 if ((*p
== len
) && !_strnicmp( (char*)p
+1, resid
, len
)) goto found_name
;
3154 else /* numeric resource id */
3156 WORD id
= LOWORD(resid
) | 0x8000;
3157 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3158 if (nameInfo
->id
== id
) goto found_name
;
3160 TRACE("No resid entry found for %p\n", typeid );
3161 heap_free( resTab
);
3165 /* Return resource data */
3166 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3167 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3169 heap_free( resTab
);
3173 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3177 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3180 This
= heap_alloc(sizeof(TLB_NEFile
));
3181 if (!This
) return E_OUTOFMEMORY
;
3183 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3185 This
->typelib_base
= NULL
;
3187 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3188 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3190 DWORD reslen
, offset
;
3191 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3193 This
->typelib_base
= heap_alloc(reslen
);
3194 if( !This
->typelib_base
)
3198 LZSeek( lzfd
, offset
, SEEK_SET
);
3199 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3201 *ppBase
= This
->typelib_base
;
3202 *pdwTLBLength
= reslen
;
3203 *ppFile
= &This
->IUnknown_iface
;
3209 if( lzfd
>= 0) LZClose( lzfd
);
3210 TLB_NEFile_Release(&This
->IUnknown_iface
);
3214 typedef struct TLB_Mapping
3216 IUnknown IUnknown_iface
;
3220 LPVOID typelib_base
;
3223 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3225 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3228 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3230 if (IsEqualIID(riid
, &IID_IUnknown
))
3233 IUnknown_AddRef(iface
);
3237 return E_NOINTERFACE
;
3240 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3242 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3243 return InterlockedIncrement(&This
->refs
);
3246 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3248 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3249 ULONG refs
= InterlockedDecrement(&This
->refs
);
3252 if (This
->typelib_base
)
3253 UnmapViewOfFile(This
->typelib_base
);
3255 CloseHandle(This
->mapping
);
3256 if (This
->file
!= INVALID_HANDLE_VALUE
)
3257 CloseHandle(This
->file
);
3263 static const IUnknownVtbl TLB_Mapping_Vtable
=
3265 TLB_Mapping_QueryInterface
,
3270 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3274 This
= heap_alloc(sizeof(TLB_Mapping
));
3276 return E_OUTOFMEMORY
;
3278 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3280 This
->file
= INVALID_HANDLE_VALUE
;
3281 This
->mapping
= NULL
;
3282 This
->typelib_base
= NULL
;
3284 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3285 if (INVALID_HANDLE_VALUE
!= This
->file
)
3287 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3290 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3291 if(This
->typelib_base
)
3293 /* retrieve file size */
3294 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3295 *ppBase
= This
->typelib_base
;
3296 *ppFile
= &This
->IUnknown_iface
;
3302 IUnknown_Release(&This
->IUnknown_iface
);
3303 return TYPE_E_CANTLOADLIBRARY
;
3306 /****************************************************************************
3309 * find the type of the typelib file and map the typelib resource into
3313 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3314 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3316 ITypeLibImpl
*entry
;
3319 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3320 LPVOID pBase
= NULL
;
3321 DWORD dwTLBLength
= 0;
3322 IUnknown
*pFile
= NULL
;
3327 index_str
= wcsrchr(pszFileName
, '\\');
3328 if(index_str
&& *++index_str
!= '\0')
3331 LONG idx
= wcstol(index_str
, &end_ptr
, 10);
3332 if(*end_ptr
== '\0')
3334 int str_len
= index_str
- pszFileName
- 1;
3336 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3337 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3342 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3344 if(wcschr(file
, '\\'))
3346 lstrcpyW(pszPath
, file
);
3350 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3351 pszPath
[len
] = '\\';
3352 memcpy(pszPath
+ len
+ 1, file
, (lstrlenW(file
) + 1) * sizeof(WCHAR
));
3356 if(file
!= pszFileName
) heap_free(file
);
3358 h
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3359 if(h
!= INVALID_HANDLE_VALUE
){
3360 GetFinalPathNameByHandleW(h
, pszPath
, cchPath
, FILE_NAME_NORMALIZED
| VOLUME_NAME_DOS
);
3364 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3366 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3367 EnterCriticalSection(&cache_section
);
3368 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3370 if (!wcsicmp(entry
->path
, pszPath
) && entry
->index
== index
)
3372 TRACE("cache hit\n");
3373 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3374 ITypeLib2_AddRef(*ppTypeLib
);
3375 LeaveCriticalSection(&cache_section
);
3379 LeaveCriticalSection(&cache_section
);
3381 /* now actually load and parse the typelib */
3383 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3384 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3385 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3386 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3387 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3390 if (dwTLBLength
>= 4)
3392 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3393 if (dwSignature
== MSFT_SIGNATURE
)
3394 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3395 else if (dwSignature
== SLTG_SIGNATURE
)
3396 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3399 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3400 ret
= TYPE_E_CANTLOADLIBRARY
;
3404 ret
= TYPE_E_CANTLOADLIBRARY
;
3405 IUnknown_Release(pFile
);
3409 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3411 TRACE("adding to cache\n");
3412 impl
->path
= heap_alloc((lstrlenW(pszPath
)+1) * sizeof(WCHAR
));
3413 lstrcpyW(impl
->path
, pszPath
);
3414 /* We should really canonicalise the path here. */
3415 impl
->index
= index
;
3417 /* FIXME: check if it has added already in the meantime */
3418 EnterCriticalSection(&cache_section
);
3419 list_add_head(&tlb_cache
, &impl
->entry
);
3420 LeaveCriticalSection(&cache_section
);
3426 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3428 ret
= TYPE_E_CANTLOADLIBRARY
;
3435 /*================== ITypeLib(2) Methods ===================================*/
3437 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3439 ITypeLibImpl
* pTypeLibImpl
;
3441 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3442 if (!pTypeLibImpl
) return NULL
;
3444 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3445 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3446 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3447 pTypeLibImpl
->ref
= 1;
3449 list_init(&pTypeLibImpl
->implib_list
);
3450 list_init(&pTypeLibImpl
->custdata_list
);
3451 list_init(&pTypeLibImpl
->name_list
);
3452 list_init(&pTypeLibImpl
->string_list
);
3453 list_init(&pTypeLibImpl
->guid_list
);
3454 list_init(&pTypeLibImpl
->ref_list
);
3455 pTypeLibImpl
->dispatch_href
= -1;
3457 return pTypeLibImpl
;
3460 /****************************************************************************
3461 * ITypeLib2_Constructor_MSFT
3463 * loading an MSFT typelib from an in-memory image
3465 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3469 MSFT_Header tlbHeader
;
3470 MSFT_SegDir tlbSegDir
;
3471 ITypeLibImpl
* pTypeLibImpl
;
3474 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3476 pTypeLibImpl
= TypeLibImpl_Constructor();
3477 if (!pTypeLibImpl
) return NULL
;
3479 /* get pointer to beginning of typelib data */
3483 cx
.pLibInfo
= pTypeLibImpl
;
3484 cx
.length
= dwTLBLength
;
3487 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3488 TRACE_(typelib
)("header:\n");
3489 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3490 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3491 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3494 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3496 /* there is a small amount of information here until the next important
3498 * the segment directory . Try to calculate the amount of data */
3499 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3501 /* now read the segment directory */
3502 TRACE("read segment directory (at %d)\n",lPSegDir
);
3503 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3504 cx
.pTblDir
= &tlbSegDir
;
3506 /* just check two entries */
3507 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3509 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3510 heap_free(pTypeLibImpl
);
3514 MSFT_ReadAllNames(&cx
);
3515 MSFT_ReadAllStrings(&cx
);
3516 MSFT_ReadAllGuids(&cx
);
3518 /* now fill our internal data */
3519 /* TLIBATTR fields */
3520 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3522 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3523 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3524 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3525 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3526 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3528 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3529 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3531 /* name, eventually add to a hash table */
3532 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3535 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3536 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3538 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3541 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3542 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3545 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3548 if(tlbHeader
.CustomDataOffset
>= 0)
3550 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3553 /* fill in type descriptions */
3554 if(tlbSegDir
.pTypdescTab
.length
> 0)
3556 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3558 pTypeLibImpl
->ctTypeDesc
= cTD
;
3559 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3560 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3563 /* FIXME: add several sanity checks here */
3564 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3565 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3567 /* FIXME: check safearray */
3569 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3571 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3573 else if(td
[0] == VT_CARRAY
)
3575 /* array descr table here */
3576 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3578 else if(td
[0] == VT_USERDEFINED
)
3580 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3582 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3585 /* second time around to fill the array subscript info */
3588 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3589 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3591 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3592 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3595 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3597 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3599 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3601 for(j
= 0; j
<td
[2]; j
++)
3603 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3604 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3605 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3606 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3611 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3612 ERR("didn't find array description data\n");
3617 /* imported type libs */
3618 if(tlbSegDir
.pImpFiles
.offset
>0)
3621 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3624 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3628 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3629 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3630 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3632 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3633 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3634 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3635 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3638 name
= heap_alloc_zero(size
+1);
3639 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3640 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3643 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3644 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3646 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3650 MSFT_ReadAllRefs(&cx
);
3652 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3655 if(tlbHeader
.nrtypeinfos
>= 0 )
3657 ITypeInfoImpl
**ppTI
;
3659 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3661 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3663 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3666 (pTypeLibImpl
->TypeInfoCount
)++;
3671 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3672 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3673 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3677 TRACE("(%p)\n", pTypeLibImpl
);
3678 return &pTypeLibImpl
->ITypeLib2_iface
;
3682 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3688 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3689 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3693 guid
->Data4
[0] = s
>> 8;
3694 guid
->Data4
[1] = s
& 0xff;
3697 for(i
= 0; i
< 6; i
++) {
3698 memcpy(b
, str
+ 24 + 2 * i
, 2);
3699 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3704 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3711 bytelen
= *(const WORD
*)ptr
;
3712 if(bytelen
== 0xffff) return 2;
3714 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3715 tmp_str
= SysAllocStringLen(NULL
, len
);
3717 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3718 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3719 SysFreeString(tmp_str
);
3724 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3729 bytelen
= *(const WORD
*)ptr
;
3730 if(bytelen
== 0xffff) return 2;
3731 *str
= heap_alloc(bytelen
+ 1);
3732 memcpy(*str
, ptr
+ 2, bytelen
);
3733 (*str
)[bytelen
] = '\0';
3737 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3742 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3743 if (tlbstr
->offset
== offset
)
3747 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3748 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3749 SysFreeString(tmp_str
);
3754 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3756 char *ptr
= pLibBlk
;
3759 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3760 FIXME("libblk magic = %04x\n", w
);
3765 if((w
= *(WORD
*)ptr
) != 0xffff) {
3766 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w
);
3771 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3773 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3775 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3778 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3779 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3782 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3783 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3785 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3788 ptr
+= 4; /* skip res12 */
3790 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3793 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3796 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3799 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3800 ptr
+= sizeof(GUID
);
3802 return ptr
- (char*)pLibBlk
;
3805 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3810 } sltg_ref_lookup_t
;
3812 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3813 HREFTYPE
*typelib_ref
)
3815 if(table
&& typeinfo_ref
< table
->num
)
3817 *typelib_ref
= table
->refs
[typeinfo_ref
];
3821 ERR_(typelib
)("Unable to find reference\n");
3826 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3831 if((*pType
& 0xe00) == 0xe00) {
3833 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3834 pTD
= pTD
->u
.lptdesc
;
3836 switch(*pType
& 0x3f) {
3839 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3840 pTD
= pTD
->u
.lptdesc
;
3843 case VT_USERDEFINED
:
3844 pTD
->vt
= VT_USERDEFINED
;
3845 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3851 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3854 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3856 pTD
->vt
= VT_CARRAY
;
3857 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3858 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3859 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3860 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3862 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3868 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3872 pTD
->vt
= VT_SAFEARRAY
;
3873 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3874 pTD
= pTD
->u
.lptdesc
;
3878 pTD
->vt
= *pType
& 0x3f;
3887 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3888 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3890 /* Handle [in/out] first */
3891 if((*pType
& 0xc000) == 0xc000)
3892 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3893 else if(*pType
& 0x8000)
3894 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3895 else if(*pType
& 0x4000)
3896 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3898 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3901 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3904 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3906 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3910 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3915 TLBRefType
*ref_type
;
3916 sltg_ref_lookup_t
*table
;
3917 HREFTYPE typelib_ref
;
3919 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3920 FIXME("Ref magic = %x\n", pRef
->magic
);
3923 name
= ( (char*)pRef
->names
+ pRef
->number
);
3925 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3926 table
->num
= pRef
->number
>> 3;
3928 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3930 /* We don't want the first href to be 0 */
3931 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3933 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3935 unsigned int lib_offs
, type_num
;
3937 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3939 name
+= SLTG_ReadStringA(name
, &refname
);
3940 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3941 FIXME_(typelib
)("Can't sscanf ref\n");
3942 if(lib_offs
!= 0xffff) {
3945 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3946 if(import
->offset
== lib_offs
)
3949 if(&import
->entry
== &pTL
->implib_list
) {
3950 char fname
[MAX_PATH
+1];
3954 import
= heap_alloc_zero(sizeof(*import
));
3955 import
->offset
= lib_offs
;
3956 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3957 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3958 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3959 &import
->wVersionMajor
,
3960 &import
->wVersionMinor
,
3961 &import
->lcid
, fname
) != 4) {
3962 FIXME_(typelib
)("can't sscanf ref %s\n",
3963 pNameTable
+ lib_offs
+ 40);
3965 len
= strlen(fname
);
3966 if(fname
[len
-1] != '#')
3967 FIXME("fname = %s\n", fname
);
3968 fname
[len
-1] = '\0';
3969 import
->name
= TLB_MultiByteToBSTR(fname
);
3970 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3972 ref_type
->pImpTLInfo
= import
;
3974 /* Store a reference to IDispatch */
3975 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3976 pTL
->dispatch_href
= typelib_ref
;
3978 } else { /* internal ref */
3979 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3981 ref_type
->reference
= typelib_ref
;
3982 ref_type
->index
= type_num
;
3985 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3987 table
->refs
[ref
] = typelib_ref
;
3990 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3991 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3992 dump_TLBRefType(pTL
);
3996 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3997 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3999 SLTG_ImplInfo
*info
;
4000 TLBImplType
*pImplType
;
4001 /* I don't really get this structure, usually it's 0x16 bytes
4002 long, but iuser.tlb contains some that are 0x18 bytes long.
4003 That's ok because we can use the next ptr to jump to the next
4004 one. But how do we know the length of the last one? The WORD
4005 at offs 0x8 might be the clue. For now I'm just assuming that
4006 the last one is the regular 0x16 bytes. */
4008 info
= (SLTG_ImplInfo
*)pBlk
;
4010 pTI
->typeattr
.cImplTypes
++;
4011 if(info
->next
== 0xffff)
4013 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4016 info
= (SLTG_ImplInfo
*)pBlk
;
4017 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
4018 pImplType
= pTI
->impltypes
;
4020 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4021 pImplType
->implflags
= info
->impltypeflags
;
4024 if(info
->next
== 0xffff)
4027 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4028 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4030 info
++; /* see comment at top of function */
4034 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4035 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4037 TLBVarDesc
*pVarDesc
;
4038 const TLBString
*prevName
= NULL
;
4039 SLTG_Variable
*pItem
;
4043 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4045 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4046 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4048 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4050 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4051 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4052 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4056 if (pItem
->name
== 0xfffe)
4057 pVarDesc
->Name
= prevName
;
4059 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4061 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4062 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4063 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4065 if(pItem
->flags
& 0x02)
4066 pType
= &pItem
->type
;
4068 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4070 if (pItem
->flags
& ~0xda)
4071 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4073 SLTG_DoElem(pType
, pBlk
,
4074 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4076 if (TRACE_ON(typelib
)) {
4078 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4079 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4082 if (pItem
->flags
& 0x40) {
4083 TRACE_(typelib
)("VAR_DISPATCH\n");
4084 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4086 else if (pItem
->flags
& 0x10) {
4087 TRACE_(typelib
)("VAR_CONST\n");
4088 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4089 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4090 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4091 if (pItem
->flags
& 0x08)
4092 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4094 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4100 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4102 TRACE_(typelib
)("len = %u\n", len
);
4103 if (len
== 0xffff) {
4106 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4107 str
= SysAllocStringLen(NULL
, alloc_len
);
4108 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4110 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4111 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4120 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4121 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4124 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4129 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4130 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4131 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4134 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4135 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4137 if (pItem
->flags
& 0x80)
4138 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4140 prevName
= pVarDesc
->Name
;
4142 pTI
->typeattr
.cVars
= cVars
;
4145 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4146 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4148 SLTG_Function
*pFunc
;
4150 TLBFuncDesc
*pFuncDesc
;
4152 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4154 pFuncDesc
= pTI
->funcdescs
;
4155 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4156 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4161 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4162 case SLTG_FUNCTION_MAGIC
:
4163 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4165 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4166 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4168 case SLTG_STATIC_FUNCTION_MAGIC
:
4169 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4172 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4175 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4177 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4178 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4179 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4180 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4181 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4182 pFuncDesc
->funcdesc
.oVft
= (pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4184 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4185 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4187 if(pFunc
->retnextopt
& 0x80)
4188 pType
= &pFunc
->rettype
;
4190 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4192 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4194 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4195 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4196 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4198 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4200 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4201 char *paramName
= pNameTable
+ *pArg
;
4203 /* If arg type follows then paramName points to the 2nd
4204 letter of the name, else the next WORD is an offset to
4205 the arg type and paramName points to the first letter.
4206 So let's take one char off paramName and see if we're
4207 pointing at an alphanumeric char. However if *pArg is
4208 0xffff or 0xfffe then the param has no name, the former
4209 meaning that the next WORD is the type, the latter
4210 meaning that the next WORD is an offset to the type. */
4215 else if(*pArg
== 0xfffe) {
4219 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4224 if(HaveOffs
) { /* the next word is an offset to type */
4225 pType
= (WORD
*)(pBlk
+ *pArg
);
4226 SLTG_DoElem(pType
, pBlk
,
4227 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4232 pArg
= SLTG_DoElem(pArg
, pBlk
,
4233 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4236 /* Are we an optional param ? */
4237 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4238 pFuncDesc
->funcdesc
.cParamsOpt
)
4239 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4242 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4243 paramName
- pNameTable
, pTI
->pTypeLib
);
4245 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4249 pTI
->typeattr
.cFuncs
= cFuncs
;
4252 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4253 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4254 SLTG_TypeInfoTail
*pTITail
)
4257 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4259 if(pTIHeader
->href_table
!= 0xffffffff) {
4260 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4266 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4267 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4269 heap_free(ref_lookup
);
4273 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4274 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4275 const SLTG_TypeInfoTail
*pTITail
)
4278 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4280 if(pTIHeader
->href_table
!= 0xffffffff) {
4281 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4287 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4288 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4291 if (pTITail
->funcs_off
!= 0xffff)
4292 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4294 heap_free(ref_lookup
);
4296 if (TRACE_ON(typelib
))
4297 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4300 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4301 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4302 const SLTG_TypeInfoTail
*pTITail
)
4304 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4307 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4308 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4309 const SLTG_TypeInfoTail
*pTITail
)
4312 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4314 if (pTITail
->simple_alias
) {
4315 /* if simple alias, no more processing required */
4316 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4317 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4321 if(pTIHeader
->href_table
!= 0xffffffff) {
4322 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4326 /* otherwise it is an offset to a type */
4327 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4329 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4330 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4332 heap_free(ref_lookup
);
4335 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4336 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4337 const SLTG_TypeInfoTail
*pTITail
)
4339 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4340 if (pTIHeader
->href_table
!= 0xffffffff)
4341 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4344 if (pTITail
->vars_off
!= 0xffff)
4345 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4347 if (pTITail
->funcs_off
!= 0xffff)
4348 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4350 if (pTITail
->impls_off
!= 0xffff)
4351 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4353 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4354 * of dispinterface functions including the IDispatch ones, so
4355 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4356 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4358 heap_free(ref_lookup
);
4359 if (TRACE_ON(typelib
))
4360 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4363 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4364 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4365 const SLTG_TypeInfoTail
*pTITail
)
4367 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4370 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4371 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4372 const SLTG_TypeInfoTail
*pTITail
)
4374 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4375 if (pTIHeader
->href_table
!= 0xffffffff)
4376 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4379 if (pTITail
->vars_off
!= 0xffff)
4380 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4382 if (pTITail
->funcs_off
!= 0xffff)
4383 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4384 heap_free(ref_lookup
);
4385 if (TRACE_ON(typelib
))
4389 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4390 manageable copy of it into this */
4403 } SLTG_InternalOtherTypeInfo
;
4405 /****************************************************************************
4406 * ITypeLib2_Constructor_SLTG
4408 * loading a SLTG typelib from an in-memory image
4410 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4412 ITypeLibImpl
*pTypeLibImpl
;
4413 SLTG_Header
*pHeader
;
4414 SLTG_BlkEntry
*pBlkEntry
;
4418 LPVOID pBlk
, pFirstBlk
;
4419 SLTG_LibBlk
*pLibBlk
;
4420 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4421 char *pAfterOTIBlks
= NULL
;
4422 char *pNameTable
, *ptr
;
4425 ITypeInfoImpl
**ppTypeInfoImpl
;
4427 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4430 pTypeLibImpl
= TypeLibImpl_Constructor();
4431 if (!pTypeLibImpl
) return NULL
;
4435 TRACE_(typelib
)("header:\n");
4436 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4437 pHeader
->nrOfFileBlks
);
4438 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4439 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4440 pHeader
->SLTG_magic
);
4444 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4445 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4447 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4448 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4450 /* Next we have a magic block */
4451 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4453 /* Let's see if we're still in sync */
4454 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4455 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4456 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4459 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4460 sizeof(SLTG_DIR_MAGIC
))) {
4461 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4465 pIndex
= (SLTG_Index
*)(pMagic
+1);
4467 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4469 pFirstBlk
= pPad9
+ 1;
4471 /* We'll set up a ptr to the main library block, which is the last one. */
4473 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4474 pBlkEntry
[order
].next
!= 0;
4475 order
= pBlkEntry
[order
].next
- 1) {
4476 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4480 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4482 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4487 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4489 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4492 ptr
= (char*)pLibBlk
+ len
;
4494 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4498 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4500 w
= *(WORD
*)(ptr
+ 2);
4503 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4504 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4505 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4507 w
= *(WORD
*)(ptr
+ 4 + len
);
4509 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4511 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4512 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4513 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4515 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4516 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4517 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4519 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4520 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4523 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4524 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4525 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4526 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4527 len
+= sizeof(SLTG_OtherTypeInfo
);
4531 pAfterOTIBlks
= ptr
;
4533 /* Skip this WORD and get the next DWORD */
4534 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4536 /* Now add this to pLibBLk look at what we're pointing at and
4537 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4538 dust and we should be pointing at the beginning of the name
4541 pNameTable
= (char*)pLibBlk
+ len
;
4543 switch(*(WORD
*)pNameTable
) {
4550 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4554 pNameTable
+= 0x216;
4558 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4560 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4563 /* Hopefully we now have enough ptrs set up to actually read in
4564 some TypeInfos. It's not clear which order to do them in, so
4565 I'll just follow the links along the BlkEntry chain and read
4566 them in the order in which they are in the file */
4568 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4569 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4571 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4572 pBlkEntry
[order
].next
!= 0;
4573 order
= pBlkEntry
[order
].next
- 1, i
++) {
4575 SLTG_TypeInfoHeader
*pTIHeader
;
4576 SLTG_TypeInfoTail
*pTITail
;
4577 SLTG_MemberHeader
*pMemHeader
;
4579 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4580 FIXME_(typelib
)("Index strings don't match\n");
4581 heap_free(pOtherTypeInfoBlks
);
4586 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4587 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4588 heap_free(pOtherTypeInfoBlks
);
4591 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4592 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4593 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4595 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4596 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4597 (*ppTypeInfoImpl
)->index
= i
;
4598 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4599 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4600 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4601 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4602 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4603 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4604 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4605 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4607 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4608 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4610 if((pTIHeader
->typeflags1
& 7) != 2)
4611 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4612 if(pTIHeader
->typeflags3
!= 2)
4613 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4615 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4616 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4617 typekind_desc
[pTIHeader
->typekind
],
4618 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4619 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4621 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4623 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4625 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4626 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4627 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4629 switch(pTIHeader
->typekind
) {
4631 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4632 pTIHeader
, pTITail
);
4636 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4637 pTIHeader
, pTITail
);
4640 case TKIND_INTERFACE
:
4641 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4642 pTIHeader
, pTITail
);
4646 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4647 pTIHeader
, pTITail
);
4651 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4652 pTIHeader
, pTITail
);
4655 case TKIND_DISPATCH
:
4656 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4657 pTIHeader
, pTITail
);
4661 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4662 pTIHeader
, pTITail
);
4666 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4671 /* could get cFuncs, cVars and cImplTypes from here
4672 but we've already set those */
4673 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4689 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4692 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4693 FIXME("Somehow processed %d TypeInfos\n", i
);
4694 heap_free(pOtherTypeInfoBlks
);
4698 heap_free(pOtherTypeInfoBlks
);
4699 return &pTypeLibImpl
->ITypeLib2_iface
;
4702 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4704 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4706 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4708 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4709 IsEqualIID(riid
,&IID_ITypeLib
)||
4710 IsEqualIID(riid
,&IID_ITypeLib2
))
4712 *ppv
= &This
->ITypeLib2_iface
;
4714 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4715 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4717 *ppv
= &This
->ICreateTypeLib2_iface
;
4722 TRACE("-- Interface: E_NOINTERFACE\n");
4723 return E_NOINTERFACE
;
4726 IUnknown_AddRef((IUnknown
*)*ppv
);
4730 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4732 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4733 ULONG ref
= InterlockedIncrement(&This
->ref
);
4735 TRACE("(%p) ref=%u\n", This
, ref
);
4740 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4742 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4743 ULONG ref
= InterlockedDecrement(&This
->ref
);
4745 TRACE("(%p) ref=%u\n",This
, ref
);
4749 TLBImpLib
*pImpLib
, *pImpLibNext
;
4750 TLBRefType
*ref_type
, *ref_type_next
;
4751 TLBString
*tlbstr
, *tlbstr_next
;
4752 TLBGuid
*tlbguid
, *tlbguid_next
;
4755 /* remove cache entry */
4758 TRACE("removing from cache list\n");
4759 EnterCriticalSection(&cache_section
);
4760 if(This
->entry
.next
)
4761 list_remove(&This
->entry
);
4762 LeaveCriticalSection(&cache_section
);
4763 heap_free(This
->path
);
4765 TRACE(" destroying ITypeLib(%p)\n",This
);
4767 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4768 list_remove(&tlbstr
->entry
);
4769 SysFreeString(tlbstr
->str
);
4773 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4774 list_remove(&tlbstr
->entry
);
4775 SysFreeString(tlbstr
->str
);
4779 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4780 list_remove(&tlbguid
->entry
);
4784 TLB_FreeCustData(&This
->custdata_list
);
4786 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4787 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4788 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4790 heap_free(This
->pTypeDesc
);
4792 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4794 if (pImpLib
->pImpTypeLib
)
4795 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4796 SysFreeString(pImpLib
->name
);
4798 list_remove(&pImpLib
->entry
);
4802 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4804 list_remove(&ref_type
->entry
);
4805 heap_free(ref_type
);
4808 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4809 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4810 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4812 heap_free(This
->typeinfos
);
4820 /* ITypeLib::GetTypeInfoCount
4822 * Returns the number of type descriptions in the type library
4824 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4826 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4827 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4828 return This
->TypeInfoCount
;
4831 /* ITypeLib::GetTypeInfo
4833 * retrieves the specified type description in the library.
4835 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4838 ITypeInfo
**ppTInfo
)
4840 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4842 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4845 return E_INVALIDARG
;
4847 if(index
>= This
->TypeInfoCount
)
4848 return TYPE_E_ELEMENTNOTFOUND
;
4850 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4851 ITypeInfo_AddRef(*ppTInfo
);
4857 /* ITypeLibs::GetTypeInfoType
4859 * Retrieves the type of a type description.
4861 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4866 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4868 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4871 return E_INVALIDARG
;
4873 if(index
>= This
->TypeInfoCount
)
4874 return TYPE_E_ELEMENTNOTFOUND
;
4876 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4881 /* ITypeLib::GetTypeInfoOfGuid
4883 * Retrieves the type description that corresponds to the specified GUID.
4886 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4889 ITypeInfo
**ppTInfo
)
4891 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4894 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4896 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4897 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4898 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4899 ITypeInfo_AddRef(*ppTInfo
);
4904 return TYPE_E_ELEMENTNOTFOUND
;
4907 /* ITypeLib::GetLibAttr
4909 * Retrieves the structure that contains the library's attributes.
4912 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4916 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4918 TRACE("(%p, %p)\n", This
, attr
);
4920 if (!attr
) return E_INVALIDARG
;
4922 *attr
= heap_alloc(sizeof(**attr
));
4923 if (!*attr
) return E_OUTOFMEMORY
;
4925 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4926 (*attr
)->lcid
= This
->set_lcid
;
4927 (*attr
)->syskind
= This
->syskind
;
4928 (*attr
)->wMajorVerNum
= This
->ver_major
;
4929 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4930 (*attr
)->wLibFlags
= This
->libflags
;
4935 /* ITypeLib::GetTypeComp
4937 * Enables a client compiler to bind to a library's types, variables,
4938 * constants, and global functions.
4941 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4943 ITypeComp
**ppTComp
)
4945 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4947 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4948 *ppTComp
= &This
->ITypeComp_iface
;
4949 ITypeComp_AddRef(*ppTComp
);
4954 /* ITypeLib::GetDocumentation
4956 * Retrieves the library's documentation string, the complete Help file name
4957 * and path, and the context identifier for the library Help topic in the Help
4960 * On a successful return all non-null BSTR pointers will have been set,
4963 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4967 BSTR
*pBstrDocString
,
4968 DWORD
*pdwHelpContext
,
4969 BSTR
*pBstrHelpFile
)
4971 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4972 HRESULT result
= E_INVALIDARG
;
4975 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4977 pBstrName
, pBstrDocString
,
4978 pdwHelpContext
, pBstrHelpFile
);
4982 /* documentation for the typelib */
4987 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4995 if (This
->DocString
)
4997 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
5001 *pBstrDocString
= NULL
;
5005 *pdwHelpContext
= This
->dwHelpContext
;
5011 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5015 *pBstrHelpFile
= NULL
;
5022 /* for a typeinfo */
5023 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5025 if(SUCCEEDED(result
))
5027 result
= ITypeInfo_GetDocumentation(pTInfo
,
5031 pdwHelpContext
, pBstrHelpFile
);
5033 ITypeInfo_Release(pTInfo
);
5038 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5040 if (pBstrName
) SysFreeString (*pBstrName
);
5042 return STG_E_INSUFFICIENTMEMORY
;
5047 * Indicates whether a passed-in string contains the name of a type or member
5048 * described in the library.
5051 static HRESULT WINAPI
ITypeLib2_fnIsName(
5057 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5059 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5061 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5065 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5066 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5067 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5068 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5069 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5071 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5072 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5073 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5074 goto ITypeLib2_fnIsName_exit
;
5077 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5078 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5079 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5085 ITypeLib2_fnIsName_exit
:
5086 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5087 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5092 /* ITypeLib::FindName
5094 * Finds occurrences of a type description in a type library. This may be used
5095 * to quickly verify that a name exists in a type library.
5098 static HRESULT WINAPI
ITypeLib2_fnFindName(
5102 ITypeInfo
**ppTInfo
,
5106 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5111 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5113 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5114 return E_INVALIDARG
;
5116 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5117 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5118 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5122 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5123 memid
[count
] = MEMBERID_NIL
;
5124 goto ITypeLib2_fnFindName_exit
;
5127 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5128 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5130 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5131 memid
[count
] = func
->funcdesc
.memid
;
5132 goto ITypeLib2_fnFindName_exit
;
5136 var
= TLB_get_vardesc_by_name(pTInfo
, name
);
5138 memid
[count
] = var
->vardesc
.memid
;
5139 goto ITypeLib2_fnFindName_exit
;
5143 ITypeLib2_fnFindName_exit
:
5144 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5145 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5148 TRACE("found %d typeinfos\n", count
);
5155 /* ITypeLib::ReleaseTLibAttr
5157 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5160 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5162 TLIBATTR
*pTLibAttr
)
5164 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5165 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5166 heap_free(pTLibAttr
);
5169 /* ITypeLib2::GetCustData
5171 * gets the custom data
5173 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5178 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5179 TLBCustData
*pCData
;
5181 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5183 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5185 return TYPE_E_ELEMENTNOTFOUND
;
5187 VariantInit(pVarVal
);
5188 VariantCopy(pVarVal
, &pCData
->data
);
5193 /* ITypeLib2::GetLibStatistics
5195 * Returns statistics about a type library that are required for efficient
5196 * sizing of hash tables.
5199 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5201 ULONG
*pcUniqueNames
,
5202 ULONG
*pcchUniqueNames
)
5204 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5206 FIXME("(%p): stub!\n", This
);
5208 if(pcUniqueNames
) *pcUniqueNames
=1;
5209 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5213 /* ITypeLib2::GetDocumentation2
5215 * Retrieves the library's documentation string, the complete Help file name
5216 * and path, the localization context to use, and the context ID for the
5217 * library Help topic in the Help file.
5220 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5224 BSTR
*pbstrHelpString
,
5225 DWORD
*pdwHelpStringContext
,
5226 BSTR
*pbstrHelpStringDll
)
5228 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5232 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5234 /* the help string should be obtained from the helpstringdll,
5235 * using the _DLLGetDocumentation function, based on the supplied
5236 * lcid. Nice to do sometime...
5240 /* documentation for the typelib */
5242 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5243 if(pdwHelpStringContext
)
5244 *pdwHelpStringContext
=This
->dwHelpContext
;
5245 if(pbstrHelpStringDll
)
5246 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5252 /* for a typeinfo */
5253 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5255 if(SUCCEEDED(result
))
5257 ITypeInfo2
* pTInfo2
;
5258 result
= ITypeInfo_QueryInterface(pTInfo
,
5260 (LPVOID
*) &pTInfo2
);
5262 if(SUCCEEDED(result
))
5264 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5268 pdwHelpStringContext
,
5269 pbstrHelpStringDll
);
5271 ITypeInfo2_Release(pTInfo2
);
5274 ITypeInfo_Release(pTInfo
);
5280 static HRESULT
TLB_copy_all_custdata(const struct list
*custdata_list
, CUSTDATA
*pCustData
)
5282 TLBCustData
*pCData
;
5286 ct
= list_count(custdata_list
);
5288 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5289 if(!pCustData
->prgCustData
)
5290 return E_OUTOFMEMORY
;
5292 pCustData
->cCustData
= ct
;
5294 cdi
= pCustData
->prgCustData
;
5295 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5296 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5297 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5305 /* ITypeLib2::GetAllCustData
5307 * Gets all custom data items for the library.
5310 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5312 CUSTDATA
*pCustData
)
5314 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5315 TRACE("(%p)->(%p)\n", This
, pCustData
);
5316 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5319 static const ITypeLib2Vtbl tlbvt
= {
5320 ITypeLib2_fnQueryInterface
,
5322 ITypeLib2_fnRelease
,
5323 ITypeLib2_fnGetTypeInfoCount
,
5324 ITypeLib2_fnGetTypeInfo
,
5325 ITypeLib2_fnGetTypeInfoType
,
5326 ITypeLib2_fnGetTypeInfoOfGuid
,
5327 ITypeLib2_fnGetLibAttr
,
5328 ITypeLib2_fnGetTypeComp
,
5329 ITypeLib2_fnGetDocumentation
,
5331 ITypeLib2_fnFindName
,
5332 ITypeLib2_fnReleaseTLibAttr
,
5334 ITypeLib2_fnGetCustData
,
5335 ITypeLib2_fnGetLibStatistics
,
5336 ITypeLib2_fnGetDocumentation2
,
5337 ITypeLib2_fnGetAllCustData
5341 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5343 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5345 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5348 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5350 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5352 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5355 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5357 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5359 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5362 static HRESULT WINAPI
ITypeLibComp_fnBind(
5367 ITypeInfo
** ppTInfo
,
5368 DESCKIND
* pDescKind
,
5371 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5372 BOOL typemismatch
= FALSE
;
5375 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5377 *pDescKind
= DESCKIND_NONE
;
5378 pBindPtr
->lptcomp
= NULL
;
5381 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5382 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5383 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5385 /* FIXME: check wFlags here? */
5386 /* FIXME: we should use a hash table to look this info up using lHash
5387 * instead of an O(n) search */
5388 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5389 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5391 if (pTypeInfo
->Name
&& !wcscmp(pTypeInfo
->Name
->str
, szName
))
5393 *pDescKind
= DESCKIND_TYPECOMP
;
5394 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5395 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5396 TRACE("module or enum: %s\n", debugstr_w(szName
));
5401 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5402 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5404 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5407 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5408 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5410 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5413 else if (hr
== TYPE_E_TYPEMISMATCH
)
5414 typemismatch
= TRUE
;
5417 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5418 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5420 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5422 ITypeInfo
*subtypeinfo
;
5424 DESCKIND subdesckind
;
5426 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5427 &subtypeinfo
, &subdesckind
, &subbindptr
);
5428 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5430 TYPEDESC tdesc_appobject
;
5431 const VARDESC vardesc_appobject
=
5434 NULL
, /* lpstrSchema */
5449 VAR_STATIC
/* varkind */
5452 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5453 tdesc_appobject
.vt
= VT_USERDEFINED
;
5455 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5457 /* cleanup things filled in by Bind call so we can put our
5458 * application object data in there instead */
5459 switch (subdesckind
)
5461 case DESCKIND_FUNCDESC
:
5462 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5464 case DESCKIND_VARDESC
:
5465 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5470 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5472 if (pTypeInfo
->hreftype
== -1)
5473 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5475 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5479 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5480 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5481 ITypeInfo_AddRef(*ppTInfo
);
5484 else if (hr
== TYPE_E_TYPEMISMATCH
)
5485 typemismatch
= TRUE
;
5491 TRACE("type mismatch %s\n", debugstr_w(szName
));
5492 return TYPE_E_TYPEMISMATCH
;
5496 TRACE("name not found %s\n", debugstr_w(szName
));
5501 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5505 ITypeInfo
** ppTInfo
,
5506 ITypeComp
** ppTComp
)
5508 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5509 ITypeInfoImpl
*info
;
5511 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5513 if(!szName
|| !ppTInfo
|| !ppTComp
)
5514 return E_INVALIDARG
;
5516 info
= TLB_get_typeinfo_by_name(This
, szName
);
5523 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5524 ITypeInfo_AddRef(*ppTInfo
);
5525 *ppTComp
= &info
->ITypeComp_iface
;
5526 ITypeComp_AddRef(*ppTComp
);
5531 static const ITypeCompVtbl tlbtcvt
=
5534 ITypeLibComp_fnQueryInterface
,
5535 ITypeLibComp_fnAddRef
,
5536 ITypeLibComp_fnRelease
,
5538 ITypeLibComp_fnBind
,
5539 ITypeLibComp_fnBindType
5542 /*================== ITypeInfo(2) Methods ===================================*/
5543 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5545 ITypeInfoImpl
*pTypeInfoImpl
;
5547 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5550 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5551 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5552 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5553 pTypeInfoImpl
->ref
= 0;
5554 pTypeInfoImpl
->hreftype
= -1;
5555 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5556 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5557 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5558 list_init(pTypeInfoImpl
->pcustdata_list
);
5560 TRACE("(%p)\n", pTypeInfoImpl
);
5561 return pTypeInfoImpl
;
5564 /* ITypeInfo::QueryInterface
5566 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5571 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5573 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5576 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5577 IsEqualIID(riid
,&IID_ITypeInfo
)||
5578 IsEqualIID(riid
,&IID_ITypeInfo2
))
5579 *ppvObject
= &This
->ITypeInfo2_iface
;
5580 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5581 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5582 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5583 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5584 *ppvObject
= &This
->ITypeComp_iface
;
5587 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5588 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5591 TRACE("-- Interface: E_NOINTERFACE\n");
5592 return E_NOINTERFACE
;
5595 /* ITypeInfo::AddRef
5597 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5599 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5600 ULONG ref
= InterlockedIncrement(&This
->ref
);
5602 TRACE("(%p)->ref is %u\n",This
, ref
);
5604 if (ref
== 1 /* incremented from 0 */)
5605 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5610 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5614 TRACE("destroying ITypeInfo(%p)\n",This
);
5616 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5619 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5620 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5622 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5623 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5624 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5625 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5627 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5628 heap_free(pFInfo
->pParamDesc
);
5629 TLB_FreeCustData(&pFInfo
->custdata_list
);
5631 heap_free(This
->funcdescs
);
5633 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5635 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5636 if (pVInfo
->vardesc_create
) {
5637 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5638 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5639 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5640 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5642 TLB_FreeCustData(&pVInfo
->custdata_list
);
5644 heap_free(This
->vardescs
);
5646 if(This
->impltypes
){
5647 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5648 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5649 TLB_FreeCustData(&pImpl
->custdata_list
);
5651 heap_free(This
->impltypes
);
5654 TLB_FreeCustData(&This
->custdata_list
);
5659 /* ITypeInfo::Release
5661 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5663 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5664 ULONG ref
= InterlockedDecrement(&This
->ref
);
5666 TRACE("(%p)->(%u)\n",This
, ref
);
5670 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5671 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5672 if (not_attached_to_typelib
)
5674 /* otherwise This will be freed when typelib is freed */
5680 /* ITypeInfo::GetTypeAttr
5682 * Retrieves a TYPEATTR structure that contains the attributes of the type
5686 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5687 LPTYPEATTR
*ppTypeAttr
)
5689 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5692 TRACE("(%p)\n",This
);
5694 size
= sizeof(**ppTypeAttr
);
5695 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5696 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5698 *ppTypeAttr
= heap_alloc(size
);
5700 return E_OUTOFMEMORY
;
5702 **ppTypeAttr
= This
->typeattr
;
5703 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5705 if (This
->tdescAlias
)
5706 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5708 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5709 /* This should include all the inherited funcs */
5710 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5711 /* This is always the size of IDispatch's vtbl */
5712 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5713 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5718 /* ITypeInfo::GetTypeComp
5720 * Retrieves the ITypeComp interface for the type description, which enables a
5721 * client compiler to bind to the type description's members.
5724 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5725 ITypeComp
* *ppTComp
)
5727 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5729 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5731 *ppTComp
= &This
->ITypeComp_iface
;
5732 ITypeComp_AddRef(*ppTComp
);
5736 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5738 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5739 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5740 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5744 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5747 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5748 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5750 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5751 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5752 *buffer
+= sizeof(PARAMDESCEX
);
5753 *pparamdescex_dest
= *pparamdescex_src
;
5754 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5755 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5756 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5757 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5760 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5764 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5766 UINT len
= SysStringLen(str
), i
;
5767 for (i
= 0; i
< len
; ++i
)
5773 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5775 if (V_VT(var
) == VT_INT
)
5776 return VariantChangeType(var
, var
, 0, VT_I4
);
5777 else if (V_VT(var
) == VT_UINT
)
5778 return VariantChangeType(var
, var
, 0, VT_UI4
);
5779 else if (V_VT(var
) == VT_BSTR
)
5780 return TLB_SanitizeBSTR(V_BSTR(var
));
5785 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5787 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5788 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5791 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5795 SIZE_T size
= sizeof(*src
);
5799 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5800 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5801 for (i
= 0; i
< src
->cParams
; i
++)
5803 size
+= sizeof(ELEMDESC
);
5804 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5807 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5808 if (!dest
) return E_OUTOFMEMORY
;
5811 if (dispinterface
) /* overwrite funckind */
5812 dest
->funckind
= FUNC_DISPATCH
;
5813 buffer
= (char *)(dest
+ 1);
5815 dest
->oVft
= dest
->oVft
& 0xFFFC;
5817 if (dest
->cScodes
) {
5818 dest
->lprgscode
= (SCODE
*)buffer
;
5819 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5820 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5822 dest
->lprgscode
= NULL
;
5824 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5827 SysFreeString((BSTR
)dest
);
5831 if (dest
->cParams
) {
5832 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5833 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5834 for (i
= 0; i
< src
->cParams
; i
++)
5836 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5842 /* undo the above actions */
5843 for (i
= i
- 1; i
>= 0; i
--)
5844 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5845 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5846 SysFreeString((BSTR
)dest
);
5850 dest
->lprgelemdescParam
= NULL
;
5852 /* special treatment for dispinterfaces: this makes functions appear
5853 * to return their [retval] value when it is really returning an
5855 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5857 if (dest
->cParams
&&
5858 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5860 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5861 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5863 ERR("elemdesc should have started with VT_PTR instead of:\n");
5865 dump_ELEMDESC(elemdesc
);
5866 return E_UNEXPECTED
;
5869 /* copy last parameter to the return value. we are using a flat
5870 * buffer so there is no danger of leaking memory in
5872 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5874 /* remove the last parameter */
5878 /* otherwise this function is made to appear to have no return
5880 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5888 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5890 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5891 if (var_desc
->varkind
== VAR_CONST
)
5892 VariantClear(var_desc
->u
.lpvarValue
);
5893 SysFreeString((BSTR
)var_desc
);
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 TLBFuncDesc
**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 index
-= implemented_funcs
;
5939 if (index
>= This
->typeattr
.cFuncs
)
5940 return TYPE_E_ELEMENTNOTFOUND
;
5942 *ppFuncDesc
= &This
->funcdescs
[index
];
5946 static HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const TLBFuncDesc
**func_desc
, UINT
*hrefoffset
)
5948 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5950 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5951 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface
, index
, func_desc
, NULL
, hrefoffset
);
5953 if (index
>= This
->typeattr
.cFuncs
)
5954 return TYPE_E_ELEMENTNOTFOUND
;
5956 *func_desc
= &This
->funcdescs
[index
];
5960 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5962 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5965 switch (pTypeDesc
->vt
)
5967 case VT_USERDEFINED
:
5968 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5972 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5975 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5983 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5986 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5987 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5988 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5991 /* ITypeInfo::GetFuncDesc
5993 * Retrieves the FUNCDESC structure that contains information about a
5994 * specified function.
5997 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5998 LPFUNCDESC
*ppFuncDesc
)
6000 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6001 const TLBFuncDesc
*internal_funcdesc
;
6003 UINT hrefoffset
= 0;
6005 TRACE("(%p) index %d\n", This
, index
);
6008 return E_INVALIDARG
;
6010 if (This
->needs_layout
)
6011 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6013 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6014 &internal_funcdesc
, &hrefoffset
);
6017 WARN("description for function %d not found\n", index
);
6021 hr
= TLB_AllocAndInitFuncDesc(
6022 &internal_funcdesc
->funcdesc
,
6024 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6026 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
6027 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6029 TRACE("-- 0x%08x\n", hr
);
6033 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6037 SIZE_T size
= sizeof(*src
);
6040 if (src
->lpstrSchema
) size
+= (lstrlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6041 if (src
->varkind
== VAR_CONST
)
6042 size
+= sizeof(VARIANT
);
6043 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6045 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6046 if (!dest
) return E_OUTOFMEMORY
;
6049 buffer
= (char *)(dest
+ 1);
6050 if (src
->lpstrSchema
)
6053 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6054 len
= lstrlenW(src
->lpstrSchema
);
6055 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6056 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6059 if (src
->varkind
== VAR_CONST
)
6063 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6064 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6065 buffer
+= sizeof(VARIANT
);
6066 VariantInit(dest
->u
.lpvarValue
);
6067 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6070 SysFreeString((BSTR
)dest
);
6074 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6077 if (src
->varkind
== VAR_CONST
)
6078 VariantClear(dest
->u
.lpvarValue
);
6079 SysFreeString((BSTR
)dest
);
6086 /* ITypeInfo::GetVarDesc
6088 * Retrieves a VARDESC structure that describes the specified variable.
6091 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6092 LPVARDESC
*ppVarDesc
)
6094 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6095 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6097 TRACE("(%p) index %d\n", This
, index
);
6099 if(index
>= This
->typeattr
.cVars
)
6100 return TYPE_E_ELEMENTNOTFOUND
;
6102 if (This
->needs_layout
)
6103 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6105 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6108 /* ITypeInfo_GetNames
6110 * Retrieves the variable with the specified member ID (or the name of the
6111 * property or method and its parameters) that correspond to the specified
6114 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6115 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6117 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6118 const TLBFuncDesc
*pFDesc
;
6119 const TLBVarDesc
*pVDesc
;
6121 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6124 return E_INVALIDARG
;
6128 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
6131 if(!cMaxNames
|| !pFDesc
->Name
)
6134 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6137 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6138 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6140 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6146 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
6149 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6154 if(This
->impltypes
&&
6155 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
6156 /* recursive search */
6159 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6160 if(SUCCEEDED(result
))
6162 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6163 ITypeInfo_Release(pTInfo
);
6166 WARN("Could not search inherited interface!\n");
6170 WARN("no names found\n");
6173 return TYPE_E_ELEMENTNOTFOUND
;
6179 /* ITypeInfo::GetRefTypeOfImplType
6181 * If a type description describes a COM class, it retrieves the type
6182 * description of the implemented interface types. For an interface,
6183 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6187 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6192 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6195 TRACE("(%p) index %d\n", This
, index
);
6196 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6200 /* only valid on dual interfaces;
6201 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6204 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6210 hr
= TYPE_E_ELEMENTNOTFOUND
;
6213 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6215 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6216 *pRefType
= This
->pTypeLib
->dispatch_href
;
6220 if(index
>= This
->typeattr
.cImplTypes
)
6221 hr
= TYPE_E_ELEMENTNOTFOUND
;
6223 *pRefType
= This
->impltypes
[index
].hRef
;
6224 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6232 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6234 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6240 /* ITypeInfo::GetImplTypeFlags
6242 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6243 * or base interface in a type description.
6245 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6246 UINT index
, INT
*pImplTypeFlags
)
6248 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6250 TRACE("(%p) index %d\n", This
, index
);
6253 return E_INVALIDARG
;
6255 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6256 *pImplTypeFlags
= 0;
6260 if(index
>= This
->typeattr
.cImplTypes
)
6261 return TYPE_E_ELEMENTNOTFOUND
;
6263 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6269 * Maps between member names and member IDs, and parameter names and
6272 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6273 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6275 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6276 const TLBVarDesc
*pVDesc
;
6280 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6283 /* init out parameters in case of failure */
6284 for (i
= 0; i
< cNames
; i
++)
6285 pMemId
[i
] = MEMBERID_NIL
;
6287 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6289 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6290 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6291 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6292 for(i
=1; i
< cNames
; i
++){
6293 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6294 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6296 if( j
<pFDesc
->funcdesc
.cParams
)
6299 ret
=DISP_E_UNKNOWNNAME
;
6301 TRACE("-- 0x%08x\n", ret
);
6305 pVDesc
= TLB_get_vardesc_by_name(This
, *rgszNames
);
6308 *pMemId
= pVDesc
->vardesc
.memid
;
6311 /* not found, see if it can be found in an inherited interface */
6312 if(This
->impltypes
) {
6313 /* recursive search */
6315 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6317 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6318 ITypeInfo_Release(pTInfo
);
6321 WARN("Could not search inherited interface!\n");
6323 WARN("no names found\n");
6324 return DISP_E_UNKNOWNNAME
;
6330 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6331 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6332 __ASM_GLOBAL_FUNC( call_method
,
6334 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6335 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6336 "movl %esp,%ebp\n\t"
6337 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6339 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6341 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6342 "movl 12(%ebp),%edx\n\t"
6343 "movl %esp,%edi\n\t"
6346 "subl %edx,%edi\n\t"
6347 "andl $~15,%edi\n\t"
6348 "movl %edi,%esp\n\t"
6349 "movl 12(%ebp),%ecx\n\t"
6350 "movl 16(%ebp),%esi\n\t"
6353 "1:\tcall *8(%ebp)\n\t"
6354 "subl %esp,%edi\n\t"
6355 "movl 20(%ebp),%ecx\n\t"
6356 "movl %edi,(%ecx)\n\t"
6357 "leal -8(%ebp),%esp\n\t"
6359 __ASM_CFI(".cfi_same_value %edi\n\t")
6361 __ASM_CFI(".cfi_same_value %esi\n\t")
6363 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6364 __ASM_CFI(".cfi_same_value %ebp\n\t")
6366 __ASM_GLOBAL_FUNC( call_double_method
,
6367 "jmp " __ASM_NAME("call_method") )
6369 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6370 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6372 int argspos
= 0, stack_offset
;
6377 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6378 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6379 pvargResult
, V_VT(pvargResult
));
6381 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6383 FIXME("unsupported calling convention %d\n",cc
);
6384 return E_INVALIDARG
;
6387 /* maximum size for an argument is sizeof(VARIANT) */
6388 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6392 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6393 func
= vtable
[oVft
/sizeof(void *)];
6394 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6396 else func
= (void *)oVft
;
6402 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6405 WARN("invalid return type %u\n", vtReturn
);
6407 return E_INVALIDARG
;
6412 for (i
= 0; i
< cActuals
; i
++)
6414 VARIANT
*arg
= prgpvarg
[i
];
6425 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6426 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6430 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6431 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6433 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6434 args
[argspos
++] = V_BOOL(arg
);
6437 args
[argspos
++] = V_UI4(arg
);
6440 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6448 call_method( func
, argspos
, args
, &stack_offset
);
6451 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6455 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6460 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6463 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6467 if (stack_offset
&& cc
== CC_STDCALL
)
6469 WARN( "stack pointer off by %d\n", stack_offset
);
6470 return DISP_E_BADCALLEE
;
6472 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6473 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6477 #elif defined(__x86_64__)
6479 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6480 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6481 __ASM_GLOBAL_FUNC( call_method
,
6483 __ASM_SEH(".seh_pushreg %rbp\n\t")
6484 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6485 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6486 "movq %rsp,%rbp\n\t"
6487 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6488 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6490 __ASM_SEH(".seh_pushreg %rsi\n\t")
6491 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6493 __ASM_SEH(".seh_pushreg %rdi\n\t")
6494 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6495 __ASM_SEH(".seh_endprologue\n\t")
6496 "movq %rcx,%rax\n\t"
6499 "cmovgq %rdx,%rcx\n\t"
6500 "leaq 0(,%rcx,8),%rdx\n\t"
6501 "subq %rdx,%rsp\n\t"
6502 "andq $~15,%rsp\n\t"
6503 "movq %rsp,%rdi\n\t"
6506 "movq 0(%rsp),%rcx\n\t"
6507 "movq 8(%rsp),%rdx\n\t"
6508 "movq 16(%rsp),%r8\n\t"
6509 "movq 24(%rsp),%r9\n\t"
6510 "movq 0(%rsp),%xmm0\n\t"
6511 "movq 8(%rsp),%xmm1\n\t"
6512 "movq 16(%rsp),%xmm2\n\t"
6513 "movq 24(%rsp),%xmm3\n\t"
6515 "leaq -16(%rbp),%rsp\n\t"
6517 __ASM_CFI(".cfi_same_value %rdi\n\t")
6519 __ASM_CFI(".cfi_same_value %rsi\n\t")
6520 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6522 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6523 __ASM_CFI(".cfi_same_value %rbp\n\t")
6525 __ASM_GLOBAL_FUNC( call_double_method
,
6526 "jmp " __ASM_NAME("call_method") )
6528 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6529 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6536 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6537 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6538 pvargResult
, V_VT(pvargResult
));
6540 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6542 FIXME("unsupported calling convention %d\n",cc
);
6543 return E_INVALIDARG
;
6546 /* maximum size for an argument is sizeof(DWORD_PTR) */
6547 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6551 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6552 func
= vtable
[oVft
/sizeof(void *)];
6553 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6555 else func
= (void *)oVft
;
6561 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6564 WARN("invalid return type %u\n", vtReturn
);
6566 return E_INVALIDARG
;
6571 for (i
= 0; i
< cActuals
; i
++)
6573 VARIANT
*arg
= prgpvarg
[i
];
6579 args
[argspos
++] = (ULONG_PTR
)arg
;
6581 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6582 args
[argspos
++] = V_BOOL(arg
);
6585 args
[argspos
++] = V_UI8(arg
);
6588 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6594 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6598 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6602 call_method( func
, argspos
, args
);
6605 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6609 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6610 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6614 #elif defined(__arm__)
6616 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6617 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6618 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6619 __ASM_GLOBAL_FUNC( call_method
,
6622 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6623 * 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)
6626 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6627 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6629 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6630 "beq 1f\n\t" /* Skip allocation if no stack args */
6631 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6632 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6633 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6634 "subs r1, r1, #4\n\t" /* Decrement count */
6635 "bgt 2b\n\t" /* Loop till done */
6639 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6641 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6642 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6644 "blx ip\n\t" /* Call the target function */
6646 "mov sp, fp\n\t" /* Clean the stack using fp */
6647 "pop {fp, pc}\n\t" /* Restore fp and return */
6649 __ASM_GLOBAL_FUNC( call_float_method
,
6650 "b " __ASM_NAME("call_method") )
6651 __ASM_GLOBAL_FUNC( call_double_method
,
6652 "b " __ASM_NAME("call_method") )
6654 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6655 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6670 int rcount
; /* 32-bit register index count */
6672 int scount
= 0; /* single-precision float register index count */
6673 int dcount
= 0; /* double-precision float register index count */
6676 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6677 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6679 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6681 FIXME("unsupported calling convention %d\n",cc
);
6682 return E_INVALIDARG
;
6690 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6691 func
= vtable
[oVft
/sizeof(void *)];
6692 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6694 else func
= (void *)oVft
;
6696 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6697 /* first as it will need to be in the 'r' registers: */
6702 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6705 WARN("invalid return type %u\n", vtReturn
);
6706 return E_INVALIDARG
;
6707 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6711 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6712 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6714 for (i
= 0; i
< cActuals
; i
++)
6716 VARIANT
*arg
= prgpvarg
[i
];
6717 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6718 int ntemp
; /* Used for counting words split between registers and stack */
6724 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6727 dcount
= max( (scount
+ 1) / 2, dcount
);
6730 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6734 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6735 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6736 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6740 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6745 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6746 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6747 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6751 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6752 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6753 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6754 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6757 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6759 /* 8-byte align 'r' and/or stack: */
6761 rcount
+= (rcount
% 2);
6765 argspos
+= (argspos
% 2);
6767 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6771 regs
.r
[rcount
++] = *pdwarg
++;
6773 args
[argspos
++] = *pdwarg
++;
6777 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6779 regs
.r
[rcount
++] = V_BOOL(arg
);
6781 args
[argspos
++] = V_BOOL(arg
);
6783 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6785 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6787 regs
.sd
.s
[scount
++] = V_R4(arg
);
6789 args
[argspos
++] = V_UI4(arg
);
6794 regs
.r
[rcount
++] = V_UI4(arg
);
6796 args
[argspos
++] = V_UI4(arg
);
6799 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6802 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
6806 case VT_EMPTY
: /* EMPTY = no return value */
6807 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6809 call_method( func
, argspos
, args
, (DWORD
*)®s
);
6812 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
6816 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
6821 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6824 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6828 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6829 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6833 #elif defined(__aarch64__)
6835 extern DWORD_PTR CDECL
call_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6836 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6837 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6838 __ASM_GLOBAL_FUNC( call_method
,
6839 "stp x29, x30, [sp, #-16]!\n\t"
6841 "sub sp, sp, x1, lsl #3\n\t"
6843 "1:\tsub x1, x1, #1\n\t"
6844 "ldr x4, [x2, x1, lsl #3]\n\t"
6845 "str x4, [sp, x1, lsl #3]\n\t"
6847 "2:\tmov x16, x0\n\t"
6849 "ldp d0, d1, [x9]\n\t"
6850 "ldp d2, d3, [x9, #0x10]\n\t"
6851 "ldp d4, d5, [x9, #0x20]\n\t"
6852 "ldp d6, d7, [x9, #0x30]\n\t"
6853 "ldp x0, x1, [x9, #0x40]\n\t"
6854 "ldp x2, x3, [x9, #0x50]\n\t"
6855 "ldp x4, x5, [x9, #0x60]\n\t"
6856 "ldp x6, x7, [x9, #0x70]\n\t"
6857 "ldr x8, [x9, #0x80]\n\t"
6860 "ldp x29, x30, [sp], #16\n\t"
6862 __ASM_GLOBAL_FUNC( call_float_method
,
6863 "b " __ASM_NAME("call_method") )
6864 __ASM_GLOBAL_FUNC( call_double_method
,
6865 "b " __ASM_NAME("call_method") )
6867 HRESULT WINAPI
DispCallFunc( void *instance
, ULONG_PTR offset
, CALLCONV cc
, VARTYPE ret_type
, UINT count
,
6868 VARTYPE
*types
, VARIANTARG
**vargs
, VARIANT
*result
)
6883 int rcount
; /* 64-bit register index count */
6884 int fpcount
= 0; /* float register index count */
6886 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6887 instance
, offset
, cc
, ret_type
, count
, types
, vargs
, result
, V_VT(result
));
6889 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6891 FIXME("unsupported calling convention %d\n",cc
);
6892 return E_INVALIDARG
;
6900 const FARPROC
*vtable
= *(FARPROC
**)instance
;
6901 func
= vtable
[offset
/sizeof(void *)];
6902 regs
.x
[rcount
++] = (DWORD_PTR
)instance
; /* the This pointer is always the first parameter */
6904 else func
= (void *)offset
;
6906 /* maximum size for an argument is 16 */
6907 args
= heap_alloc( 16 * count
);
6909 for (i
= 0; i
< count
; i
++)
6911 VARIANT
*arg
= vargs
[i
];
6916 if (fpcount
< 8) regs
.fp
[fpcount
++].f
= V_R4(arg
);
6917 else *(float *)&args
[argspos
++] = V_R4(arg
);
6921 if (fpcount
< 8) regs
.fp
[fpcount
++].d
= V_R8(arg
);
6922 else *(double *)&args
[argspos
++] = V_R8(arg
);
6927 memcpy( ®s
.x
[rcount
], arg
, sizeof(*arg
) );
6932 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6937 if (rcount
< 8) regs
.x
[rcount
++] = (DWORD_PTR
)arg
;
6938 else args
[argspos
++] = (DWORD_PTR
)arg
;
6940 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6941 if (rcount
< 8) regs
.x
[rcount
++] = V_BOOL(arg
);
6942 else args
[argspos
++] = V_BOOL(arg
);
6945 if (rcount
< 8) regs
.x
[rcount
++] = V_UI8(arg
);
6946 else args
[argspos
++] = V_UI8(arg
);
6949 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(types
[i
]), debugstr_variant(arg
));
6952 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 16-byte */
6958 return E_INVALIDARG
;
6961 regs
.x
[8] = (DWORD_PTR
)result
; /* x8 is a pointer to the result */
6962 call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6965 V_R4(result
) = call_float_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6969 V_R8(result
) = call_double_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6972 V_UI8(result
) = call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6976 if (ret_type
!= VT_VARIANT
) V_VT(result
) = ret_type
;
6977 TRACE("retval: %s\n", debugstr_variant(result
));
6981 #else /* __aarch64__ */
6983 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6984 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6986 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6987 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6993 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6996 ITypeInfo
*tinfo2
= NULL
;
6997 TYPEATTR
*tattr
= NULL
;
6999 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
7002 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
7004 tdesc
->u
.hreftype
, hr
);
7007 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7010 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
7011 ITypeInfo_Release(tinfo2
);
7015 switch (tattr
->typekind
)
7022 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
7025 case TKIND_INTERFACE
:
7026 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
7032 case TKIND_DISPATCH
:
7041 FIXME("TKIND_RECORD unhandled.\n");
7046 FIXME("TKIND_UNION unhandled.\n");
7051 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
7055 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7056 ITypeInfo_Release(tinfo2
);
7060 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
7064 /* enforce only one level of pointer indirection */
7065 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
7067 tdesc
= tdesc
->u
.lptdesc
;
7069 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7070 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7071 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7072 if ((tdesc
->vt
== VT_USERDEFINED
) ||
7073 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
7075 VARTYPE vt_userdefined
= 0;
7076 const TYPEDESC
*tdesc_userdefined
= tdesc
;
7077 if (tdesc
->vt
== VT_PTR
)
7079 vt_userdefined
= VT_BYREF
;
7080 tdesc_userdefined
= tdesc
->u
.lptdesc
;
7082 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
7084 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
7085 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
7087 *vt
|= vt_userdefined
;
7099 case VT_USERDEFINED
:
7100 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
7107 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
7108 hr
= DISP_E_BADVARTYPE
;
7112 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
7127 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
7134 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
7138 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7140 ITypeInfo_Release(tinfo2
);
7144 switch(tattr
->typekind
) {
7146 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.u
.hreftype
, guid
);
7149 case TKIND_INTERFACE
:
7150 case TKIND_DISPATCH
:
7151 *guid
= tattr
->guid
;
7155 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
7157 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
7158 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
7162 if (i
== tattr
->cImplTypes
)
7165 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
7166 if (SUCCEEDED(hres
))
7167 hres
= get_iface_guid(tinfo2
, href
, guid
);
7171 ERR("Unexpected typekind %d\n", tattr
->typekind
);
7172 hres
= E_UNEXPECTED
;
7175 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7176 ITypeInfo_Release(tinfo2
);
7180 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7182 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7185 #define INVBUF_ELEMENT_SIZE \
7186 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7187 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7188 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7189 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7190 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7191 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7192 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7193 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7195 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7200 DISPPARAMS
*pDispParams
,
7201 VARIANT
*pVarResult
,
7202 EXCEPINFO
*pExcepInfo
,
7205 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7207 unsigned int var_index
;
7210 const TLBFuncDesc
*pFuncInfo
;
7213 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7214 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
7217 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7218 return DISP_E_MEMBERNOTFOUND
;
7222 ERR("NULL pDispParams not allowed\n");
7223 return E_INVALIDARG
;
7226 dump_DispParms(pDispParams
);
7228 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7230 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7231 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7232 return E_INVALIDARG
;
7235 /* we do this instead of using GetFuncDesc since it will return a fake
7236 * FUNCDESC for dispinterfaces and we want the real function description */
7237 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7238 pFuncInfo
= &This
->funcdescs
[fdc
];
7239 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7240 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7241 !func_restricted( &pFuncInfo
->funcdesc
))
7245 if (fdc
< This
->typeattr
.cFuncs
) {
7246 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7250 TRACE("invoking:\n");
7251 dump_TLBFuncDescOne(pFuncInfo
);
7254 switch (func_desc
->funckind
) {
7255 case FUNC_PUREVIRTUAL
:
7256 case FUNC_VIRTUAL
: {
7257 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7259 VARIANT retval
; /* pointer for storing byref retvals in */
7260 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7261 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7262 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7263 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7264 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7265 UINT vargs_converted
=0;
7270 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7272 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7274 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7275 hres
= DISP_E_PARAMNOTFOUND
;
7280 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7282 ERR("functions with the vararg attribute do not support named arguments\n");
7283 hres
= DISP_E_NONAMEDARGS
;
7287 for (i
= 0; i
< func_desc
->cParams
; i
++)
7289 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7290 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7295 TRACE("changing args\n");
7296 for (i
= 0; i
< func_desc
->cParams
; i
++)
7298 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7299 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7300 VARIANTARG
*src_arg
;
7302 if (wParamFlags
& PARAMFLAG_FLCID
)
7305 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7307 V_I4(arg
) = This
->pTypeLib
->lcid
;
7316 for (j
= 0; j
< cNamedArgs
; j
++)
7317 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7319 src_arg
= &pDispParams
->rgvarg
[j
];
7324 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7326 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7330 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7332 /* under most conditions the caller is not allowed to
7333 * pass in a dispparam arg in the index of what would be
7334 * the retval parameter. however, there is an exception
7335 * where the extra parameter is used in an extra
7336 * IDispatch::Invoke below */
7337 if ((i
< pDispParams
->cArgs
) &&
7338 ((func_desc
->cParams
!= 1) || !pVarResult
||
7339 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7341 hres
= DISP_E_BADPARAMCOUNT
;
7345 /* note: this check is placed so that if the caller passes
7346 * in a VARIANTARG for the retval we just ignore it, like
7348 if (i
== func_desc
->cParams
- 1)
7351 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7352 memset(arg
, 0, sizeof(*arg
));
7353 V_VT(arg
) = rgvt
[i
];
7354 memset(&retval
, 0, sizeof(retval
));
7355 V_BYREF(arg
) = &retval
;
7359 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7360 hres
= E_UNEXPECTED
;
7364 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7365 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7367 TRACE("%s\n", debugstr_variant(src_arg
));
7369 if(rgvt
[i
]!=V_VT(src_arg
))
7371 if (rgvt
[i
] == VT_VARIANT
)
7372 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7373 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7375 if (rgvt
[i
] == V_VT(src_arg
))
7376 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7379 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7380 if (wParamFlags
& PARAMFLAG_FIN
)
7381 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7382 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7384 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7386 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7388 SAFEARRAYBOUND bound
;
7392 bound
.cElements
= pDispParams
->cArgs
-i
;
7393 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7395 ERR("SafeArrayCreate failed\n");
7398 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7401 ERR("SafeArrayAccessData failed with %x\n", hres
);
7402 SafeArrayDestroy(a
);
7405 for (j
= 0; j
< bound
.cElements
; j
++)
7406 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7407 hres
= SafeArrayUnaccessData(a
);
7410 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7411 SafeArrayDestroy(a
);
7414 if (rgvt
[i
] & VT_BYREF
)
7415 V_BYREF(&rgvarg
[i
]) = &a
;
7417 V_ARRAY(&rgvarg
[i
]) = a
;
7418 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7420 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7422 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7423 if (wParamFlags
& PARAMFLAG_FIN
)
7424 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7426 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7427 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7428 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7430 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7432 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7433 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7437 /* FIXME: this doesn't work for VT_BYREF arguments if
7438 * they are not the same type as in the paramdesc */
7439 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7440 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7441 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7446 ERR("failed to convert param %d to %s from %s\n", i
,
7447 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7450 prgpvarg
[i
] = &rgvarg
[i
];
7454 prgpvarg
[i
] = src_arg
;
7457 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7458 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7459 && V_UNKNOWN(prgpvarg
[i
])) {
7460 IUnknown
*userdefined_iface
;
7463 if (tdesc
->vt
== VT_PTR
)
7464 tdesc
= tdesc
->u
.lptdesc
;
7466 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->u
.hreftype
, &guid
);
7470 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7472 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7476 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7477 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7480 else if (wParamFlags
& PARAMFLAG_FOPT
)
7483 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7484 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7486 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7492 VARIANTARG
*missing_arg
;
7493 /* if the function wants a pointer to a variant then
7494 * set that up, otherwise just pass the VT_ERROR in
7495 * the argument by value */
7496 if (rgvt
[i
] & VT_BYREF
)
7498 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7499 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7500 V_VARIANTREF(arg
) = missing_arg
;
7504 V_VT(missing_arg
) = VT_ERROR
;
7505 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7510 hres
= DISP_E_BADPARAMCOUNT
;
7514 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7516 /* VT_VOID is a special case for return types, so it is not
7517 * handled in the general function */
7518 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7519 V_VT(&varresult
) = VT_EMPTY
;
7522 V_VT(&varresult
) = 0;
7523 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7524 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7527 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7528 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7529 prgpvarg
, &varresult
);
7531 vargs_converted
= 0;
7533 for (i
= 0; i
< func_desc
->cParams
; i
++)
7535 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7536 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7538 if (wParamFlags
& PARAMFLAG_FLCID
)
7540 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7542 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7546 VariantInit(pVarResult
);
7547 /* deref return value */
7548 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7551 VARIANT_ClearInd(prgpvarg
[i
]);
7553 else if (vargs_converted
< pDispParams
->cArgs
)
7555 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7556 if (wParamFlags
& PARAMFLAG_FOUT
)
7558 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7560 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7564 ERR("failed to convert param %d to vt %d\n", i
,
7565 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7570 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7571 func_desc
->cParamsOpt
< 0 &&
7572 i
== func_desc
->cParams
-1)
7574 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7577 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7580 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7583 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7586 ERR("SafeArrayAccessData failed with %x\n", hres
);
7589 for (j
= 0; j
<= ubound
; j
++)
7590 VariantClear(&v
[j
]);
7591 hres
= SafeArrayUnaccessData(a
);
7594 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7598 VariantClear(&rgvarg
[i
]);
7601 else if (wParamFlags
& PARAMFLAG_FOPT
)
7603 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7604 VariantClear(&rgvarg
[i
]);
7607 VariantClear(&missing_arg
[i
]);
7610 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7612 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7613 hres
= DISP_E_EXCEPTION
;
7616 IErrorInfo
*pErrorInfo
;
7617 pExcepInfo
->scode
= V_ERROR(&varresult
);
7618 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7620 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7621 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7622 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7623 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7625 IErrorInfo_Release(pErrorInfo
);
7629 if (V_VT(&varresult
) != VT_ERROR
)
7631 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7635 VariantClear(pVarResult
);
7636 *pVarResult
= varresult
;
7639 VariantClear(&varresult
);
7642 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7643 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7644 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7645 (pDispParams
->cArgs
!= 0))
7647 if (V_VT(pVarResult
) == VT_DISPATCH
)
7649 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7650 /* Note: not VariantClear; we still need the dispatch
7651 * pointer to be valid */
7652 VariantInit(pVarResult
);
7653 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7654 GetSystemDefaultLCID(), wFlags
,
7655 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7656 IDispatch_Release(pDispatch
);
7660 VariantClear(pVarResult
);
7661 hres
= DISP_E_NOTACOLLECTION
;
7669 case FUNC_DISPATCH
: {
7672 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7673 if (SUCCEEDED(hres
)) {
7674 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7675 hres
= IDispatch_Invoke(
7676 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7677 pVarResult
,pExcepInfo
,pArgErr
7680 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7681 IDispatch_Release(disp
);
7683 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7687 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7692 TRACE("-- 0x%08x\n", hres
);
7695 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7698 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7699 if(FAILED(hres
)) return hres
;
7701 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7702 dump_VARDESC(var_desc
);
7703 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7707 /* not found, look for it in inherited interfaces */
7708 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7709 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7710 if(This
->impltypes
) {
7711 /* recursive search */
7713 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7714 if(SUCCEEDED(hres
)){
7715 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7716 ITypeInfo_Release(pTInfo
);
7719 WARN("Could not search inherited interface!\n");
7722 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7723 return DISP_E_MEMBERNOTFOUND
;
7726 /* ITypeInfo::GetDocumentation
7728 * Retrieves the documentation string, the complete Help file name and path,
7729 * and the context ID for the Help topic for a specified type description.
7731 * (Can be tested by the Visual Basic Editor in Word for instance.)
7733 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7734 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7735 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7737 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7738 const TLBFuncDesc
*pFDesc
;
7739 const TLBVarDesc
*pVDesc
;
7740 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7741 " HelpContext(%p) HelpFile(%p)\n",
7742 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7743 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7745 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7747 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7749 *pdwHelpContext
=This
->dwHelpContext
;
7751 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7753 }else {/* for a member */
7754 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
7757 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7759 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7761 *pdwHelpContext
=pFDesc
->helpcontext
;
7763 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7766 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
7769 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7771 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7773 *pdwHelpContext
=pVDesc
->HelpContext
;
7775 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7780 if(This
->impltypes
&&
7781 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7782 /* recursive search */
7785 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7786 if(SUCCEEDED(result
)) {
7787 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7788 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7789 ITypeInfo_Release(pTInfo
);
7792 WARN("Could not search inherited interface!\n");
7795 WARN("member %d not found\n", memid
);
7796 return TYPE_E_ELEMENTNOTFOUND
;
7799 /* ITypeInfo::GetDllEntry
7801 * Retrieves a description or specification of an entry point for a function
7804 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7805 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7808 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7809 const TLBFuncDesc
*pFDesc
;
7811 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7813 if (pBstrDllName
) *pBstrDllName
= NULL
;
7814 if (pBstrName
) *pBstrName
= NULL
;
7815 if (pwOrdinal
) *pwOrdinal
= 0;
7817 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7818 return TYPE_E_BADMODULEKIND
;
7820 pFDesc
= TLB_get_funcdesc_by_memberid_invkind(This
, memid
, invKind
);
7821 if (!pFDesc
) return TYPE_E_ELEMENTNOTFOUND
;
7823 dump_TypeInfo(This
);
7824 if (TRACE_ON(ole
)) dump_TLBFuncDescOne(pFDesc
);
7826 if (pBstrDllName
) *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7828 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1))
7830 if (pBstrName
) *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7831 if (pwOrdinal
) *pwOrdinal
= -1;
7835 if (pBstrName
) *pBstrName
= NULL
;
7836 if (pwOrdinal
) *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7841 /* internal function to make the inherited interfaces' methods appear
7842 * part of the interface */
7843 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7844 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7846 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7849 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7851 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7853 ITypeInfo
*pSubTypeInfo
;
7855 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7859 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7861 ITypeInfo_Release(pSubTypeInfo
);
7865 *hRefType
-= DISPATCH_HREF_OFFSET
;
7867 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7868 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7873 struct search_res_tlb_params
7879 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7881 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7882 static const WCHAR formatW
[] = {'\\','%','d',0};
7883 WCHAR szPath
[MAX_PATH
+1];
7884 ITypeLib
*pTLib
= NULL
;
7888 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7891 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7894 if (swprintf(szPath
+ len
, ARRAY_SIZE(szPath
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7897 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7900 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7901 if (IsEqualGUID(params
->guid
, impl
->guid
))
7903 params
->pTLib
= pTLib
;
7904 return FALSE
; /* stop enumeration */
7906 ITypeLib_Release(pTLib
);
7912 /* ITypeInfo::GetRefTypeInfo
7914 * If a type description references other type descriptions, it retrieves
7915 * the referenced type descriptions.
7917 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7920 ITypeInfo
**ppTInfo
)
7922 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7923 ITypeInfo
*type_info
= NULL
;
7924 HRESULT result
= E_FAIL
;
7925 TLBRefType
*ref_type
;
7929 return E_INVALIDARG
;
7931 if ((INT
)hRefType
< 0) {
7932 ITypeInfoImpl
*pTypeInfoImpl
;
7934 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7935 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7936 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7937 return TYPE_E_ELEMENTNOTFOUND
;
7939 /* when we meet a DUAL typeinfo, we must create the alternate
7942 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7944 *pTypeInfoImpl
= *This
;
7945 pTypeInfoImpl
->ref
= 0;
7946 list_init(&pTypeInfoImpl
->custdata_list
);
7948 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7949 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7951 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7953 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7954 /* the AddRef implicitly adds a reference to the parent typelib, which
7955 * stops the copied data from being destroyed until the new typeinfo's
7956 * refcount goes to zero, but we need to signal to the new instance to
7957 * not free its data structures when it is destroyed */
7958 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7959 ITypeInfo_AddRef(*ppTInfo
);
7961 TRACE("got dual interface %p\n", *ppTInfo
);
7965 if ((hRefType
& DISPATCH_HREF_MASK
) && (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7966 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &hRefType
, ppTInfo
);
7968 if(!(hRefType
& 0x1))
7970 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7972 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7975 type_info
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7976 ITypeInfo_AddRef(type_info
);
7984 ITypeLib
*pTLib
= NULL
;
7986 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7988 if(ref_type
->reference
== (hRefType
& (~0x3)))
7991 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7993 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7997 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7999 TRACE("internal reference\n");
8000 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
8002 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
8003 TRACE("typeinfo in imported typelib that is already loaded\n");
8004 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
8005 ITypeLib_AddRef(pTLib
);
8008 /* Search in cached typelibs */
8009 ITypeLibImpl
*entry
;
8011 EnterCriticalSection(&cache_section
);
8012 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
8015 && IsEqualIID(&entry
->guid
->guid
, TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
))
8016 && entry
->ver_major
== ref_type
->pImpTLInfo
->wVersionMajor
8017 && entry
->ver_minor
== ref_type
->pImpTLInfo
->wVersionMinor
8018 && entry
->set_lcid
== ref_type
->pImpTLInfo
->lcid
)
8020 TRACE("got cached %p\n", entry
);
8021 pTLib
= (ITypeLib
*)&entry
->ITypeLib2_iface
;
8022 ITypeLib_AddRef(pTLib
);
8027 LeaveCriticalSection(&cache_section
);
8031 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
8032 struct search_res_tlb_params params
;
8034 TRACE("typeinfo in imported typelib that isn't already loaded\n");
8036 /* Search in resource table */
8037 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
8038 params
.pTLib
= NULL
;
8039 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
8042 pTLib
= params
.pTLib
;
8051 /* Search on disk */
8052 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
8053 ref_type
->pImpTLInfo
->wVersionMajor
,
8054 ref_type
->pImpTLInfo
->wVersionMinor
,
8055 This
->pTypeLib
->syskind
,
8056 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
8058 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
8060 result
= LoadTypeLib(libnam
, &pTLib
);
8061 SysFreeString(libnam
);
8064 if(SUCCEEDED(result
)) {
8065 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
8066 ITypeLib_AddRef(pTLib
);
8070 if(SUCCEEDED(result
)) {
8071 if(ref_type
->index
== TLB_REF_USE_GUID
)
8072 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), &type_info
);
8074 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, &type_info
);
8077 ITypeLib_Release(pTLib
);
8080 WARN("(%p) failed hreftype 0x%04x\n", This
, hRefType
);
8085 if ((hRefType
& 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info
, -2, ppTInfo
)))
8086 ITypeInfo_Release(type_info
);
8087 else *ppTInfo
= type_info
;
8089 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
8090 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
8094 /* ITypeInfo::AddressOfMember
8096 * Retrieves the addresses of static functions or variables, such as those
8099 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
8100 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
8102 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8108 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
8110 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
8114 module
= LoadLibraryW(dll
);
8117 ERR("couldn't load %s\n", debugstr_w(dll
));
8119 SysFreeString(entry
);
8120 return STG_E_FILENOTFOUND
;
8122 /* FIXME: store library somewhere where we can free it */
8127 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
8128 entryA
= heap_alloc(len
);
8129 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
8131 *ppv
= GetProcAddress(module
, entryA
);
8133 ERR("function not found %s\n", debugstr_a(entryA
));
8139 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
8141 ERR("function not found %d\n", ordinal
);
8145 SysFreeString(entry
);
8148 return TYPE_E_DLLFUNCTIONNOTFOUND
;
8153 /* ITypeInfo::CreateInstance
8155 * Creates a new instance of a type that describes a component object class
8158 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
8159 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
8161 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8165 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8171 WARN("Not able to aggregate\n");
8172 return CLASS_E_NOAGGREGATION
;
8175 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8176 if(FAILED(hr
)) return hr
;
8178 if(pTA
->typekind
!= TKIND_COCLASS
)
8180 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8186 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8189 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8190 TRACE("GetActiveObject rets %08x\n", hr
);
8193 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8194 IUnknown_Release(pUnk
);
8199 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8200 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8204 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8208 /* ITypeInfo::GetMops
8210 * Retrieves marshalling information.
8212 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
8215 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8216 FIXME("(%p %d) stub!\n", This
, memid
);
8221 /* ITypeInfo::GetContainingTypeLib
8223 * Retrieves the containing type library and the index of the type description
8224 * within that type library.
8226 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8227 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8229 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8231 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8233 *pIndex
=This
->index
;
8234 TRACE("returning pIndex=%d\n", *pIndex
);
8238 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8239 ITypeLib_AddRef(*ppTLib
);
8240 TRACE("returning ppTLib=%p\n", *ppTLib
);
8246 /* ITypeInfo::ReleaseTypeAttr
8248 * Releases a TYPEATTR previously returned by Get
8251 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8252 TYPEATTR
* pTypeAttr
)
8254 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8255 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8256 heap_free(pTypeAttr
);
8259 /* ITypeInfo::ReleaseFuncDesc
8261 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8263 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8265 FUNCDESC
*pFuncDesc
)
8267 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8270 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8272 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8273 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8274 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8276 SysFreeString((BSTR
)pFuncDesc
);
8279 /* ITypeInfo::ReleaseVarDesc
8281 * Releases a VARDESC previously returned by GetVarDesc.
8283 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8286 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8287 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8289 TLB_FreeVarDesc(pVarDesc
);
8292 /* ITypeInfo2::GetTypeKind
8294 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8297 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8298 TYPEKIND
*pTypeKind
)
8300 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8301 *pTypeKind
= This
->typeattr
.typekind
;
8302 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8306 /* ITypeInfo2::GetTypeFlags
8308 * Returns the type flags without any allocations. This returns a DWORD type
8309 * flag, which expands the type flags without growing the TYPEATTR (type
8313 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8315 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8316 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8317 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
8321 /* ITypeInfo2::GetFuncIndexOfMemId
8322 * Binds to a specific member based on a known DISPID, where the member name
8323 * is not known (for example, when binding to a default member).
8326 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8327 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8329 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8333 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8334 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8335 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8338 if(fdc
< This
->typeattr
.cFuncs
) {
8342 result
= TYPE_E_ELEMENTNOTFOUND
;
8344 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8345 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8349 /* TypeInfo2::GetVarIndexOfMemId
8351 * Binds to a specific member based on a known DISPID, where the member name
8352 * is not known (for example, when binding to a default member).
8355 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8356 MEMBERID memid
, UINT
*pVarIndex
)
8358 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8359 TLBVarDesc
*pVarInfo
;
8361 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8363 pVarInfo
= TLB_get_vardesc_by_memberid(This
, memid
);
8365 return TYPE_E_ELEMENTNOTFOUND
;
8367 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8372 /* ITypeInfo2::GetCustData
8374 * Gets the custom data
8376 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8381 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8382 TLBCustData
*pCData
;
8384 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8386 if(!guid
|| !pVarVal
)
8387 return E_INVALIDARG
;
8389 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8391 VariantInit( pVarVal
);
8393 VariantCopy( pVarVal
, &pCData
->data
);
8395 VariantClear( pVarVal
);
8399 /* ITypeInfo2::GetFuncCustData
8401 * Gets the custom data
8403 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8409 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8410 const TLBFuncDesc
*desc
;
8415 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8417 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &desc
, &hrefoffset
);
8420 WARN("description for function %d not found\n", index
);
8424 VariantInit(pVarVal
);
8425 data
= TLB_get_custdata_by_guid(&desc
->custdata_list
, guid
);
8426 return data
? VariantCopy(pVarVal
, &data
->data
) : S_OK
;
8429 /* ITypeInfo2::GetParamCustData
8431 * Gets the custom data
8433 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8440 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8441 const TLBFuncDesc
*pFDesc
;
8442 TLBCustData
*pCData
;
8446 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8447 debugstr_guid(guid
), pVarVal
);
8449 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8453 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8454 return TYPE_E_ELEMENTNOTFOUND
;
8456 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8458 return TYPE_E_ELEMENTNOTFOUND
;
8460 VariantInit(pVarVal
);
8461 VariantCopy(pVarVal
, &pCData
->data
);
8466 /* ITypeInfo2::GetVarCustData
8468 * Gets the custom data
8470 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8476 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8477 TLBCustData
*pCData
;
8478 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8480 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8482 if(index
>= This
->typeattr
.cVars
)
8483 return TYPE_E_ELEMENTNOTFOUND
;
8485 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8487 return TYPE_E_ELEMENTNOTFOUND
;
8489 VariantInit(pVarVal
);
8490 VariantCopy(pVarVal
, &pCData
->data
);
8495 /* ITypeInfo2::GetImplCustData
8497 * Gets the custom data
8499 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8505 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8506 TLBCustData
*pCData
;
8507 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8509 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8511 if(index
>= This
->typeattr
.cImplTypes
)
8512 return TYPE_E_ELEMENTNOTFOUND
;
8514 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8516 return TYPE_E_ELEMENTNOTFOUND
;
8518 VariantInit(pVarVal
);
8519 VariantCopy(pVarVal
, &pCData
->data
);
8524 /* ITypeInfo2::GetDocumentation2
8526 * Retrieves the documentation string, the complete Help file name and path,
8527 * the localization context to use, and the context ID for the library Help
8528 * topic in the Help file.
8531 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8535 BSTR
*pbstrHelpString
,
8536 DWORD
*pdwHelpStringContext
,
8537 BSTR
*pbstrHelpStringDll
)
8539 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8540 const TLBFuncDesc
*pFDesc
;
8541 const TLBVarDesc
*pVDesc
;
8542 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8543 "HelpStringContext(%p) HelpStringDll(%p)\n",
8544 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8545 pbstrHelpStringDll
);
8546 /* the help string should be obtained from the helpstringdll,
8547 * using the _DLLGetDocumentation function, based on the supplied
8548 * lcid. Nice to do sometime...
8550 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8552 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8553 if(pdwHelpStringContext
)
8554 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8555 if(pbstrHelpStringDll
)
8556 *pbstrHelpStringDll
=
8557 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8559 }else {/* for a member */
8560 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
8563 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8564 if(pdwHelpStringContext
)
8565 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8566 if(pbstrHelpStringDll
)
8567 *pbstrHelpStringDll
=
8568 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8571 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
8574 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8575 if(pdwHelpStringContext
)
8576 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8577 if(pbstrHelpStringDll
)
8578 *pbstrHelpStringDll
=
8579 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8583 return TYPE_E_ELEMENTNOTFOUND
;
8586 /* ITypeInfo2::GetAllCustData
8588 * Gets all custom data items for the Type info.
8591 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8593 CUSTDATA
*pCustData
)
8595 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8597 TRACE("%p %p\n", This
, pCustData
);
8599 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8602 /* ITypeInfo2::GetAllFuncCustData
8604 * Gets all custom data items for the specified Function
8607 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8610 CUSTDATA
*pCustData
)
8612 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8613 const TLBFuncDesc
*pFDesc
;
8617 TRACE("%p %u %p\n", This
, index
, pCustData
);
8619 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &pFDesc
, &hrefoffset
);
8623 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8626 /* ITypeInfo2::GetAllParamCustData
8628 * Gets all custom data items for the Functions
8631 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8632 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8634 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8635 const TLBFuncDesc
*pFDesc
;
8639 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8641 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8645 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8646 return TYPE_E_ELEMENTNOTFOUND
;
8648 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8651 /* ITypeInfo2::GetAllVarCustData
8653 * Gets all custom data items for the specified Variable
8656 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8657 UINT index
, CUSTDATA
*pCustData
)
8659 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8660 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8662 TRACE("%p %u %p\n", This
, index
, pCustData
);
8664 if(index
>= This
->typeattr
.cVars
)
8665 return TYPE_E_ELEMENTNOTFOUND
;
8667 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8670 /* ITypeInfo2::GetAllImplCustData
8672 * Gets all custom data items for the specified implementation type
8675 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8678 CUSTDATA
*pCustData
)
8680 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8681 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8683 TRACE("%p %u %p\n", This
, index
, pCustData
);
8685 if(index
>= This
->typeattr
.cImplTypes
)
8686 return TYPE_E_ELEMENTNOTFOUND
;
8688 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8691 static const ITypeInfo2Vtbl tinfvt
=
8694 ITypeInfo_fnQueryInterface
,
8696 ITypeInfo_fnRelease
,
8698 ITypeInfo_fnGetTypeAttr
,
8699 ITypeInfo_fnGetTypeComp
,
8700 ITypeInfo_fnGetFuncDesc
,
8701 ITypeInfo_fnGetVarDesc
,
8702 ITypeInfo_fnGetNames
,
8703 ITypeInfo_fnGetRefTypeOfImplType
,
8704 ITypeInfo_fnGetImplTypeFlags
,
8705 ITypeInfo_fnGetIDsOfNames
,
8707 ITypeInfo_fnGetDocumentation
,
8708 ITypeInfo_fnGetDllEntry
,
8709 ITypeInfo_fnGetRefTypeInfo
,
8710 ITypeInfo_fnAddressOfMember
,
8711 ITypeInfo_fnCreateInstance
,
8712 ITypeInfo_fnGetMops
,
8713 ITypeInfo_fnGetContainingTypeLib
,
8714 ITypeInfo_fnReleaseTypeAttr
,
8715 ITypeInfo_fnReleaseFuncDesc
,
8716 ITypeInfo_fnReleaseVarDesc
,
8718 ITypeInfo2_fnGetTypeKind
,
8719 ITypeInfo2_fnGetTypeFlags
,
8720 ITypeInfo2_fnGetFuncIndexOfMemId
,
8721 ITypeInfo2_fnGetVarIndexOfMemId
,
8722 ITypeInfo2_fnGetCustData
,
8723 ITypeInfo2_fnGetFuncCustData
,
8724 ITypeInfo2_fnGetParamCustData
,
8725 ITypeInfo2_fnGetVarCustData
,
8726 ITypeInfo2_fnGetImplTypeCustData
,
8727 ITypeInfo2_fnGetDocumentation2
,
8728 ITypeInfo2_fnGetAllCustData
,
8729 ITypeInfo2_fnGetAllFuncCustData
,
8730 ITypeInfo2_fnGetAllParamCustData
,
8731 ITypeInfo2_fnGetAllVarCustData
,
8732 ITypeInfo2_fnGetAllImplTypeCustData
,
8735 /******************************************************************************
8736 * CreateDispTypeInfo [OLEAUT32.31]
8738 * Build type information for an object so it can be called through an
8739 * IDispatch interface.
8742 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8743 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8746 * This call allows an objects methods to be accessed through IDispatch, by
8747 * building an ITypeInfo object that IDispatch can use to call through.
8749 HRESULT WINAPI
CreateDispTypeInfo(
8750 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8751 LCID lcid
, /* [I] Locale Id */
8752 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8754 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8755 ITypeLibImpl
*pTypeLibImpl
;
8756 unsigned int param
, func
;
8757 TLBFuncDesc
*pFuncDesc
;
8761 pTypeLibImpl
= TypeLibImpl_Constructor();
8762 if (!pTypeLibImpl
) return E_FAIL
;
8764 pTypeLibImpl
->TypeInfoCount
= 2;
8765 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8767 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8768 pTIIface
->pTypeLib
= pTypeLibImpl
;
8769 pTIIface
->index
= 0;
8770 pTIIface
->Name
= NULL
;
8771 pTIIface
->dwHelpContext
= -1;
8772 pTIIface
->guid
= NULL
;
8773 pTIIface
->typeattr
.lcid
= lcid
;
8774 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8775 pTIIface
->typeattr
.wMajorVerNum
= 0;
8776 pTIIface
->typeattr
.wMinorVerNum
= 0;
8777 pTIIface
->typeattr
.cbAlignment
= 2;
8778 pTIIface
->typeattr
.cbSizeInstance
= -1;
8779 pTIIface
->typeattr
.cbSizeVft
= -1;
8780 pTIIface
->typeattr
.cFuncs
= 0;
8781 pTIIface
->typeattr
.cImplTypes
= 0;
8782 pTIIface
->typeattr
.cVars
= 0;
8783 pTIIface
->typeattr
.wTypeFlags
= 0;
8784 pTIIface
->hreftype
= 0;
8786 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8787 pFuncDesc
= pTIIface
->funcdescs
;
8788 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8789 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8790 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8791 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8792 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8793 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8794 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8795 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8796 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8797 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8798 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8799 pFuncDesc
->funcdesc
.cScodes
= 0;
8800 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8801 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8802 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8803 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8804 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8805 md
->cArgs
* sizeof(ELEMDESC
));
8806 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8807 for(param
= 0; param
< md
->cArgs
; param
++) {
8808 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8809 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8811 pFuncDesc
->helpcontext
= 0;
8812 pFuncDesc
->HelpStringContext
= 0;
8813 pFuncDesc
->HelpString
= NULL
;
8814 pFuncDesc
->Entry
= NULL
;
8815 list_init(&pFuncDesc
->custdata_list
);
8816 pTIIface
->typeattr
.cFuncs
++;
8820 dump_TypeInfo(pTIIface
);
8822 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8823 pTIClass
->pTypeLib
= pTypeLibImpl
;
8824 pTIClass
->index
= 1;
8825 pTIClass
->Name
= NULL
;
8826 pTIClass
->dwHelpContext
= -1;
8827 pTIClass
->guid
= NULL
;
8828 pTIClass
->typeattr
.lcid
= lcid
;
8829 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8830 pTIClass
->typeattr
.wMajorVerNum
= 0;
8831 pTIClass
->typeattr
.wMinorVerNum
= 0;
8832 pTIClass
->typeattr
.cbAlignment
= 2;
8833 pTIClass
->typeattr
.cbSizeInstance
= -1;
8834 pTIClass
->typeattr
.cbSizeVft
= -1;
8835 pTIClass
->typeattr
.cFuncs
= 0;
8836 pTIClass
->typeattr
.cImplTypes
= 1;
8837 pTIClass
->typeattr
.cVars
= 0;
8838 pTIClass
->typeattr
.wTypeFlags
= 0;
8839 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8841 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8843 ref
= heap_alloc_zero(sizeof(*ref
));
8844 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8845 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8847 dump_TypeInfo(pTIClass
);
8849 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8851 ITypeInfo_AddRef(*pptinfo
);
8852 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8858 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8860 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8862 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8865 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8867 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8869 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8872 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8874 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8876 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8879 static HRESULT WINAPI
ITypeComp_fnBind(
8884 ITypeInfo
** ppTInfo
,
8885 DESCKIND
* pDescKind
,
8888 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8889 const TLBFuncDesc
*pFDesc
;
8890 const TLBVarDesc
*pVDesc
;
8891 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8894 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8896 *pDescKind
= DESCKIND_NONE
;
8897 pBindPtr
->lpfuncdesc
= NULL
;
8900 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8901 pFDesc
= &This
->funcdescs
[fdc
];
8902 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8903 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8906 /* name found, but wrong flags */
8907 hr
= TYPE_E_TYPEMISMATCH
;
8911 if (fdc
< This
->typeattr
.cFuncs
)
8913 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8915 &pBindPtr
->lpfuncdesc
,
8916 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8919 *pDescKind
= DESCKIND_FUNCDESC
;
8920 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8921 ITypeInfo_AddRef(*ppTInfo
);
8924 pVDesc
= TLB_get_vardesc_by_name(This
, szName
);
8926 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8929 *pDescKind
= DESCKIND_VARDESC
;
8930 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8931 ITypeInfo_AddRef(*ppTInfo
);
8936 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8937 /* recursive search */
8941 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8944 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8945 ITypeInfo_Release(pTInfo
);
8949 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8950 ITypeComp_Release(pTComp
);
8951 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8952 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8954 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8955 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8956 SysFreeString((BSTR
)tmp
);
8960 WARN("Could not search inherited interface!\n");
8962 if (hr
== DISP_E_MEMBERNOTFOUND
)
8964 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8968 static HRESULT WINAPI
ITypeComp_fnBindType(
8972 ITypeInfo
** ppTInfo
,
8973 ITypeComp
** ppTComp
)
8975 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8977 /* strange behaviour (does nothing) but like the
8980 if (!ppTInfo
|| !ppTComp
)
8989 static const ITypeCompVtbl tcompvt
=
8992 ITypeComp_fnQueryInterface
,
8994 ITypeComp_fnRelease
,
8997 ITypeComp_fnBindType
9000 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
9001 ICreateTypeLib2
** ppctlib
)
9006 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
9008 if (!szFile
) return E_INVALIDARG
;
9010 This
= TypeLibImpl_Constructor();
9012 return E_OUTOFMEMORY
;
9014 This
->lcid
= GetSystemDefaultLCID();
9015 This
->syskind
= syskind
;
9016 This
->ptr_size
= get_ptr_size(syskind
);
9018 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
9020 ITypeLib2_Release(&This
->ITypeLib2_iface
);
9021 return E_OUTOFMEMORY
;
9023 lstrcpyW(This
->path
, szFile
);
9025 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
9026 ITypeLib2_Release(&This
->ITypeLib2_iface
);
9030 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
9031 REFIID riid
, void **object
)
9033 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9035 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
9038 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
9040 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9042 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
9045 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
9047 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9049 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
9052 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
9053 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
9055 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9056 ITypeInfoImpl
*info
;
9059 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
9061 if (!ctinfo
|| !name
)
9062 return E_INVALIDARG
;
9064 info
= TLB_get_typeinfo_by_name(This
, name
);
9066 return TYPE_E_NAMECONFLICT
;
9068 if (This
->typeinfos
)
9069 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
9070 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
9072 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
9074 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
9076 info
->pTypeLib
= This
;
9077 info
->Name
= TLB_append_str(&This
->name_list
, name
);
9078 info
->index
= This
->TypeInfoCount
;
9079 info
->typeattr
.typekind
= kind
;
9080 info
->typeattr
.cbAlignment
= 4;
9082 switch (info
->typeattr
.typekind
) {
9084 case TKIND_INTERFACE
:
9085 case TKIND_DISPATCH
:
9087 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
9091 info
->typeattr
.cbSizeInstance
= 0;
9094 info
->typeattr
.cbSizeInstance
= 2;
9097 info
->typeattr
.cbSizeInstance
= -0x75;
9100 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
9101 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
9105 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
9106 &IID_ICreateTypeInfo
, (void **)ctinfo
);
9108 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
9112 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
9114 ++This
->TypeInfoCount
;
9119 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
9122 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9124 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
9127 return E_INVALIDARG
;
9129 This
->Name
= TLB_append_str(&This
->name_list
, name
);
9134 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
9135 WORD majorVerNum
, WORD minorVerNum
)
9137 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9139 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
9141 This
->ver_major
= majorVerNum
;
9142 This
->ver_minor
= minorVerNum
;
9147 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
9150 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9152 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9154 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
9159 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
9162 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9164 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9167 return E_INVALIDARG
;
9169 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
9174 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
9175 LPOLESTR helpFileName
)
9177 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9179 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9182 return E_INVALIDARG
;
9184 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9189 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9192 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9194 TRACE("%p %d\n", This
, helpContext
);
9196 This
->dwHelpContext
= helpContext
;
9201 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9204 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9206 TRACE("%p %x\n", This
, lcid
);
9208 This
->set_lcid
= lcid
;
9213 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9216 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9218 TRACE("%p %x\n", This
, libFlags
);
9220 This
->libflags
= libFlags
;
9225 typedef struct tagWMSFT_SegContents
{
9228 } WMSFT_SegContents
;
9230 typedef struct tagWMSFT_TLBFile
{
9232 WMSFT_SegContents typeinfo_seg
;
9233 WMSFT_SegContents impfile_seg
;
9234 WMSFT_SegContents impinfo_seg
;
9235 WMSFT_SegContents ref_seg
;
9236 WMSFT_SegContents guidhash_seg
;
9237 WMSFT_SegContents guid_seg
;
9238 WMSFT_SegContents namehash_seg
;
9239 WMSFT_SegContents name_seg
;
9240 WMSFT_SegContents string_seg
;
9241 WMSFT_SegContents typdesc_seg
;
9242 WMSFT_SegContents arraydesc_seg
;
9243 WMSFT_SegContents custdata_seg
;
9244 WMSFT_SegContents cdguids_seg
;
9246 WMSFT_SegContents aux_seg
;
9249 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9250 WMSFT_TLBFile
*file
)
9256 file
->string_seg
.len
= 0;
9257 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9260 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9262 return E_UNEXPECTED
;
9264 size
+= sizeof(INT16
);
9266 size
= (size
+ 4) & ~0x3;
9270 file
->string_seg
.len
+= size
;
9272 /* temporarily use str->offset to store the length of the aligned,
9273 * converted string */
9277 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9280 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9283 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9284 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9286 heap_free(file
->string_seg
.data
);
9287 return E_UNEXPECTED
;
9290 *((INT16
*)data
) = size
;
9292 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9296 str
->offset
= last_offs
;
9303 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9304 WMSFT_TLBFile
*file
)
9309 MSFT_NameIntro
*last_intro
= NULL
;
9311 file
->header
.nametablecount
= 0;
9312 file
->header
.nametablechars
= 0;
9314 file
->name_seg
.len
= 0;
9315 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9318 size
= lstrlenW(str
->str
);
9319 file
->header
.nametablechars
+= size
;
9320 file
->header
.nametablecount
++;
9322 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9324 return E_UNEXPECTED
;
9326 size
+= sizeof(MSFT_NameIntro
);
9328 size
= (size
+ 4) & ~0x3;
9332 file
->name_seg
.len
+= size
;
9334 /* temporarily use str->offset to store the length of the aligned,
9335 * converted string */
9339 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9340 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9343 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9345 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9347 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9348 data
+ sizeof(MSFT_NameIntro
),
9349 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9351 heap_free(file
->name_seg
.data
);
9352 return E_UNEXPECTED
;
9354 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9356 intro
->hreftype
= -1; /* TODO? */
9357 intro
->namelen
= size
& 0xFF;
9358 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9359 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9360 intro
->namelen
|= hash
<< 16;
9361 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9362 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9364 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9365 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9367 /* update str->offset to actual value to use in other
9368 * compilation functions that require positions within
9369 * the string table */
9373 str
->offset
= last_offs
;
9378 last_intro
->hreftype
= 0; /* last one is 0? */
9383 static inline int hash_guid(GUID
*guid
)
9387 for (i
= 0; i
< 8; i
++)
9388 hash
^= ((const short *)guid
)[i
];
9393 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9396 MSFT_GuidEntry
*entry
;
9398 int hash_key
, *guidhashtab
;
9400 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9401 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9403 entry
= file
->guid_seg
.data
;
9405 guidhashtab
= file
->guidhash_seg
.data
;
9406 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9407 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9408 entry
->hreftype
= guid
->hreftype
;
9410 hash_key
= hash_guid(&guid
->guid
);
9411 entry
->next_hash
= guidhashtab
[hash_key
];
9412 guidhashtab
[hash_key
] = offs
;
9414 guid
->offset
= offs
;
9415 offs
+= sizeof(MSFT_GuidEntry
);
9422 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9425 VARTYPE arg_type
= V_VT(value
);
9428 DWORD ret
= file
->custdata_seg
.len
;
9430 if(arg_type
== VT_INT
)
9432 if(arg_type
== VT_UINT
)
9436 if(V_VT(value
) != arg_type
) {
9437 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9439 ERR("VariantChangeType failed: %08x\n", hres
);
9444 /* Check if default value can be stored in-place */
9449 if(V_UI4(&v
) > 0x3ffffff)
9462 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9465 /* have to allocate space in custdata_seg */
9474 /* Construct the data to be allocated */
9477 if(file
->custdata_seg
.data
){
9478 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9479 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9480 file
->custdata_seg
.len
+= sizeof(int) * 2;
9482 file
->custdata_seg
.len
= sizeof(int) * 2;
9483 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9486 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9487 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9489 /* TODO: Check if the encoded data is already present in custdata_seg */
9495 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9498 if(file
->custdata_seg
.data
){
9499 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9500 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9501 file
->custdata_seg
.len
+= len
;
9503 file
->custdata_seg
.len
= len
;
9504 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9507 *((unsigned short *)data
) = V_VT(value
);
9508 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9509 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9510 if(V_BSTR(&v
)[i
] <= 0x7f)
9511 data
[i
+6] = V_BSTR(&v
)[i
];
9515 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9516 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9519 /* TODO: Check if the encoded data is already present in custdata_seg */
9524 FIXME("Argument type not yet handled\n");
9529 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9531 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9533 DWORD offs
= file
->arraydesc_seg
.len
;
9537 /* TODO: we should check for duplicates, but that's harder because each
9538 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9539 * at the library-level) */
9541 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9542 if(!file
->arraydesc_seg
.data
)
9543 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9545 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9546 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9548 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9549 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9550 for(i
= 0; i
< desc
->cDims
; ++i
){
9551 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9552 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9558 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9564 VARTYPE vt
, subtype
;
9575 vt
= desc
->vt
& VT_TYPEMASK
;
9577 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9579 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9580 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9582 *out_size
+= 2 * sizeof(DWORD
);
9583 }else if(vt
== VT_CARRAY
){
9584 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9585 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9587 }else if(vt
== VT_USERDEFINED
){
9588 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9589 encoded
[1] = desc
->u
.hreftype
;
9590 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9592 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9610 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9613 data
= file
->typdesc_seg
.data
;
9614 while(offs
< file
->typdesc_seg
.len
){
9615 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9617 offs
+= sizeof(encoded
);
9620 file
->typdesc_seg
.len
+= sizeof(encoded
);
9621 if(!file
->typdesc_seg
.data
)
9622 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9624 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9626 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9631 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9633 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9634 DWORD ret
= cdguids_seg
->len
, offs
;
9635 MSFT_CDGuid
*cdguid
;
9638 if(list_empty(custdata_list
))
9641 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9642 if(!cdguids_seg
->data
){
9643 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9645 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9646 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9649 offs
= ret
+ sizeof(MSFT_CDGuid
);
9650 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9651 cdguid
->GuidOffset
= cd
->guid
->offset
;
9652 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9653 cdguid
->next
= offs
;
9654 offs
+= sizeof(MSFT_CDGuid
);
9664 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9665 WMSFT_TLBFile
*file
)
9667 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9668 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9669 MSFT_VarRecord
*varrecord
;
9670 MSFT_FuncRecord
*funcrecord
;
9672 DWORD
*name
, *offsets
, offs
;
9674 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9675 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9677 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9679 /* optional fields */
9680 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9681 if(!list_empty(&desc
->custdata_list
))
9682 recorded_size
+= 7 * sizeof(INT
);
9683 else if(desc
->HelpStringContext
!= 0)
9684 recorded_size
+= 6 * sizeof(INT
);
9686 else if(desc
->Entry
)
9687 recorded_size
+= 3 * sizeof(INT
);
9688 else if(desc
->HelpString
)
9689 recorded_size
+= 2 * sizeof(INT
);
9690 else if(desc
->helpcontext
)
9691 recorded_size
+= sizeof(INT
);
9693 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9695 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9696 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9697 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9702 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9705 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9706 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9708 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9710 /* optional fields */
9711 if(desc
->HelpStringContext
!= 0)
9712 recorded_size
+= 5 * sizeof(INT
);
9713 else if(!list_empty(&desc
->custdata_list
))
9714 recorded_size
+= 4 * sizeof(INT
);
9716 else if(desc
->HelpString
)
9717 recorded_size
+= 2 * sizeof(INT
);
9718 else if(desc
->HelpContext
!= 0)
9719 recorded_size
+= sizeof(INT
);
9721 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9724 if(!recorded_size
&& !extra_size
)
9727 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9729 aux_seg
->len
+= recorded_size
+ extra_size
;
9731 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9734 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9736 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9738 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9740 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9743 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9744 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9745 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9746 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9748 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9749 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9750 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9751 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9754 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9759 * ^has_param_defaults
9760 * ^oEntry_is_intresource
9762 funcrecord
->FKCCIC
=
9763 desc
->funcdesc
.funckind
|
9764 (desc
->funcdesc
.invkind
<< 3) |
9765 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9766 (desc
->funcdesc
.callconv
<< 8);
9768 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9769 funcrecord
->FKCCIC
|= 0x2000;
9771 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9772 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9773 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9774 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9777 if(paramdefault_size
> 0)
9778 funcrecord
->FKCCIC
|= 0x1000;
9780 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9781 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9783 /* optional fields */
9785 if(!list_empty(&desc
->custdata_list
)){
9786 size
+= 7 * sizeof(INT
);
9787 funcrecord
->HelpContext
= desc
->helpcontext
;
9788 if(desc
->HelpString
)
9789 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9791 funcrecord
->oHelpString
= -1;
9793 funcrecord
->oEntry
= -1;
9794 else if(IS_INTRESOURCE(desc
->Entry
))
9795 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9797 funcrecord
->oEntry
= desc
->Entry
->offset
;
9798 funcrecord
->res9
= -1;
9799 funcrecord
->resA
= -1;
9800 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9801 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9802 }else if(desc
->HelpStringContext
!= 0){
9803 size
+= 6 * sizeof(INT
);
9804 funcrecord
->HelpContext
= desc
->helpcontext
;
9805 if(desc
->HelpString
)
9806 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9808 funcrecord
->oHelpString
= -1;
9810 funcrecord
->oEntry
= -1;
9811 else if(IS_INTRESOURCE(desc
->Entry
))
9812 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9814 funcrecord
->oEntry
= desc
->Entry
->offset
;
9815 funcrecord
->res9
= -1;
9816 funcrecord
->resA
= -1;
9817 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9818 }else if(desc
->Entry
){
9819 size
+= 3 * sizeof(INT
);
9820 funcrecord
->HelpContext
= desc
->helpcontext
;
9821 if(desc
->HelpString
)
9822 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9824 funcrecord
->oHelpString
= -1;
9826 funcrecord
->oEntry
= -1;
9827 else if(IS_INTRESOURCE(desc
->Entry
))
9828 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9830 funcrecord
->oEntry
= desc
->Entry
->offset
;
9831 }else if(desc
->HelpString
){
9832 size
+= 2 * sizeof(INT
);
9833 funcrecord
->HelpContext
= desc
->helpcontext
;
9834 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9835 }else if(desc
->helpcontext
){
9836 size
+= sizeof(INT
);
9837 funcrecord
->HelpContext
= desc
->helpcontext
;
9840 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9841 size
+= paramdefault_size
;
9843 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9844 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9846 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9847 if(desc
->pParamDesc
[j
].Name
)
9848 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9851 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9853 if(paramdefault_size
){
9854 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9855 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9856 else if(paramdefault_size
)
9861 size
+= sizeof(MSFT_ParameterInfo
);
9864 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9870 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9873 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9874 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9875 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9876 DWORD size
= 5 * sizeof(INT
);
9878 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9879 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9880 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9881 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9883 if(desc
->vardesc
.varkind
== VAR_CONST
){
9884 varrecord
->vardescsize
+= sizeof(VARIANT
);
9885 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9887 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9890 if(desc
->HelpStringContext
!= 0){
9891 size
+= 5 * sizeof(INT
);
9892 varrecord
->HelpContext
= desc
->HelpContext
;
9893 if(desc
->HelpString
)
9894 varrecord
->HelpString
= desc
->HelpString
->offset
;
9896 varrecord
->HelpString
= -1;
9897 varrecord
->res9
= -1;
9898 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9899 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9900 }else if(!list_empty(&desc
->custdata_list
)){
9901 size
+= 4 * sizeof(INT
);
9902 varrecord
->HelpContext
= desc
->HelpContext
;
9903 if(desc
->HelpString
)
9904 varrecord
->HelpString
= desc
->HelpString
->offset
;
9906 varrecord
->HelpString
= -1;
9907 varrecord
->res9
= -1;
9908 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9909 }else if(desc
->HelpString
){
9910 size
+= 2 * sizeof(INT
);
9911 varrecord
->HelpContext
= desc
->HelpContext
;
9912 if(desc
->HelpString
)
9913 varrecord
->HelpString
= desc
->HelpString
->offset
;
9915 varrecord
->HelpString
= -1;
9916 }else if(desc
->HelpContext
!= 0){
9917 size
+= sizeof(INT
);
9918 varrecord
->HelpContext
= desc
->HelpContext
;
9921 varrecord
->Info
= size
| (i
<< 16);
9927 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9930 memid
= (MEMBERID
*)varrecord
;
9931 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9932 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9933 *memid
= desc
->funcdesc
.memid
;
9936 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9937 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9938 *memid
= desc
->vardesc
.memid
;
9942 name
= (UINT
*)memid
;
9943 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9944 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9946 *name
= desc
->Name
->offset
;
9951 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9952 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9954 *name
= desc
->Name
->offset
;
9963 typedef struct tagWMSFT_RefChunk
{
9970 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9972 DWORD offs
= file
->ref_seg
.len
, i
;
9973 WMSFT_RefChunk
*chunk
;
9975 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9976 if(!file
->ref_seg
.data
)
9977 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9979 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9981 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9983 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9984 chunk
->href
= info
->impltypes
[i
].hRef
;
9985 chunk
->res04
= info
->impltypes
[i
].implflags
;
9987 if(i
< info
->typeattr
.cImplTypes
- 1)
9988 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9997 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
10001 size
= sizeof(MSFT_TypeInfoBase
);
10004 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
10005 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
10006 base
->typekind
= TKIND_DISPATCH
;
10008 base
->typekind
= info
->typeattr
.typekind
;
10009 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
10010 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
10011 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
10016 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
10022 base
->posguid
= info
->guid
->offset
;
10024 base
->posguid
= -1;
10025 base
->flags
= info
->typeattr
.wTypeFlags
;
10027 base
->NameOffset
= info
->Name
->offset
;
10029 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
10030 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
10032 base
->NameOffset
= -1;
10034 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
10035 if(info
->DocString
)
10036 base
->docstringoffs
= info
->DocString
->offset
;
10038 base
->docstringoffs
= -1;
10039 base
->helpstringcontext
= info
->dwHelpStringContext
;
10040 base
->helpcontext
= info
->dwHelpContext
;
10041 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
10042 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
10043 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
10044 base
->size
= info
->typeattr
.cbSizeInstance
;
10045 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
10046 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
10047 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
10048 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
10049 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
10051 base
->datatype1
= info
->DllName
->offset
;
10053 base
->datatype1
= -1;
10055 if(info
->typeattr
.cImplTypes
> 0)
10056 base
->datatype1
= info
->impltypes
[0].hRef
;
10058 base
->datatype1
= -1;
10060 base
->datatype2
= index
; /* FIXME: i think there's more here */
10068 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
10072 file
->typeinfo_seg
.len
= 0;
10073 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10074 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10075 *junk
= file
->typeinfo_seg
.len
;
10077 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
10080 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
10081 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
10083 file
->aux_seg
.len
= 0;
10084 file
->aux_seg
.data
= NULL
;
10086 file
->typeinfo_seg
.len
= 0;
10087 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10088 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10089 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
10090 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
10094 typedef struct tagWMSFT_ImpFile
{
10100 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10103 WMSFT_ImpFile
*impfile
;
10105 DWORD last_offs
= 0;
10107 file
->impfile_seg
.len
= 0;
10108 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10112 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10116 path
= implib
->name
;
10117 size
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
), NULL
, 0, NULL
, NULL
);
10119 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10122 size
+= sizeof(INT16
);
10124 size
= (size
+ 4) & ~0x3;
10128 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
10131 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
10133 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10134 int strlen
= 0, size
;
10136 impfile
= (WMSFT_ImpFile
*)data
;
10137 impfile
->guid_offs
= implib
->guid
->offset
;
10138 impfile
->lcid
= implib
->lcid
;
10139 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
10141 data
+= sizeof(WMSFT_ImpFile
);
10144 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10148 path
= implib
->name
;
10149 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
),
10150 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
10152 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10155 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
10157 size
= strlen
+ sizeof(INT16
);
10159 size
= (size
+ 4) & ~0x3;
10162 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
10165 implib
->offset
= last_offs
;
10166 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
10170 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10172 MSFT_ImpInfo
*info
;
10173 TLBRefType
*ref_type
;
10176 WMSFT_compile_impfile(This
, file
);
10178 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
10179 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
10181 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10182 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10183 if(ref_type
->index
== TLB_REF_USE_GUID
){
10184 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10185 info
->oGuid
= ref_type
->guid
->offset
;
10187 info
->oGuid
= ref_type
->index
;
10188 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10194 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10196 file
->guidhash_seg
.len
= 0x80;
10197 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10198 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10201 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10203 file
->namehash_seg
.len
= 0x200;
10204 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10205 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10208 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10210 if(contents
&& contents
->len
){
10211 segdir
->offset
= *running_offset
;
10212 segdir
->length
= contents
->len
;
10213 *running_offset
+= segdir
->length
;
10215 segdir
->offset
= -1;
10216 segdir
->length
= 0;
10219 /* TODO: do these ever change? */
10220 segdir
->res08
= -1;
10221 segdir
->res0c
= 0xf;
10224 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10228 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10231 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10235 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10237 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10238 base
->memoffset
+= file_len
;
10245 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10247 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10248 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10249 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10250 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10251 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10252 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10253 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10254 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10255 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10256 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10257 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10258 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10259 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10260 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10263 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10265 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10266 WMSFT_TLBFile file
;
10267 DWORD written
, junk_size
, junk_offs
, running_offset
;
10274 TRACE("%p\n", This
);
10276 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10277 if(This
->typeinfos
[i
]->needs_layout
)
10278 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10280 memset(&file
, 0, sizeof(file
));
10282 file
.header
.magic1
= 0x5446534D;
10283 file
.header
.magic2
= 0x00010002;
10284 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10285 file
.header
.lcid2
= This
->set_lcid
;
10286 file
.header
.varflags
= 0x40 | This
->syskind
;
10287 if (This
->HelpFile
)
10288 file
.header
.varflags
|= 0x10;
10289 if (This
->HelpStringDll
)
10290 file
.header
.varflags
|= HELPDLLFLAG
;
10291 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10292 file
.header
.flags
= This
->libflags
;
10293 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10294 file
.header
.helpcontext
= This
->dwHelpContext
;
10295 file
.header
.res44
= 0x20;
10296 file
.header
.res48
= 0x80;
10297 file
.header
.dispatchpos
= This
->dispatch_href
;
10299 WMSFT_compile_namehash(This
, &file
);
10300 /* do name and string compilation to get offsets for other compilations */
10301 hres
= WMSFT_compile_names(This
, &file
);
10303 WMSFT_free_file(&file
);
10307 hres
= WMSFT_compile_strings(This
, &file
);
10309 WMSFT_free_file(&file
);
10313 WMSFT_compile_guidhash(This
, &file
);
10314 hres
= WMSFT_compile_guids(This
, &file
);
10316 WMSFT_free_file(&file
);
10321 file
.header
.helpfile
= This
->HelpFile
->offset
;
10323 file
.header
.helpfile
= -1;
10325 if(This
->DocString
)
10326 file
.header
.helpstring
= This
->DocString
->offset
;
10328 file
.header
.helpstring
= -1;
10330 /* do some more segment compilation */
10331 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10332 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10335 file
.header
.NameOffset
= This
->Name
->offset
;
10337 file
.header
.NameOffset
= -1;
10339 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10342 file
.header
.posguid
= This
->guid
->offset
;
10344 file
.header
.posguid
= -1;
10346 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10347 if(file
.header
.varflags
& HELPDLLFLAG
)
10348 junk_size
+= sizeof(DWORD
);
10350 junk
= heap_alloc_zero(junk_size
);
10351 if(file
.header
.varflags
& HELPDLLFLAG
){
10352 *junk
= This
->HelpStringDll
->offset
;
10361 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10362 WMSFT_compile_impinfo(This
, &file
);
10364 running_offset
= 0;
10366 TRACE("header at: 0x%x\n", running_offset
);
10367 running_offset
+= sizeof(file
.header
);
10369 TRACE("junk at: 0x%x\n", running_offset
);
10370 running_offset
+= junk_size
;
10372 TRACE("segdir at: 0x%x\n", running_offset
);
10373 running_offset
+= sizeof(file
.segdir
);
10375 TRACE("typeinfo at: 0x%x\n", running_offset
);
10376 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10378 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10379 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10381 TRACE("guidtab at: 0x%x\n", running_offset
);
10382 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10384 TRACE("reftab at: 0x%x\n", running_offset
);
10385 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10387 TRACE("impinfo at: 0x%x\n", running_offset
);
10388 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10390 TRACE("impfiles at: 0x%x\n", running_offset
);
10391 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10393 TRACE("namehashtab at: 0x%x\n", running_offset
);
10394 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10396 TRACE("nametab at: 0x%x\n", running_offset
);
10397 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10399 TRACE("stringtab at: 0x%x\n", running_offset
);
10400 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10402 TRACE("typdesc at: 0x%x\n", running_offset
);
10403 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10405 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10406 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10408 TRACE("custdata at: 0x%x\n", running_offset
);
10409 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10411 TRACE("cdguids at: 0x%x\n", running_offset
);
10412 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10414 TRACE("res0e at: 0x%x\n", running_offset
);
10415 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10417 TRACE("res0f at: 0x%x\n", running_offset
);
10418 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10420 TRACE("aux_seg at: 0x%x\n", running_offset
);
10422 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10424 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10425 FILE_ATTRIBUTE_NORMAL
, 0);
10426 if (outfile
== INVALID_HANDLE_VALUE
){
10427 WMSFT_free_file(&file
);
10429 return TYPE_E_IOERROR
;
10432 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10434 WMSFT_free_file(&file
);
10435 CloseHandle(outfile
);
10437 return TYPE_E_IOERROR
;
10440 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10443 WMSFT_free_file(&file
);
10444 CloseHandle(outfile
);
10445 return TYPE_E_IOERROR
;
10448 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10450 WMSFT_free_file(&file
);
10451 CloseHandle(outfile
);
10452 return TYPE_E_IOERROR
;
10455 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10456 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10457 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10458 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10459 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10460 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10461 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10462 WMSFT_write_segment(outfile
, &file
.name_seg
);
10463 WMSFT_write_segment(outfile
, &file
.string_seg
);
10464 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10465 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10466 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10467 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10468 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10470 WMSFT_free_file(&file
);
10472 CloseHandle(outfile
);
10477 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10480 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10481 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10485 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10486 REFGUID guid
, VARIANT
*varVal
)
10488 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10491 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10493 if (!guid
|| !varVal
)
10494 return E_INVALIDARG
;
10496 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10498 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10501 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10502 ULONG helpStringContext
)
10504 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10505 FIXME("%p %u - stub\n", This
, helpStringContext
);
10509 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10512 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10513 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10516 return E_INVALIDARG
;
10518 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10523 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10524 ICreateTypeLib2_fnQueryInterface
,
10525 ICreateTypeLib2_fnAddRef
,
10526 ICreateTypeLib2_fnRelease
,
10527 ICreateTypeLib2_fnCreateTypeInfo
,
10528 ICreateTypeLib2_fnSetName
,
10529 ICreateTypeLib2_fnSetVersion
,
10530 ICreateTypeLib2_fnSetGuid
,
10531 ICreateTypeLib2_fnSetDocString
,
10532 ICreateTypeLib2_fnSetHelpFileName
,
10533 ICreateTypeLib2_fnSetHelpContext
,
10534 ICreateTypeLib2_fnSetLcid
,
10535 ICreateTypeLib2_fnSetLibFlags
,
10536 ICreateTypeLib2_fnSaveAllChanges
,
10537 ICreateTypeLib2_fnDeleteTypeInfo
,
10538 ICreateTypeLib2_fnSetCustData
,
10539 ICreateTypeLib2_fnSetHelpStringContext
,
10540 ICreateTypeLib2_fnSetHelpStringDll
10543 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10544 REFIID riid
, void **object
)
10546 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10548 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10551 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10553 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10555 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10558 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10560 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10562 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10565 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10568 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10570 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10572 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10577 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10580 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10584 TRACE("%p %x\n", This
, typeFlags
);
10586 if (typeFlags
& TYPEFLAG_FDUAL
) {
10587 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10589 ITypeInfo
*dispatch
;
10593 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10597 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10598 ITypeLib_Release(stdole
);
10602 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10603 ITypeInfo_Release(dispatch
);
10608 old_flags
= This
->typeattr
.wTypeFlags
;
10609 This
->typeattr
.wTypeFlags
= typeFlags
;
10611 hres
= ICreateTypeInfo2_LayOut(iface
);
10612 if (FAILED(hres
)) {
10613 This
->typeattr
.wTypeFlags
= old_flags
;
10620 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10623 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10625 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10628 return E_INVALIDARG
;
10630 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10635 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10638 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10640 TRACE("%p %d\n", This
, helpContext
);
10642 This
->dwHelpContext
= helpContext
;
10647 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10648 WORD majorVerNum
, WORD minorVerNum
)
10650 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10652 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10654 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10655 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10660 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10661 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10663 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10665 ITypeLib
*container
;
10666 TLBRefType
*ref_type
;
10668 TYPEATTR
*typeattr
;
10672 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10674 if (!typeInfo
|| !refType
)
10675 return E_INVALIDARG
;
10677 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10681 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10682 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10684 ITypeLib_Release(container
);
10686 *refType
= target
->hreftype
;
10691 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10692 if (FAILED(hres
)) {
10693 ITypeLib_Release(container
);
10697 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10698 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10699 implib
->lcid
== libattr
->lcid
&&
10700 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10701 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10705 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10706 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10708 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10709 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10710 implib
->name
= SysAllocString(our_container
->path
);
10712 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10713 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10715 implib
->name
= NULL
;
10716 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10720 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10721 implib
->lcid
= libattr
->lcid
;
10722 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10723 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10725 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10728 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10729 ITypeLib_Release(container
);
10731 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10736 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10737 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10738 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10739 ref_type
->tkind
== typeattr
->typekind
)
10744 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10745 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10747 ref_type
->tkind
= typeattr
->typekind
;
10748 ref_type
->pImpTLInfo
= implib
;
10749 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10751 ref_type
->index
= TLB_REF_USE_GUID
;
10753 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10755 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10758 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10760 *refType
= ref_type
->reference
| 0x1;
10762 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10763 This
->pTypeLib
->dispatch_href
= *refType
;
10768 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10769 UINT index
, FUNCDESC
*funcDesc
)
10771 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10772 TLBFuncDesc tmp_func_desc
, *func_desc
;
10777 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10779 if (!funcDesc
|| funcDesc
->oVft
& 3)
10780 return E_INVALIDARG
;
10782 switch (This
->typeattr
.typekind
) {
10784 if (funcDesc
->funckind
!= FUNC_STATIC
)
10785 return TYPE_E_BADMODULEKIND
;
10787 case TKIND_DISPATCH
:
10788 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10789 return TYPE_E_BADMODULEKIND
;
10792 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10793 return TYPE_E_BADMODULEKIND
;
10796 if (index
> This
->typeattr
.cFuncs
)
10797 return TYPE_E_ELEMENTNOTFOUND
;
10799 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10800 !funcDesc
->cParams
)
10801 return TYPE_E_INCONSISTENTPROPFUNCS
;
10804 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10805 funcDesc
->oVft
% 8 != 0)
10806 return E_INVALIDARG
;
10809 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10810 TLBFuncDesc_Constructor(&tmp_func_desc
);
10812 tmp_func_desc
.funcdesc
= *funcDesc
;
10814 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10815 tmp_func_desc
.funcdesc
.oVft
|= 1;
10817 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10818 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10819 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10821 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10822 tmp_func_desc
.funcdesc
.cScodes
= 0;
10825 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10826 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10827 buf_size
+= sizeof(ELEMDESC
);
10828 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10830 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10831 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10833 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10834 if (FAILED(hres
)) {
10835 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10836 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10840 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10841 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10842 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10843 if (FAILED(hres
)) {
10844 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10845 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10848 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10849 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10850 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10851 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10852 if (FAILED(hres
)) {
10853 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10854 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10860 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10862 if (This
->funcdescs
) {
10863 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10864 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10866 if (index
< This
->typeattr
.cFuncs
) {
10867 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10868 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10869 func_desc
= This
->funcdescs
+ index
;
10871 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10873 /* move custdata lists to the new memory location */
10874 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10876 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
10879 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10881 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10882 list_init(&func_desc
->custdata_list
);
10884 ++This
->typeattr
.cFuncs
;
10886 This
->needs_layout
= TRUE
;
10891 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10892 UINT index
, HREFTYPE refType
)
10894 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10895 TLBImplType
*impl_type
;
10898 TRACE("%p %u %d\n", This
, index
, refType
);
10900 switch(This
->typeattr
.typekind
){
10901 case TKIND_COCLASS
: {
10903 FIXME("Unhandled index: -1\n");
10907 if(index
!= This
->typeattr
.cImplTypes
)
10908 return TYPE_E_ELEMENTNOTFOUND
;
10912 case TKIND_INTERFACE
:
10913 case TKIND_DISPATCH
:
10914 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10915 return TYPE_E_ELEMENTNOTFOUND
;
10918 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10922 if (This
->impltypes
){
10925 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10926 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10928 if (index
< This
->typeattr
.cImplTypes
) {
10929 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10930 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10931 impl_type
= This
->impltypes
+ index
;
10933 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10935 /* move custdata lists to the new memory location */
10936 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10938 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
10941 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10943 memset(impl_type
, 0, sizeof(TLBImplType
));
10944 TLBImplType_Constructor(impl_type
);
10945 impl_type
->hRef
= refType
;
10947 ++This
->typeattr
.cImplTypes
;
10949 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10950 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10952 hres
= ICreateTypeInfo2_LayOut(iface
);
10959 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10960 UINT index
, INT implTypeFlags
)
10962 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10963 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10965 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10967 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10968 return TYPE_E_BADMODULEKIND
;
10970 if (index
>= This
->typeattr
.cImplTypes
)
10971 return TYPE_E_ELEMENTNOTFOUND
;
10973 impl_type
->implflags
= implTypeFlags
;
10978 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10981 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10983 TRACE("%p %d\n", This
, alignment
);
10985 This
->typeattr
.cbAlignment
= alignment
;
10990 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10993 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10995 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10998 return E_INVALIDARG
;
11000 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
11002 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
11007 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
11008 UINT index
, VARDESC
*varDesc
)
11010 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11011 TLBVarDesc
*var_desc
;
11013 TRACE("%p %u %p\n", This
, index
, varDesc
);
11015 if (This
->vardescs
){
11018 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
11019 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
11021 if (index
< This
->typeattr
.cVars
) {
11022 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
11023 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
11024 var_desc
= This
->vardescs
+ index
;
11026 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
11028 /* move custdata lists to the new memory location */
11029 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
11031 TLB_relink_custdata(&This
->vardescs
[i
].custdata_list
);
11034 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
11036 TLBVarDesc_Constructor(var_desc
);
11037 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
11038 var_desc
->vardesc
= *var_desc
->vardesc_create
;
11040 ++This
->typeattr
.cVars
;
11042 This
->needs_layout
= TRUE
;
11047 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
11048 UINT index
, LPOLESTR
*names
, UINT numNames
)
11050 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11051 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11054 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
11057 return E_INVALIDARG
;
11059 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
11060 return TYPE_E_ELEMENTNOTFOUND
;
11062 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
11063 if(numNames
> func_desc
->funcdesc
.cParams
)
11064 return TYPE_E_ELEMENTNOTFOUND
;
11066 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
11067 return TYPE_E_ELEMENTNOTFOUND
;
11069 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
11070 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
11071 if (iter
->Name
&& !wcscmp(TLB_get_bstr(iter
->Name
), *names
)) {
11072 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11073 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11074 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
11076 return TYPE_E_AMBIGUOUSNAME
;
11080 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
11082 for (i
= 1; i
< numNames
; ++i
) {
11083 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
11084 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
11090 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
11091 UINT index
, LPOLESTR name
)
11093 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11095 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
11098 return E_INVALIDARG
;
11100 if(index
>= This
->typeattr
.cVars
)
11101 return TYPE_E_ELEMENTNOTFOUND
;
11103 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11107 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
11108 TYPEDESC
*tdescAlias
)
11110 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11113 TRACE("%p %p\n", This
, tdescAlias
);
11116 return E_INVALIDARG
;
11118 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
11119 return TYPE_E_BADMODULEKIND
;
11121 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
11125 heap_free(This
->tdescAlias
);
11126 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
11127 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
11132 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
11133 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
11135 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11136 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
11140 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
11141 UINT index
, LPOLESTR docString
)
11143 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11144 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11146 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11149 return E_INVALIDARG
;
11151 if(index
>= This
->typeattr
.cFuncs
)
11152 return TYPE_E_ELEMENTNOTFOUND
;
11154 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11159 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11160 UINT index
, LPOLESTR docString
)
11162 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11163 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11165 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11168 return E_INVALIDARG
;
11170 if(index
>= This
->typeattr
.cVars
)
11171 return TYPE_E_ELEMENTNOTFOUND
;
11173 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11178 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11179 UINT index
, DWORD helpContext
)
11181 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11182 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11184 TRACE("%p %u %d\n", This
, index
, helpContext
);
11186 if(index
>= This
->typeattr
.cFuncs
)
11187 return TYPE_E_ELEMENTNOTFOUND
;
11189 func_desc
->helpcontext
= helpContext
;
11194 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11195 UINT index
, DWORD helpContext
)
11197 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11198 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11200 TRACE("%p %u %d\n", This
, index
, helpContext
);
11202 if(index
>= This
->typeattr
.cVars
)
11203 return TYPE_E_ELEMENTNOTFOUND
;
11205 var_desc
->HelpContext
= helpContext
;
11210 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11211 UINT index
, BSTR bstrMops
)
11213 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11214 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11218 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11221 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11223 TRACE("%p %p\n", This
, idlDesc
);
11226 return E_INVALIDARG
;
11228 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11229 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11234 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11236 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11237 ITypeInfo2
*tinfo
= &This
->ITypeInfo2_iface
;
11238 TLBFuncDesc
*func_desc
;
11239 UINT user_vft
= 0, i
, depth
= 0;
11240 HRESULT hres
= S_OK
;
11242 TRACE("%p\n", This
);
11244 This
->needs_layout
= FALSE
;
11246 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11251 hres
= ITypeInfo2_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11253 if (SUCCEEDED(hres
)) {
11254 hres
= ITypeInfo2_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11256 if (SUCCEEDED(hres
)) {
11257 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11258 if (FAILED(hres
)) {
11259 ITypeInfo_Release(inh
);
11262 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11263 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11267 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11268 if(SUCCEEDED(hres
)){
11270 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11271 if(SUCCEEDED(hres
)){
11272 ITypeInfo_Release(inh
);
11276 }while(SUCCEEDED(hres
));
11279 ITypeInfo_Release(inh
);
11280 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11281 This
->typeattr
.cbSizeVft
= 0;
11285 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11286 This
->typeattr
.cbSizeVft
= 0;
11290 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11291 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11293 This
->typeattr
.cbSizeVft
= 0;
11295 func_desc
= This
->funcdescs
;
11297 while (i
< This
->typeattr
.cFuncs
) {
11298 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11299 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11301 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11302 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11304 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11306 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11309 BOOL reset
= FALSE
;
11311 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11313 iter
= This
->funcdescs
;
11314 while (j
< This
->typeattr
.cFuncs
) {
11315 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11317 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11320 ++func_desc
->funcdesc
.memid
;
11321 iter
= This
->funcdescs
;
11334 if (user_vft
> This
->typeattr
.cbSizeVft
)
11335 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11337 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11338 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11339 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11341 BOOL reset
= FALSE
;
11344 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11346 iter
= This
->vardescs
;
11347 while (j
< This
->typeattr
.cVars
) {
11348 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11350 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11353 ++var_desc
->vardesc
.memid
;
11354 iter
= This
->vardescs
;
11367 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11370 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11371 FIXME("%p %u - stub\n", This
, index
);
11375 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11376 MEMBERID memid
, INVOKEKIND invKind
)
11378 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11379 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11383 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11386 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11387 FIXME("%p %u - stub\n", This
, index
);
11391 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11394 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11395 FIXME("%p %x - stub\n", This
, memid
);
11399 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11402 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11405 TRACE("%p %u\n", This
, index
);
11407 if (index
>= This
->typeattr
.cImplTypes
)
11408 return TYPE_E_ELEMENTNOTFOUND
;
11410 TLB_FreeCustData(&This
->impltypes
[index
].custdata_list
);
11411 --This
->typeattr
.cImplTypes
;
11413 if (index
< This
->typeattr
.cImplTypes
)
11415 memmove(This
->impltypes
+ index
, This
->impltypes
+ index
+ 1, (This
->typeattr
.cImplTypes
- index
) *
11416 sizeof(*This
->impltypes
));
11417 for (i
= index
; i
< This
->typeattr
.cImplTypes
; ++i
)
11418 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
11424 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11425 REFGUID guid
, VARIANT
*varVal
)
11429 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11431 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11433 if (!guid
|| !varVal
)
11434 return E_INVALIDARG
;
11436 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11438 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11441 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11442 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11444 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11445 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11449 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11450 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11452 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11453 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11457 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11458 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11460 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11461 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11465 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11466 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11468 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11469 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11473 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11474 ULONG helpStringContext
)
11476 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11478 TRACE("%p %u\n", This
, helpStringContext
);
11480 This
->dwHelpStringContext
= helpStringContext
;
11485 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11486 UINT index
, ULONG helpStringContext
)
11488 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11489 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11493 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11494 UINT index
, ULONG helpStringContext
)
11496 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11497 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11501 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11503 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11504 FIXME("%p - stub\n", This
);
11508 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11511 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11513 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11516 return E_INVALIDARG
;
11518 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11523 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11524 ICreateTypeInfo2_fnQueryInterface
,
11525 ICreateTypeInfo2_fnAddRef
,
11526 ICreateTypeInfo2_fnRelease
,
11527 ICreateTypeInfo2_fnSetGuid
,
11528 ICreateTypeInfo2_fnSetTypeFlags
,
11529 ICreateTypeInfo2_fnSetDocString
,
11530 ICreateTypeInfo2_fnSetHelpContext
,
11531 ICreateTypeInfo2_fnSetVersion
,
11532 ICreateTypeInfo2_fnAddRefTypeInfo
,
11533 ICreateTypeInfo2_fnAddFuncDesc
,
11534 ICreateTypeInfo2_fnAddImplType
,
11535 ICreateTypeInfo2_fnSetImplTypeFlags
,
11536 ICreateTypeInfo2_fnSetAlignment
,
11537 ICreateTypeInfo2_fnSetSchema
,
11538 ICreateTypeInfo2_fnAddVarDesc
,
11539 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11540 ICreateTypeInfo2_fnSetVarName
,
11541 ICreateTypeInfo2_fnSetTypeDescAlias
,
11542 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11543 ICreateTypeInfo2_fnSetFuncDocString
,
11544 ICreateTypeInfo2_fnSetVarDocString
,
11545 ICreateTypeInfo2_fnSetFuncHelpContext
,
11546 ICreateTypeInfo2_fnSetVarHelpContext
,
11547 ICreateTypeInfo2_fnSetMops
,
11548 ICreateTypeInfo2_fnSetTypeIdldesc
,
11549 ICreateTypeInfo2_fnLayOut
,
11550 ICreateTypeInfo2_fnDeleteFuncDesc
,
11551 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11552 ICreateTypeInfo2_fnDeleteVarDesc
,
11553 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11554 ICreateTypeInfo2_fnDeleteImplType
,
11555 ICreateTypeInfo2_fnSetCustData
,
11556 ICreateTypeInfo2_fnSetFuncCustData
,
11557 ICreateTypeInfo2_fnSetParamCustData
,
11558 ICreateTypeInfo2_fnSetVarCustData
,
11559 ICreateTypeInfo2_fnSetImplTypeCustData
,
11560 ICreateTypeInfo2_fnSetHelpStringContext
,
11561 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11562 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11563 ICreateTypeInfo2_fnInvalidate
,
11564 ICreateTypeInfo2_fnSetName
11567 /******************************************************************************
11568 * ClearCustData (OLEAUT32.171)
11570 * Clear a custom data type's data.
11573 * lpCust [I] The custom data type instance
11578 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11580 if (lpCust
&& lpCust
->cCustData
)
11582 if (lpCust
->prgCustData
)
11586 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11587 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11589 CoTaskMemFree(lpCust
->prgCustData
);
11590 lpCust
->prgCustData
= NULL
;
11592 lpCust
->cCustData
= 0;