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 TLBVarDesc
*TLB_get_vardesc_by_memberid(ITypeInfoImpl
*typeinfo
, MEMBERID memid
)
1708 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1710 if (typeinfo
->vardescs
[i
].vardesc
.memid
== memid
)
1711 return &typeinfo
->vardescs
[i
];
1717 static inline TLBVarDesc
*TLB_get_vardesc_by_name(ITypeInfoImpl
*typeinfo
, const OLECHAR
*name
)
1721 for (i
= 0; i
< typeinfo
->typeattr
.cVars
; ++i
)
1723 if (!lstrcmpiW(TLB_get_bstr(typeinfo
->vardescs
[i
].Name
), name
))
1724 return &typeinfo
->vardescs
[i
];
1730 static inline TLBCustData
*TLB_get_custdata_by_guid(const struct list
*custdata_list
, REFGUID guid
)
1732 TLBCustData
*cust_data
;
1733 LIST_FOR_EACH_ENTRY(cust_data
, custdata_list
, TLBCustData
, entry
)
1734 if(IsEqualIID(TLB_get_guid_null(cust_data
->guid
), guid
))
1739 static inline ITypeInfoImpl
*TLB_get_typeinfo_by_name(ITypeLibImpl
*typelib
, const OLECHAR
*name
)
1743 for (i
= 0; i
< typelib
->TypeInfoCount
; ++i
)
1745 if (!lstrcmpiW(TLB_get_bstr(typelib
->typeinfos
[i
]->Name
), name
))
1746 return typelib
->typeinfos
[i
];
1752 static void TLBVarDesc_Constructor(TLBVarDesc
*var_desc
)
1754 list_init(&var_desc
->custdata_list
);
1757 static TLBVarDesc
*TLBVarDesc_Alloc(UINT n
)
1761 ret
= heap_alloc_zero(sizeof(TLBVarDesc
) * n
);
1766 TLBVarDesc_Constructor(&ret
[n
-1]);
1773 static TLBParDesc
*TLBParDesc_Constructor(UINT n
)
1777 ret
= heap_alloc_zero(sizeof(TLBParDesc
) * n
);
1782 list_init(&ret
[n
-1].custdata_list
);
1789 static void TLBFuncDesc_Constructor(TLBFuncDesc
*func_desc
)
1791 list_init(&func_desc
->custdata_list
);
1794 static TLBFuncDesc
*TLBFuncDesc_Alloc(UINT n
)
1798 ret
= heap_alloc_zero(sizeof(TLBFuncDesc
) * n
);
1803 TLBFuncDesc_Constructor(&ret
[n
-1]);
1810 static void TLBImplType_Constructor(TLBImplType
*impl
)
1812 list_init(&impl
->custdata_list
);
1815 static TLBImplType
*TLBImplType_Alloc(UINT n
)
1819 ret
= heap_alloc_zero(sizeof(TLBImplType
) * n
);
1824 TLBImplType_Constructor(&ret
[n
-1]);
1831 static TLBGuid
*TLB_append_guid(struct list
*guid_list
,
1832 const GUID
*new_guid
, HREFTYPE hreftype
)
1836 LIST_FOR_EACH_ENTRY(guid
, guid_list
, TLBGuid
, entry
) {
1837 if (IsEqualGUID(&guid
->guid
, new_guid
))
1841 guid
= heap_alloc(sizeof(TLBGuid
));
1845 memcpy(&guid
->guid
, new_guid
, sizeof(GUID
));
1846 guid
->hreftype
= hreftype
;
1848 list_add_tail(guid_list
, &guid
->entry
);
1853 static HRESULT
TLB_set_custdata(struct list
*custdata_list
, TLBGuid
*tlbguid
, VARIANT
*var
)
1855 TLBCustData
*cust_data
;
1867 return DISP_E_BADVARTYPE
;
1870 cust_data
= TLB_get_custdata_by_guid(custdata_list
, TLB_get_guid_null(tlbguid
));
1873 cust_data
= heap_alloc(sizeof(TLBCustData
));
1875 return E_OUTOFMEMORY
;
1877 cust_data
->guid
= tlbguid
;
1878 VariantInit(&cust_data
->data
);
1880 list_add_tail(custdata_list
, &cust_data
->entry
);
1882 VariantClear(&cust_data
->data
);
1884 return VariantCopy(&cust_data
->data
, var
);
1887 /* Used to update list pointers after list itself was moved. */
1888 static void TLB_relink_custdata(struct list
*custdata_list
)
1890 if (custdata_list
->prev
== custdata_list
->next
)
1891 list_init(custdata_list
);
1894 custdata_list
->prev
->next
= custdata_list
;
1895 custdata_list
->next
->prev
= custdata_list
;
1899 static TLBString
*TLB_append_str(struct list
*string_list
, BSTR new_str
)
1906 LIST_FOR_EACH_ENTRY(str
, string_list
, TLBString
, entry
) {
1907 if (wcscmp(str
->str
, new_str
) == 0)
1911 str
= heap_alloc(sizeof(TLBString
));
1915 str
->str
= SysAllocString(new_str
);
1921 list_add_tail(string_list
, &str
->entry
);
1926 static HRESULT
TLB_get_size_from_hreftype(ITypeInfoImpl
*info
, HREFTYPE href
,
1927 ULONG
*size
, WORD
*align
)
1933 hr
= ITypeInfo2_GetRefTypeInfo(&info
->ITypeInfo2_iface
, href
, &other
);
1937 hr
= ITypeInfo_GetTypeAttr(other
, &attr
);
1939 ITypeInfo_Release(other
);
1944 *size
= attr
->cbSizeInstance
;
1946 *align
= attr
->cbAlignment
;
1948 ITypeInfo_ReleaseTypeAttr(other
, attr
);
1949 ITypeInfo_Release(other
);
1954 static HRESULT
TLB_size_instance(ITypeInfoImpl
*info
, SYSKIND sys
,
1955 TYPEDESC
*tdesc
, ULONG
*size
, WORD
*align
)
1957 ULONG i
, sub
, ptr_size
;
1960 ptr_size
= get_ptr_size(sys
);
1999 *size
= sizeof(DATE
);
2002 *size
= sizeof(VARIANT
);
2004 if(sys
== SYS_WIN32
)
2005 *size
-= 8; /* 32-bit VARIANT is 8 bytes smaller than 64-bit VARIANT */
2009 *size
= sizeof(DECIMAL
);
2016 for(i
= 0; i
< tdesc
->u
.lpadesc
->cDims
; ++i
)
2017 *size
+= tdesc
->u
.lpadesc
->rgbounds
[i
].cElements
;
2018 hr
= TLB_size_instance(info
, sys
, &tdesc
->u
.lpadesc
->tdescElem
, &sub
, align
);
2023 case VT_USERDEFINED
:
2024 return TLB_get_size_from_hreftype(info
, tdesc
->u
.hreftype
, size
, align
);
2026 FIXME("Unsized VT: 0x%x\n", tdesc
->vt
);
2040 /**********************************************************************
2042 * Functions for reading MSFT typelibs (those created by CreateTypeLib2)
2045 static inline void MSFT_Seek(TLBContext
*pcx
, LONG where
)
2047 if (where
!= DO_NOT_SEEK
)
2049 where
+= pcx
->oStart
;
2050 if (where
> pcx
->length
)
2053 ERR("seek beyond end (%d/%d)\n", where
, pcx
->length
);
2061 static DWORD
MSFT_Read(void *buffer
, DWORD count
, TLBContext
*pcx
, LONG where
)
2063 TRACE_(typelib
)("pos=0x%08x len=0x%08x 0x%08x 0x%08x 0x%08x\n",
2064 pcx
->pos
, count
, pcx
->oStart
, pcx
->length
, where
);
2066 MSFT_Seek(pcx
, where
);
2067 if (pcx
->pos
+ count
> pcx
->length
) count
= pcx
->length
- pcx
->pos
;
2068 memcpy( buffer
, (char *)pcx
->mapping
+ pcx
->pos
, count
);
2073 static DWORD
MSFT_ReadLEDWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2078 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2079 FromLEDWords(buffer
, ret
);
2084 static DWORD
MSFT_ReadLEWords(void *buffer
, DWORD count
, TLBContext
*pcx
,
2089 ret
= MSFT_Read(buffer
, count
, pcx
, where
);
2090 FromLEWords(buffer
, ret
);
2095 static HRESULT
MSFT_ReadAllGuids(TLBContext
*pcx
)
2098 MSFT_GuidEntry entry
;
2101 MSFT_Seek(pcx
, pcx
->pTblDir
->pGuidTab
.offset
);
2103 if (offs
>= pcx
->pTblDir
->pGuidTab
.length
)
2106 MSFT_ReadLEWords(&entry
, sizeof(MSFT_GuidEntry
), pcx
, DO_NOT_SEEK
);
2108 guid
= heap_alloc(sizeof(TLBGuid
));
2110 guid
->offset
= offs
;
2111 guid
->guid
= entry
.guid
;
2112 guid
->hreftype
= entry
.hreftype
;
2114 list_add_tail(&pcx
->pLibInfo
->guid_list
, &guid
->entry
);
2116 offs
+= sizeof(MSFT_GuidEntry
);
2120 static TLBGuid
*MSFT_ReadGuid( int offset
, TLBContext
*pcx
)
2124 LIST_FOR_EACH_ENTRY(ret
, &pcx
->pLibInfo
->guid_list
, TLBGuid
, entry
){
2125 if(ret
->offset
== offset
){
2126 TRACE_(typelib
)("%s\n", debugstr_guid(&ret
->guid
));
2134 static HREFTYPE
MSFT_ReadHreftype( TLBContext
*pcx
, int offset
)
2136 MSFT_NameIntro niName
;
2140 ERR_(typelib
)("bad offset %d\n", offset
);
2144 MSFT_ReadLEDWords(&niName
, sizeof(niName
), pcx
,
2145 pcx
->pTblDir
->pNametab
.offset
+offset
);
2147 return niName
.hreftype
;
2150 static HRESULT
MSFT_ReadAllNames(TLBContext
*pcx
)
2153 MSFT_NameIntro intro
;
2155 int offs
= 0, lengthInChars
;
2157 MSFT_Seek(pcx
, pcx
->pTblDir
->pNametab
.offset
);
2161 if (offs
>= pcx
->pTblDir
->pNametab
.length
)
2164 MSFT_ReadLEWords(&intro
, sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2165 intro
.namelen
&= 0xFF;
2166 len_piece
= intro
.namelen
+ sizeof(MSFT_NameIntro
);
2168 len_piece
= (len_piece
+ 4) & ~0x3;
2172 string
= heap_alloc(len_piece
+ 1);
2173 MSFT_Read(string
, len_piece
- sizeof(MSFT_NameIntro
), pcx
, DO_NOT_SEEK
);
2174 string
[intro
.namelen
] = '\0';
2176 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2177 string
, -1, NULL
, 0);
2178 if (!lengthInChars
) {
2180 return E_UNEXPECTED
;
2183 tlbstr
= heap_alloc(sizeof(TLBString
));
2185 tlbstr
->offset
= offs
;
2186 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2187 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2191 list_add_tail(&pcx
->pLibInfo
->name_list
, &tlbstr
->entry
);
2197 static TLBString
*MSFT_ReadName( TLBContext
*pcx
, int offset
)
2201 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->name_list
, TLBString
, entry
) {
2202 if (tlbstr
->offset
== offset
) {
2203 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2211 static TLBString
*MSFT_ReadString( TLBContext
*pcx
, int offset
)
2215 LIST_FOR_EACH_ENTRY(tlbstr
, &pcx
->pLibInfo
->string_list
, TLBString
, entry
) {
2216 if (tlbstr
->offset
== offset
) {
2217 TRACE_(typelib
)("%s\n", debugstr_w(tlbstr
->str
));
2226 * read a value and fill a VARIANT structure
2228 static void MSFT_ReadValue( VARIANT
* pVar
, int offset
, TLBContext
*pcx
)
2232 TRACE_(typelib
)("\n");
2234 if(offset
<0) { /* data are packed in here */
2235 V_VT(pVar
) = (offset
& 0x7c000000 )>> 26;
2236 V_I4(pVar
) = offset
& 0x3ffffff;
2239 MSFT_ReadLEWords(&(V_VT(pVar
)), sizeof(VARTYPE
), pcx
,
2240 pcx
->pTblDir
->pCustData
.offset
+ offset
);
2241 TRACE_(typelib
)("Vartype = %x\n", V_VT(pVar
));
2242 switch (V_VT(pVar
)){
2243 case VT_EMPTY
: /* FIXME: is this right? */
2244 case VT_NULL
: /* FIXME: is this right? */
2245 case VT_I2
: /* this should not happen */
2256 case VT_VOID
: /* FIXME: is this right? */
2264 case VT_DECIMAL
: /* FIXME: is this right? */
2267 /* pointer types with known behaviour */
2270 MSFT_ReadLEDWords(&size
, sizeof(INT
), pcx
, DO_NOT_SEEK
);
2272 V_BSTR(pVar
) = NULL
;
2274 ptr
= heap_alloc_zero(size
);
2275 MSFT_Read(ptr
, size
, pcx
, DO_NOT_SEEK
);
2276 V_BSTR(pVar
)=SysAllocStringLen(NULL
,size
);
2277 /* FIXME: do we need a AtoW conversion here? */
2278 V_UNION(pVar
, bstrVal
[size
])='\0';
2279 while(size
--) V_UNION(pVar
, bstrVal
[size
])=ptr
[size
];
2284 /* FIXME: this will not work AT ALL when the variant contains a pointer */
2291 case VT_USERDEFINED
:
2297 case VT_STREAMED_OBJECT
:
2298 case VT_STORED_OBJECT
:
2299 case VT_BLOB_OBJECT
:
2304 FIXME("VARTYPE %d is not supported, setting pointer to NULL\n",
2308 if(size
>0) /* (big|small) endian correct? */
2309 MSFT_Read(&(V_I2(pVar
)), size
, pcx
, DO_NOT_SEEK
);
2313 * create a linked list with custom data
2315 static int MSFT_CustData( TLBContext
*pcx
, int offset
, struct list
*custdata_list
)
2321 TRACE_(typelib
)("\n");
2323 if (pcx
->pTblDir
->pCDGuids
.offset
< 0) return 0;
2327 pNew
=heap_alloc_zero(sizeof(TLBCustData
));
2328 MSFT_ReadLEDWords(&entry
, sizeof(entry
), pcx
, pcx
->pTblDir
->pCDGuids
.offset
+offset
);
2329 pNew
->guid
= MSFT_ReadGuid(entry
.GuidOffset
, pcx
);
2330 MSFT_ReadValue(&(pNew
->data
), entry
.DataOffset
, pcx
);
2331 list_add_head(custdata_list
, &pNew
->entry
);
2332 offset
= entry
.next
;
2337 static void MSFT_GetTdesc(TLBContext
*pcx
, INT type
, TYPEDESC
*pTd
)
2340 pTd
->vt
=type
& VT_TYPEMASK
;
2342 *pTd
=pcx
->pLibInfo
->pTypeDesc
[type
/(2*sizeof(INT
))];
2344 TRACE_(typelib
)("vt type = %X\n", pTd
->vt
);
2347 static BOOL
TLB_is_propgetput(INVOKEKIND invkind
)
2349 return (invkind
== INVOKE_PROPERTYGET
||
2350 invkind
== INVOKE_PROPERTYPUT
||
2351 invkind
== INVOKE_PROPERTYPUTREF
);
2355 MSFT_DoFuncs(TLBContext
* pcx
,
2360 TLBFuncDesc
** pptfd
)
2363 * member information is stored in a data structure at offset
2364 * indicated by the memoffset field of the typeinfo structure
2365 * There are several distinctive parts.
2366 * The first part starts with a field that holds the total length
2367 * of this (first) part excluding this field. Then follow the records,
2368 * for each member there is one record.
2370 * The first entry is always the length of the record (including this
2372 * The rest of the record depends on the type of the member. If there is
2373 * a field indicating the member type (function, variable, interface, etc)
2374 * I have not found it yet. At this time we depend on the information
2375 * in the type info and the usual order how things are stored.
2377 * Second follows an array sized nrMEM*sizeof(INT) with a member id
2380 * Third is an equal sized array with file offsets to the name entry
2383 * The fourth and last (?) part is an array with offsets to the records
2384 * in the first part of this file segment.
2387 int infolen
, nameoffset
, reclength
, i
;
2388 int recoffset
= offset
+ sizeof(INT
);
2390 char *recbuf
= heap_alloc(0xffff);
2391 MSFT_FuncRecord
*pFuncRec
= (MSFT_FuncRecord
*)recbuf
;
2392 TLBFuncDesc
*ptfd_prev
= NULL
, *ptfd
;
2394 TRACE_(typelib
)("\n");
2396 MSFT_ReadLEDWords(&infolen
, sizeof(INT
), pcx
, offset
);
2398 *pptfd
= TLBFuncDesc_Alloc(cFuncs
);
2400 for ( i
= 0; i
< cFuncs
; i
++ )
2404 /* name, eventually add to a hash table */
2405 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2406 offset
+ infolen
+ (cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2408 /* read the function information record */
2409 MSFT_ReadLEDWords(&reclength
, sizeof(pFuncRec
->Info
), pcx
, recoffset
);
2411 reclength
&= 0xffff;
2413 MSFT_ReadLEDWords(&pFuncRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_FuncRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2415 /* size without argument data */
2416 optional
= reclength
- pFuncRec
->nrargs
*sizeof(MSFT_ParameterInfo
);
2417 if (pFuncRec
->FKCCIC
& 0x1000)
2418 optional
-= pFuncRec
->nrargs
* sizeof(INT
);
2420 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpContext
))
2421 ptfd
->helpcontext
= pFuncRec
->HelpContext
;
2423 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oHelpString
))
2424 ptfd
->HelpString
= MSFT_ReadString(pcx
, pFuncRec
->oHelpString
);
2426 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oEntry
))
2428 if (pFuncRec
->FKCCIC
& 0x2000 )
2430 if (!IS_INTRESOURCE(pFuncRec
->oEntry
))
2431 ERR("ordinal 0x%08x invalid, IS_INTRESOURCE is false\n", pFuncRec
->oEntry
);
2432 ptfd
->Entry
= (TLBString
*)(DWORD_PTR
)LOWORD(pFuncRec
->oEntry
);
2435 ptfd
->Entry
= MSFT_ReadString(pcx
, pFuncRec
->oEntry
);
2438 ptfd
->Entry
= (TLBString
*)-1;
2440 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, HelpStringContext
))
2441 ptfd
->HelpStringContext
= pFuncRec
->HelpStringContext
;
2443 if (optional
> FIELD_OFFSET(MSFT_FuncRecord
, oCustData
) && pFuncRec
->FKCCIC
& 0x80)
2444 MSFT_CustData(pcx
, pFuncRec
->oCustData
, &ptfd
->custdata_list
);
2446 /* fill the FuncDesc Structure */
2447 MSFT_ReadLEDWords( & ptfd
->funcdesc
.memid
, sizeof(INT
), pcx
,
2448 offset
+ infolen
+ ( i
+ 1) * sizeof(INT
));
2450 ptfd
->funcdesc
.funckind
= (pFuncRec
->FKCCIC
) & 0x7;
2451 ptfd
->funcdesc
.invkind
= (pFuncRec
->FKCCIC
) >> 3 & 0xF;
2452 ptfd
->funcdesc
.callconv
= (pFuncRec
->FKCCIC
) >> 8 & 0xF;
2453 ptfd
->funcdesc
.cParams
= pFuncRec
->nrargs
;
2454 ptfd
->funcdesc
.cParamsOpt
= pFuncRec
->nroargs
;
2455 ptfd
->funcdesc
.oVft
= (pFuncRec
->VtableOffset
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
2456 ptfd
->funcdesc
.wFuncFlags
= LOWORD(pFuncRec
->Flags
) ;
2458 /* nameoffset is sometimes -1 on the second half of a propget/propput
2459 * pair of functions */
2460 if ((nameoffset
== -1) && (i
> 0) &&
2461 TLB_is_propgetput(ptfd_prev
->funcdesc
.invkind
) &&
2462 TLB_is_propgetput(ptfd
->funcdesc
.invkind
))
2463 ptfd
->Name
= ptfd_prev
->Name
;
2465 ptfd
->Name
= MSFT_ReadName(pcx
, nameoffset
);
2469 &ptfd
->funcdesc
.elemdescFunc
.tdesc
);
2471 /* do the parameters/arguments */
2472 if(pFuncRec
->nrargs
)
2475 MSFT_ParameterInfo paraminfo
;
2477 ptfd
->funcdesc
.lprgelemdescParam
=
2478 heap_alloc_zero(pFuncRec
->nrargs
* (sizeof(ELEMDESC
) + sizeof(PARAMDESCEX
)));
2480 ptfd
->pParamDesc
= TLBParDesc_Constructor(pFuncRec
->nrargs
);
2482 MSFT_ReadLEDWords(¶minfo
, sizeof(paraminfo
), pcx
,
2483 recoffset
+ reclength
- pFuncRec
->nrargs
* sizeof(MSFT_ParameterInfo
));
2485 for ( j
= 0 ; j
< pFuncRec
->nrargs
; j
++ )
2487 ELEMDESC
*elemdesc
= &ptfd
->funcdesc
.lprgelemdescParam
[j
];
2493 elemdesc
->u
.paramdesc
.wParamFlags
= paraminfo
.Flags
;
2496 if (paraminfo
.oName
!= -1)
2497 ptfd
->pParamDesc
[j
].Name
=
2498 MSFT_ReadName( pcx
, paraminfo
.oName
);
2499 TRACE_(typelib
)("param[%d] = %s\n", j
, debugstr_w(TLB_get_bstr(ptfd
->pParamDesc
[j
].Name
)));
2502 if ( (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
) &&
2503 (pFuncRec
->FKCCIC
& 0x1000) )
2505 INT
* pInt
= (INT
*)((char *)pFuncRec
+
2507 (pFuncRec
->nrargs
* 4) * sizeof(INT
) );
2509 PARAMDESC
* pParamDesc
= &elemdesc
->u
.paramdesc
;
2511 pParamDesc
->pparamdescex
= (PARAMDESCEX
*)(ptfd
->funcdesc
.lprgelemdescParam
+pFuncRec
->nrargs
)+j
;
2512 pParamDesc
->pparamdescex
->cBytes
= sizeof(PARAMDESCEX
);
2514 MSFT_ReadValue(&(pParamDesc
->pparamdescex
->varDefaultValue
),
2518 elemdesc
->u
.paramdesc
.pparamdescex
= NULL
;
2521 if (optional
> (FIELD_OFFSET(MSFT_FuncRecord
, oArgCustData
) +
2522 j
*sizeof(pFuncRec
->oArgCustData
[0])) &&
2523 pFuncRec
->FKCCIC
& 0x80 )
2526 pFuncRec
->oArgCustData
[j
],
2527 &ptfd
->pParamDesc
[j
].custdata_list
);
2530 /* SEEK value = jump to offset,
2531 * from there jump to the end of record,
2532 * go back by (j-1) arguments
2534 MSFT_ReadLEDWords( ¶minfo
,
2535 sizeof(MSFT_ParameterInfo
), pcx
,
2536 recoffset
+ reclength
- ((pFuncRec
->nrargs
- j
- 1)
2537 * sizeof(MSFT_ParameterInfo
)));
2541 /* scode is not used: archaic win16 stuff FIXME: right? */
2542 ptfd
->funcdesc
.cScodes
= 0 ;
2543 ptfd
->funcdesc
.lprgscode
= NULL
;
2547 recoffset
+= reclength
;
2552 static void MSFT_DoVars(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int cFuncs
,
2553 int cVars
, int offset
, TLBVarDesc
** pptvd
)
2555 int infolen
, nameoffset
, reclength
;
2557 MSFT_VarRecord
*pVarRec
= (MSFT_VarRecord
*)recbuf
;
2562 TRACE_(typelib
)("\n");
2564 ptvd
= *pptvd
= TLBVarDesc_Alloc(cVars
);
2565 MSFT_ReadLEDWords(&infolen
,sizeof(INT
), pcx
, offset
);
2566 MSFT_ReadLEDWords(&recoffset
,sizeof(INT
), pcx
, offset
+ infolen
+
2567 ((cFuncs
+cVars
)*2+cFuncs
+ 1)*sizeof(INT
));
2568 recoffset
+= offset
+sizeof(INT
);
2569 for(i
=0;i
<cVars
;i
++, ++ptvd
){
2570 /* name, eventually add to a hash table */
2571 MSFT_ReadLEDWords(&nameoffset
, sizeof(INT
), pcx
,
2572 offset
+ infolen
+ (2*cFuncs
+ cVars
+ i
+ 1) * sizeof(INT
));
2573 ptvd
->Name
=MSFT_ReadName(pcx
, nameoffset
);
2574 /* read the variable information record */
2575 MSFT_ReadLEDWords(&reclength
, sizeof(pVarRec
->Info
), pcx
, recoffset
);
2577 MSFT_ReadLEDWords(&pVarRec
->DataType
, reclength
- FIELD_OFFSET(MSFT_VarRecord
, DataType
), pcx
, DO_NOT_SEEK
);
2580 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpContext
))
2581 ptvd
->HelpContext
= pVarRec
->HelpContext
;
2583 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpString
))
2584 ptvd
->HelpString
= MSFT_ReadString(pcx
, pVarRec
->HelpString
);
2586 if(reclength
> FIELD_OFFSET(MSFT_VarRecord
, HelpStringContext
))
2587 ptvd
->HelpStringContext
= pVarRec
->HelpStringContext
;
2589 /* fill the VarDesc Structure */
2590 MSFT_ReadLEDWords(&ptvd
->vardesc
.memid
, sizeof(INT
), pcx
,
2591 offset
+ infolen
+ (cFuncs
+ i
+ 1) * sizeof(INT
));
2592 ptvd
->vardesc
.varkind
= pVarRec
->VarKind
;
2593 ptvd
->vardesc
.wVarFlags
= pVarRec
->Flags
;
2594 MSFT_GetTdesc(pcx
, pVarRec
->DataType
,
2595 &ptvd
->vardesc
.elemdescVar
.tdesc
);
2596 /* ptvd->vardesc.lpstrSchema; is reserved (SDK) FIXME?? */
2597 if(pVarRec
->VarKind
== VAR_CONST
){
2598 ptvd
->vardesc
.u
.lpvarValue
= heap_alloc_zero(sizeof(VARIANT
));
2599 MSFT_ReadValue(ptvd
->vardesc
.u
.lpvarValue
,
2600 pVarRec
->OffsValue
, pcx
);
2602 ptvd
->vardesc
.u
.oInst
=pVarRec
->OffsValue
;
2603 recoffset
+= reclength
;
2607 /* process Implemented Interfaces of a com class */
2608 static void MSFT_DoImplTypes(TLBContext
*pcx
, ITypeInfoImpl
*pTI
, int count
,
2612 MSFT_RefRecord refrec
;
2615 TRACE_(typelib
)("\n");
2617 pTI
->impltypes
= TLBImplType_Alloc(count
);
2618 pImpl
= pTI
->impltypes
;
2619 for(i
=0;i
<count
;i
++){
2620 if(offset
<0) break; /* paranoia */
2621 MSFT_ReadLEDWords(&refrec
,sizeof(refrec
),pcx
,offset
+pcx
->pTblDir
->pRefTab
.offset
);
2622 pImpl
->hRef
= refrec
.reftype
;
2623 pImpl
->implflags
=refrec
.flags
;
2624 MSFT_CustData(pcx
, refrec
.oCustData
, &pImpl
->custdata_list
);
2625 offset
=refrec
.onext
;
2631 /* when a 32-bit typelib is loaded in 64-bit mode, we need to resize pointers
2632 * and some structures, and fix the alignment */
2633 static void TLB_fix_32on64_typeinfo(ITypeInfoImpl
*info
)
2635 if(info
->typeattr
.typekind
== TKIND_ALIAS
){
2636 switch(info
->tdescAlias
->vt
){
2644 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2645 info
->typeattr
.cbAlignment
= sizeof(void*);
2648 case VT_USERDEFINED
:
2649 TLB_size_instance(info
, SYS_WIN64
, info
->tdescAlias
, &info
->typeattr
.cbSizeInstance
, &info
->typeattr
.cbAlignment
);
2652 info
->typeattr
.cbSizeInstance
= sizeof(VARIANT
);
2653 info
->typeattr
.cbAlignment
= 8;
2655 if(info
->typeattr
.cbSizeInstance
< sizeof(void*))
2656 info
->typeattr
.cbAlignment
= info
->typeattr
.cbSizeInstance
;
2658 info
->typeattr
.cbAlignment
= sizeof(void*);
2661 }else if(info
->typeattr
.typekind
== TKIND_INTERFACE
||
2662 info
->typeattr
.typekind
== TKIND_DISPATCH
||
2663 info
->typeattr
.typekind
== TKIND_COCLASS
){
2664 info
->typeattr
.cbSizeInstance
= sizeof(void*);
2665 info
->typeattr
.cbAlignment
= sizeof(void*);
2671 * process a typeinfo record
2673 static ITypeInfoImpl
* MSFT_DoTypeInfo(
2676 ITypeLibImpl
* pLibInfo
)
2678 MSFT_TypeInfoBase tiBase
;
2679 ITypeInfoImpl
*ptiRet
;
2681 TRACE_(typelib
)("count=%u\n", count
);
2683 ptiRet
= ITypeInfoImpl_Constructor();
2684 MSFT_ReadLEDWords(&tiBase
, sizeof(tiBase
) ,pcx
,
2685 pcx
->pTblDir
->pTypeInfoTab
.offset
+count
*sizeof(tiBase
));
2687 /* this is where we are coming from */
2688 ptiRet
->pTypeLib
= pLibInfo
;
2689 ptiRet
->index
=count
;
2691 ptiRet
->guid
= MSFT_ReadGuid(tiBase
.posguid
, pcx
);
2692 ptiRet
->typeattr
.lcid
= pLibInfo
->set_lcid
; /* FIXME: correct? */
2693 ptiRet
->typeattr
.lpstrSchema
= NULL
; /* reserved */
2694 ptiRet
->typeattr
.cbSizeInstance
= tiBase
.size
;
2695 ptiRet
->typeattr
.typekind
= tiBase
.typekind
& 0xF;
2696 ptiRet
->typeattr
.cFuncs
= LOWORD(tiBase
.cElement
);
2697 ptiRet
->typeattr
.cVars
= HIWORD(tiBase
.cElement
);
2698 ptiRet
->typeattr
.cbAlignment
= (tiBase
.typekind
>> 11 )& 0x1F; /* there are more flags there */
2699 ptiRet
->typeattr
.wTypeFlags
= tiBase
.flags
;
2700 ptiRet
->typeattr
.wMajorVerNum
= LOWORD(tiBase
.version
);
2701 ptiRet
->typeattr
.wMinorVerNum
= HIWORD(tiBase
.version
);
2702 ptiRet
->typeattr
.cImplTypes
= tiBase
.cImplTypes
;
2703 ptiRet
->typeattr
.cbSizeVft
= tiBase
.cbSizeVft
;
2704 if (ptiRet
->typeattr
.typekind
== TKIND_ALIAS
) {
2706 MSFT_GetTdesc(pcx
, tiBase
.datatype1
, &tmp
);
2707 ptiRet
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(&tmp
, TRUE
));
2708 TLB_CopyTypeDesc(NULL
, &tmp
, ptiRet
->tdescAlias
);
2712 /* IDLDESC idldescType; *//* never saw this one != zero */
2714 /* name, eventually add to a hash table */
2715 ptiRet
->Name
=MSFT_ReadName(pcx
, tiBase
.NameOffset
);
2716 ptiRet
->hreftype
= MSFT_ReadHreftype(pcx
, tiBase
.NameOffset
);
2717 TRACE_(typelib
)("reading %s\n", debugstr_w(TLB_get_bstr(ptiRet
->Name
)));
2719 ptiRet
->DocString
=MSFT_ReadString(pcx
, tiBase
.docstringoffs
);
2720 ptiRet
->dwHelpStringContext
=tiBase
.helpstringcontext
;
2721 ptiRet
->dwHelpContext
=tiBase
.helpcontext
;
2723 if (ptiRet
->typeattr
.typekind
== TKIND_MODULE
)
2724 ptiRet
->DllName
= MSFT_ReadString(pcx
, tiBase
.datatype1
);
2726 /* note: InfoType's Help file and HelpStringDll come from the containing
2727 * library. Further HelpString and Docstring appear to be the same thing :(
2730 if(ptiRet
->typeattr
.cFuncs
>0 )
2731 MSFT_DoFuncs(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2732 ptiRet
->typeattr
.cVars
,
2733 tiBase
.memoffset
, &ptiRet
->funcdescs
);
2735 if(ptiRet
->typeattr
.cVars
>0 )
2736 MSFT_DoVars(pcx
, ptiRet
, ptiRet
->typeattr
.cFuncs
,
2737 ptiRet
->typeattr
.cVars
,
2738 tiBase
.memoffset
, &ptiRet
->vardescs
);
2739 if(ptiRet
->typeattr
.cImplTypes
>0 ) {
2740 switch(ptiRet
->typeattr
.typekind
)
2743 MSFT_DoImplTypes(pcx
, ptiRet
, ptiRet
->typeattr
.cImplTypes
,
2746 case TKIND_DISPATCH
:
2747 /* This is not -1 when the interface is a non-base dual interface or
2748 when a dispinterface wraps an interface, i.e., the idl 'dispinterface x {interface y;};'.
2749 Note however that GetRefTypeOfImplType(0) always returns a ref to IDispatch and
2753 if (tiBase
.datatype1
!= -1)
2755 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2756 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2760 ptiRet
->impltypes
= TLBImplType_Alloc(1);
2761 ptiRet
->impltypes
[0].hRef
= tiBase
.datatype1
;
2765 MSFT_CustData(pcx
, tiBase
.oCustData
, ptiRet
->pcustdata_list
);
2767 TRACE_(typelib
)("%s guid: %s kind:%s\n",
2768 debugstr_w(TLB_get_bstr(ptiRet
->Name
)),
2769 debugstr_guid(TLB_get_guidref(ptiRet
->guid
)),
2770 typekind_desc
[ptiRet
->typeattr
.typekind
]);
2771 if (TRACE_ON(typelib
))
2772 dump_TypeInfo(ptiRet
);
2777 static HRESULT
MSFT_ReadAllStrings(TLBContext
*pcx
)
2780 INT16 len_str
, len_piece
;
2781 int offs
= 0, lengthInChars
;
2783 MSFT_Seek(pcx
, pcx
->pTblDir
->pStringtab
.offset
);
2787 if (offs
>= pcx
->pTblDir
->pStringtab
.length
)
2790 MSFT_ReadLEWords(&len_str
, sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2791 len_piece
= len_str
+ sizeof(INT16
);
2793 len_piece
= (len_piece
+ 4) & ~0x3;
2797 string
= heap_alloc(len_piece
+ 1);
2798 MSFT_Read(string
, len_piece
- sizeof(INT16
), pcx
, DO_NOT_SEEK
);
2799 string
[len_str
] = '\0';
2801 lengthInChars
= MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
| MB_ERR_INVALID_CHARS
,
2802 string
, -1, NULL
, 0);
2803 if (!lengthInChars
) {
2805 return E_UNEXPECTED
;
2808 tlbstr
= heap_alloc(sizeof(TLBString
));
2810 tlbstr
->offset
= offs
;
2811 tlbstr
->str
= SysAllocStringByteLen(NULL
, lengthInChars
* sizeof(WCHAR
));
2812 MultiByteToWideChar(CP_ACP
, MB_PRECOMPOSED
, string
, -1, tlbstr
->str
, lengthInChars
);
2816 list_add_tail(&pcx
->pLibInfo
->string_list
, &tlbstr
->entry
);
2822 static HRESULT
MSFT_ReadAllRefs(TLBContext
*pcx
)
2827 MSFT_Seek(pcx
, pcx
->pTblDir
->pImpInfo
.offset
);
2828 while (offs
< pcx
->pTblDir
->pImpInfo
.length
) {
2829 MSFT_ImpInfo impinfo
;
2832 MSFT_ReadLEDWords(&impinfo
, sizeof(impinfo
), pcx
, DO_NOT_SEEK
);
2834 ref
= heap_alloc_zero(sizeof(TLBRefType
));
2835 list_add_tail(&pcx
->pLibInfo
->ref_list
, &ref
->entry
);
2837 LIST_FOR_EACH_ENTRY(pImpLib
, &pcx
->pLibInfo
->implib_list
, TLBImpLib
, entry
)
2838 if(pImpLib
->offset
==impinfo
.oImpFile
)
2841 if(&pImpLib
->entry
!= &pcx
->pLibInfo
->implib_list
){
2842 ref
->reference
= offs
;
2843 ref
->pImpTLInfo
= pImpLib
;
2844 if(impinfo
.flags
& MSFT_IMPINFO_OFFSET_IS_GUID
) {
2845 ref
->guid
= MSFT_ReadGuid(impinfo
.oGuid
, pcx
);
2846 TRACE("importing by guid %s\n", debugstr_guid(TLB_get_guidref(ref
->guid
)));
2847 ref
->index
= TLB_REF_USE_GUID
;
2849 ref
->index
= impinfo
.oGuid
;
2851 ERR("Cannot find a reference\n");
2852 ref
->reference
= -1;
2853 ref
->pImpTLInfo
= TLB_REF_NOT_FOUND
;
2856 offs
+= sizeof(impinfo
);
2862 /* Because type library parsing has some degree of overhead, and some apps repeatedly load the same
2863 * typelibs over and over, we cache them here. According to MSDN Microsoft have a similar scheme in
2864 * place. This will cause a deliberate memory leak, but generally losing RAM for cycles is an acceptable
2867 static struct list tlb_cache
= LIST_INIT(tlb_cache
);
2868 static CRITICAL_SECTION cache_section
;
2869 static CRITICAL_SECTION_DEBUG cache_section_debug
=
2871 0, 0, &cache_section
,
2872 { &cache_section_debug
.ProcessLocksList
, &cache_section_debug
.ProcessLocksList
},
2873 0, 0, { (DWORD_PTR
)(__FILE__
": typelib loader cache") }
2875 static CRITICAL_SECTION cache_section
= { &cache_section_debug
, -1, 0, 0, 0, 0 };
2878 typedef struct TLB_PEFile
2880 IUnknown IUnknown_iface
;
2883 HRSRC typelib_resource
;
2884 HGLOBAL typelib_global
;
2885 LPVOID typelib_base
;
2888 static inline TLB_PEFile
*pefile_impl_from_IUnknown(IUnknown
*iface
)
2890 return CONTAINING_RECORD(iface
, TLB_PEFile
, IUnknown_iface
);
2893 static HRESULT WINAPI
TLB_PEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2895 if (IsEqualIID(riid
, &IID_IUnknown
))
2898 IUnknown_AddRef(iface
);
2902 return E_NOINTERFACE
;
2905 static ULONG WINAPI
TLB_PEFile_AddRef(IUnknown
*iface
)
2907 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2908 return InterlockedIncrement(&This
->refs
);
2911 static ULONG WINAPI
TLB_PEFile_Release(IUnknown
*iface
)
2913 TLB_PEFile
*This
= pefile_impl_from_IUnknown(iface
);
2914 ULONG refs
= InterlockedDecrement(&This
->refs
);
2917 if (This
->typelib_global
)
2918 FreeResource(This
->typelib_global
);
2920 FreeLibrary(This
->dll
);
2926 static const IUnknownVtbl TLB_PEFile_Vtable
=
2928 TLB_PEFile_QueryInterface
,
2933 static HRESULT
TLB_PEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
2936 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
2938 This
= heap_alloc(sizeof(TLB_PEFile
));
2940 return E_OUTOFMEMORY
;
2942 This
->IUnknown_iface
.lpVtbl
= &TLB_PEFile_Vtable
;
2945 This
->typelib_resource
= NULL
;
2946 This
->typelib_global
= NULL
;
2947 This
->typelib_base
= NULL
;
2949 This
->dll
= LoadLibraryExW(path
, 0, DONT_RESOLVE_DLL_REFERENCES
|
2950 LOAD_LIBRARY_AS_DATAFILE
| LOAD_WITH_ALTERED_SEARCH_PATH
);
2954 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
2955 This
->typelib_resource
= FindResourceW(This
->dll
, MAKEINTRESOURCEW(index
), TYPELIBW
);
2956 if (This
->typelib_resource
)
2958 This
->typelib_global
= LoadResource(This
->dll
, This
->typelib_resource
);
2959 if (This
->typelib_global
)
2961 This
->typelib_base
= LockResource(This
->typelib_global
);
2963 if (This
->typelib_base
)
2965 *pdwTLBLength
= SizeofResource(This
->dll
, This
->typelib_resource
);
2966 *ppBase
= This
->typelib_base
;
2967 *ppFile
= &This
->IUnknown_iface
;
2973 TRACE("No TYPELIB resource found\n");
2977 TLB_PEFile_Release(&This
->IUnknown_iface
);
2981 typedef struct TLB_NEFile
2983 IUnknown IUnknown_iface
;
2985 LPVOID typelib_base
;
2988 static inline TLB_NEFile
*nefile_impl_from_IUnknown(IUnknown
*iface
)
2990 return CONTAINING_RECORD(iface
, TLB_NEFile
, IUnknown_iface
);
2993 static HRESULT WINAPI
TLB_NEFile_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
2995 if (IsEqualIID(riid
, &IID_IUnknown
))
2998 IUnknown_AddRef(iface
);
3002 return E_NOINTERFACE
;
3005 static ULONG WINAPI
TLB_NEFile_AddRef(IUnknown
*iface
)
3007 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3008 return InterlockedIncrement(&This
->refs
);
3011 static ULONG WINAPI
TLB_NEFile_Release(IUnknown
*iface
)
3013 TLB_NEFile
*This
= nefile_impl_from_IUnknown(iface
);
3014 ULONG refs
= InterlockedDecrement(&This
->refs
);
3017 heap_free(This
->typelib_base
);
3023 static const IUnknownVtbl TLB_NEFile_Vtable
=
3025 TLB_NEFile_QueryInterface
,
3030 /***********************************************************************
3031 * read_xx_header [internal]
3033 static int read_xx_header( HFILE lzfd
)
3035 IMAGE_DOS_HEADER mzh
;
3038 LZSeek( lzfd
, 0, SEEK_SET
);
3039 if ( sizeof(mzh
) != LZRead( lzfd
, (LPSTR
)&mzh
, sizeof(mzh
) ) )
3041 if ( mzh
.e_magic
!= IMAGE_DOS_SIGNATURE
)
3044 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3045 if ( 2 != LZRead( lzfd
, magic
, 2 ) )
3048 LZSeek( lzfd
, mzh
.e_lfanew
, SEEK_SET
);
3050 if ( magic
[0] == 'N' && magic
[1] == 'E' )
3051 return IMAGE_OS2_SIGNATURE
;
3052 if ( magic
[0] == 'P' && magic
[1] == 'E' )
3053 return IMAGE_NT_SIGNATURE
;
3056 WARN("Can't handle %s files.\n", magic
);
3061 /***********************************************************************
3062 * find_ne_resource [internal]
3064 static BOOL
find_ne_resource( HFILE lzfd
, LPCSTR
typeid, LPCSTR resid
,
3065 DWORD
*resLen
, DWORD
*resOff
)
3067 IMAGE_OS2_HEADER nehd
;
3068 NE_TYPEINFO
*typeInfo
;
3069 NE_NAMEINFO
*nameInfo
;
3075 /* Read in NE header */
3076 nehdoffset
= LZSeek( lzfd
, 0, SEEK_CUR
);
3077 if ( sizeof(nehd
) != LZRead( lzfd
, (LPSTR
)&nehd
, sizeof(nehd
) ) ) return FALSE
;
3079 resTabSize
= nehd
.ne_restab
- nehd
.ne_rsrctab
;
3082 TRACE("No resources in NE dll\n" );
3086 /* Read in resource table */
3087 resTab
= heap_alloc( resTabSize
);
3088 if ( !resTab
) return FALSE
;
3090 LZSeek( lzfd
, nehd
.ne_rsrctab
+ nehdoffset
, SEEK_SET
);
3091 if ( resTabSize
!= LZRead( lzfd
, (char*)resTab
, resTabSize
) )
3093 heap_free( resTab
);
3098 typeInfo
= (NE_TYPEINFO
*)(resTab
+ 2);
3100 if (!IS_INTRESOURCE(typeid)) /* named type */
3102 BYTE len
= strlen( typeid );
3103 while (typeInfo
->type_id
)
3105 if (!(typeInfo
->type_id
& 0x8000))
3107 BYTE
*p
= resTab
+ typeInfo
->type_id
;
3108 if ((*p
== len
) && !_strnicmp( (char*)p
+1, typeid, len
)) goto found_type
;
3110 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3111 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3114 else /* numeric type id */
3116 WORD id
= LOWORD(typeid) | 0x8000;
3117 while (typeInfo
->type_id
)
3119 if (typeInfo
->type_id
== id
) goto found_type
;
3120 typeInfo
= (NE_TYPEINFO
*)((char *)(typeInfo
+ 1) +
3121 typeInfo
->count
* sizeof(NE_NAMEINFO
));
3124 TRACE("No typeid entry found for %p\n", typeid );
3125 heap_free( resTab
);
3129 nameInfo
= (NE_NAMEINFO
*)(typeInfo
+ 1);
3131 if (!IS_INTRESOURCE(resid
)) /* named resource */
3133 BYTE len
= strlen( resid
);
3134 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3136 BYTE
*p
= resTab
+ nameInfo
->id
;
3137 if (nameInfo
->id
& 0x8000) continue;
3138 if ((*p
== len
) && !_strnicmp( (char*)p
+1, resid
, len
)) goto found_name
;
3141 else /* numeric resource id */
3143 WORD id
= LOWORD(resid
) | 0x8000;
3144 for (count
= typeInfo
->count
; count
> 0; count
--, nameInfo
++)
3145 if (nameInfo
->id
== id
) goto found_name
;
3147 TRACE("No resid entry found for %p\n", typeid );
3148 heap_free( resTab
);
3152 /* Return resource data */
3153 if ( resLen
) *resLen
= nameInfo
->length
<< *(WORD
*)resTab
;
3154 if ( resOff
) *resOff
= nameInfo
->offset
<< *(WORD
*)resTab
;
3156 heap_free( resTab
);
3160 static HRESULT
TLB_NEFile_Open(LPCWSTR path
, INT index
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
){
3164 HRESULT hr
= TYPE_E_CANTLOADLIBRARY
;
3167 This
= heap_alloc(sizeof(TLB_NEFile
));
3168 if (!This
) return E_OUTOFMEMORY
;
3170 This
->IUnknown_iface
.lpVtbl
= &TLB_NEFile_Vtable
;
3172 This
->typelib_base
= NULL
;
3174 lzfd
= LZOpenFileW( (LPWSTR
)path
, &ofs
, OF_READ
);
3175 if ( lzfd
>= 0 && read_xx_header( lzfd
) == IMAGE_OS2_SIGNATURE
)
3177 DWORD reslen
, offset
;
3178 if( find_ne_resource( lzfd
, "TYPELIB", MAKEINTRESOURCEA(index
), &reslen
, &offset
) )
3180 This
->typelib_base
= heap_alloc(reslen
);
3181 if( !This
->typelib_base
)
3185 LZSeek( lzfd
, offset
, SEEK_SET
);
3186 reslen
= LZRead( lzfd
, This
->typelib_base
, reslen
);
3188 *ppBase
= This
->typelib_base
;
3189 *pdwTLBLength
= reslen
;
3190 *ppFile
= &This
->IUnknown_iface
;
3196 if( lzfd
>= 0) LZClose( lzfd
);
3197 TLB_NEFile_Release(&This
->IUnknown_iface
);
3201 typedef struct TLB_Mapping
3203 IUnknown IUnknown_iface
;
3207 LPVOID typelib_base
;
3210 static inline TLB_Mapping
*mapping_impl_from_IUnknown(IUnknown
*iface
)
3212 return CONTAINING_RECORD(iface
, TLB_Mapping
, IUnknown_iface
);
3215 static HRESULT WINAPI
TLB_Mapping_QueryInterface(IUnknown
*iface
, REFIID riid
, void **ppv
)
3217 if (IsEqualIID(riid
, &IID_IUnknown
))
3220 IUnknown_AddRef(iface
);
3224 return E_NOINTERFACE
;
3227 static ULONG WINAPI
TLB_Mapping_AddRef(IUnknown
*iface
)
3229 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3230 return InterlockedIncrement(&This
->refs
);
3233 static ULONG WINAPI
TLB_Mapping_Release(IUnknown
*iface
)
3235 TLB_Mapping
*This
= mapping_impl_from_IUnknown(iface
);
3236 ULONG refs
= InterlockedDecrement(&This
->refs
);
3239 if (This
->typelib_base
)
3240 UnmapViewOfFile(This
->typelib_base
);
3242 CloseHandle(This
->mapping
);
3243 if (This
->file
!= INVALID_HANDLE_VALUE
)
3244 CloseHandle(This
->file
);
3250 static const IUnknownVtbl TLB_Mapping_Vtable
=
3252 TLB_Mapping_QueryInterface
,
3257 static HRESULT
TLB_Mapping_Open(LPCWSTR path
, LPVOID
*ppBase
, DWORD
*pdwTLBLength
, IUnknown
**ppFile
)
3261 This
= heap_alloc(sizeof(TLB_Mapping
));
3263 return E_OUTOFMEMORY
;
3265 This
->IUnknown_iface
.lpVtbl
= &TLB_Mapping_Vtable
;
3267 This
->file
= INVALID_HANDLE_VALUE
;
3268 This
->mapping
= NULL
;
3269 This
->typelib_base
= NULL
;
3271 This
->file
= CreateFileW(path
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, 0);
3272 if (INVALID_HANDLE_VALUE
!= This
->file
)
3274 This
->mapping
= CreateFileMappingW(This
->file
, NULL
, PAGE_READONLY
| SEC_COMMIT
, 0, 0, NULL
);
3277 This
->typelib_base
= MapViewOfFile(This
->mapping
, FILE_MAP_READ
, 0, 0, 0);
3278 if(This
->typelib_base
)
3280 /* retrieve file size */
3281 *pdwTLBLength
= GetFileSize(This
->file
, NULL
);
3282 *ppBase
= This
->typelib_base
;
3283 *ppFile
= &This
->IUnknown_iface
;
3289 IUnknown_Release(&This
->IUnknown_iface
);
3290 return TYPE_E_CANTLOADLIBRARY
;
3293 /****************************************************************************
3296 * find the type of the typelib file and map the typelib resource into
3300 #define SLTG_SIGNATURE 0x47544c53 /* "SLTG" */
3301 static HRESULT
TLB_ReadTypeLib(LPCWSTR pszFileName
, LPWSTR pszPath
, UINT cchPath
, ITypeLib2
**ppTypeLib
)
3303 ITypeLibImpl
*entry
;
3306 LPWSTR index_str
, file
= (LPWSTR
)pszFileName
;
3307 LPVOID pBase
= NULL
;
3308 DWORD dwTLBLength
= 0;
3309 IUnknown
*pFile
= NULL
;
3314 index_str
= wcsrchr(pszFileName
, '\\');
3315 if(index_str
&& *++index_str
!= '\0')
3318 LONG idx
= wcstol(index_str
, &end_ptr
, 10);
3319 if(*end_ptr
== '\0')
3321 int str_len
= index_str
- pszFileName
- 1;
3323 file
= heap_alloc((str_len
+ 1) * sizeof(WCHAR
));
3324 memcpy(file
, pszFileName
, str_len
* sizeof(WCHAR
));
3329 if(!SearchPathW(NULL
, file
, NULL
, cchPath
, pszPath
, NULL
))
3331 if(wcschr(file
, '\\'))
3333 lstrcpyW(pszPath
, file
);
3337 int len
= GetSystemDirectoryW(pszPath
, cchPath
);
3338 pszPath
[len
] = '\\';
3339 memcpy(pszPath
+ len
+ 1, file
, (lstrlenW(file
) + 1) * sizeof(WCHAR
));
3343 if(file
!= pszFileName
) heap_free(file
);
3345 h
= CreateFileW(pszPath
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3346 if(h
!= INVALID_HANDLE_VALUE
){
3347 GetFinalPathNameByHandleW(h
, pszPath
, cchPath
, FILE_NAME_NORMALIZED
| VOLUME_NAME_DOS
);
3351 TRACE_(typelib
)("File %s index %d\n", debugstr_w(pszPath
), index
);
3353 /* We look the path up in the typelib cache. If found, we just addref it, and return the pointer. */
3354 EnterCriticalSection(&cache_section
);
3355 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
3357 if (!wcsicmp(entry
->path
, pszPath
) && entry
->index
== index
)
3359 TRACE("cache hit\n");
3360 *ppTypeLib
= &entry
->ITypeLib2_iface
;
3361 ITypeLib2_AddRef(*ppTypeLib
);
3362 LeaveCriticalSection(&cache_section
);
3366 LeaveCriticalSection(&cache_section
);
3368 /* now actually load and parse the typelib */
3370 ret
= TLB_PEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3371 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3372 ret
= TLB_NEFile_Open(pszPath
, index
, &pBase
, &dwTLBLength
, &pFile
);
3373 if (ret
== TYPE_E_CANTLOADLIBRARY
)
3374 ret
= TLB_Mapping_Open(pszPath
, &pBase
, &dwTLBLength
, &pFile
);
3377 if (dwTLBLength
>= 4)
3379 DWORD dwSignature
= FromLEDWord(*((DWORD
*) pBase
));
3380 if (dwSignature
== MSFT_SIGNATURE
)
3381 *ppTypeLib
= ITypeLib2_Constructor_MSFT(pBase
, dwTLBLength
);
3382 else if (dwSignature
== SLTG_SIGNATURE
)
3383 *ppTypeLib
= ITypeLib2_Constructor_SLTG(pBase
, dwTLBLength
);
3386 FIXME("Header type magic 0x%08x not supported.\n",dwSignature
);
3387 ret
= TYPE_E_CANTLOADLIBRARY
;
3391 ret
= TYPE_E_CANTLOADLIBRARY
;
3392 IUnknown_Release(pFile
);
3396 ITypeLibImpl
*impl
= impl_from_ITypeLib2(*ppTypeLib
);
3398 TRACE("adding to cache\n");
3399 impl
->path
= heap_alloc((lstrlenW(pszPath
)+1) * sizeof(WCHAR
));
3400 lstrcpyW(impl
->path
, pszPath
);
3401 /* We should really canonicalise the path here. */
3402 impl
->index
= index
;
3404 /* FIXME: check if it has added already in the meantime */
3405 EnterCriticalSection(&cache_section
);
3406 list_add_head(&tlb_cache
, &impl
->entry
);
3407 LeaveCriticalSection(&cache_section
);
3413 ERR("Loading of typelib %s failed with error %d\n", debugstr_w(pszFileName
), GetLastError());
3415 ret
= TYPE_E_CANTLOADLIBRARY
;
3422 /*================== ITypeLib(2) Methods ===================================*/
3424 static ITypeLibImpl
* TypeLibImpl_Constructor(void)
3426 ITypeLibImpl
* pTypeLibImpl
;
3428 pTypeLibImpl
= heap_alloc_zero(sizeof(ITypeLibImpl
));
3429 if (!pTypeLibImpl
) return NULL
;
3431 pTypeLibImpl
->ITypeLib2_iface
.lpVtbl
= &tlbvt
;
3432 pTypeLibImpl
->ITypeComp_iface
.lpVtbl
= &tlbtcvt
;
3433 pTypeLibImpl
->ICreateTypeLib2_iface
.lpVtbl
= &CreateTypeLib2Vtbl
;
3434 pTypeLibImpl
->ref
= 1;
3436 list_init(&pTypeLibImpl
->implib_list
);
3437 list_init(&pTypeLibImpl
->custdata_list
);
3438 list_init(&pTypeLibImpl
->name_list
);
3439 list_init(&pTypeLibImpl
->string_list
);
3440 list_init(&pTypeLibImpl
->guid_list
);
3441 list_init(&pTypeLibImpl
->ref_list
);
3442 pTypeLibImpl
->dispatch_href
= -1;
3444 return pTypeLibImpl
;
3447 /****************************************************************************
3448 * ITypeLib2_Constructor_MSFT
3450 * loading an MSFT typelib from an in-memory image
3452 static ITypeLib2
* ITypeLib2_Constructor_MSFT(LPVOID pLib
, DWORD dwTLBLength
)
3456 MSFT_Header tlbHeader
;
3457 MSFT_SegDir tlbSegDir
;
3458 ITypeLibImpl
* pTypeLibImpl
;
3461 TRACE("%p, TLB length = %d\n", pLib
, dwTLBLength
);
3463 pTypeLibImpl
= TypeLibImpl_Constructor();
3464 if (!pTypeLibImpl
) return NULL
;
3466 /* get pointer to beginning of typelib data */
3470 cx
.pLibInfo
= pTypeLibImpl
;
3471 cx
.length
= dwTLBLength
;
3474 MSFT_ReadLEDWords(&tlbHeader
, sizeof(tlbHeader
), &cx
, 0);
3475 TRACE_(typelib
)("header:\n");
3476 TRACE_(typelib
)("\tmagic1=0x%08x ,magic2=0x%08x\n",tlbHeader
.magic1
,tlbHeader
.magic2
);
3477 if (tlbHeader
.magic1
!= MSFT_SIGNATURE
) {
3478 FIXME("Header type magic 0x%08x not supported.\n",tlbHeader
.magic1
);
3481 TRACE_(typelib
)("\tdispatchpos = 0x%x\n", tlbHeader
.dispatchpos
);
3483 /* there is a small amount of information here until the next important
3485 * the segment directory . Try to calculate the amount of data */
3486 lPSegDir
= sizeof(tlbHeader
) + (tlbHeader
.nrtypeinfos
)*4 + ((tlbHeader
.varflags
& HELPDLLFLAG
)? 4 :0);
3488 /* now read the segment directory */
3489 TRACE("read segment directory (at %d)\n",lPSegDir
);
3490 MSFT_ReadLEDWords(&tlbSegDir
, sizeof(tlbSegDir
), &cx
, lPSegDir
);
3491 cx
.pTblDir
= &tlbSegDir
;
3493 /* just check two entries */
3494 if ( tlbSegDir
.pTypeInfoTab
.res0c
!= 0x0F || tlbSegDir
.pImpInfo
.res0c
!= 0x0F)
3496 ERR("cannot find the table directory, ptr=0x%x\n",lPSegDir
);
3497 heap_free(pTypeLibImpl
);
3501 MSFT_ReadAllNames(&cx
);
3502 MSFT_ReadAllStrings(&cx
);
3503 MSFT_ReadAllGuids(&cx
);
3505 /* now fill our internal data */
3506 /* TLIBATTR fields */
3507 pTypeLibImpl
->guid
= MSFT_ReadGuid(tlbHeader
.posguid
, &cx
);
3509 pTypeLibImpl
->syskind
= tlbHeader
.varflags
& 0x0f; /* check the mask */
3510 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3511 pTypeLibImpl
->ver_major
= LOWORD(tlbHeader
.version
);
3512 pTypeLibImpl
->ver_minor
= HIWORD(tlbHeader
.version
);
3513 pTypeLibImpl
->libflags
= ((WORD
) tlbHeader
.flags
& 0xffff) /* check mask */ | LIBFLAG_FHASDISKIMAGE
;
3515 pTypeLibImpl
->set_lcid
= tlbHeader
.lcid2
;
3516 pTypeLibImpl
->lcid
= tlbHeader
.lcid
;
3518 /* name, eventually add to a hash table */
3519 pTypeLibImpl
->Name
= MSFT_ReadName(&cx
, tlbHeader
.NameOffset
);
3522 pTypeLibImpl
->DocString
= MSFT_ReadString(&cx
, tlbHeader
.helpstring
);
3523 pTypeLibImpl
->HelpFile
= MSFT_ReadString(&cx
, tlbHeader
.helpfile
);
3525 if( tlbHeader
.varflags
& HELPDLLFLAG
)
3528 MSFT_ReadLEDWords(&offset
, sizeof(offset
), &cx
, sizeof(tlbHeader
));
3529 pTypeLibImpl
->HelpStringDll
= MSFT_ReadString(&cx
, offset
);
3532 pTypeLibImpl
->dwHelpContext
= tlbHeader
.helpstringcontext
;
3535 if(tlbHeader
.CustomDataOffset
>= 0)
3537 MSFT_CustData(&cx
, tlbHeader
.CustomDataOffset
, &pTypeLibImpl
->custdata_list
);
3540 /* fill in type descriptions */
3541 if(tlbSegDir
.pTypdescTab
.length
> 0)
3543 int i
, j
, cTD
= tlbSegDir
.pTypdescTab
.length
/ (2*sizeof(INT
));
3545 pTypeLibImpl
->ctTypeDesc
= cTD
;
3546 pTypeLibImpl
->pTypeDesc
= heap_alloc_zero( cTD
* sizeof(TYPEDESC
));
3547 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pTypdescTab
.offset
);
3550 /* FIXME: add several sanity checks here */
3551 pTypeLibImpl
->pTypeDesc
[i
].vt
= td
[0] & VT_TYPEMASK
;
3552 if(td
[0] == VT_PTR
|| td
[0] == VT_SAFEARRAY
)
3554 /* FIXME: check safearray */
3556 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &std_typedesc
[td
[2]];
3558 pTypeLibImpl
->pTypeDesc
[i
].u
.lptdesc
= &pTypeLibImpl
->pTypeDesc
[td
[2]/8];
3560 else if(td
[0] == VT_CARRAY
)
3562 /* array descr table here */
3563 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= (void *)(INT_PTR
)td
[2]; /* temp store offset in*/
3565 else if(td
[0] == VT_USERDEFINED
)
3567 pTypeLibImpl
->pTypeDesc
[i
].u
.hreftype
= MAKELONG(td
[2],td
[3]);
3569 if(++i
<cTD
) MSFT_ReadLEWords(td
, sizeof(td
), &cx
, DO_NOT_SEEK
);
3572 /* second time around to fill the array subscript info */
3575 if(pTypeLibImpl
->pTypeDesc
[i
].vt
!= VT_CARRAY
) continue;
3576 if(tlbSegDir
.pArrayDescriptions
.offset
>0)
3578 MSFT_ReadLEWords(td
, sizeof(td
), &cx
, tlbSegDir
.pArrayDescriptions
.offset
+ (INT_PTR
)pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
);
3579 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
)+sizeof(SAFEARRAYBOUND
)*(td
[3]-1));
3582 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
.vt
= td
[0] & VT_TYPEMASK
;
3584 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->tdescElem
= cx
.pLibInfo
->pTypeDesc
[td
[0]/(2*sizeof(INT
))];
3586 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->cDims
= td
[2];
3588 for(j
= 0; j
<td
[2]; j
++)
3590 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].cElements
,
3591 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3592 MSFT_ReadLEDWords(& pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
->rgbounds
[j
].lLbound
,
3593 sizeof(INT
), &cx
, DO_NOT_SEEK
);
3598 pTypeLibImpl
->pTypeDesc
[i
].u
.lpadesc
= NULL
;
3599 ERR("didn't find array description data\n");
3604 /* imported type libs */
3605 if(tlbSegDir
.pImpFiles
.offset
>0)
3608 int oGuid
, offset
= tlbSegDir
.pImpFiles
.offset
;
3611 while(offset
< tlbSegDir
.pImpFiles
.offset
+tlbSegDir
.pImpFiles
.length
)
3615 pImpLib
= heap_alloc_zero(sizeof(TLBImpLib
));
3616 pImpLib
->offset
= offset
- tlbSegDir
.pImpFiles
.offset
;
3617 MSFT_ReadLEDWords(&oGuid
, sizeof(INT
), &cx
, offset
);
3619 MSFT_ReadLEDWords(&pImpLib
->lcid
, sizeof(LCID
), &cx
, DO_NOT_SEEK
);
3620 MSFT_ReadLEWords(&pImpLib
->wVersionMajor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3621 MSFT_ReadLEWords(&pImpLib
->wVersionMinor
, sizeof(WORD
), &cx
, DO_NOT_SEEK
);
3622 MSFT_ReadLEWords(& size
, sizeof(UINT16
), &cx
, DO_NOT_SEEK
);
3625 name
= heap_alloc_zero(size
+1);
3626 MSFT_Read(name
, size
, &cx
, DO_NOT_SEEK
);
3627 pImpLib
->name
= TLB_MultiByteToBSTR(name
);
3630 pImpLib
->guid
= MSFT_ReadGuid(oGuid
, &cx
);
3631 offset
= (offset
+ sizeof(INT
) + sizeof(DWORD
) + sizeof(LCID
) + sizeof(UINT16
) + size
+ 3) & ~3;
3633 list_add_tail(&pTypeLibImpl
->implib_list
, &pImpLib
->entry
);
3637 MSFT_ReadAllRefs(&cx
);
3639 pTypeLibImpl
->dispatch_href
= tlbHeader
.dispatchpos
;
3642 if(tlbHeader
.nrtypeinfos
>= 0 )
3644 ITypeInfoImpl
**ppTI
;
3646 ppTI
= pTypeLibImpl
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*) * tlbHeader
.nrtypeinfos
);
3648 for(i
= 0; i
< tlbHeader
.nrtypeinfos
; i
++)
3650 *ppTI
= MSFT_DoTypeInfo(&cx
, i
, pTypeLibImpl
);
3653 (pTypeLibImpl
->TypeInfoCount
)++;
3658 if(pTypeLibImpl
->syskind
== SYS_WIN32
){
3659 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; ++i
)
3660 TLB_fix_32on64_typeinfo(pTypeLibImpl
->typeinfos
[i
]);
3664 TRACE("(%p)\n", pTypeLibImpl
);
3665 return &pTypeLibImpl
->ITypeLib2_iface
;
3669 static BOOL
TLB_GUIDFromString(const char *str
, GUID
*guid
)
3675 if(sscanf(str
, "%x-%hx-%hx-%hx", &guid
->Data1
, &guid
->Data2
, &guid
->Data3
, &s
) != 4) {
3676 FIXME("Can't parse guid %s\n", debugstr_guid(guid
));
3680 guid
->Data4
[0] = s
>> 8;
3681 guid
->Data4
[1] = s
& 0xff;
3684 for(i
= 0; i
< 6; i
++) {
3685 memcpy(b
, str
+ 24 + 2 * i
, 2);
3686 guid
->Data4
[i
+ 2] = strtol(b
, NULL
, 16);
3691 static WORD
SLTG_ReadString(const char *ptr
, const TLBString
**pStr
, ITypeLibImpl
*lib
)
3698 bytelen
= *(const WORD
*)ptr
;
3699 if(bytelen
== 0xffff) return 2;
3701 len
= MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, NULL
, 0);
3702 tmp_str
= SysAllocStringLen(NULL
, len
);
3704 MultiByteToWideChar(CP_ACP
, 0, ptr
+ 2, bytelen
, tmp_str
, len
);
3705 *pStr
= TLB_append_str(&lib
->string_list
, tmp_str
);
3706 SysFreeString(tmp_str
);
3711 static WORD
SLTG_ReadStringA(const char *ptr
, char **str
)
3716 bytelen
= *(const WORD
*)ptr
;
3717 if(bytelen
== 0xffff) return 2;
3718 *str
= heap_alloc(bytelen
+ 1);
3719 memcpy(*str
, ptr
+ 2, bytelen
);
3720 (*str
)[bytelen
] = '\0';
3724 static TLBString
*SLTG_ReadName(const char *pNameTable
, int offset
, ITypeLibImpl
*lib
)
3729 LIST_FOR_EACH_ENTRY(tlbstr
, &lib
->name_list
, TLBString
, entry
) {
3730 if (tlbstr
->offset
== offset
)
3734 tmp_str
= TLB_MultiByteToBSTR(pNameTable
+ offset
);
3735 tlbstr
= TLB_append_str(&lib
->name_list
, tmp_str
);
3736 SysFreeString(tmp_str
);
3741 static DWORD
SLTG_ReadLibBlk(LPVOID pLibBlk
, ITypeLibImpl
*pTypeLibImpl
)
3743 char *ptr
= pLibBlk
;
3746 if((w
= *(WORD
*)ptr
) != SLTG_LIBBLK_MAGIC
) {
3747 FIXME("libblk magic = %04x\n", w
);
3752 if((w
= *(WORD
*)ptr
) != 0xffff) {
3753 FIXME("LibBlk.res06 = %04x. Assuming string and skipping\n", w
);
3758 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->DocString
, pTypeLibImpl
);
3760 ptr
+= SLTG_ReadString(ptr
, &pTypeLibImpl
->HelpFile
, pTypeLibImpl
);
3762 pTypeLibImpl
->dwHelpContext
= *(DWORD
*)ptr
;
3765 pTypeLibImpl
->syskind
= *(WORD
*)ptr
;
3766 pTypeLibImpl
->ptr_size
= get_ptr_size(pTypeLibImpl
->syskind
);
3769 if(SUBLANGID(*(WORD
*)ptr
) == SUBLANG_NEUTRAL
)
3770 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= MAKELCID(MAKELANGID(PRIMARYLANGID(*(WORD
*)ptr
),0),0);
3772 pTypeLibImpl
->lcid
= pTypeLibImpl
->set_lcid
= 0;
3775 ptr
+= 4; /* skip res12 */
3777 pTypeLibImpl
->libflags
= *(WORD
*)ptr
;
3780 pTypeLibImpl
->ver_major
= *(WORD
*)ptr
;
3783 pTypeLibImpl
->ver_minor
= *(WORD
*)ptr
;
3786 pTypeLibImpl
->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, (GUID
*)ptr
, -2);
3787 ptr
+= sizeof(GUID
);
3789 return ptr
- (char*)pLibBlk
;
3792 /* stores a mapping between the sltg typeinfo's references and the typelib's HREFTYPEs */
3797 } sltg_ref_lookup_t
;
3799 static HRESULT
sltg_get_typelib_ref(const sltg_ref_lookup_t
*table
, DWORD typeinfo_ref
,
3800 HREFTYPE
*typelib_ref
)
3802 if(table
&& typeinfo_ref
< table
->num
)
3804 *typelib_ref
= table
->refs
[typeinfo_ref
];
3808 ERR_(typelib
)("Unable to find reference\n");
3813 static WORD
*SLTG_DoType(WORD
*pType
, char *pBlk
, TYPEDESC
*pTD
, const sltg_ref_lookup_t
*ref_lookup
)
3818 if((*pType
& 0xe00) == 0xe00) {
3820 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3821 pTD
= pTD
->u
.lptdesc
;
3823 switch(*pType
& 0x3f) {
3826 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3827 pTD
= pTD
->u
.lptdesc
;
3830 case VT_USERDEFINED
:
3831 pTD
->vt
= VT_USERDEFINED
;
3832 sltg_get_typelib_ref(ref_lookup
, *(++pType
) / 4, &pTD
->u
.hreftype
);
3838 /* *(pType+1) is offset to a SAFEARRAY, *(pType+2) is type of
3841 SAFEARRAY
*pSA
= (SAFEARRAY
*)(pBlk
+ *(++pType
));
3843 pTD
->vt
= VT_CARRAY
;
3844 pTD
->u
.lpadesc
= heap_alloc_zero(sizeof(ARRAYDESC
) + (pSA
->cDims
- 1) * sizeof(SAFEARRAYBOUND
));
3845 pTD
->u
.lpadesc
->cDims
= pSA
->cDims
;
3846 memcpy(pTD
->u
.lpadesc
->rgbounds
, pSA
->rgsabound
,
3847 pSA
->cDims
* sizeof(SAFEARRAYBOUND
));
3849 pTD
= &pTD
->u
.lpadesc
->tdescElem
;
3855 /* FIXME: *(pType+1) gives an offset to SAFEARRAY, is this
3859 pTD
->vt
= VT_SAFEARRAY
;
3860 pTD
->u
.lptdesc
= heap_alloc_zero(sizeof(TYPEDESC
));
3861 pTD
= pTD
->u
.lptdesc
;
3865 pTD
->vt
= *pType
& 0x3f;
3874 static WORD
*SLTG_DoElem(WORD
*pType
, char *pBlk
,
3875 ELEMDESC
*pElem
, const sltg_ref_lookup_t
*ref_lookup
)
3877 /* Handle [in/out] first */
3878 if((*pType
& 0xc000) == 0xc000)
3879 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
3880 else if(*pType
& 0x8000)
3881 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
| PARAMFLAG_FOUT
;
3882 else if(*pType
& 0x4000)
3883 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FOUT
;
3885 pElem
->u
.paramdesc
.wParamFlags
= PARAMFLAG_FIN
;
3888 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FLCID
;
3891 pElem
->u
.paramdesc
.wParamFlags
|= PARAMFLAG_FRETVAL
;
3893 return SLTG_DoType(pType
, pBlk
, &pElem
->tdesc
, ref_lookup
);
3897 static sltg_ref_lookup_t
*SLTG_DoRefs(SLTG_RefInfo
*pRef
, ITypeLibImpl
*pTL
,
3902 TLBRefType
*ref_type
;
3903 sltg_ref_lookup_t
*table
;
3904 HREFTYPE typelib_ref
;
3906 if(pRef
->magic
!= SLTG_REF_MAGIC
) {
3907 FIXME("Ref magic = %x\n", pRef
->magic
);
3910 name
= ( (char*)pRef
->names
+ pRef
->number
);
3912 table
= heap_alloc(sizeof(*table
) + ((pRef
->number
>> 3) - 1) * sizeof(table
->refs
[0]));
3913 table
->num
= pRef
->number
>> 3;
3915 /* FIXME should scan the existing list and reuse matching refs added by previous typeinfos */
3917 /* We don't want the first href to be 0 */
3918 typelib_ref
= (list_count(&pTL
->ref_list
) + 1) << 2;
3920 for(ref
= 0; ref
< pRef
->number
>> 3; ref
++) {
3922 unsigned int lib_offs
, type_num
;
3924 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
3926 name
+= SLTG_ReadStringA(name
, &refname
);
3927 if(sscanf(refname
, "*\\R%x*#%x", &lib_offs
, &type_num
) != 2)
3928 FIXME_(typelib
)("Can't sscanf ref\n");
3929 if(lib_offs
!= 0xffff) {
3932 LIST_FOR_EACH_ENTRY(import
, &pTL
->implib_list
, TLBImpLib
, entry
)
3933 if(import
->offset
== lib_offs
)
3936 if(&import
->entry
== &pTL
->implib_list
) {
3937 char fname
[MAX_PATH
+1];
3941 import
= heap_alloc_zero(sizeof(*import
));
3942 import
->offset
= lib_offs
;
3943 TLB_GUIDFromString( pNameTable
+ lib_offs
+ 4, &tmpguid
);
3944 import
->guid
= TLB_append_guid(&pTL
->guid_list
, &tmpguid
, 2);
3945 if(sscanf(pNameTable
+ lib_offs
+ 40, "}#%hd.%hd#%x#%s",
3946 &import
->wVersionMajor
,
3947 &import
->wVersionMinor
,
3948 &import
->lcid
, fname
) != 4) {
3949 FIXME_(typelib
)("can't sscanf ref %s\n",
3950 pNameTable
+ lib_offs
+ 40);
3952 len
= strlen(fname
);
3953 if(fname
[len
-1] != '#')
3954 FIXME("fname = %s\n", fname
);
3955 fname
[len
-1] = '\0';
3956 import
->name
= TLB_MultiByteToBSTR(fname
);
3957 list_add_tail(&pTL
->implib_list
, &import
->entry
);
3959 ref_type
->pImpTLInfo
= import
;
3961 /* Store a reference to IDispatch */
3962 if(pTL
->dispatch_href
== -1 && IsEqualGUID(&import
->guid
->guid
, &IID_StdOle
) && type_num
== 4)
3963 pTL
->dispatch_href
= typelib_ref
;
3965 } else { /* internal ref */
3966 ref_type
->pImpTLInfo
= TLB_REF_INTERNAL
;
3968 ref_type
->reference
= typelib_ref
;
3969 ref_type
->index
= type_num
;
3972 list_add_tail(&pTL
->ref_list
, &ref_type
->entry
);
3974 table
->refs
[ref
] = typelib_ref
;
3977 if((BYTE
)*name
!= SLTG_REF_MAGIC
)
3978 FIXME_(typelib
)("End of ref block magic = %x\n", *name
);
3979 dump_TLBRefType(pTL
);
3983 static char *SLTG_DoImpls(char *pBlk
, ITypeInfoImpl
*pTI
,
3984 BOOL OneOnly
, const sltg_ref_lookup_t
*ref_lookup
)
3986 SLTG_ImplInfo
*info
;
3987 TLBImplType
*pImplType
;
3988 /* I don't really get this structure, usually it's 0x16 bytes
3989 long, but iuser.tlb contains some that are 0x18 bytes long.
3990 That's ok because we can use the next ptr to jump to the next
3991 one. But how do we know the length of the last one? The WORD
3992 at offs 0x8 might be the clue. For now I'm just assuming that
3993 the last one is the regular 0x16 bytes. */
3995 info
= (SLTG_ImplInfo
*)pBlk
;
3997 pTI
->typeattr
.cImplTypes
++;
3998 if(info
->next
== 0xffff)
4000 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4003 info
= (SLTG_ImplInfo
*)pBlk
;
4004 pTI
->impltypes
= TLBImplType_Alloc(pTI
->typeattr
.cImplTypes
);
4005 pImplType
= pTI
->impltypes
;
4007 sltg_get_typelib_ref(ref_lookup
, info
->ref
, &pImplType
->hRef
);
4008 pImplType
->implflags
= info
->impltypeflags
;
4011 if(info
->next
== 0xffff)
4014 FIXME_(typelib
)("Interface inheriting more than one interface\n");
4015 info
= (SLTG_ImplInfo
*)(pBlk
+ info
->next
);
4017 info
++; /* see comment at top of function */
4021 static void SLTG_DoVars(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
, unsigned short cVars
,
4022 const char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4024 TLBVarDesc
*pVarDesc
;
4025 const TLBString
*prevName
= NULL
;
4026 SLTG_Variable
*pItem
;
4030 pVarDesc
= pTI
->vardescs
= TLBVarDesc_Alloc(cVars
);
4032 for(pItem
= (SLTG_Variable
*)pFirstItem
, i
= 0; i
< cVars
;
4033 pItem
= (SLTG_Variable
*)(pBlk
+ pItem
->next
), i
++, ++pVarDesc
) {
4035 pVarDesc
->vardesc
.memid
= pItem
->memid
;
4037 if (pItem
->magic
!= SLTG_VAR_MAGIC
&&
4038 pItem
->magic
!= SLTG_VAR_WITH_FLAGS_MAGIC
) {
4039 FIXME_(typelib
)("var magic = %02x\n", pItem
->magic
);
4043 if (pItem
->name
== 0xfffe)
4044 pVarDesc
->Name
= prevName
;
4046 pVarDesc
->Name
= SLTG_ReadName(pNameTable
, pItem
->name
, pTI
->pTypeLib
);
4048 TRACE_(typelib
)("name: %s\n", debugstr_w(TLB_get_bstr(pVarDesc
->Name
)));
4049 TRACE_(typelib
)("byte_offs = 0x%x\n", pItem
->byte_offs
);
4050 TRACE_(typelib
)("memid = 0x%x\n", pItem
->memid
);
4052 if(pItem
->flags
& 0x02)
4053 pType
= &pItem
->type
;
4055 pType
= (WORD
*)(pBlk
+ pItem
->type
);
4057 if (pItem
->flags
& ~0xda)
4058 FIXME_(typelib
)("unhandled flags = %02x\n", pItem
->flags
& ~0xda);
4060 SLTG_DoElem(pType
, pBlk
,
4061 &pVarDesc
->vardesc
.elemdescVar
, ref_lookup
);
4063 if (TRACE_ON(typelib
)) {
4065 dump_TypeDesc(&pVarDesc
->vardesc
.elemdescVar
.tdesc
, buf
);
4066 TRACE_(typelib
)("elemdescVar: %s\n", buf
);
4069 if (pItem
->flags
& 0x40) {
4070 TRACE_(typelib
)("VAR_DISPATCH\n");
4071 pVarDesc
->vardesc
.varkind
= VAR_DISPATCH
;
4073 else if (pItem
->flags
& 0x10) {
4074 TRACE_(typelib
)("VAR_CONST\n");
4075 pVarDesc
->vardesc
.varkind
= VAR_CONST
;
4076 pVarDesc
->vardesc
.u
.lpvarValue
= heap_alloc(sizeof(VARIANT
));
4077 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_INT
;
4078 if (pItem
->flags
& 0x08)
4079 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) = pItem
->byte_offs
;
4081 switch (pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
)
4087 WORD len
= *(WORD
*)(pBlk
+ pItem
->byte_offs
);
4089 TRACE_(typelib
)("len = %u\n", len
);
4090 if (len
== 0xffff) {
4093 INT alloc_len
= MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, NULL
, 0);
4094 str
= SysAllocStringLen(NULL
, alloc_len
);
4095 MultiByteToWideChar(CP_ACP
, 0, pBlk
+ pItem
->byte_offs
+ 2, len
, str
, alloc_len
);
4097 V_VT(pVarDesc
->vardesc
.u
.lpvarValue
) = VT_BSTR
;
4098 V_BSTR(pVarDesc
->vardesc
.u
.lpvarValue
) = str
;
4107 V_INT(pVarDesc
->vardesc
.u
.lpvarValue
) =
4108 *(INT
*)(pBlk
+ pItem
->byte_offs
);
4111 FIXME_(typelib
)("VAR_CONST unimplemented for type %d\n", pVarDesc
->vardesc
.elemdescVar
.tdesc
.vt
);
4116 TRACE_(typelib
)("VAR_PERINSTANCE\n");
4117 pVarDesc
->vardesc
.u
.oInst
= pItem
->byte_offs
;
4118 pVarDesc
->vardesc
.varkind
= VAR_PERINSTANCE
;
4121 if (pItem
->magic
== SLTG_VAR_WITH_FLAGS_MAGIC
)
4122 pVarDesc
->vardesc
.wVarFlags
= pItem
->varflags
;
4124 if (pItem
->flags
& 0x80)
4125 pVarDesc
->vardesc
.wVarFlags
|= VARFLAG_FREADONLY
;
4127 prevName
= pVarDesc
->Name
;
4129 pTI
->typeattr
.cVars
= cVars
;
4132 static void SLTG_DoFuncs(char *pBlk
, char *pFirstItem
, ITypeInfoImpl
*pTI
,
4133 unsigned short cFuncs
, char *pNameTable
, const sltg_ref_lookup_t
*ref_lookup
)
4135 SLTG_Function
*pFunc
;
4137 TLBFuncDesc
*pFuncDesc
;
4139 pTI
->funcdescs
= TLBFuncDesc_Alloc(cFuncs
);
4141 pFuncDesc
= pTI
->funcdescs
;
4142 for(pFunc
= (SLTG_Function
*)pFirstItem
, i
= 0; i
< cFuncs
&& pFunc
!= (SLTG_Function
*)0xFFFF;
4143 pFunc
= (SLTG_Function
*)(pBlk
+ pFunc
->next
), i
++, ++pFuncDesc
) {
4148 switch (pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
) {
4149 case SLTG_FUNCTION_MAGIC
:
4150 pFuncDesc
->funcdesc
.funckind
= FUNC_PUREVIRTUAL
;
4152 case SLTG_DISPATCH_FUNCTION_MAGIC
:
4153 pFuncDesc
->funcdesc
.funckind
= FUNC_DISPATCH
;
4155 case SLTG_STATIC_FUNCTION_MAGIC
:
4156 pFuncDesc
->funcdesc
.funckind
= FUNC_STATIC
;
4159 FIXME("unimplemented func magic = %02x\n", pFunc
->magic
& ~SLTG_FUNCTION_FLAGS_PRESENT
);
4162 pFuncDesc
->Name
= SLTG_ReadName(pNameTable
, pFunc
->name
, pTI
->pTypeLib
);
4164 pFuncDesc
->funcdesc
.memid
= pFunc
->dispid
;
4165 pFuncDesc
->funcdesc
.invkind
= pFunc
->inv
>> 4;
4166 pFuncDesc
->funcdesc
.callconv
= pFunc
->nacc
& 0x7;
4167 pFuncDesc
->funcdesc
.cParams
= pFunc
->nacc
>> 3;
4168 pFuncDesc
->funcdesc
.cParamsOpt
= (pFunc
->retnextopt
& 0x7e) >> 1;
4169 pFuncDesc
->funcdesc
.oVft
= (pFunc
->vtblpos
& ~1) * sizeof(void *) / pTI
->pTypeLib
->ptr_size
;
4171 if(pFunc
->magic
& SLTG_FUNCTION_FLAGS_PRESENT
)
4172 pFuncDesc
->funcdesc
.wFuncFlags
= pFunc
->funcflags
;
4174 if(pFunc
->retnextopt
& 0x80)
4175 pType
= &pFunc
->rettype
;
4177 pType
= (WORD
*)(pBlk
+ pFunc
->rettype
);
4179 SLTG_DoElem(pType
, pBlk
, &pFuncDesc
->funcdesc
.elemdescFunc
, ref_lookup
);
4181 pFuncDesc
->funcdesc
.lprgelemdescParam
=
4182 heap_alloc_zero(pFuncDesc
->funcdesc
.cParams
* sizeof(ELEMDESC
));
4183 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(pFuncDesc
->funcdesc
.cParams
);
4185 pArg
= (WORD
*)(pBlk
+ pFunc
->arg_off
);
4187 for(param
= 0; param
< pFuncDesc
->funcdesc
.cParams
; param
++) {
4188 char *paramName
= pNameTable
+ *pArg
;
4190 /* If arg type follows then paramName points to the 2nd
4191 letter of the name, else the next WORD is an offset to
4192 the arg type and paramName points to the first letter.
4193 So let's take one char off paramName and see if we're
4194 pointing at an alphanumeric char. However if *pArg is
4195 0xffff or 0xfffe then the param has no name, the former
4196 meaning that the next WORD is the type, the latter
4197 meaning that the next WORD is an offset to the type. */
4202 else if(*pArg
== 0xfffe) {
4206 else if(paramName
[-1] && !isalnum(paramName
[-1]))
4211 if(HaveOffs
) { /* the next word is an offset to type */
4212 pType
= (WORD
*)(pBlk
+ *pArg
);
4213 SLTG_DoElem(pType
, pBlk
,
4214 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4219 pArg
= SLTG_DoElem(pArg
, pBlk
,
4220 &pFuncDesc
->funcdesc
.lprgelemdescParam
[param
], ref_lookup
);
4223 /* Are we an optional param ? */
4224 if(pFuncDesc
->funcdesc
.cParams
- param
<=
4225 pFuncDesc
->funcdesc
.cParamsOpt
)
4226 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].u
.paramdesc
.wParamFlags
|= PARAMFLAG_FOPT
;
4229 pFuncDesc
->pParamDesc
[param
].Name
= SLTG_ReadName(pNameTable
,
4230 paramName
- pNameTable
, pTI
->pTypeLib
);
4232 pFuncDesc
->pParamDesc
[param
].Name
= pFuncDesc
->Name
;
4236 pTI
->typeattr
.cFuncs
= cFuncs
;
4239 static void SLTG_ProcessCoClass(char *pBlk
, ITypeInfoImpl
*pTI
,
4240 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4241 SLTG_TypeInfoTail
*pTITail
)
4244 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4246 if(pTIHeader
->href_table
!= 0xffffffff) {
4247 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4253 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4254 SLTG_DoImpls(pFirstItem
, pTI
, FALSE
, ref_lookup
);
4256 heap_free(ref_lookup
);
4260 static void SLTG_ProcessInterface(char *pBlk
, ITypeInfoImpl
*pTI
,
4261 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4262 const SLTG_TypeInfoTail
*pTITail
)
4265 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4267 if(pTIHeader
->href_table
!= 0xffffffff) {
4268 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4274 if(*(WORD
*)pFirstItem
== SLTG_IMPL_MAGIC
) {
4275 SLTG_DoImpls(pFirstItem
, pTI
, TRUE
, ref_lookup
);
4278 if (pTITail
->funcs_off
!= 0xffff)
4279 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4281 heap_free(ref_lookup
);
4283 if (TRACE_ON(typelib
))
4284 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4287 static void SLTG_ProcessRecord(char *pBlk
, ITypeInfoImpl
*pTI
,
4288 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4289 const SLTG_TypeInfoTail
*pTITail
)
4291 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4294 static void SLTG_ProcessAlias(char *pBlk
, ITypeInfoImpl
*pTI
,
4295 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4296 const SLTG_TypeInfoTail
*pTITail
)
4299 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4301 if (pTITail
->simple_alias
) {
4302 /* if simple alias, no more processing required */
4303 pTI
->tdescAlias
= heap_alloc_zero(sizeof(TYPEDESC
));
4304 pTI
->tdescAlias
->vt
= pTITail
->tdescalias_vt
;
4308 if(pTIHeader
->href_table
!= 0xffffffff) {
4309 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4313 /* otherwise it is an offset to a type */
4314 pType
= (WORD
*)(pBlk
+ pTITail
->tdescalias_vt
);
4316 pTI
->tdescAlias
= heap_alloc(sizeof(TYPEDESC
));
4317 SLTG_DoType(pType
, pBlk
, pTI
->tdescAlias
, ref_lookup
);
4319 heap_free(ref_lookup
);
4322 static void SLTG_ProcessDispatch(char *pBlk
, ITypeInfoImpl
*pTI
,
4323 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4324 const SLTG_TypeInfoTail
*pTITail
)
4326 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4327 if (pTIHeader
->href_table
!= 0xffffffff)
4328 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4331 if (pTITail
->vars_off
!= 0xffff)
4332 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4334 if (pTITail
->funcs_off
!= 0xffff)
4335 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4337 if (pTITail
->impls_off
!= 0xffff)
4338 SLTG_DoImpls(pBlk
+ pTITail
->impls_off
, pTI
, FALSE
, ref_lookup
);
4340 /* this is necessary to cope with MSFT typelibs that set cFuncs to the number
4341 * of dispinterface functions including the IDispatch ones, so
4342 * ITypeInfo::GetFuncDesc takes the real value for cFuncs from cbSizeVft */
4343 pTI
->typeattr
.cbSizeVft
= pTI
->typeattr
.cFuncs
* pTI
->pTypeLib
->ptr_size
;
4345 heap_free(ref_lookup
);
4346 if (TRACE_ON(typelib
))
4347 dump_TLBFuncDesc(pTI
->funcdescs
, pTI
->typeattr
.cFuncs
);
4350 static void SLTG_ProcessEnum(char *pBlk
, ITypeInfoImpl
*pTI
,
4351 const char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4352 const SLTG_TypeInfoTail
*pTITail
)
4354 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, NULL
);
4357 static void SLTG_ProcessModule(char *pBlk
, ITypeInfoImpl
*pTI
,
4358 char *pNameTable
, SLTG_TypeInfoHeader
*pTIHeader
,
4359 const SLTG_TypeInfoTail
*pTITail
)
4361 sltg_ref_lookup_t
*ref_lookup
= NULL
;
4362 if (pTIHeader
->href_table
!= 0xffffffff)
4363 ref_lookup
= SLTG_DoRefs((SLTG_RefInfo
*)((char *)pTIHeader
+ pTIHeader
->href_table
), pTI
->pTypeLib
,
4366 if (pTITail
->vars_off
!= 0xffff)
4367 SLTG_DoVars(pBlk
, pBlk
+ pTITail
->vars_off
, pTI
, pTITail
->cVars
, pNameTable
, ref_lookup
);
4369 if (pTITail
->funcs_off
!= 0xffff)
4370 SLTG_DoFuncs(pBlk
, pBlk
+ pTITail
->funcs_off
, pTI
, pTITail
->cFuncs
, pNameTable
, ref_lookup
);
4371 heap_free(ref_lookup
);
4372 if (TRACE_ON(typelib
))
4376 /* Because SLTG_OtherTypeInfo is such a painful struct, we make a more
4377 manageable copy of it into this */
4390 } SLTG_InternalOtherTypeInfo
;
4392 /****************************************************************************
4393 * ITypeLib2_Constructor_SLTG
4395 * loading a SLTG typelib from an in-memory image
4397 static ITypeLib2
* ITypeLib2_Constructor_SLTG(LPVOID pLib
, DWORD dwTLBLength
)
4399 ITypeLibImpl
*pTypeLibImpl
;
4400 SLTG_Header
*pHeader
;
4401 SLTG_BlkEntry
*pBlkEntry
;
4405 LPVOID pBlk
, pFirstBlk
;
4406 SLTG_LibBlk
*pLibBlk
;
4407 SLTG_InternalOtherTypeInfo
*pOtherTypeInfoBlks
;
4408 char *pAfterOTIBlks
= NULL
;
4409 char *pNameTable
, *ptr
;
4412 ITypeInfoImpl
**ppTypeInfoImpl
;
4414 TRACE_(typelib
)("%p, TLB length = %d\n", pLib
, dwTLBLength
);
4417 pTypeLibImpl
= TypeLibImpl_Constructor();
4418 if (!pTypeLibImpl
) return NULL
;
4422 TRACE_(typelib
)("header:\n");
4423 TRACE_(typelib
)("\tmagic=0x%08x, file blocks = %d\n", pHeader
->SLTG_magic
,
4424 pHeader
->nrOfFileBlks
);
4425 if (pHeader
->SLTG_magic
!= SLTG_SIGNATURE
) {
4426 FIXME_(typelib
)("Header type magic 0x%08x not supported.\n",
4427 pHeader
->SLTG_magic
);
4431 /* There are pHeader->nrOfFileBlks - 2 TypeInfo records in this typelib */
4432 pTypeLibImpl
->TypeInfoCount
= pHeader
->nrOfFileBlks
- 2;
4434 /* This points to pHeader->nrOfFileBlks - 1 of SLTG_BlkEntry */
4435 pBlkEntry
= (SLTG_BlkEntry
*)(pHeader
+ 1);
4437 /* Next we have a magic block */
4438 pMagic
= (SLTG_Magic
*)(pBlkEntry
+ pHeader
->nrOfFileBlks
- 1);
4440 /* Let's see if we're still in sync */
4441 if(memcmp(pMagic
->CompObj_magic
, SLTG_COMPOBJ_MAGIC
,
4442 sizeof(SLTG_COMPOBJ_MAGIC
))) {
4443 FIXME_(typelib
)("CompObj magic = %s\n", pMagic
->CompObj_magic
);
4446 if(memcmp(pMagic
->dir_magic
, SLTG_DIR_MAGIC
,
4447 sizeof(SLTG_DIR_MAGIC
))) {
4448 FIXME_(typelib
)("dir magic = %s\n", pMagic
->dir_magic
);
4452 pIndex
= (SLTG_Index
*)(pMagic
+1);
4454 pPad9
= (SLTG_Pad9
*)(pIndex
+ pTypeLibImpl
->TypeInfoCount
);
4456 pFirstBlk
= pPad9
+ 1;
4458 /* We'll set up a ptr to the main library block, which is the last one. */
4460 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1;
4461 pBlkEntry
[order
].next
!= 0;
4462 order
= pBlkEntry
[order
].next
- 1) {
4463 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4467 len
= SLTG_ReadLibBlk(pLibBlk
, pTypeLibImpl
);
4469 /* Now there are 0x40 bytes of 0xffff with the numbers 0 to TypeInfoCount
4474 /* And now TypeInfoCount of SLTG_OtherTypeInfo */
4476 pOtherTypeInfoBlks
= heap_alloc_zero(sizeof(*pOtherTypeInfoBlks
) * pTypeLibImpl
->TypeInfoCount
);
4479 ptr
= (char*)pLibBlk
+ len
;
4481 for(i
= 0; i
< pTypeLibImpl
->TypeInfoCount
; i
++) {
4485 pOtherTypeInfoBlks
[i
].small_no
= *(WORD
*)ptr
;
4487 w
= *(WORD
*)(ptr
+ 2);
4490 pOtherTypeInfoBlks
[i
].index_name
= heap_alloc(w
+1);
4491 memcpy(pOtherTypeInfoBlks
[i
].index_name
, ptr
+ 4, w
);
4492 pOtherTypeInfoBlks
[i
].index_name
[w
] = '\0';
4494 w
= *(WORD
*)(ptr
+ 4 + len
);
4496 TRACE_(typelib
)("\twith %s\n", debugstr_an(ptr
+ 6 + len
, w
));
4498 pOtherTypeInfoBlks
[i
].other_name
= heap_alloc(w
+1);
4499 memcpy(pOtherTypeInfoBlks
[i
].other_name
, ptr
+ 6 + len
, w
);
4500 pOtherTypeInfoBlks
[i
].other_name
[w
] = '\0';
4502 pOtherTypeInfoBlks
[i
].res1a
= *(WORD
*)(ptr
+ len
+ 6);
4503 pOtherTypeInfoBlks
[i
].name_offs
= *(WORD
*)(ptr
+ len
+ 8);
4504 extra
= pOtherTypeInfoBlks
[i
].more_bytes
= *(WORD
*)(ptr
+ 10 + len
);
4506 pOtherTypeInfoBlks
[i
].extra
= heap_alloc(extra
);
4507 memcpy(pOtherTypeInfoBlks
[i
].extra
, ptr
+ 12, extra
);
4510 pOtherTypeInfoBlks
[i
].res20
= *(WORD
*)(ptr
+ 12 + len
);
4511 pOtherTypeInfoBlks
[i
].helpcontext
= *(DWORD
*)(ptr
+ 14 + len
);
4512 pOtherTypeInfoBlks
[i
].res26
= *(WORD
*)(ptr
+ 18 + len
);
4513 memcpy(&pOtherTypeInfoBlks
[i
].uuid
, ptr
+ 20 + len
, sizeof(GUID
));
4514 len
+= sizeof(SLTG_OtherTypeInfo
);
4518 pAfterOTIBlks
= ptr
;
4520 /* Skip this WORD and get the next DWORD */
4521 len
= *(DWORD
*)(pAfterOTIBlks
+ 2);
4523 /* Now add this to pLibBLk look at what we're pointing at and
4524 possibly add 0x20, then add 0x216, sprinkle a bit a magic
4525 dust and we should be pointing at the beginning of the name
4528 pNameTable
= (char*)pLibBlk
+ len
;
4530 switch(*(WORD
*)pNameTable
) {
4537 FIXME_(typelib
)("pNameTable jump = %x\n", *(WORD
*)pNameTable
);
4541 pNameTable
+= 0x216;
4545 TRACE_(typelib
)("Library name is %s\n", pNameTable
+ pLibBlk
->name
);
4547 pTypeLibImpl
->Name
= SLTG_ReadName(pNameTable
, pLibBlk
->name
, pTypeLibImpl
);
4550 /* Hopefully we now have enough ptrs set up to actually read in
4551 some TypeInfos. It's not clear which order to do them in, so
4552 I'll just follow the links along the BlkEntry chain and read
4553 them in the order in which they are in the file */
4555 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
4556 ppTypeInfoImpl
= pTypeLibImpl
->typeinfos
;
4558 for(pBlk
= pFirstBlk
, order
= pHeader
->first_blk
- 1, i
= 0;
4559 pBlkEntry
[order
].next
!= 0;
4560 order
= pBlkEntry
[order
].next
- 1, i
++) {
4562 SLTG_TypeInfoHeader
*pTIHeader
;
4563 SLTG_TypeInfoTail
*pTITail
;
4564 SLTG_MemberHeader
*pMemHeader
;
4566 if(strcmp(pBlkEntry
[order
].index_string
+ (char*)pMagic
, pOtherTypeInfoBlks
[i
].index_name
)) {
4567 FIXME_(typelib
)("Index strings don't match\n");
4568 heap_free(pOtherTypeInfoBlks
);
4573 if(pTIHeader
->magic
!= SLTG_TIHEADER_MAGIC
) {
4574 FIXME_(typelib
)("TypeInfoHeader magic = %04x\n", pTIHeader
->magic
);
4575 heap_free(pOtherTypeInfoBlks
);
4578 TRACE_(typelib
)("pTIHeader->res06 = %x, pTIHeader->res0e = %x, "
4579 "pTIHeader->res16 = %x, pTIHeader->res1e = %x\n",
4580 pTIHeader
->res06
, pTIHeader
->res0e
, pTIHeader
->res16
, pTIHeader
->res1e
);
4582 *ppTypeInfoImpl
= ITypeInfoImpl_Constructor();
4583 (*ppTypeInfoImpl
)->pTypeLib
= pTypeLibImpl
;
4584 (*ppTypeInfoImpl
)->index
= i
;
4585 (*ppTypeInfoImpl
)->Name
= SLTG_ReadName(pNameTable
, pOtherTypeInfoBlks
[i
].name_offs
, pTypeLibImpl
);
4586 (*ppTypeInfoImpl
)->dwHelpContext
= pOtherTypeInfoBlks
[i
].helpcontext
;
4587 (*ppTypeInfoImpl
)->guid
= TLB_append_guid(&pTypeLibImpl
->guid_list
, &pOtherTypeInfoBlks
[i
].uuid
, 2);
4588 (*ppTypeInfoImpl
)->typeattr
.typekind
= pTIHeader
->typekind
;
4589 (*ppTypeInfoImpl
)->typeattr
.wMajorVerNum
= pTIHeader
->major_version
;
4590 (*ppTypeInfoImpl
)->typeattr
.wMinorVerNum
= pTIHeader
->minor_version
;
4591 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
=
4592 (pTIHeader
->typeflags1
>> 3) | (pTIHeader
->typeflags2
<< 5);
4594 if((*ppTypeInfoImpl
)->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
4595 (*ppTypeInfoImpl
)->typeattr
.typekind
= TKIND_DISPATCH
;
4597 if((pTIHeader
->typeflags1
& 7) != 2)
4598 FIXME_(typelib
)("typeflags1 = %02x\n", pTIHeader
->typeflags1
);
4599 if(pTIHeader
->typeflags3
!= 2)
4600 FIXME_(typelib
)("typeflags3 = %02x\n", pTIHeader
->typeflags3
);
4602 TRACE_(typelib
)("TypeInfo %s of kind %s guid %s typeflags %04x\n",
4603 debugstr_w(TLB_get_bstr((*ppTypeInfoImpl
)->Name
)),
4604 typekind_desc
[pTIHeader
->typekind
],
4605 debugstr_guid(TLB_get_guidref((*ppTypeInfoImpl
)->guid
)),
4606 (*ppTypeInfoImpl
)->typeattr
.wTypeFlags
);
4608 pMemHeader
= (SLTG_MemberHeader
*)((char *)pBlk
+ pTIHeader
->elem_table
);
4610 pTITail
= (SLTG_TypeInfoTail
*)((char *)(pMemHeader
+ 1) + pMemHeader
->cbExtra
);
4612 (*ppTypeInfoImpl
)->typeattr
.cbAlignment
= pTITail
->cbAlignment
;
4613 (*ppTypeInfoImpl
)->typeattr
.cbSizeInstance
= pTITail
->cbSizeInstance
;
4614 (*ppTypeInfoImpl
)->typeattr
.cbSizeVft
= pTITail
->cbSizeVft
;
4616 switch(pTIHeader
->typekind
) {
4618 SLTG_ProcessEnum((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4619 pTIHeader
, pTITail
);
4623 SLTG_ProcessRecord((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4624 pTIHeader
, pTITail
);
4627 case TKIND_INTERFACE
:
4628 SLTG_ProcessInterface((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4629 pTIHeader
, pTITail
);
4633 SLTG_ProcessCoClass((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4634 pTIHeader
, pTITail
);
4638 SLTG_ProcessAlias((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4639 pTIHeader
, pTITail
);
4642 case TKIND_DISPATCH
:
4643 SLTG_ProcessDispatch((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4644 pTIHeader
, pTITail
);
4648 SLTG_ProcessModule((char *)(pMemHeader
+ 1), *ppTypeInfoImpl
, pNameTable
,
4649 pTIHeader
, pTITail
);
4653 FIXME("Not processing typekind %d\n", pTIHeader
->typekind
);
4658 /* could get cFuncs, cVars and cImplTypes from here
4659 but we've already set those */
4660 #define X(x) TRACE_(typelib)("tt "#x": %x\n",pTITail->res##x);
4676 pBlk
= (char*)pBlk
+ pBlkEntry
[order
].len
;
4679 if(i
!= pTypeLibImpl
->TypeInfoCount
) {
4680 FIXME("Somehow processed %d TypeInfos\n", i
);
4681 heap_free(pOtherTypeInfoBlks
);
4685 heap_free(pOtherTypeInfoBlks
);
4686 return &pTypeLibImpl
->ITypeLib2_iface
;
4689 static HRESULT WINAPI
ITypeLib2_fnQueryInterface(ITypeLib2
*iface
, REFIID riid
, void **ppv
)
4691 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4693 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
4695 if(IsEqualIID(riid
, &IID_IUnknown
) ||
4696 IsEqualIID(riid
,&IID_ITypeLib
)||
4697 IsEqualIID(riid
,&IID_ITypeLib2
))
4699 *ppv
= &This
->ITypeLib2_iface
;
4701 else if(IsEqualIID(riid
, &IID_ICreateTypeLib
) ||
4702 IsEqualIID(riid
, &IID_ICreateTypeLib2
))
4704 *ppv
= &This
->ICreateTypeLib2_iface
;
4709 TRACE("-- Interface: E_NOINTERFACE\n");
4710 return E_NOINTERFACE
;
4713 IUnknown_AddRef((IUnknown
*)*ppv
);
4717 static ULONG WINAPI
ITypeLib2_fnAddRef( ITypeLib2
*iface
)
4719 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4720 ULONG ref
= InterlockedIncrement(&This
->ref
);
4722 TRACE("(%p) ref=%u\n", This
, ref
);
4727 static ULONG WINAPI
ITypeLib2_fnRelease( ITypeLib2
*iface
)
4729 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4730 ULONG ref
= InterlockedDecrement(&This
->ref
);
4732 TRACE("(%p) ref=%u\n",This
, ref
);
4736 TLBImpLib
*pImpLib
, *pImpLibNext
;
4737 TLBRefType
*ref_type
, *ref_type_next
;
4738 TLBString
*tlbstr
, *tlbstr_next
;
4739 TLBGuid
*tlbguid
, *tlbguid_next
;
4742 /* remove cache entry */
4745 TRACE("removing from cache list\n");
4746 EnterCriticalSection(&cache_section
);
4747 if(This
->entry
.next
)
4748 list_remove(&This
->entry
);
4749 LeaveCriticalSection(&cache_section
);
4750 heap_free(This
->path
);
4752 TRACE(" destroying ITypeLib(%p)\n",This
);
4754 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->string_list
, TLBString
, entry
) {
4755 list_remove(&tlbstr
->entry
);
4756 SysFreeString(tlbstr
->str
);
4760 LIST_FOR_EACH_ENTRY_SAFE(tlbstr
, tlbstr_next
, &This
->name_list
, TLBString
, entry
) {
4761 list_remove(&tlbstr
->entry
);
4762 SysFreeString(tlbstr
->str
);
4766 LIST_FOR_EACH_ENTRY_SAFE(tlbguid
, tlbguid_next
, &This
->guid_list
, TLBGuid
, entry
) {
4767 list_remove(&tlbguid
->entry
);
4771 TLB_FreeCustData(&This
->custdata_list
);
4773 for (i
= 0; i
< This
->ctTypeDesc
; i
++)
4774 if (This
->pTypeDesc
[i
].vt
== VT_CARRAY
)
4775 heap_free(This
->pTypeDesc
[i
].u
.lpadesc
);
4777 heap_free(This
->pTypeDesc
);
4779 LIST_FOR_EACH_ENTRY_SAFE(pImpLib
, pImpLibNext
, &This
->implib_list
, TLBImpLib
, entry
)
4781 if (pImpLib
->pImpTypeLib
)
4782 ITypeLib2_Release(&pImpLib
->pImpTypeLib
->ITypeLib2_iface
);
4783 SysFreeString(pImpLib
->name
);
4785 list_remove(&pImpLib
->entry
);
4789 LIST_FOR_EACH_ENTRY_SAFE(ref_type
, ref_type_next
, &This
->ref_list
, TLBRefType
, entry
)
4791 list_remove(&ref_type
->entry
);
4792 heap_free(ref_type
);
4795 for (i
= 0; i
< This
->TypeInfoCount
; ++i
){
4796 heap_free(This
->typeinfos
[i
]->tdescAlias
);
4797 ITypeInfoImpl_Destroy(This
->typeinfos
[i
]);
4799 heap_free(This
->typeinfos
);
4807 /* ITypeLib::GetTypeInfoCount
4809 * Returns the number of type descriptions in the type library
4811 static UINT WINAPI
ITypeLib2_fnGetTypeInfoCount( ITypeLib2
*iface
)
4813 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4814 TRACE("(%p)->count is %d\n",This
, This
->TypeInfoCount
);
4815 return This
->TypeInfoCount
;
4818 /* ITypeLib::GetTypeInfo
4820 * retrieves the specified type description in the library.
4822 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfo(
4825 ITypeInfo
**ppTInfo
)
4827 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4829 TRACE("%p %u %p\n", This
, index
, ppTInfo
);
4832 return E_INVALIDARG
;
4834 if(index
>= This
->TypeInfoCount
)
4835 return TYPE_E_ELEMENTNOTFOUND
;
4837 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[index
]->ITypeInfo2_iface
;
4838 ITypeInfo_AddRef(*ppTInfo
);
4844 /* ITypeLibs::GetTypeInfoType
4846 * Retrieves the type of a type description.
4848 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoType(
4853 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4855 TRACE("(%p, %d, %p)\n", This
, index
, pTKind
);
4858 return E_INVALIDARG
;
4860 if(index
>= This
->TypeInfoCount
)
4861 return TYPE_E_ELEMENTNOTFOUND
;
4863 *pTKind
= This
->typeinfos
[index
]->typeattr
.typekind
;
4868 /* ITypeLib::GetTypeInfoOfGuid
4870 * Retrieves the type description that corresponds to the specified GUID.
4873 static HRESULT WINAPI
ITypeLib2_fnGetTypeInfoOfGuid(
4876 ITypeInfo
**ppTInfo
)
4878 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4881 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), ppTInfo
);
4883 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
4884 if(IsEqualIID(TLB_get_guid_null(This
->typeinfos
[i
]->guid
), guid
)){
4885 *ppTInfo
= (ITypeInfo
*)&This
->typeinfos
[i
]->ITypeInfo2_iface
;
4886 ITypeInfo_AddRef(*ppTInfo
);
4891 return TYPE_E_ELEMENTNOTFOUND
;
4894 /* ITypeLib::GetLibAttr
4896 * Retrieves the structure that contains the library's attributes.
4899 static HRESULT WINAPI
ITypeLib2_fnGetLibAttr(
4903 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4905 TRACE("(%p, %p)\n", This
, attr
);
4907 if (!attr
) return E_INVALIDARG
;
4909 *attr
= heap_alloc(sizeof(**attr
));
4910 if (!*attr
) return E_OUTOFMEMORY
;
4912 (*attr
)->guid
= *TLB_get_guid_null(This
->guid
);
4913 (*attr
)->lcid
= This
->set_lcid
;
4914 (*attr
)->syskind
= This
->syskind
;
4915 (*attr
)->wMajorVerNum
= This
->ver_major
;
4916 (*attr
)->wMinorVerNum
= This
->ver_minor
;
4917 (*attr
)->wLibFlags
= This
->libflags
;
4922 /* ITypeLib::GetTypeComp
4924 * Enables a client compiler to bind to a library's types, variables,
4925 * constants, and global functions.
4928 static HRESULT WINAPI
ITypeLib2_fnGetTypeComp(
4930 ITypeComp
**ppTComp
)
4932 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4934 TRACE("(%p)->(%p)\n",This
,ppTComp
);
4935 *ppTComp
= &This
->ITypeComp_iface
;
4936 ITypeComp_AddRef(*ppTComp
);
4941 /* ITypeLib::GetDocumentation
4943 * Retrieves the library's documentation string, the complete Help file name
4944 * and path, and the context identifier for the library Help topic in the Help
4947 * On a successful return all non-null BSTR pointers will have been set,
4950 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation(
4954 BSTR
*pBstrDocString
,
4955 DWORD
*pdwHelpContext
,
4956 BSTR
*pBstrHelpFile
)
4958 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
4959 HRESULT result
= E_INVALIDARG
;
4962 TRACE("(%p) index %d Name(%p) DocString(%p) HelpContext(%p) HelpFile(%p)\n",
4964 pBstrName
, pBstrDocString
,
4965 pdwHelpContext
, pBstrHelpFile
);
4969 /* documentation for the typelib */
4974 if(!(*pBstrName
= SysAllocString(TLB_get_bstr(This
->Name
))))
4982 if (This
->DocString
)
4984 if(!(*pBstrDocString
= SysAllocString(TLB_get_bstr(This
->DocString
))))
4988 *pBstrDocString
= NULL
;
4992 *pdwHelpContext
= This
->dwHelpContext
;
4998 if(!(*pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->HelpFile
))))
5002 *pBstrHelpFile
= NULL
;
5009 /* for a typeinfo */
5010 result
= ITypeLib2_fnGetTypeInfo(iface
, index
, &pTInfo
);
5012 if(SUCCEEDED(result
))
5014 result
= ITypeInfo_GetDocumentation(pTInfo
,
5018 pdwHelpContext
, pBstrHelpFile
);
5020 ITypeInfo_Release(pTInfo
);
5025 if (pBstrDocString
) SysFreeString (*pBstrDocString
);
5027 if (pBstrName
) SysFreeString (*pBstrName
);
5029 return STG_E_INSUFFICIENTMEMORY
;
5034 * Indicates whether a passed-in string contains the name of a type or member
5035 * described in the library.
5038 static HRESULT WINAPI
ITypeLib2_fnIsName(
5044 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5046 UINT nNameBufLen
= (lstrlenW(szNameBuf
)+1)*sizeof(WCHAR
), fdc
, vrc
;
5048 TRACE("(%p)->(%s,%08x,%p)\n", This
, debugstr_w(szNameBuf
), lHashVal
,
5052 for(tic
= 0; tic
< This
->TypeInfoCount
; ++tic
){
5053 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5054 if(!TLB_str_memcmp(szNameBuf
, pTInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5055 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5056 TLBFuncDesc
*pFInfo
= &pTInfo
->funcdescs
[fdc
];
5058 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5059 for(pc
=0; pc
< pFInfo
->funcdesc
.cParams
; pc
++){
5060 if(!TLB_str_memcmp(szNameBuf
, pFInfo
->pParamDesc
[pc
].Name
, nNameBufLen
))
5061 goto ITypeLib2_fnIsName_exit
;
5064 for(vrc
= 0; vrc
< pTInfo
->typeattr
.cVars
; ++vrc
){
5065 TLBVarDesc
*pVInfo
= &pTInfo
->vardescs
[vrc
];
5066 if(!TLB_str_memcmp(szNameBuf
, pVInfo
->Name
, nNameBufLen
)) goto ITypeLib2_fnIsName_exit
;
5072 ITypeLib2_fnIsName_exit
:
5073 TRACE("(%p)slow! search for %s: %sfound!\n", This
,
5074 debugstr_w(szNameBuf
), *pfName
? "" : "NOT ");
5079 /* ITypeLib::FindName
5081 * Finds occurrences of a type description in a type library. This may be used
5082 * to quickly verify that a name exists in a type library.
5085 static HRESULT WINAPI
ITypeLib2_fnFindName(
5089 ITypeInfo
**ppTInfo
,
5093 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5098 TRACE("(%p)->(%s %u %p %p %p)\n", This
, debugstr_w(name
), hash
, ppTInfo
, memid
, found
);
5100 if ((!name
&& hash
== 0) || !ppTInfo
|| !memid
|| !found
)
5101 return E_INVALIDARG
;
5103 len
= (lstrlenW(name
) + 1)*sizeof(WCHAR
);
5104 for(tic
= 0; count
< *found
&& tic
< This
->TypeInfoCount
; ++tic
) {
5105 ITypeInfoImpl
*pTInfo
= This
->typeinfos
[tic
];
5109 if(!TLB_str_memcmp(name
, pTInfo
->Name
, len
)) {
5110 memid
[count
] = MEMBERID_NIL
;
5111 goto ITypeLib2_fnFindName_exit
;
5114 for(fdc
= 0; fdc
< pTInfo
->typeattr
.cFuncs
; ++fdc
) {
5115 TLBFuncDesc
*func
= &pTInfo
->funcdescs
[fdc
];
5117 if(!TLB_str_memcmp(name
, func
->Name
, len
)) {
5118 memid
[count
] = func
->funcdesc
.memid
;
5119 goto ITypeLib2_fnFindName_exit
;
5123 var
= TLB_get_vardesc_by_name(pTInfo
, name
);
5125 memid
[count
] = var
->vardesc
.memid
;
5126 goto ITypeLib2_fnFindName_exit
;
5130 ITypeLib2_fnFindName_exit
:
5131 ITypeInfo2_AddRef(&pTInfo
->ITypeInfo2_iface
);
5132 ppTInfo
[count
] = (ITypeInfo
*)&pTInfo
->ITypeInfo2_iface
;
5135 TRACE("found %d typeinfos\n", count
);
5142 /* ITypeLib::ReleaseTLibAttr
5144 * Releases the TLIBATTR originally obtained from ITypeLib::GetLibAttr.
5147 static VOID WINAPI
ITypeLib2_fnReleaseTLibAttr(
5149 TLIBATTR
*pTLibAttr
)
5151 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5152 TRACE("(%p)->(%p)\n", This
, pTLibAttr
);
5153 heap_free(pTLibAttr
);
5156 /* ITypeLib2::GetCustData
5158 * gets the custom data
5160 static HRESULT WINAPI
ITypeLib2_fnGetCustData(
5165 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5166 TLBCustData
*pCData
;
5168 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(guid
), pVarVal
);
5170 pCData
= TLB_get_custdata_by_guid(&This
->custdata_list
, guid
);
5172 return TYPE_E_ELEMENTNOTFOUND
;
5174 VariantInit(pVarVal
);
5175 VariantCopy(pVarVal
, &pCData
->data
);
5180 /* ITypeLib2::GetLibStatistics
5182 * Returns statistics about a type library that are required for efficient
5183 * sizing of hash tables.
5186 static HRESULT WINAPI
ITypeLib2_fnGetLibStatistics(
5188 ULONG
*pcUniqueNames
,
5189 ULONG
*pcchUniqueNames
)
5191 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5193 FIXME("(%p): stub!\n", This
);
5195 if(pcUniqueNames
) *pcUniqueNames
=1;
5196 if(pcchUniqueNames
) *pcchUniqueNames
=1;
5200 /* ITypeLib2::GetDocumentation2
5202 * Retrieves the library's documentation string, the complete Help file name
5203 * and path, the localization context to use, and the context ID for the
5204 * library Help topic in the Help file.
5207 static HRESULT WINAPI
ITypeLib2_fnGetDocumentation2(
5211 BSTR
*pbstrHelpString
,
5212 DWORD
*pdwHelpStringContext
,
5213 BSTR
*pbstrHelpStringDll
)
5215 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5219 FIXME("(%p) index %d lcid %d half implemented stub!\n", This
, index
, lcid
);
5221 /* the help string should be obtained from the helpstringdll,
5222 * using the _DLLGetDocumentation function, based on the supplied
5223 * lcid. Nice to do sometime...
5227 /* documentation for the typelib */
5229 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->DocString
));
5230 if(pdwHelpStringContext
)
5231 *pdwHelpStringContext
=This
->dwHelpContext
;
5232 if(pbstrHelpStringDll
)
5233 *pbstrHelpStringDll
=SysAllocString(TLB_get_bstr(This
->HelpStringDll
));
5239 /* for a typeinfo */
5240 result
=ITypeLib2_GetTypeInfo(iface
, index
, &pTInfo
);
5242 if(SUCCEEDED(result
))
5244 ITypeInfo2
* pTInfo2
;
5245 result
= ITypeInfo_QueryInterface(pTInfo
,
5247 (LPVOID
*) &pTInfo2
);
5249 if(SUCCEEDED(result
))
5251 result
= ITypeInfo2_GetDocumentation2(pTInfo2
,
5255 pdwHelpStringContext
,
5256 pbstrHelpStringDll
);
5258 ITypeInfo2_Release(pTInfo2
);
5261 ITypeInfo_Release(pTInfo
);
5267 static HRESULT
TLB_copy_all_custdata(const struct list
*custdata_list
, CUSTDATA
*pCustData
)
5269 TLBCustData
*pCData
;
5273 ct
= list_count(custdata_list
);
5275 pCustData
->prgCustData
= CoTaskMemAlloc(ct
* sizeof(CUSTDATAITEM
));
5276 if(!pCustData
->prgCustData
)
5277 return E_OUTOFMEMORY
;
5279 pCustData
->cCustData
= ct
;
5281 cdi
= pCustData
->prgCustData
;
5282 LIST_FOR_EACH_ENTRY(pCData
, custdata_list
, TLBCustData
, entry
){
5283 cdi
->guid
= *TLB_get_guid_null(pCData
->guid
);
5284 VariantCopy(&cdi
->varValue
, &pCData
->data
);
5292 /* ITypeLib2::GetAllCustData
5294 * Gets all custom data items for the library.
5297 static HRESULT WINAPI
ITypeLib2_fnGetAllCustData(
5299 CUSTDATA
*pCustData
)
5301 ITypeLibImpl
*This
= impl_from_ITypeLib2(iface
);
5302 TRACE("(%p)->(%p)\n", This
, pCustData
);
5303 return TLB_copy_all_custdata(&This
->custdata_list
, pCustData
);
5306 static const ITypeLib2Vtbl tlbvt
= {
5307 ITypeLib2_fnQueryInterface
,
5309 ITypeLib2_fnRelease
,
5310 ITypeLib2_fnGetTypeInfoCount
,
5311 ITypeLib2_fnGetTypeInfo
,
5312 ITypeLib2_fnGetTypeInfoType
,
5313 ITypeLib2_fnGetTypeInfoOfGuid
,
5314 ITypeLib2_fnGetLibAttr
,
5315 ITypeLib2_fnGetTypeComp
,
5316 ITypeLib2_fnGetDocumentation
,
5318 ITypeLib2_fnFindName
,
5319 ITypeLib2_fnReleaseTLibAttr
,
5321 ITypeLib2_fnGetCustData
,
5322 ITypeLib2_fnGetLibStatistics
,
5323 ITypeLib2_fnGetDocumentation2
,
5324 ITypeLib2_fnGetAllCustData
5328 static HRESULT WINAPI
ITypeLibComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
5330 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5332 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, ppv
);
5335 static ULONG WINAPI
ITypeLibComp_fnAddRef(ITypeComp
* iface
)
5337 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5339 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
5342 static ULONG WINAPI
ITypeLibComp_fnRelease(ITypeComp
* iface
)
5344 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5346 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
5349 static HRESULT WINAPI
ITypeLibComp_fnBind(
5354 ITypeInfo
** ppTInfo
,
5355 DESCKIND
* pDescKind
,
5358 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5359 BOOL typemismatch
= FALSE
;
5362 TRACE("(%p)->(%s, 0x%x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5364 *pDescKind
= DESCKIND_NONE
;
5365 pBindPtr
->lptcomp
= NULL
;
5368 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
5369 ITypeInfoImpl
*pTypeInfo
= This
->typeinfos
[i
];
5370 TRACE("testing %s\n", debugstr_w(TLB_get_bstr(pTypeInfo
->Name
)));
5372 /* FIXME: check wFlags here? */
5373 /* FIXME: we should use a hash table to look this info up using lHash
5374 * instead of an O(n) search */
5375 if ((pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
) ||
5376 (pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
))
5378 if (pTypeInfo
->Name
&& !wcscmp(pTypeInfo
->Name
->str
, szName
))
5380 *pDescKind
= DESCKIND_TYPECOMP
;
5381 pBindPtr
->lptcomp
= &pTypeInfo
->ITypeComp_iface
;
5382 ITypeComp_AddRef(pBindPtr
->lptcomp
);
5383 TRACE("module or enum: %s\n", debugstr_w(szName
));
5388 if ((pTypeInfo
->typeattr
.typekind
== TKIND_MODULE
) ||
5389 (pTypeInfo
->typeattr
.typekind
== TKIND_ENUM
))
5391 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5394 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
5395 if (SUCCEEDED(hr
) && (*pDescKind
!= DESCKIND_NONE
))
5397 TRACE("found in module or in enum: %s\n", debugstr_w(szName
));
5400 else if (hr
== TYPE_E_TYPEMISMATCH
)
5401 typemismatch
= TRUE
;
5404 if ((pTypeInfo
->typeattr
.typekind
== TKIND_COCLASS
) &&
5405 (pTypeInfo
->typeattr
.wTypeFlags
& TYPEFLAG_FAPPOBJECT
))
5407 ITypeComp
*pSubTypeComp
= &pTypeInfo
->ITypeComp_iface
;
5409 ITypeInfo
*subtypeinfo
;
5411 DESCKIND subdesckind
;
5413 hr
= ITypeComp_Bind(pSubTypeComp
, szName
, lHash
, wFlags
,
5414 &subtypeinfo
, &subdesckind
, &subbindptr
);
5415 if (SUCCEEDED(hr
) && (subdesckind
!= DESCKIND_NONE
))
5417 TYPEDESC tdesc_appobject
;
5418 const VARDESC vardesc_appobject
=
5421 NULL
, /* lpstrSchema */
5436 VAR_STATIC
/* varkind */
5439 tdesc_appobject
.u
.hreftype
= pTypeInfo
->hreftype
;
5440 tdesc_appobject
.vt
= VT_USERDEFINED
;
5442 TRACE("found in implicit app object: %s\n", debugstr_w(szName
));
5444 /* cleanup things filled in by Bind call so we can put our
5445 * application object data in there instead */
5446 switch (subdesckind
)
5448 case DESCKIND_FUNCDESC
:
5449 ITypeInfo_ReleaseFuncDesc(subtypeinfo
, subbindptr
.lpfuncdesc
);
5451 case DESCKIND_VARDESC
:
5452 ITypeInfo_ReleaseVarDesc(subtypeinfo
, subbindptr
.lpvardesc
);
5457 if (subtypeinfo
) ITypeInfo_Release(subtypeinfo
);
5459 if (pTypeInfo
->hreftype
== -1)
5460 FIXME("no hreftype for interface %p\n", pTypeInfo
);
5462 hr
= TLB_AllocAndInitVarDesc(&vardesc_appobject
, &pBindPtr
->lpvardesc
);
5466 *pDescKind
= DESCKIND_IMPLICITAPPOBJ
;
5467 *ppTInfo
= (ITypeInfo
*)&pTypeInfo
->ITypeInfo2_iface
;
5468 ITypeInfo_AddRef(*ppTInfo
);
5471 else if (hr
== TYPE_E_TYPEMISMATCH
)
5472 typemismatch
= TRUE
;
5478 TRACE("type mismatch %s\n", debugstr_w(szName
));
5479 return TYPE_E_TYPEMISMATCH
;
5483 TRACE("name not found %s\n", debugstr_w(szName
));
5488 static HRESULT WINAPI
ITypeLibComp_fnBindType(
5492 ITypeInfo
** ppTInfo
,
5493 ITypeComp
** ppTComp
)
5495 ITypeLibImpl
*This
= impl_from_ITypeComp(iface
);
5496 ITypeInfoImpl
*info
;
5498 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
5500 if(!szName
|| !ppTInfo
|| !ppTComp
)
5501 return E_INVALIDARG
;
5503 info
= TLB_get_typeinfo_by_name(This
, szName
);
5510 *ppTInfo
= (ITypeInfo
*)&info
->ITypeInfo2_iface
;
5511 ITypeInfo_AddRef(*ppTInfo
);
5512 *ppTComp
= &info
->ITypeComp_iface
;
5513 ITypeComp_AddRef(*ppTComp
);
5518 static const ITypeCompVtbl tlbtcvt
=
5521 ITypeLibComp_fnQueryInterface
,
5522 ITypeLibComp_fnAddRef
,
5523 ITypeLibComp_fnRelease
,
5525 ITypeLibComp_fnBind
,
5526 ITypeLibComp_fnBindType
5529 /*================== ITypeInfo(2) Methods ===================================*/
5530 static ITypeInfoImpl
* ITypeInfoImpl_Constructor(void)
5532 ITypeInfoImpl
*pTypeInfoImpl
;
5534 pTypeInfoImpl
= heap_alloc_zero(sizeof(ITypeInfoImpl
));
5537 pTypeInfoImpl
->ITypeInfo2_iface
.lpVtbl
= &tinfvt
;
5538 pTypeInfoImpl
->ITypeComp_iface
.lpVtbl
= &tcompvt
;
5539 pTypeInfoImpl
->ICreateTypeInfo2_iface
.lpVtbl
= &CreateTypeInfo2Vtbl
;
5540 pTypeInfoImpl
->ref
= 0;
5541 pTypeInfoImpl
->hreftype
= -1;
5542 pTypeInfoImpl
->typeattr
.memidConstructor
= MEMBERID_NIL
;
5543 pTypeInfoImpl
->typeattr
.memidDestructor
= MEMBERID_NIL
;
5544 pTypeInfoImpl
->pcustdata_list
= &pTypeInfoImpl
->custdata_list
;
5545 list_init(pTypeInfoImpl
->pcustdata_list
);
5547 TRACE("(%p)\n", pTypeInfoImpl
);
5548 return pTypeInfoImpl
;
5551 /* ITypeInfo::QueryInterface
5553 static HRESULT WINAPI
ITypeInfo_fnQueryInterface(
5558 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5560 TRACE("(%p)->(IID: %s)\n",This
,debugstr_guid(riid
));
5563 if(IsEqualIID(riid
, &IID_IUnknown
) ||
5564 IsEqualIID(riid
,&IID_ITypeInfo
)||
5565 IsEqualIID(riid
,&IID_ITypeInfo2
))
5566 *ppvObject
= &This
->ITypeInfo2_iface
;
5567 else if(IsEqualIID(riid
, &IID_ICreateTypeInfo
) ||
5568 IsEqualIID(riid
, &IID_ICreateTypeInfo2
))
5569 *ppvObject
= &This
->ICreateTypeInfo2_iface
;
5570 else if(IsEqualIID(riid
, &IID_ITypeComp
))
5571 *ppvObject
= &This
->ITypeComp_iface
;
5574 IUnknown_AddRef((IUnknown
*)*ppvObject
);
5575 TRACE("-- Interface: (%p)->(%p)\n",ppvObject
,*ppvObject
);
5578 TRACE("-- Interface: E_NOINTERFACE\n");
5579 return E_NOINTERFACE
;
5582 /* ITypeInfo::AddRef
5584 static ULONG WINAPI
ITypeInfo_fnAddRef( ITypeInfo2
*iface
)
5586 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5587 ULONG ref
= InterlockedIncrement(&This
->ref
);
5589 TRACE("(%p)->ref is %u\n",This
, ref
);
5591 if (ref
== 1 /* incremented from 0 */)
5592 ITypeLib2_AddRef(&This
->pTypeLib
->ITypeLib2_iface
);
5597 static void ITypeInfoImpl_Destroy(ITypeInfoImpl
*This
)
5601 TRACE("destroying ITypeInfo(%p)\n",This
);
5603 for (i
= 0; i
< This
->typeattr
.cFuncs
; ++i
)
5606 TLBFuncDesc
*pFInfo
= &This
->funcdescs
[i
];
5607 for(j
= 0; j
< pFInfo
->funcdesc
.cParams
; j
++)
5609 ELEMDESC
*elemdesc
= &pFInfo
->funcdesc
.lprgelemdescParam
[j
];
5610 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5611 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5612 TLB_FreeCustData(&pFInfo
->pParamDesc
[j
].custdata_list
);
5614 heap_free(pFInfo
->funcdesc
.lprgelemdescParam
);
5615 heap_free(pFInfo
->pParamDesc
);
5616 TLB_FreeCustData(&pFInfo
->custdata_list
);
5618 heap_free(This
->funcdescs
);
5620 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
)
5622 TLBVarDesc
*pVInfo
= &This
->vardescs
[i
];
5623 if (pVInfo
->vardesc_create
) {
5624 TLB_FreeVarDesc(pVInfo
->vardesc_create
);
5625 } else if (pVInfo
->vardesc
.varkind
== VAR_CONST
) {
5626 VariantClear(pVInfo
->vardesc
.u
.lpvarValue
);
5627 heap_free(pVInfo
->vardesc
.u
.lpvarValue
);
5629 TLB_FreeCustData(&pVInfo
->custdata_list
);
5631 heap_free(This
->vardescs
);
5633 if(This
->impltypes
){
5634 for (i
= 0; i
< This
->typeattr
.cImplTypes
; ++i
){
5635 TLBImplType
*pImpl
= &This
->impltypes
[i
];
5636 TLB_FreeCustData(&pImpl
->custdata_list
);
5638 heap_free(This
->impltypes
);
5641 TLB_FreeCustData(&This
->custdata_list
);
5646 /* ITypeInfo::Release
5648 static ULONG WINAPI
ITypeInfo_fnRelease(ITypeInfo2
*iface
)
5650 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5651 ULONG ref
= InterlockedDecrement(&This
->ref
);
5653 TRACE("(%p)->(%u)\n",This
, ref
);
5657 BOOL not_attached_to_typelib
= This
->not_attached_to_typelib
;
5658 ITypeLib2_Release(&This
->pTypeLib
->ITypeLib2_iface
);
5659 if (not_attached_to_typelib
)
5661 /* otherwise This will be freed when typelib is freed */
5667 /* ITypeInfo::GetTypeAttr
5669 * Retrieves a TYPEATTR structure that contains the attributes of the type
5673 static HRESULT WINAPI
ITypeInfo_fnGetTypeAttr( ITypeInfo2
*iface
,
5674 LPTYPEATTR
*ppTypeAttr
)
5676 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5679 TRACE("(%p)\n",This
);
5681 size
= sizeof(**ppTypeAttr
);
5682 if (This
->typeattr
.typekind
== TKIND_ALIAS
&& This
->tdescAlias
)
5683 size
+= TLB_SizeTypeDesc(This
->tdescAlias
, FALSE
);
5685 *ppTypeAttr
= heap_alloc(size
);
5687 return E_OUTOFMEMORY
;
5689 **ppTypeAttr
= This
->typeattr
;
5690 (*ppTypeAttr
)->guid
= *TLB_get_guid_null(This
->guid
);
5692 if (This
->tdescAlias
)
5693 TLB_CopyTypeDesc(&(*ppTypeAttr
)->tdescAlias
, This
->tdescAlias
, *ppTypeAttr
+ 1);
5695 if((*ppTypeAttr
)->typekind
== TKIND_DISPATCH
) {
5696 /* This should include all the inherited funcs */
5697 (*ppTypeAttr
)->cFuncs
= (*ppTypeAttr
)->cbSizeVft
/ This
->pTypeLib
->ptr_size
;
5698 /* This is always the size of IDispatch's vtbl */
5699 (*ppTypeAttr
)->cbSizeVft
= sizeof(IDispatchVtbl
);
5700 (*ppTypeAttr
)->wTypeFlags
&= ~TYPEFLAG_FOLEAUTOMATION
;
5705 /* ITypeInfo::GetTypeComp
5707 * Retrieves the ITypeComp interface for the type description, which enables a
5708 * client compiler to bind to the type description's members.
5711 static HRESULT WINAPI
ITypeInfo_fnGetTypeComp( ITypeInfo2
*iface
,
5712 ITypeComp
* *ppTComp
)
5714 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5716 TRACE("(%p)->(%p)\n", This
, ppTComp
);
5718 *ppTComp
= &This
->ITypeComp_iface
;
5719 ITypeComp_AddRef(*ppTComp
);
5723 static SIZE_T
TLB_SizeElemDesc( const ELEMDESC
*elemdesc
)
5725 SIZE_T size
= TLB_SizeTypeDesc(&elemdesc
->tdesc
, FALSE
);
5726 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5727 size
+= sizeof(*elemdesc
->u
.paramdesc
.pparamdescex
);
5731 static HRESULT
TLB_CopyElemDesc( const ELEMDESC
*src
, ELEMDESC
*dest
, char **buffer
)
5734 *buffer
= TLB_CopyTypeDesc(&dest
->tdesc
, &src
->tdesc
, *buffer
);
5735 if (src
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5737 const PARAMDESCEX
*pparamdescex_src
= src
->u
.paramdesc
.pparamdescex
;
5738 PARAMDESCEX
*pparamdescex_dest
= dest
->u
.paramdesc
.pparamdescex
= (PARAMDESCEX
*)*buffer
;
5739 *buffer
+= sizeof(PARAMDESCEX
);
5740 *pparamdescex_dest
= *pparamdescex_src
;
5741 pparamdescex_dest
->cBytes
= sizeof(PARAMDESCEX
);
5742 VariantInit(&pparamdescex_dest
->varDefaultValue
);
5743 return VariantCopy(&pparamdescex_dest
->varDefaultValue
,
5744 (VARIANTARG
*)&pparamdescex_src
->varDefaultValue
);
5747 dest
->u
.paramdesc
.pparamdescex
= NULL
;
5751 static HRESULT
TLB_SanitizeBSTR(BSTR str
)
5753 UINT len
= SysStringLen(str
), i
;
5754 for (i
= 0; i
< len
; ++i
)
5760 static HRESULT
TLB_SanitizeVariant(VARIANT
*var
)
5762 if (V_VT(var
) == VT_INT
)
5763 return VariantChangeType(var
, var
, 0, VT_I4
);
5764 else if (V_VT(var
) == VT_UINT
)
5765 return VariantChangeType(var
, var
, 0, VT_UI4
);
5766 else if (V_VT(var
) == VT_BSTR
)
5767 return TLB_SanitizeBSTR(V_BSTR(var
));
5772 static void TLB_FreeElemDesc( ELEMDESC
*elemdesc
)
5774 if (elemdesc
->u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
5775 VariantClear(&elemdesc
->u
.paramdesc
.pparamdescex
->varDefaultValue
);
5778 static HRESULT
TLB_AllocAndInitFuncDesc( const FUNCDESC
*src
, FUNCDESC
**dest_ptr
, BOOL dispinterface
)
5782 SIZE_T size
= sizeof(*src
);
5786 size
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5787 size
+= TLB_SizeElemDesc(&src
->elemdescFunc
);
5788 for (i
= 0; i
< src
->cParams
; i
++)
5790 size
+= sizeof(ELEMDESC
);
5791 size
+= TLB_SizeElemDesc(&src
->lprgelemdescParam
[i
]);
5794 dest
= (FUNCDESC
*)SysAllocStringByteLen(NULL
, size
);
5795 if (!dest
) return E_OUTOFMEMORY
;
5798 if (dispinterface
) /* overwrite funckind */
5799 dest
->funckind
= FUNC_DISPATCH
;
5800 buffer
= (char *)(dest
+ 1);
5802 dest
->oVft
= dest
->oVft
& 0xFFFC;
5804 if (dest
->cScodes
) {
5805 dest
->lprgscode
= (SCODE
*)buffer
;
5806 memcpy(dest
->lprgscode
, src
->lprgscode
, sizeof(*src
->lprgscode
) * src
->cScodes
);
5807 buffer
+= sizeof(*src
->lprgscode
) * src
->cScodes
;
5809 dest
->lprgscode
= NULL
;
5811 hr
= TLB_CopyElemDesc(&src
->elemdescFunc
, &dest
->elemdescFunc
, &buffer
);
5814 SysFreeString((BSTR
)dest
);
5818 if (dest
->cParams
) {
5819 dest
->lprgelemdescParam
= (ELEMDESC
*)buffer
;
5820 buffer
+= sizeof(ELEMDESC
) * src
->cParams
;
5821 for (i
= 0; i
< src
->cParams
; i
++)
5823 hr
= TLB_CopyElemDesc(&src
->lprgelemdescParam
[i
], &dest
->lprgelemdescParam
[i
], &buffer
);
5829 /* undo the above actions */
5830 for (i
= i
- 1; i
>= 0; i
--)
5831 TLB_FreeElemDesc(&dest
->lprgelemdescParam
[i
]);
5832 TLB_FreeElemDesc(&dest
->elemdescFunc
);
5833 SysFreeString((BSTR
)dest
);
5837 dest
->lprgelemdescParam
= NULL
;
5839 /* special treatment for dispinterfaces: this makes functions appear
5840 * to return their [retval] value when it is really returning an
5842 if (dispinterface
&& dest
->elemdescFunc
.tdesc
.vt
== VT_HRESULT
)
5844 if (dest
->cParams
&&
5845 (dest
->lprgelemdescParam
[dest
->cParams
- 1].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
))
5847 ELEMDESC
*elemdesc
= &dest
->lprgelemdescParam
[dest
->cParams
- 1];
5848 if (elemdesc
->tdesc
.vt
!= VT_PTR
)
5850 ERR("elemdesc should have started with VT_PTR instead of:\n");
5852 dump_ELEMDESC(elemdesc
);
5853 return E_UNEXPECTED
;
5856 /* copy last parameter to the return value. we are using a flat
5857 * buffer so there is no danger of leaking memory in
5859 dest
->elemdescFunc
.tdesc
= *elemdesc
->tdesc
.u
.lptdesc
;
5861 /* remove the last parameter */
5865 /* otherwise this function is made to appear to have no return
5867 dest
->elemdescFunc
.tdesc
.vt
= VT_VOID
;
5875 static void TLB_FreeVarDesc(VARDESC
*var_desc
)
5877 TLB_FreeElemDesc(&var_desc
->elemdescVar
);
5878 if (var_desc
->varkind
== VAR_CONST
)
5879 VariantClear(var_desc
->u
.lpvarValue
);
5880 SysFreeString((BSTR
)var_desc
);
5883 /* internal function to make the inherited interfaces' methods appear
5884 * part of the interface */
5885 static HRESULT
ITypeInfoImpl_GetInternalDispatchFuncDesc( ITypeInfo
*iface
,
5886 UINT index
, const TLBFuncDesc
**ppFuncDesc
, UINT
*funcs
, UINT
*hrefoffset
)
5888 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5890 UINT implemented_funcs
= 0;
5895 *hrefoffset
= DISPATCH_HREF_OFFSET
;
5899 ITypeInfo
*pSubTypeInfo
;
5902 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
5906 hr
= ITypeInfoImpl_GetInternalDispatchFuncDesc(pSubTypeInfo
,
5909 &sub_funcs
, hrefoffset
);
5910 implemented_funcs
+= sub_funcs
;
5911 ITypeInfo_Release(pSubTypeInfo
);
5914 *hrefoffset
+= DISPATCH_HREF_OFFSET
;
5918 *funcs
= implemented_funcs
+ This
->typeattr
.cFuncs
;
5922 if (index
< implemented_funcs
)
5923 return E_INVALIDARG
;
5924 index
-= implemented_funcs
;
5926 if (index
>= This
->typeattr
.cFuncs
)
5927 return TYPE_E_ELEMENTNOTFOUND
;
5929 *ppFuncDesc
= &This
->funcdescs
[index
];
5933 static HRESULT
ITypeInfoImpl_GetInternalFuncDesc( ITypeInfo
*iface
, UINT index
, const TLBFuncDesc
**func_desc
, UINT
*hrefoffset
)
5935 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
5937 if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
5938 return ITypeInfoImpl_GetInternalDispatchFuncDesc(iface
, index
, func_desc
, NULL
, hrefoffset
);
5940 if (index
>= This
->typeattr
.cFuncs
)
5941 return TYPE_E_ELEMENTNOTFOUND
;
5943 *func_desc
= &This
->funcdescs
[index
];
5947 static inline void ITypeInfoImpl_ElemDescAddHrefOffset( LPELEMDESC pElemDesc
, UINT hrefoffset
)
5949 TYPEDESC
*pTypeDesc
= &pElemDesc
->tdesc
;
5952 switch (pTypeDesc
->vt
)
5954 case VT_USERDEFINED
:
5955 pTypeDesc
->u
.hreftype
+= hrefoffset
;
5959 pTypeDesc
= pTypeDesc
->u
.lptdesc
;
5962 pTypeDesc
= &pTypeDesc
->u
.lpadesc
->tdescElem
;
5970 static inline void ITypeInfoImpl_FuncDescAddHrefOffset( LPFUNCDESC pFuncDesc
, UINT hrefoffset
)
5973 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
5974 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->lprgelemdescParam
[i
], hrefoffset
);
5975 ITypeInfoImpl_ElemDescAddHrefOffset(&pFuncDesc
->elemdescFunc
, hrefoffset
);
5978 /* ITypeInfo::GetFuncDesc
5980 * Retrieves the FUNCDESC structure that contains information about a
5981 * specified function.
5984 static HRESULT WINAPI
ITypeInfo_fnGetFuncDesc( ITypeInfo2
*iface
, UINT index
,
5985 LPFUNCDESC
*ppFuncDesc
)
5987 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
5988 const TLBFuncDesc
*internal_funcdesc
;
5990 UINT hrefoffset
= 0;
5992 TRACE("(%p) index %d\n", This
, index
);
5995 return E_INVALIDARG
;
5997 if (This
->needs_layout
)
5998 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6000 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
,
6001 &internal_funcdesc
, &hrefoffset
);
6004 WARN("description for function %d not found\n", index
);
6008 hr
= TLB_AllocAndInitFuncDesc(
6009 &internal_funcdesc
->funcdesc
,
6011 This
->typeattr
.typekind
== TKIND_DISPATCH
);
6013 if ((This
->typeattr
.typekind
== TKIND_DISPATCH
) && hrefoffset
)
6014 ITypeInfoImpl_FuncDescAddHrefOffset(*ppFuncDesc
, hrefoffset
);
6016 TRACE("-- 0x%08x\n", hr
);
6020 static HRESULT
TLB_AllocAndInitVarDesc( const VARDESC
*src
, VARDESC
**dest_ptr
)
6024 SIZE_T size
= sizeof(*src
);
6027 if (src
->lpstrSchema
) size
+= (lstrlenW(src
->lpstrSchema
) + 1) * sizeof(WCHAR
);
6028 if (src
->varkind
== VAR_CONST
)
6029 size
+= sizeof(VARIANT
);
6030 size
+= TLB_SizeElemDesc(&src
->elemdescVar
);
6032 dest
= (VARDESC
*)SysAllocStringByteLen(NULL
, size
);
6033 if (!dest
) return E_OUTOFMEMORY
;
6036 buffer
= (char *)(dest
+ 1);
6037 if (src
->lpstrSchema
)
6040 dest
->lpstrSchema
= (LPOLESTR
)buffer
;
6041 len
= lstrlenW(src
->lpstrSchema
);
6042 memcpy(dest
->lpstrSchema
, src
->lpstrSchema
, (len
+ 1) * sizeof(WCHAR
));
6043 buffer
+= (len
+ 1) * sizeof(WCHAR
);
6046 if (src
->varkind
== VAR_CONST
)
6050 dest
->u
.lpvarValue
= (VARIANT
*)buffer
;
6051 *dest
->u
.lpvarValue
= *src
->u
.lpvarValue
;
6052 buffer
+= sizeof(VARIANT
);
6053 VariantInit(dest
->u
.lpvarValue
);
6054 hr
= VariantCopy(dest
->u
.lpvarValue
, src
->u
.lpvarValue
);
6057 SysFreeString((BSTR
)dest
);
6061 hr
= TLB_CopyElemDesc(&src
->elemdescVar
, &dest
->elemdescVar
, &buffer
);
6064 if (src
->varkind
== VAR_CONST
)
6065 VariantClear(dest
->u
.lpvarValue
);
6066 SysFreeString((BSTR
)dest
);
6073 /* ITypeInfo::GetVarDesc
6075 * Retrieves a VARDESC structure that describes the specified variable.
6078 static HRESULT WINAPI
ITypeInfo_fnGetVarDesc( ITypeInfo2
*iface
, UINT index
,
6079 LPVARDESC
*ppVarDesc
)
6081 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6082 const TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
6084 TRACE("(%p) index %d\n", This
, index
);
6086 if(index
>= This
->typeattr
.cVars
)
6087 return TYPE_E_ELEMENTNOTFOUND
;
6089 if (This
->needs_layout
)
6090 ICreateTypeInfo2_LayOut(&This
->ICreateTypeInfo2_iface
);
6092 return TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, ppVarDesc
);
6095 /* ITypeInfo_GetNames
6097 * Retrieves the variable with the specified member ID (or the name of the
6098 * property or method and its parameters) that correspond to the specified
6101 static HRESULT WINAPI
ITypeInfo_fnGetNames( ITypeInfo2
*iface
, MEMBERID memid
,
6102 BSTR
*rgBstrNames
, UINT cMaxNames
, UINT
*pcNames
)
6104 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6105 const TLBFuncDesc
*pFDesc
;
6106 const TLBVarDesc
*pVDesc
;
6108 TRACE("(%p) memid=0x%08x Maxname=%d\n", This
, memid
, cMaxNames
);
6111 return E_INVALIDARG
;
6115 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
6118 if(!cMaxNames
|| !pFDesc
->Name
)
6121 *rgBstrNames
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
6124 for(i
= 0; i
< pFDesc
->funcdesc
.cParams
; ++i
){
6125 if(*pcNames
>= cMaxNames
|| !pFDesc
->pParamDesc
[i
].Name
)
6127 rgBstrNames
[*pcNames
] = SysAllocString(TLB_get_bstr(pFDesc
->pParamDesc
[i
].Name
));
6133 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
6136 *rgBstrNames
=SysAllocString(TLB_get_bstr(pVDesc
->Name
));
6141 if(This
->impltypes
&&
6142 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
6143 /* recursive search */
6146 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6147 if(SUCCEEDED(result
))
6149 result
=ITypeInfo_GetNames(pTInfo
, memid
, rgBstrNames
, cMaxNames
, pcNames
);
6150 ITypeInfo_Release(pTInfo
);
6153 WARN("Could not search inherited interface!\n");
6157 WARN("no names found\n");
6160 return TYPE_E_ELEMENTNOTFOUND
;
6166 /* ITypeInfo::GetRefTypeOfImplType
6168 * If a type description describes a COM class, it retrieves the type
6169 * description of the implemented interface types. For an interface,
6170 * GetRefTypeOfImplType returns the type information for inherited interfaces,
6174 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeOfImplType(
6179 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6182 TRACE("(%p) index %d\n", This
, index
);
6183 if (TRACE_ON(ole
)) dump_TypeInfo(This
);
6187 /* only valid on dual interfaces;
6188 retrieve the associated TKIND_INTERFACE handle for the current TKIND_DISPATCH
6191 if (This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
6197 hr
= TYPE_E_ELEMENTNOTFOUND
;
6200 else if(index
== 0 && This
->typeattr
.typekind
== TKIND_DISPATCH
)
6202 /* All TKIND_DISPATCHs are made to look like they inherit from IDispatch */
6203 *pRefType
= This
->pTypeLib
->dispatch_href
;
6207 if(index
>= This
->typeattr
.cImplTypes
)
6208 hr
= TYPE_E_ELEMENTNOTFOUND
;
6210 *pRefType
= This
->impltypes
[index
].hRef
;
6211 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
6219 TRACE("SUCCESS -- hRef = 0x%08x\n", *pRefType
);
6221 TRACE("FAILURE -- hresult = 0x%08x\n", hr
);
6227 /* ITypeInfo::GetImplTypeFlags
6229 * Retrieves the IMPLTYPEFLAGS enumeration for one implemented interface
6230 * or base interface in a type description.
6232 static HRESULT WINAPI
ITypeInfo_fnGetImplTypeFlags( ITypeInfo2
*iface
,
6233 UINT index
, INT
*pImplTypeFlags
)
6235 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6237 TRACE("(%p) index %d\n", This
, index
);
6240 return E_INVALIDARG
;
6242 if(This
->typeattr
.typekind
== TKIND_DISPATCH
&& index
== 0){
6243 *pImplTypeFlags
= 0;
6247 if(index
>= This
->typeattr
.cImplTypes
)
6248 return TYPE_E_ELEMENTNOTFOUND
;
6250 *pImplTypeFlags
= This
->impltypes
[index
].implflags
;
6256 * Maps between member names and member IDs, and parameter names and
6259 static HRESULT WINAPI
ITypeInfo_fnGetIDsOfNames( ITypeInfo2
*iface
,
6260 LPOLESTR
*rgszNames
, UINT cNames
, MEMBERID
*pMemId
)
6262 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
6263 const TLBVarDesc
*pVDesc
;
6267 TRACE("(%p) Name %s cNames %d\n", This
, debugstr_w(*rgszNames
),
6270 /* init out parameters in case of failure */
6271 for (i
= 0; i
< cNames
; i
++)
6272 pMemId
[i
] = MEMBERID_NIL
;
6274 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
) {
6276 const TLBFuncDesc
*pFDesc
= &This
->funcdescs
[fdc
];
6277 if(!lstrcmpiW(*rgszNames
, TLB_get_bstr(pFDesc
->Name
))) {
6278 if(cNames
) *pMemId
=pFDesc
->funcdesc
.memid
;
6279 for(i
=1; i
< cNames
; i
++){
6280 for(j
=0; j
<pFDesc
->funcdesc
.cParams
; j
++)
6281 if(!lstrcmpiW(rgszNames
[i
],TLB_get_bstr(pFDesc
->pParamDesc
[j
].Name
)))
6283 if( j
<pFDesc
->funcdesc
.cParams
)
6286 ret
=DISP_E_UNKNOWNNAME
;
6288 TRACE("-- 0x%08x\n", ret
);
6292 pVDesc
= TLB_get_vardesc_by_name(This
, *rgszNames
);
6295 *pMemId
= pVDesc
->vardesc
.memid
;
6298 /* not found, see if it can be found in an inherited interface */
6299 if(This
->impltypes
) {
6300 /* recursive search */
6302 ret
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
6304 ret
=ITypeInfo_GetIDsOfNames(pTInfo
, rgszNames
, cNames
, pMemId
);
6305 ITypeInfo_Release(pTInfo
);
6308 WARN("Could not search inherited interface!\n");
6310 WARN("no names found\n");
6311 return DISP_E_UNKNOWNNAME
;
6317 extern LONGLONG
call_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6318 extern double call_double_method( void *func
, int nb_args
, const DWORD
*args
, int *stack_offset
);
6319 __ASM_GLOBAL_FUNC( call_method
,
6321 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t")
6322 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t")
6323 "movl %esp,%ebp\n\t"
6324 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t")
6326 __ASM_CFI(".cfi_rel_offset %esi,-4\n\t")
6328 __ASM_CFI(".cfi_rel_offset %edi,-8\n\t")
6329 "movl 12(%ebp),%edx\n\t"
6330 "movl %esp,%edi\n\t"
6333 "subl %edx,%edi\n\t"
6334 "andl $~15,%edi\n\t"
6335 "movl %edi,%esp\n\t"
6336 "movl 12(%ebp),%ecx\n\t"
6337 "movl 16(%ebp),%esi\n\t"
6340 "1:\tcall *8(%ebp)\n\t"
6341 "subl %esp,%edi\n\t"
6342 "movl 20(%ebp),%ecx\n\t"
6343 "movl %edi,(%ecx)\n\t"
6344 "leal -8(%ebp),%esp\n\t"
6346 __ASM_CFI(".cfi_same_value %edi\n\t")
6348 __ASM_CFI(".cfi_same_value %esi\n\t")
6350 __ASM_CFI(".cfi_def_cfa %esp,4\n\t")
6351 __ASM_CFI(".cfi_same_value %ebp\n\t")
6353 __ASM_GLOBAL_FUNC( call_double_method
,
6354 "jmp " __ASM_NAME("call_method") )
6356 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6357 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6359 int argspos
= 0, stack_offset
;
6364 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6365 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6366 pvargResult
, V_VT(pvargResult
));
6368 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6370 FIXME("unsupported calling convention %d\n",cc
);
6371 return E_INVALIDARG
;
6374 /* maximum size for an argument is sizeof(VARIANT) */
6375 args
= heap_alloc(sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 2 );
6379 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6380 func
= vtable
[oVft
/sizeof(void *)];
6381 args
[argspos
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6383 else func
= (void *)oVft
;
6389 args
[argspos
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6392 WARN("invalid return type %u\n", vtReturn
);
6394 return E_INVALIDARG
;
6399 for (i
= 0; i
< cActuals
; i
++)
6401 VARIANT
*arg
= prgpvarg
[i
];
6412 memcpy( &args
[argspos
], &V_I8(arg
), sizeof(V_I8(arg
)) );
6413 argspos
+= sizeof(V_I8(arg
)) / sizeof(DWORD
);
6417 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6418 argspos
+= sizeof(*arg
) / sizeof(DWORD
);
6420 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6421 args
[argspos
++] = V_BOOL(arg
);
6424 args
[argspos
++] = V_UI4(arg
);
6427 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6435 call_method( func
, argspos
, args
, &stack_offset
);
6438 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6442 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, &stack_offset
);
6447 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6450 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, &stack_offset
);
6454 if (stack_offset
&& cc
== CC_STDCALL
)
6456 WARN( "stack pointer off by %d\n", stack_offset
);
6457 return DISP_E_BADCALLEE
;
6459 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6460 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6464 #elif defined(__x86_64__)
6466 extern DWORD_PTR CDECL
call_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6467 extern double CDECL
call_double_method( void *func
, int nb_args
, const DWORD_PTR
*args
);
6468 __ASM_GLOBAL_FUNC( call_method
,
6470 __ASM_SEH(".seh_pushreg %rbp\n\t")
6471 __ASM_CFI(".cfi_adjust_cfa_offset 8\n\t")
6472 __ASM_CFI(".cfi_rel_offset %rbp,0\n\t")
6473 "movq %rsp,%rbp\n\t"
6474 __ASM_SEH(".seh_setframe %rbp,0\n\t")
6475 __ASM_CFI(".cfi_def_cfa_register %rbp\n\t")
6477 __ASM_SEH(".seh_pushreg %rsi\n\t")
6478 __ASM_CFI(".cfi_rel_offset %rsi,-8\n\t")
6480 __ASM_SEH(".seh_pushreg %rdi\n\t")
6481 __ASM_CFI(".cfi_rel_offset %rdi,-16\n\t")
6482 __ASM_SEH(".seh_endprologue\n\t")
6483 "movq %rcx,%rax\n\t"
6486 "cmovgq %rdx,%rcx\n\t"
6487 "leaq 0(,%rcx,8),%rdx\n\t"
6488 "subq %rdx,%rsp\n\t"
6489 "andq $~15,%rsp\n\t"
6490 "movq %rsp,%rdi\n\t"
6493 "movq 0(%rsp),%rcx\n\t"
6494 "movq 8(%rsp),%rdx\n\t"
6495 "movq 16(%rsp),%r8\n\t"
6496 "movq 24(%rsp),%r9\n\t"
6497 "movq 0(%rsp),%xmm0\n\t"
6498 "movq 8(%rsp),%xmm1\n\t"
6499 "movq 16(%rsp),%xmm2\n\t"
6500 "movq 24(%rsp),%xmm3\n\t"
6502 "leaq -16(%rbp),%rsp\n\t"
6504 __ASM_CFI(".cfi_same_value %rdi\n\t")
6506 __ASM_CFI(".cfi_same_value %rsi\n\t")
6507 __ASM_CFI(".cfi_def_cfa_register %rsp\n\t")
6509 __ASM_CFI(".cfi_adjust_cfa_offset -8\n\t")
6510 __ASM_CFI(".cfi_same_value %rbp\n\t")
6512 __ASM_GLOBAL_FUNC( call_double_method
,
6513 "jmp " __ASM_NAME("call_method") )
6515 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6516 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6523 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6524 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
,
6525 pvargResult
, V_VT(pvargResult
));
6527 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6529 FIXME("unsupported calling convention %d\n",cc
);
6530 return E_INVALIDARG
;
6533 /* maximum size for an argument is sizeof(DWORD_PTR) */
6534 args
= heap_alloc( sizeof(DWORD_PTR
) * (cActuals
+ 2) );
6538 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6539 func
= vtable
[oVft
/sizeof(void *)];
6540 args
[argspos
++] = (DWORD_PTR
)pvInstance
; /* the This pointer is always the first parameter */
6542 else func
= (void *)oVft
;
6548 args
[argspos
++] = (DWORD_PTR
)pvargResult
; /* arg 0 is a pointer to the result */
6551 WARN("invalid return type %u\n", vtReturn
);
6553 return E_INVALIDARG
;
6558 for (i
= 0; i
< cActuals
; i
++)
6560 VARIANT
*arg
= prgpvarg
[i
];
6566 args
[argspos
++] = (ULONG_PTR
)arg
;
6568 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6569 args
[argspos
++] = V_BOOL(arg
);
6572 args
[argspos
++] = V_UI8(arg
);
6575 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6581 V_R4(pvargResult
) = call_double_method( func
, argspos
, args
);
6585 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
);
6589 call_method( func
, argspos
, args
);
6592 V_UI8(pvargResult
) = call_method( func
, argspos
, args
);
6596 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6597 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6601 #elif defined(__arm__)
6603 extern LONGLONG CDECL
call_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6604 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6605 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD
*stk_args
, const DWORD
*reg_args
);
6606 __ASM_GLOBAL_FUNC( call_method
,
6609 * r2 = *stk_args (pointer to 'nb_stk_args' DWORD values to push on stack)
6610 * 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)
6613 "push {fp, lr}\n\t" /* Save frame pointer and return address (stack still aligned to 8 bytes) */
6614 "mov fp, sp\n\t" /* Save stack pointer as our frame for cleaning the stack on return */
6616 "lsls r1, r1, #2\n\t" /* r1 = nb_stk_args * sizeof(DWORD) */
6617 "beq 1f\n\t" /* Skip allocation if no stack args */
6618 "add r2, r2, r1\n" /* Calculate ending address of incoming stack data */
6619 "2:\tldr ip, [r2, #-4]!\n\t" /* Get next value */
6620 "str ip, [sp, #-4]!\n\t" /* Push it on the stack */
6621 "subs r1, r1, #4\n\t" /* Decrement count */
6622 "bgt 2b\n\t" /* Loop till done */
6626 "vldm r3!, {s0-s15}\n\t" /* Load the s0-s15/d0-d7 arguments */
6628 "mov ip, r0\n\t" /* Save the function call address to ip before we nuke r0 with arguments to pass */
6629 "ldm r3, {r0-r3}\n\t" /* Load the r0-r3 arguments */
6631 "blx ip\n\t" /* Call the target function */
6633 "mov sp, fp\n\t" /* Clean the stack using fp */
6634 "pop {fp, pc}\n\t" /* Restore fp and return */
6636 __ASM_GLOBAL_FUNC( call_float_method
,
6637 "b " __ASM_NAME("call_method") )
6638 __ASM_GLOBAL_FUNC( call_double_method
,
6639 "b " __ASM_NAME("call_method") )
6641 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6642 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6657 int rcount
; /* 32-bit register index count */
6659 int scount
= 0; /* single-precision float register index count */
6660 int dcount
= 0; /* double-precision float register index count */
6663 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6664 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6666 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6668 FIXME("unsupported calling convention %d\n",cc
);
6669 return E_INVALIDARG
;
6677 const FARPROC
*vtable
= *(FARPROC
**)pvInstance
;
6678 func
= vtable
[oVft
/sizeof(void *)];
6679 regs
.r
[rcount
++] = (DWORD
)pvInstance
; /* the This pointer is always the first parameter */
6681 else func
= (void *)oVft
;
6683 /* Determine if we need to pass a pointer for the return value as arg 0. If so, do that */
6684 /* first as it will need to be in the 'r' registers: */
6689 regs
.r
[rcount
++] = (DWORD
)pvargResult
; /* arg 0 is a pointer to the result */
6692 WARN("invalid return type %u\n", vtReturn
);
6693 return E_INVALIDARG
;
6694 default: /* And all others are in 'r', 's', or 'd' registers or have no return value */
6698 /* maximum size for an argument is sizeof(VARIANT). Also allow for return pointer and stack alignment. */
6699 args
= heap_alloc( sizeof(VARIANT
) * cActuals
+ sizeof(DWORD
) * 4 );
6701 for (i
= 0; i
< cActuals
; i
++)
6703 VARIANT
*arg
= prgpvarg
[i
];
6704 DWORD
*pdwarg
= (DWORD
*)(arg
); /* a reinterpret_cast of the variant, used for copying structures when they are split between registers and stack */
6705 int ntemp
; /* Used for counting words split between registers and stack */
6711 case VT_R8
: /* these must be 8-byte aligned, and put in 'd' regs or stack, as they are double-floats */
6714 dcount
= max( (scount
+ 1) / 2, dcount
);
6717 regs
.sd
.d
[dcount
++] = V_R8(arg
);
6721 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6722 memcpy( &args
[argspos
], &V_R8(arg
), sizeof(V_R8(arg
)) );
6723 argspos
+= sizeof(V_R8(arg
)) / sizeof(DWORD
);
6727 case VT_I8
: /* these must be 8-byte aligned, and put in 'r' regs or stack, as they are long-longs */
6732 rcount
+= (rcount
% 2); /* align rcount to 8-byte register pair */
6733 memcpy( ®s
.r
[rcount
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6734 rcount
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6738 rcount
= 4; /* Make sure we flag that all 'r' regs are full */
6739 argspos
+= (argspos
% 2); /* align argspos to 8-bytes */
6740 memcpy( &args
[argspos
], &V_UI8(arg
), sizeof(V_UI8(arg
)) );
6741 argspos
+= sizeof(V_UI8(arg
)) / sizeof(DWORD
);
6744 case VT_DECIMAL
: /* these structures are 8-byte aligned, and put in 'r' regs or stack, can be split between the two */
6746 /* 8-byte align 'r' and/or stack: */
6748 rcount
+= (rcount
% 2);
6752 argspos
+= (argspos
% 2);
6754 ntemp
= sizeof(*arg
) / sizeof(DWORD
);
6758 regs
.r
[rcount
++] = *pdwarg
++;
6760 args
[argspos
++] = *pdwarg
++;
6764 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6766 regs
.r
[rcount
++] = V_BOOL(arg
);
6768 args
[argspos
++] = V_BOOL(arg
);
6770 case VT_R4
: /* these must be 4-byte aligned, and put in 's' regs or stack, as they are single-floats */
6772 if (!(scount
% 2)) scount
= max( scount
, dcount
* 2 );
6774 regs
.sd
.s
[scount
++] = V_R4(arg
);
6776 args
[argspos
++] = V_UI4(arg
);
6781 regs
.r
[rcount
++] = V_UI4(arg
);
6783 args
[argspos
++] = V_UI4(arg
);
6786 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(prgvt
[i
]), debugstr_variant(arg
));
6789 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 8-byte */
6793 case VT_EMPTY
: /* EMPTY = no return value */
6794 case VT_DECIMAL
: /* DECIMAL and VARIANT already have a pointer argument passed (see above) */
6796 call_method( func
, argspos
, args
, (DWORD
*)®s
);
6799 V_R4(pvargResult
) = call_float_method( func
, argspos
, args
, (DWORD
*)®s
);
6803 V_R8(pvargResult
) = call_double_method( func
, argspos
, args
, (DWORD
*)®s
);
6808 V_UI8(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6811 V_UI4(pvargResult
) = call_method( func
, argspos
, args
, (DWORD
*)®s
);
6815 if (vtReturn
!= VT_VARIANT
) V_VT(pvargResult
) = vtReturn
;
6816 TRACE("retval: %s\n", debugstr_variant(pvargResult
));
6820 #elif defined(__aarch64__)
6822 extern DWORD_PTR CDECL
call_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6823 extern float CDECL
call_float_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6824 extern double CDECL
call_double_method( void *func
, int nb_stk_args
, const DWORD_PTR
*stk_args
, const DWORD_PTR
*reg_args
);
6825 __ASM_GLOBAL_FUNC( call_method
,
6826 "stp x29, x30, [sp, #-16]!\n\t"
6828 "sub sp, sp, x1, lsl #3\n\t"
6830 "1:\tsub x1, x1, #1\n\t"
6831 "ldr x4, [x2, x1, lsl #3]\n\t"
6832 "str x4, [sp, x1, lsl #3]\n\t"
6834 "2:\tmov x16, x0\n\t"
6836 "ldp d0, d1, [x9]\n\t"
6837 "ldp d2, d3, [x9, #0x10]\n\t"
6838 "ldp d4, d5, [x9, #0x20]\n\t"
6839 "ldp d6, d7, [x9, #0x30]\n\t"
6840 "ldp x0, x1, [x9, #0x40]\n\t"
6841 "ldp x2, x3, [x9, #0x50]\n\t"
6842 "ldp x4, x5, [x9, #0x60]\n\t"
6843 "ldp x6, x7, [x9, #0x70]\n\t"
6844 "ldr x8, [x9, #0x80]\n\t"
6847 "ldp x29, x30, [sp], #16\n\t"
6849 __ASM_GLOBAL_FUNC( call_float_method
,
6850 "b " __ASM_NAME("call_method") )
6851 __ASM_GLOBAL_FUNC( call_double_method
,
6852 "b " __ASM_NAME("call_method") )
6854 HRESULT WINAPI
DispCallFunc( void *instance
, ULONG_PTR offset
, CALLCONV cc
, VARTYPE ret_type
, UINT count
,
6855 VARTYPE
*types
, VARIANTARG
**vargs
, VARIANT
*result
)
6870 int rcount
; /* 64-bit register index count */
6871 int fpcount
= 0; /* float register index count */
6873 TRACE("(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d))\n",
6874 instance
, offset
, cc
, ret_type
, count
, types
, vargs
, result
, V_VT(result
));
6876 if (cc
!= CC_STDCALL
&& cc
!= CC_CDECL
)
6878 FIXME("unsupported calling convention %d\n",cc
);
6879 return E_INVALIDARG
;
6887 const FARPROC
*vtable
= *(FARPROC
**)instance
;
6888 func
= vtable
[offset
/sizeof(void *)];
6889 regs
.x
[rcount
++] = (DWORD_PTR
)instance
; /* the This pointer is always the first parameter */
6891 else func
= (void *)offset
;
6893 /* maximum size for an argument is 16 */
6894 args
= heap_alloc( 16 * count
);
6896 for (i
= 0; i
< count
; i
++)
6898 VARIANT
*arg
= vargs
[i
];
6903 if (fpcount
< 8) regs
.fp
[fpcount
++].f
= V_R4(arg
);
6904 else *(float *)&args
[argspos
++] = V_R4(arg
);
6908 if (fpcount
< 8) regs
.fp
[fpcount
++].d
= V_R8(arg
);
6909 else *(double *)&args
[argspos
++] = V_R8(arg
);
6914 memcpy( ®s
.x
[rcount
], arg
, sizeof(*arg
) );
6919 memcpy( &args
[argspos
], arg
, sizeof(*arg
) );
6924 if (rcount
< 8) regs
.x
[rcount
++] = (DWORD_PTR
)arg
;
6925 else args
[argspos
++] = (DWORD_PTR
)arg
;
6927 case VT_BOOL
: /* VT_BOOL is 16-bit but BOOL is 32-bit, needs to be extended */
6928 if (rcount
< 8) regs
.x
[rcount
++] = V_BOOL(arg
);
6929 else args
[argspos
++] = V_BOOL(arg
);
6932 if (rcount
< 8) regs
.x
[rcount
++] = V_UI8(arg
);
6933 else args
[argspos
++] = V_UI8(arg
);
6936 TRACE("arg %u: type %s %s\n", i
, debugstr_vt(types
[i
]), debugstr_variant(arg
));
6939 argspos
+= (argspos
% 2); /* Make sure stack function alignment is 16-byte */
6945 return E_INVALIDARG
;
6948 regs
.x
[8] = (DWORD_PTR
)result
; /* x8 is a pointer to the result */
6949 call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6952 V_R4(result
) = call_float_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6956 V_R8(result
) = call_double_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6959 V_UI8(result
) = call_method( func
, argspos
, args
, (DWORD_PTR
*)®s
);
6963 if (ret_type
!= VT_VARIANT
) V_VT(result
) = ret_type
;
6964 TRACE("retval: %s\n", debugstr_variant(result
));
6968 #else /* __aarch64__ */
6970 HRESULT WINAPI
DispCallFunc( void* pvInstance
, ULONG_PTR oVft
, CALLCONV cc
, VARTYPE vtReturn
,
6971 UINT cActuals
, VARTYPE
* prgvt
, VARIANTARG
** prgpvarg
, VARIANT
* pvargResult
)
6973 FIXME( "(%p, %ld, %d, %d, %d, %p, %p, %p (vt=%d)): not implemented for this CPU\n",
6974 pvInstance
, oVft
, cc
, vtReturn
, cActuals
, prgvt
, prgpvarg
, pvargResult
, V_VT(pvargResult
));
6980 static HRESULT
userdefined_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
6983 ITypeInfo
*tinfo2
= NULL
;
6984 TYPEATTR
*tattr
= NULL
;
6986 hr
= ITypeInfo_GetRefTypeInfo(tinfo
, tdesc
->u
.hreftype
, &tinfo2
);
6989 ERR("Could not get typeinfo of hreftype %x for VT_USERDEFINED, "
6991 tdesc
->u
.hreftype
, hr
);
6994 hr
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
6997 ERR("ITypeInfo_GetTypeAttr failed, hr = 0x%08x\n", hr
);
6998 ITypeInfo_Release(tinfo2
);
7002 switch (tattr
->typekind
)
7009 hr
= typedescvt_to_variantvt(tinfo2
, &tattr
->tdescAlias
, vt
);
7012 case TKIND_INTERFACE
:
7013 if (tattr
->wTypeFlags
& TYPEFLAG_FDISPATCHABLE
)
7019 case TKIND_DISPATCH
:
7028 FIXME("TKIND_RECORD unhandled.\n");
7033 FIXME("TKIND_UNION unhandled.\n");
7038 FIXME("TKIND %d unhandled.\n",tattr
->typekind
);
7042 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7043 ITypeInfo_Release(tinfo2
);
7047 static HRESULT
typedescvt_to_variantvt(ITypeInfo
*tinfo
, const TYPEDESC
*tdesc
, VARTYPE
*vt
)
7051 /* enforce only one level of pointer indirection */
7052 if (!(*vt
& VT_BYREF
) && !(*vt
& VT_ARRAY
) && (tdesc
->vt
== VT_PTR
))
7054 tdesc
= tdesc
->u
.lptdesc
;
7056 /* munch VT_PTR -> VT_USERDEFINED(interface) into VT_UNKNOWN or
7057 * VT_DISPATCH and VT_PTR -> VT_PTR -> VT_USERDEFINED(interface) into
7058 * VT_BYREF|VT_DISPATCH or VT_BYREF|VT_UNKNOWN */
7059 if ((tdesc
->vt
== VT_USERDEFINED
) ||
7060 ((tdesc
->vt
== VT_PTR
) && (tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
)))
7062 VARTYPE vt_userdefined
= 0;
7063 const TYPEDESC
*tdesc_userdefined
= tdesc
;
7064 if (tdesc
->vt
== VT_PTR
)
7066 vt_userdefined
= VT_BYREF
;
7067 tdesc_userdefined
= tdesc
->u
.lptdesc
;
7069 hr
= userdefined_to_variantvt(tinfo
, tdesc_userdefined
, &vt_userdefined
);
7071 (((vt_userdefined
& VT_TYPEMASK
) == VT_UNKNOWN
) ||
7072 ((vt_userdefined
& VT_TYPEMASK
) == VT_DISPATCH
)))
7074 *vt
|= vt_userdefined
;
7086 case VT_USERDEFINED
:
7087 hr
= userdefined_to_variantvt(tinfo
, tdesc
, vt
);
7094 ERR("cannot convert type %d into variant VT\n", tdesc
->vt
);
7095 hr
= DISP_E_BADVARTYPE
;
7099 hr
= typedescvt_to_variantvt(tinfo
, tdesc
->u
.lptdesc
, vt
);
7114 static HRESULT
get_iface_guid(ITypeInfo
*tinfo
, HREFTYPE href
, GUID
*guid
)
7121 hres
= ITypeInfo_GetRefTypeInfo(tinfo
, href
, &tinfo2
);
7125 hres
= ITypeInfo_GetTypeAttr(tinfo2
, &tattr
);
7127 ITypeInfo_Release(tinfo2
);
7131 switch(tattr
->typekind
) {
7133 hres
= get_iface_guid(tinfo2
, tattr
->tdescAlias
.u
.hreftype
, guid
);
7136 case TKIND_INTERFACE
:
7137 case TKIND_DISPATCH
:
7138 *guid
= tattr
->guid
;
7142 for (i
= 0; i
< tattr
->cImplTypes
; i
++)
7144 ITypeInfo_GetImplTypeFlags(tinfo2
, i
, &flags
);
7145 if (flags
& IMPLTYPEFLAG_FDEFAULT
)
7149 if (i
== tattr
->cImplTypes
)
7152 hres
= ITypeInfo_GetRefTypeOfImplType(tinfo2
, i
, &href
);
7153 if (SUCCEEDED(hres
))
7154 hres
= get_iface_guid(tinfo2
, href
, guid
);
7158 ERR("Unexpected typekind %d\n", tattr
->typekind
);
7159 hres
= E_UNEXPECTED
;
7162 ITypeInfo_ReleaseTypeAttr(tinfo2
, tattr
);
7163 ITypeInfo_Release(tinfo2
);
7167 static inline BOOL
func_restricted( const FUNCDESC
*desc
)
7169 return (desc
->wFuncFlags
& FUNCFLAG_FRESTRICTED
) && (desc
->memid
>= 0);
7172 #define INVBUF_ELEMENT_SIZE \
7173 (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *) + sizeof(VARTYPE))
7174 #define INVBUF_GET_ARG_ARRAY(buffer, params) (buffer)
7175 #define INVBUF_GET_MISSING_ARG_ARRAY(buffer, params) \
7176 ((VARIANTARG *)((char *)(buffer) + sizeof(VARIANTARG) * (params)))
7177 #define INVBUF_GET_ARG_PTR_ARRAY(buffer, params) \
7178 ((VARIANTARG **)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG)) * (params)))
7179 #define INVBUF_GET_ARG_TYPE_ARRAY(buffer, params) \
7180 ((VARTYPE *)((char *)(buffer) + (sizeof(VARIANTARG) + sizeof(VARIANTARG) + sizeof(VARIANTARG *)) * (params)))
7182 static HRESULT WINAPI
ITypeInfo_fnInvoke(
7187 DISPPARAMS
*pDispParams
,
7188 VARIANT
*pVarResult
,
7189 EXCEPINFO
*pExcepInfo
,
7192 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7194 unsigned int var_index
;
7197 const TLBFuncDesc
*pFuncInfo
;
7200 TRACE("(%p)(%p,id=%d,flags=0x%08x,%p,%p,%p,%p)\n",
7201 This
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
7204 if( This
->typeattr
.wTypeFlags
& TYPEFLAG_FRESTRICTED
)
7205 return DISP_E_MEMBERNOTFOUND
;
7209 ERR("NULL pDispParams not allowed\n");
7210 return E_INVALIDARG
;
7213 dump_DispParms(pDispParams
);
7215 if (pDispParams
->cNamedArgs
> pDispParams
->cArgs
)
7217 ERR("named argument array cannot be bigger than argument array (%d/%d)\n",
7218 pDispParams
->cNamedArgs
, pDispParams
->cArgs
);
7219 return E_INVALIDARG
;
7222 /* we do this instead of using GetFuncDesc since it will return a fake
7223 * FUNCDESC for dispinterfaces and we want the real function description */
7224 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
7225 pFuncInfo
= &This
->funcdescs
[fdc
];
7226 if ((memid
== pFuncInfo
->funcdesc
.memid
) &&
7227 (wFlags
& pFuncInfo
->funcdesc
.invkind
) &&
7228 !func_restricted( &pFuncInfo
->funcdesc
))
7232 if (fdc
< This
->typeattr
.cFuncs
) {
7233 const FUNCDESC
*func_desc
= &pFuncInfo
->funcdesc
;
7237 TRACE("invoking:\n");
7238 dump_TLBFuncDescOne(pFuncInfo
);
7241 switch (func_desc
->funckind
) {
7242 case FUNC_PUREVIRTUAL
:
7243 case FUNC_VIRTUAL
: {
7244 void *buffer
= heap_alloc_zero(INVBUF_ELEMENT_SIZE
* func_desc
->cParams
);
7246 VARIANT retval
; /* pointer for storing byref retvals in */
7247 VARIANTARG
**prgpvarg
= INVBUF_GET_ARG_PTR_ARRAY(buffer
, func_desc
->cParams
);
7248 VARIANTARG
*rgvarg
= INVBUF_GET_ARG_ARRAY(buffer
, func_desc
->cParams
);
7249 VARTYPE
*rgvt
= INVBUF_GET_ARG_TYPE_ARRAY(buffer
, func_desc
->cParams
);
7250 UINT cNamedArgs
= pDispParams
->cNamedArgs
;
7251 DISPID
*rgdispidNamedArgs
= pDispParams
->rgdispidNamedArgs
;
7252 UINT vargs_converted
=0;
7257 if (func_desc
->invkind
& (INVOKE_PROPERTYPUT
|INVOKE_PROPERTYPUTREF
))
7259 if (!cNamedArgs
|| (rgdispidNamedArgs
[0] != DISPID_PROPERTYPUT
))
7261 ERR("first named arg for property put invocation must be DISPID_PROPERTYPUT\n");
7262 hres
= DISP_E_PARAMNOTFOUND
;
7267 if (func_desc
->cParamsOpt
< 0 && cNamedArgs
)
7269 ERR("functions with the vararg attribute do not support named arguments\n");
7270 hres
= DISP_E_NONAMEDARGS
;
7274 for (i
= 0; i
< func_desc
->cParams
; i
++)
7276 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7277 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, tdesc
, &rgvt
[i
]);
7282 TRACE("changing args\n");
7283 for (i
= 0; i
< func_desc
->cParams
; i
++)
7285 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7286 TYPEDESC
*tdesc
= &func_desc
->lprgelemdescParam
[i
].tdesc
;
7287 VARIANTARG
*src_arg
;
7289 if (wParamFlags
& PARAMFLAG_FLCID
)
7292 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7294 V_I4(arg
) = This
->pTypeLib
->lcid
;
7303 for (j
= 0; j
< cNamedArgs
; j
++)
7304 if (rgdispidNamedArgs
[j
] == i
|| (i
== func_desc
->cParams
-1 && rgdispidNamedArgs
[j
] == DISPID_PROPERTYPUT
))
7306 src_arg
= &pDispParams
->rgvarg
[j
];
7311 if (!src_arg
&& vargs_converted
+ cNamedArgs
< pDispParams
->cArgs
)
7313 src_arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7317 if (wParamFlags
& PARAMFLAG_FRETVAL
)
7319 /* under most conditions the caller is not allowed to
7320 * pass in a dispparam arg in the index of what would be
7321 * the retval parameter. however, there is an exception
7322 * where the extra parameter is used in an extra
7323 * IDispatch::Invoke below */
7324 if ((i
< pDispParams
->cArgs
) &&
7325 ((func_desc
->cParams
!= 1) || !pVarResult
||
7326 !(func_desc
->invkind
& INVOKE_PROPERTYGET
)))
7328 hres
= DISP_E_BADPARAMCOUNT
;
7332 /* note: this check is placed so that if the caller passes
7333 * in a VARIANTARG for the retval we just ignore it, like
7335 if (i
== func_desc
->cParams
- 1)
7338 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7339 memset(arg
, 0, sizeof(*arg
));
7340 V_VT(arg
) = rgvt
[i
];
7341 memset(&retval
, 0, sizeof(retval
));
7342 V_BYREF(arg
) = &retval
;
7346 ERR("[retval] parameter must be the last parameter of the method (%d/%d)\n", i
, func_desc
->cParams
);
7347 hres
= E_UNEXPECTED
;
7351 else if (src_arg
&& !((wParamFlags
& PARAMFLAG_FOPT
) &&
7352 V_VT(src_arg
) == VT_ERROR
&& V_ERROR(src_arg
) == DISP_E_PARAMNOTFOUND
))
7354 TRACE("%s\n", debugstr_variant(src_arg
));
7356 if(rgvt
[i
]!=V_VT(src_arg
))
7358 if (rgvt
[i
] == VT_VARIANT
)
7359 hres
= VariantCopy(&rgvarg
[i
], src_arg
);
7360 else if (rgvt
[i
] == (VT_VARIANT
| VT_BYREF
))
7362 if (rgvt
[i
] == V_VT(src_arg
))
7363 V_VARIANTREF(&rgvarg
[i
]) = V_VARIANTREF(src_arg
);
7366 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7367 if (wParamFlags
& PARAMFLAG_FIN
)
7368 hres
= VariantCopy(&missing_arg
[i
], src_arg
);
7369 V_VARIANTREF(&rgvarg
[i
]) = &missing_arg
[i
];
7371 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7373 else if ((rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
) || rgvt
[i
] == (VT_VARIANT
| VT_ARRAY
| VT_BYREF
)) && func_desc
->cParamsOpt
< 0)
7375 SAFEARRAYBOUND bound
;
7379 bound
.cElements
= pDispParams
->cArgs
-i
;
7380 if (!(a
= SafeArrayCreate(VT_VARIANT
, 1, &bound
)))
7382 ERR("SafeArrayCreate failed\n");
7385 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7388 ERR("SafeArrayAccessData failed with %x\n", hres
);
7389 SafeArrayDestroy(a
);
7392 for (j
= 0; j
< bound
.cElements
; j
++)
7393 VariantCopy(&v
[j
], &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - i
- j
]);
7394 hres
= SafeArrayUnaccessData(a
);
7397 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7398 SafeArrayDestroy(a
);
7401 if (rgvt
[i
] & VT_BYREF
)
7402 V_BYREF(&rgvarg
[i
]) = &a
;
7404 V_ARRAY(&rgvarg
[i
]) = a
;
7405 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7407 else if ((rgvt
[i
] & VT_BYREF
) && !V_ISBYREF(src_arg
))
7409 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7410 if (wParamFlags
& PARAMFLAG_FIN
)
7411 hres
= VariantChangeType(&missing_arg
[i
], src_arg
, 0, rgvt
[i
] & ~VT_BYREF
);
7413 V_VT(&missing_arg
[i
]) = rgvt
[i
] & ~VT_BYREF
;
7414 V_BYREF(&rgvarg
[i
]) = &V_NONE(&missing_arg
[i
]);
7415 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7417 else if ((rgvt
[i
] & VT_BYREF
) && (rgvt
[i
] == V_VT(src_arg
)))
7419 V_BYREF(&rgvarg
[i
]) = V_BYREF(src_arg
);
7420 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7424 /* FIXME: this doesn't work for VT_BYREF arguments if
7425 * they are not the same type as in the paramdesc */
7426 V_VT(&rgvarg
[i
]) = V_VT(src_arg
);
7427 hres
= VariantChangeType(&rgvarg
[i
], src_arg
, 0, rgvt
[i
]);
7428 V_VT(&rgvarg
[i
]) = rgvt
[i
];
7433 ERR("failed to convert param %d to %s from %s\n", i
,
7434 debugstr_vt(rgvt
[i
]), debugstr_variant(src_arg
));
7437 prgpvarg
[i
] = &rgvarg
[i
];
7441 prgpvarg
[i
] = src_arg
;
7444 if((tdesc
->vt
== VT_USERDEFINED
|| (tdesc
->vt
== VT_PTR
&& tdesc
->u
.lptdesc
->vt
== VT_USERDEFINED
))
7445 && (V_VT(prgpvarg
[i
]) == VT_DISPATCH
|| V_VT(prgpvarg
[i
]) == VT_UNKNOWN
)
7446 && V_UNKNOWN(prgpvarg
[i
])) {
7447 IUnknown
*userdefined_iface
;
7450 if (tdesc
->vt
== VT_PTR
)
7451 tdesc
= tdesc
->u
.lptdesc
;
7453 hres
= get_iface_guid((ITypeInfo
*)iface
, tdesc
->u
.hreftype
, &guid
);
7457 hres
= IUnknown_QueryInterface(V_UNKNOWN(prgpvarg
[i
]), &guid
, (void**)&userdefined_iface
);
7459 ERR("argument does not support %s interface\n", debugstr_guid(&guid
));
7463 IUnknown_Release(V_UNKNOWN(prgpvarg
[i
]));
7464 V_UNKNOWN(prgpvarg
[i
]) = userdefined_iface
;
7467 else if (wParamFlags
& PARAMFLAG_FOPT
)
7470 arg
= prgpvarg
[i
] = &rgvarg
[i
];
7471 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7473 hres
= VariantCopy(arg
, &func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
7479 VARIANTARG
*missing_arg
;
7480 /* if the function wants a pointer to a variant then
7481 * set that up, otherwise just pass the VT_ERROR in
7482 * the argument by value */
7483 if (rgvt
[i
] & VT_BYREF
)
7485 missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
) + i
;
7486 V_VT(arg
) = VT_VARIANT
| VT_BYREF
;
7487 V_VARIANTREF(arg
) = missing_arg
;
7491 V_VT(missing_arg
) = VT_ERROR
;
7492 V_ERROR(missing_arg
) = DISP_E_PARAMNOTFOUND
;
7497 hres
= DISP_E_BADPARAMCOUNT
;
7501 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7503 /* VT_VOID is a special case for return types, so it is not
7504 * handled in the general function */
7505 if (func_desc
->elemdescFunc
.tdesc
.vt
== VT_VOID
)
7506 V_VT(&varresult
) = VT_EMPTY
;
7509 V_VT(&varresult
) = 0;
7510 hres
= typedescvt_to_variantvt((ITypeInfo
*)iface
, &func_desc
->elemdescFunc
.tdesc
, &V_VT(&varresult
));
7511 if (FAILED(hres
)) goto func_fail
; /* FIXME: we don't free changed types here */
7514 hres
= DispCallFunc(pIUnk
, func_desc
->oVft
& 0xFFFC, func_desc
->callconv
,
7515 V_VT(&varresult
), func_desc
->cParams
, rgvt
,
7516 prgpvarg
, &varresult
);
7518 vargs_converted
= 0;
7520 for (i
= 0; i
< func_desc
->cParams
; i
++)
7522 USHORT wParamFlags
= func_desc
->lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
;
7523 VARIANTARG
*missing_arg
= INVBUF_GET_MISSING_ARG_ARRAY(buffer
, func_desc
->cParams
);
7525 if (wParamFlags
& PARAMFLAG_FLCID
)
7527 else if (wParamFlags
& PARAMFLAG_FRETVAL
)
7529 TRACE("[retval] value: %s\n", debugstr_variant(prgpvarg
[i
]));
7533 VariantInit(pVarResult
);
7534 /* deref return value */
7535 hres
= VariantCopyInd(pVarResult
, prgpvarg
[i
]);
7538 VARIANT_ClearInd(prgpvarg
[i
]);
7540 else if (vargs_converted
< pDispParams
->cArgs
)
7542 VARIANTARG
*arg
= &pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
];
7543 if (wParamFlags
& PARAMFLAG_FOUT
)
7545 if ((rgvt
[i
] & VT_BYREF
) && !(V_VT(arg
) & VT_BYREF
))
7547 hres
= VariantChangeType(arg
, &rgvarg
[i
], 0, V_VT(arg
));
7551 ERR("failed to convert param %d to vt %d\n", i
,
7552 V_VT(&pDispParams
->rgvarg
[pDispParams
->cArgs
- 1 - vargs_converted
]));
7557 else if (V_VT(prgpvarg
[i
]) == (VT_VARIANT
| VT_ARRAY
) &&
7558 func_desc
->cParamsOpt
< 0 &&
7559 i
== func_desc
->cParams
-1)
7561 SAFEARRAY
*a
= V_ARRAY(prgpvarg
[i
]);
7564 hres
= SafeArrayGetUBound(a
, 1, &ubound
);
7567 ERR("SafeArrayGetUBound failed with %x\n", hres
);
7570 hres
= SafeArrayAccessData(a
, (LPVOID
)&v
);
7573 ERR("SafeArrayAccessData failed with %x\n", hres
);
7576 for (j
= 0; j
<= ubound
; j
++)
7577 VariantClear(&v
[j
]);
7578 hres
= SafeArrayUnaccessData(a
);
7581 ERR("SafeArrayUnaccessData failed with %x\n", hres
);
7585 VariantClear(&rgvarg
[i
]);
7588 else if (wParamFlags
& PARAMFLAG_FOPT
)
7590 if (wParamFlags
& PARAMFLAG_FHASDEFAULT
)
7591 VariantClear(&rgvarg
[i
]);
7594 VariantClear(&missing_arg
[i
]);
7597 if ((V_VT(&varresult
) == VT_ERROR
) && FAILED(V_ERROR(&varresult
)))
7599 WARN("invoked function failed with error 0x%08x\n", V_ERROR(&varresult
));
7600 hres
= DISP_E_EXCEPTION
;
7603 IErrorInfo
*pErrorInfo
;
7604 pExcepInfo
->scode
= V_ERROR(&varresult
);
7605 if (GetErrorInfo(0, &pErrorInfo
) == S_OK
)
7607 IErrorInfo_GetDescription(pErrorInfo
, &pExcepInfo
->bstrDescription
);
7608 IErrorInfo_GetHelpFile(pErrorInfo
, &pExcepInfo
->bstrHelpFile
);
7609 IErrorInfo_GetSource(pErrorInfo
, &pExcepInfo
->bstrSource
);
7610 IErrorInfo_GetHelpContext(pErrorInfo
, &pExcepInfo
->dwHelpContext
);
7612 IErrorInfo_Release(pErrorInfo
);
7616 if (V_VT(&varresult
) != VT_ERROR
)
7618 TRACE("varresult value: %s\n", debugstr_variant(&varresult
));
7622 VariantClear(pVarResult
);
7623 *pVarResult
= varresult
;
7626 VariantClear(&varresult
);
7629 if (SUCCEEDED(hres
) && pVarResult
&& (func_desc
->cParams
== 1) &&
7630 (func_desc
->invkind
& INVOKE_PROPERTYGET
) &&
7631 (func_desc
->lprgelemdescParam
[0].u
.paramdesc
.wParamFlags
& PARAMFLAG_FRETVAL
) &&
7632 (pDispParams
->cArgs
!= 0))
7634 if (V_VT(pVarResult
) == VT_DISPATCH
)
7636 IDispatch
*pDispatch
= V_DISPATCH(pVarResult
);
7637 /* Note: not VariantClear; we still need the dispatch
7638 * pointer to be valid */
7639 VariantInit(pVarResult
);
7640 hres
= IDispatch_Invoke(pDispatch
, DISPID_VALUE
, &IID_NULL
,
7641 GetSystemDefaultLCID(), wFlags
,
7642 pDispParams
, pVarResult
, pExcepInfo
, pArgErr
);
7643 IDispatch_Release(pDispatch
);
7647 VariantClear(pVarResult
);
7648 hres
= DISP_E_NOTACOLLECTION
;
7656 case FUNC_DISPATCH
: {
7659 hres
= IUnknown_QueryInterface((LPUNKNOWN
)pIUnk
,&IID_IDispatch
,(LPVOID
*)&disp
);
7660 if (SUCCEEDED(hres
)) {
7661 FIXME("Calling Invoke in IDispatch iface. untested!\n");
7662 hres
= IDispatch_Invoke(
7663 disp
,memid
,&IID_NULL
,LOCALE_USER_DEFAULT
,wFlags
,pDispParams
,
7664 pVarResult
,pExcepInfo
,pArgErr
7667 FIXME("IDispatch::Invoke failed with %08x. (Could be not a real error?)\n", hres
);
7668 IDispatch_Release(disp
);
7670 FIXME("FUNC_DISPATCH used on object without IDispatch iface?\n");
7674 FIXME("Unknown function invocation type %d\n", func_desc
->funckind
);
7679 TRACE("-- 0x%08x\n", hres
);
7682 } else if(SUCCEEDED(hres
= ITypeInfo2_GetVarIndexOfMemId(iface
, memid
, &var_index
))) {
7685 hres
= ITypeInfo2_GetVarDesc(iface
, var_index
, &var_desc
);
7686 if(FAILED(hres
)) return hres
;
7688 FIXME("varseek: Found memid, but variable-based invoking not supported\n");
7689 dump_VARDESC(var_desc
);
7690 ITypeInfo2_ReleaseVarDesc(iface
, var_desc
);
7694 /* not found, look for it in inherited interfaces */
7695 ITypeInfo2_GetTypeKind(iface
, &type_kind
);
7696 if(type_kind
== TKIND_INTERFACE
|| type_kind
== TKIND_DISPATCH
) {
7697 if(This
->impltypes
) {
7698 /* recursive search */
7700 hres
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7701 if(SUCCEEDED(hres
)){
7702 hres
= ITypeInfo_Invoke(pTInfo
,pIUnk
,memid
,wFlags
,pDispParams
,pVarResult
,pExcepInfo
,pArgErr
);
7703 ITypeInfo_Release(pTInfo
);
7706 WARN("Could not search inherited interface!\n");
7709 WARN("did not find member id %d, flags 0x%x!\n", memid
, wFlags
);
7710 return DISP_E_MEMBERNOTFOUND
;
7713 /* ITypeInfo::GetDocumentation
7715 * Retrieves the documentation string, the complete Help file name and path,
7716 * and the context ID for the Help topic for a specified type description.
7718 * (Can be tested by the Visual Basic Editor in Word for instance.)
7720 static HRESULT WINAPI
ITypeInfo_fnGetDocumentation( ITypeInfo2
*iface
,
7721 MEMBERID memid
, BSTR
*pBstrName
, BSTR
*pBstrDocString
,
7722 DWORD
*pdwHelpContext
, BSTR
*pBstrHelpFile
)
7724 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7725 const TLBFuncDesc
*pFDesc
;
7726 const TLBVarDesc
*pVDesc
;
7727 TRACE("(%p) memid %d Name(%p) DocString(%p)"
7728 " HelpContext(%p) HelpFile(%p)\n",
7729 This
, memid
, pBstrName
, pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7730 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
7732 *pBstrName
=SysAllocString(TLB_get_bstr(This
->Name
));
7734 *pBstrDocString
=SysAllocString(TLB_get_bstr(This
->DocString
));
7736 *pdwHelpContext
=This
->dwHelpContext
;
7738 *pBstrHelpFile
=SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7740 }else {/* for a member */
7741 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
7744 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Name
));
7746 *pBstrDocString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
7748 *pdwHelpContext
=pFDesc
->helpcontext
;
7750 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7753 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
7756 *pBstrName
= SysAllocString(TLB_get_bstr(pVDesc
->Name
));
7758 *pBstrDocString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
7760 *pdwHelpContext
=pVDesc
->HelpContext
;
7762 *pBstrHelpFile
= SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpFile
));
7767 if(This
->impltypes
&&
7768 (This
->typeattr
.typekind
== TKIND_INTERFACE
|| This
->typeattr
.typekind
== TKIND_DISPATCH
)) {
7769 /* recursive search */
7772 result
= ITypeInfo2_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pTInfo
);
7773 if(SUCCEEDED(result
)) {
7774 result
= ITypeInfo_GetDocumentation(pTInfo
, memid
, pBstrName
,
7775 pBstrDocString
, pdwHelpContext
, pBstrHelpFile
);
7776 ITypeInfo_Release(pTInfo
);
7779 WARN("Could not search inherited interface!\n");
7782 WARN("member %d not found\n", memid
);
7783 return TYPE_E_ELEMENTNOTFOUND
;
7786 /* ITypeInfo::GetDllEntry
7788 * Retrieves a description or specification of an entry point for a function
7791 static HRESULT WINAPI
ITypeInfo_fnGetDllEntry( ITypeInfo2
*iface
, MEMBERID memid
,
7792 INVOKEKIND invKind
, BSTR
*pBstrDllName
, BSTR
*pBstrName
,
7795 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7796 const TLBFuncDesc
*pFDesc
;
7798 TRACE("(%p)->(memid %x, %d, %p, %p, %p)\n", This
, memid
, invKind
, pBstrDllName
, pBstrName
, pwOrdinal
);
7800 if (pBstrDllName
) *pBstrDllName
= NULL
;
7801 if (pBstrName
) *pBstrName
= NULL
;
7802 if (pwOrdinal
) *pwOrdinal
= 0;
7804 if (This
->typeattr
.typekind
!= TKIND_MODULE
)
7805 return TYPE_E_BADMODULEKIND
;
7807 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
7809 dump_TypeInfo(This
);
7811 dump_TLBFuncDescOne(pFDesc
);
7814 *pBstrDllName
= SysAllocString(TLB_get_bstr(This
->DllName
));
7816 if (!IS_INTRESOURCE(pFDesc
->Entry
) && (pFDesc
->Entry
!= (void*)-1)) {
7818 *pBstrName
= SysAllocString(TLB_get_bstr(pFDesc
->Entry
));
7826 *pwOrdinal
= LOWORD(pFDesc
->Entry
);
7829 return TYPE_E_ELEMENTNOTFOUND
;
7832 /* internal function to make the inherited interfaces' methods appear
7833 * part of the interface */
7834 static HRESULT
ITypeInfoImpl_GetDispatchRefTypeInfo( ITypeInfo
*iface
,
7835 HREFTYPE
*hRefType
, ITypeInfo
**ppTInfo
)
7837 ITypeInfoImpl
*This
= impl_from_ITypeInfo(iface
);
7840 TRACE("%p, 0x%x\n", iface
, *hRefType
);
7842 if (This
->impltypes
&& (*hRefType
& DISPATCH_HREF_MASK
))
7844 ITypeInfo
*pSubTypeInfo
;
7846 hr
= ITypeInfo_GetRefTypeInfo(iface
, This
->impltypes
[0].hRef
, &pSubTypeInfo
);
7850 hr
= ITypeInfoImpl_GetDispatchRefTypeInfo(pSubTypeInfo
,
7852 ITypeInfo_Release(pSubTypeInfo
);
7856 *hRefType
-= DISPATCH_HREF_OFFSET
;
7858 if (!(*hRefType
& DISPATCH_HREF_MASK
))
7859 return ITypeInfo_GetRefTypeInfo(iface
, *hRefType
, ppTInfo
);
7864 struct search_res_tlb_params
7870 static BOOL CALLBACK
search_res_tlb(HMODULE hModule
, LPCWSTR lpszType
, LPWSTR lpszName
, LONG_PTR lParam
)
7872 struct search_res_tlb_params
*params
= (LPVOID
)lParam
;
7873 static const WCHAR formatW
[] = {'\\','%','d',0};
7874 WCHAR szPath
[MAX_PATH
+1];
7875 ITypeLib
*pTLib
= NULL
;
7879 if (IS_INTRESOURCE(lpszName
) == FALSE
)
7882 if (!(len
= GetModuleFileNameW(hModule
, szPath
, MAX_PATH
)))
7885 if (swprintf(szPath
+ len
, ARRAY_SIZE(szPath
) - len
, formatW
, LOWORD(lpszName
)) < 0)
7888 ret
= LoadTypeLibEx(szPath
, REGKIND_NONE
, &pTLib
);
7891 ITypeLibImpl
*impl
= impl_from_ITypeLib(pTLib
);
7892 if (IsEqualGUID(params
->guid
, impl
->guid
))
7894 params
->pTLib
= pTLib
;
7895 return FALSE
; /* stop enumeration */
7897 ITypeLib_Release(pTLib
);
7903 /* ITypeInfo::GetRefTypeInfo
7905 * If a type description references other type descriptions, it retrieves
7906 * the referenced type descriptions.
7908 static HRESULT WINAPI
ITypeInfo_fnGetRefTypeInfo(
7911 ITypeInfo
**ppTInfo
)
7913 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
7914 ITypeInfo
*type_info
= NULL
;
7915 HRESULT result
= E_FAIL
;
7916 TLBRefType
*ref_type
;
7920 return E_INVALIDARG
;
7922 if ((INT
)hRefType
< 0) {
7923 ITypeInfoImpl
*pTypeInfoImpl
;
7925 if (!(This
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
) ||
7926 !(This
->typeattr
.typekind
== TKIND_INTERFACE
||
7927 This
->typeattr
.typekind
== TKIND_DISPATCH
))
7928 return TYPE_E_ELEMENTNOTFOUND
;
7930 /* when we meet a DUAL typeinfo, we must create the alternate
7933 pTypeInfoImpl
= ITypeInfoImpl_Constructor();
7935 *pTypeInfoImpl
= *This
;
7936 pTypeInfoImpl
->ref
= 0;
7937 list_init(&pTypeInfoImpl
->custdata_list
);
7939 if (This
->typeattr
.typekind
== TKIND_INTERFACE
)
7940 pTypeInfoImpl
->typeattr
.typekind
= TKIND_DISPATCH
;
7942 pTypeInfoImpl
->typeattr
.typekind
= TKIND_INTERFACE
;
7944 *ppTInfo
= (ITypeInfo
*)&pTypeInfoImpl
->ITypeInfo2_iface
;
7945 /* the AddRef implicitly adds a reference to the parent typelib, which
7946 * stops the copied data from being destroyed until the new typeinfo's
7947 * refcount goes to zero, but we need to signal to the new instance to
7948 * not free its data structures when it is destroyed */
7949 pTypeInfoImpl
->not_attached_to_typelib
= TRUE
;
7950 ITypeInfo_AddRef(*ppTInfo
);
7952 TRACE("got dual interface %p\n", *ppTInfo
);
7956 if ((hRefType
& DISPATCH_HREF_MASK
) && (This
->typeattr
.typekind
== TKIND_DISPATCH
))
7957 return ITypeInfoImpl_GetDispatchRefTypeInfo((ITypeInfo
*)iface
, &hRefType
, ppTInfo
);
7959 if(!(hRefType
& 0x1))
7961 for(i
= 0; i
< This
->pTypeLib
->TypeInfoCount
; ++i
)
7963 if (This
->pTypeLib
->typeinfos
[i
]->hreftype
== (hRefType
&(~0x3)))
7966 type_info
= (ITypeInfo
*)&This
->pTypeLib
->typeinfos
[i
]->ITypeInfo2_iface
;
7967 ITypeInfo_AddRef(type_info
);
7975 ITypeLib
*pTLib
= NULL
;
7977 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
)
7979 if(ref_type
->reference
== (hRefType
& (~0x3)))
7982 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
)
7984 FIXME("Can't find pRefType for ref %x\n", hRefType
);
7988 if(ref_type
->pImpTLInfo
== TLB_REF_INTERNAL
) {
7990 TRACE("internal reference\n");
7991 result
= ITypeInfo2_GetContainingTypeLib(iface
, &pTLib
, &Index
);
7993 if(ref_type
->pImpTLInfo
->pImpTypeLib
) {
7994 TRACE("typeinfo in imported typelib that is already loaded\n");
7995 pTLib
= (ITypeLib
*)&ref_type
->pImpTLInfo
->pImpTypeLib
->ITypeLib2_iface
;
7996 ITypeLib_AddRef(pTLib
);
7999 /* Search in cached typelibs */
8000 ITypeLibImpl
*entry
;
8002 EnterCriticalSection(&cache_section
);
8003 LIST_FOR_EACH_ENTRY(entry
, &tlb_cache
, ITypeLibImpl
, entry
)
8006 && IsEqualIID(&entry
->guid
->guid
, TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
))
8007 && entry
->ver_major
== ref_type
->pImpTLInfo
->wVersionMajor
8008 && entry
->ver_minor
== ref_type
->pImpTLInfo
->wVersionMinor
8009 && entry
->set_lcid
== ref_type
->pImpTLInfo
->lcid
)
8011 TRACE("got cached %p\n", entry
);
8012 pTLib
= (ITypeLib
*)&entry
->ITypeLib2_iface
;
8013 ITypeLib_AddRef(pTLib
);
8018 LeaveCriticalSection(&cache_section
);
8022 static const WCHAR TYPELIBW
[] = {'T','Y','P','E','L','I','B',0};
8023 struct search_res_tlb_params params
;
8025 TRACE("typeinfo in imported typelib that isn't already loaded\n");
8027 /* Search in resource table */
8028 params
.guid
= TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
);
8029 params
.pTLib
= NULL
;
8030 EnumResourceNamesW(NULL
, TYPELIBW
, search_res_tlb
, (LONG_PTR
)¶ms
);
8033 pTLib
= params
.pTLib
;
8042 /* Search on disk */
8043 result
= query_typelib_path(TLB_get_guid_null(ref_type
->pImpTLInfo
->guid
),
8044 ref_type
->pImpTLInfo
->wVersionMajor
,
8045 ref_type
->pImpTLInfo
->wVersionMinor
,
8046 This
->pTypeLib
->syskind
,
8047 ref_type
->pImpTLInfo
->lcid
, &libnam
, TRUE
);
8049 libnam
= SysAllocString(ref_type
->pImpTLInfo
->name
);
8051 result
= LoadTypeLib(libnam
, &pTLib
);
8052 SysFreeString(libnam
);
8055 if(SUCCEEDED(result
)) {
8056 ref_type
->pImpTLInfo
->pImpTypeLib
= impl_from_ITypeLib(pTLib
);
8057 ITypeLib_AddRef(pTLib
);
8061 if(SUCCEEDED(result
)) {
8062 if(ref_type
->index
== TLB_REF_USE_GUID
)
8063 result
= ITypeLib_GetTypeInfoOfGuid(pTLib
, TLB_get_guid_null(ref_type
->guid
), &type_info
);
8065 result
= ITypeLib_GetTypeInfo(pTLib
, ref_type
->index
, &type_info
);
8068 ITypeLib_Release(pTLib
);
8071 WARN("(%p) failed hreftype 0x%04x\n", This
, hRefType
);
8076 if ((hRefType
& 0x2) && SUCCEEDED(ITypeInfo_GetRefTypeInfo(type_info
, -2, ppTInfo
)))
8077 ITypeInfo_Release(type_info
);
8078 else *ppTInfo
= type_info
;
8080 TRACE("(%p) hreftype 0x%04x loaded %s (%p)\n", This
, hRefType
,
8081 SUCCEEDED(result
)? "SUCCESS":"FAILURE", *ppTInfo
);
8085 /* ITypeInfo::AddressOfMember
8087 * Retrieves the addresses of static functions or variables, such as those
8090 static HRESULT WINAPI
ITypeInfo_fnAddressOfMember( ITypeInfo2
*iface
,
8091 MEMBERID memid
, INVOKEKIND invKind
, PVOID
*ppv
)
8093 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8099 TRACE("(%p)->(0x%x, 0x%x, %p)\n", This
, memid
, invKind
, ppv
);
8101 hr
= ITypeInfo2_GetDllEntry(iface
, memid
, invKind
, &dll
, &entry
, &ordinal
);
8105 module
= LoadLibraryW(dll
);
8108 ERR("couldn't load %s\n", debugstr_w(dll
));
8110 SysFreeString(entry
);
8111 return STG_E_FILENOTFOUND
;
8113 /* FIXME: store library somewhere where we can free it */
8118 INT len
= WideCharToMultiByte(CP_ACP
, 0, entry
, -1, NULL
, 0, NULL
, NULL
);
8119 entryA
= heap_alloc(len
);
8120 WideCharToMultiByte(CP_ACP
, 0, entry
, -1, entryA
, len
, NULL
, NULL
);
8122 *ppv
= GetProcAddress(module
, entryA
);
8124 ERR("function not found %s\n", debugstr_a(entryA
));
8130 *ppv
= GetProcAddress(module
, MAKEINTRESOURCEA(ordinal
));
8132 ERR("function not found %d\n", ordinal
);
8136 SysFreeString(entry
);
8139 return TYPE_E_DLLFUNCTIONNOTFOUND
;
8144 /* ITypeInfo::CreateInstance
8146 * Creates a new instance of a type that describes a component object class
8149 static HRESULT WINAPI
ITypeInfo_fnCreateInstance( ITypeInfo2
*iface
,
8150 IUnknown
*pOuterUnk
, REFIID riid
, VOID
**ppvObj
)
8152 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8156 TRACE("(%p)->(%p, %s, %p)\n", This
, pOuterUnk
, debugstr_guid(riid
), ppvObj
);
8162 WARN("Not able to aggregate\n");
8163 return CLASS_E_NOAGGREGATION
;
8166 hr
= ITypeInfo2_GetTypeAttr(iface
, &pTA
);
8167 if(FAILED(hr
)) return hr
;
8169 if(pTA
->typekind
!= TKIND_COCLASS
)
8171 WARN("CreateInstance on typeinfo of type %x\n", pTA
->typekind
);
8177 if(pTA
->wTypeFlags
& TYPEFLAG_FAPPOBJECT
)
8180 hr
= GetActiveObject(&pTA
->guid
, NULL
, &pUnk
);
8181 TRACE("GetActiveObject rets %08x\n", hr
);
8184 hr
= IUnknown_QueryInterface(pUnk
, riid
, ppvObj
);
8185 IUnknown_Release(pUnk
);
8190 hr
= CoCreateInstance(&pTA
->guid
, NULL
,
8191 CLSCTX_INPROC_SERVER
| CLSCTX_LOCAL_SERVER
,
8195 ITypeInfo2_ReleaseTypeAttr(iface
, pTA
);
8199 /* ITypeInfo::GetMops
8201 * Retrieves marshalling information.
8203 static HRESULT WINAPI
ITypeInfo_fnGetMops( ITypeInfo2
*iface
, MEMBERID memid
,
8206 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8207 FIXME("(%p %d) stub!\n", This
, memid
);
8212 /* ITypeInfo::GetContainingTypeLib
8214 * Retrieves the containing type library and the index of the type description
8215 * within that type library.
8217 static HRESULT WINAPI
ITypeInfo_fnGetContainingTypeLib( ITypeInfo2
*iface
,
8218 ITypeLib
* *ppTLib
, UINT
*pIndex
)
8220 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8222 /* If a pointer is null, we simply ignore it, the ATL in particular passes pIndex as 0 */
8224 *pIndex
=This
->index
;
8225 TRACE("returning pIndex=%d\n", *pIndex
);
8229 *ppTLib
= (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
;
8230 ITypeLib_AddRef(*ppTLib
);
8231 TRACE("returning ppTLib=%p\n", *ppTLib
);
8237 /* ITypeInfo::ReleaseTypeAttr
8239 * Releases a TYPEATTR previously returned by Get
8242 static void WINAPI
ITypeInfo_fnReleaseTypeAttr( ITypeInfo2
*iface
,
8243 TYPEATTR
* pTypeAttr
)
8245 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8246 TRACE("(%p)->(%p)\n", This
, pTypeAttr
);
8247 heap_free(pTypeAttr
);
8250 /* ITypeInfo::ReleaseFuncDesc
8252 * Releases a FUNCDESC previously returned by GetFuncDesc. *
8254 static void WINAPI
ITypeInfo_fnReleaseFuncDesc(
8256 FUNCDESC
*pFuncDesc
)
8258 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8261 TRACE("(%p)->(%p)\n", This
, pFuncDesc
);
8263 for (i
= 0; i
< pFuncDesc
->cParams
; i
++)
8264 TLB_FreeElemDesc(&pFuncDesc
->lprgelemdescParam
[i
]);
8265 TLB_FreeElemDesc(&pFuncDesc
->elemdescFunc
);
8267 SysFreeString((BSTR
)pFuncDesc
);
8270 /* ITypeInfo::ReleaseVarDesc
8272 * Releases a VARDESC previously returned by GetVarDesc.
8274 static void WINAPI
ITypeInfo_fnReleaseVarDesc( ITypeInfo2
*iface
,
8277 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8278 TRACE("(%p)->(%p)\n", This
, pVarDesc
);
8280 TLB_FreeVarDesc(pVarDesc
);
8283 /* ITypeInfo2::GetTypeKind
8285 * Returns the TYPEKIND enumeration quickly, without doing any allocations.
8288 static HRESULT WINAPI
ITypeInfo2_fnGetTypeKind( ITypeInfo2
* iface
,
8289 TYPEKIND
*pTypeKind
)
8291 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8292 *pTypeKind
= This
->typeattr
.typekind
;
8293 TRACE("(%p) type 0x%0x\n", This
,*pTypeKind
);
8297 /* ITypeInfo2::GetTypeFlags
8299 * Returns the type flags without any allocations. This returns a DWORD type
8300 * flag, which expands the type flags without growing the TYPEATTR (type
8304 static HRESULT WINAPI
ITypeInfo2_fnGetTypeFlags( ITypeInfo2
*iface
, ULONG
*pTypeFlags
)
8306 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8307 *pTypeFlags
=This
->typeattr
.wTypeFlags
;
8308 TRACE("(%p) flags 0x%x\n", This
,*pTypeFlags
);
8312 /* ITypeInfo2::GetFuncIndexOfMemId
8313 * Binds to a specific member based on a known DISPID, where the member name
8314 * is not known (for example, when binding to a default member).
8317 static HRESULT WINAPI
ITypeInfo2_fnGetFuncIndexOfMemId( ITypeInfo2
* iface
,
8318 MEMBERID memid
, INVOKEKIND invKind
, UINT
*pFuncIndex
)
8320 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8324 for (fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8325 const TLBFuncDesc
*pFuncInfo
= &This
->funcdescs
[fdc
];
8326 if(memid
== pFuncInfo
->funcdesc
.memid
&& (invKind
& pFuncInfo
->funcdesc
.invkind
))
8329 if(fdc
< This
->typeattr
.cFuncs
) {
8333 result
= TYPE_E_ELEMENTNOTFOUND
;
8335 TRACE("(%p) memid 0x%08x invKind 0x%04x -> %s\n", This
,
8336 memid
, invKind
, SUCCEEDED(result
) ? "SUCCESS" : "FAILED");
8340 /* TypeInfo2::GetVarIndexOfMemId
8342 * Binds to a specific member based on a known DISPID, where the member name
8343 * is not known (for example, when binding to a default member).
8346 static HRESULT WINAPI
ITypeInfo2_fnGetVarIndexOfMemId( ITypeInfo2
* iface
,
8347 MEMBERID memid
, UINT
*pVarIndex
)
8349 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8350 TLBVarDesc
*pVarInfo
;
8352 TRACE("%p %d %p\n", iface
, memid
, pVarIndex
);
8354 pVarInfo
= TLB_get_vardesc_by_memberid(This
, memid
);
8356 return TYPE_E_ELEMENTNOTFOUND
;
8358 *pVarIndex
= (pVarInfo
- This
->vardescs
);
8363 /* ITypeInfo2::GetCustData
8365 * Gets the custom data
8367 static HRESULT WINAPI
ITypeInfo2_fnGetCustData(
8372 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8373 TLBCustData
*pCData
;
8375 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8377 if(!guid
|| !pVarVal
)
8378 return E_INVALIDARG
;
8380 pCData
= TLB_get_custdata_by_guid(This
->pcustdata_list
, guid
);
8382 VariantInit( pVarVal
);
8384 VariantCopy( pVarVal
, &pCData
->data
);
8386 VariantClear( pVarVal
);
8390 /* ITypeInfo2::GetFuncCustData
8392 * Gets the custom data
8394 static HRESULT WINAPI
ITypeInfo2_fnGetFuncCustData(
8400 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8401 const TLBFuncDesc
*desc
;
8406 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8408 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &desc
, &hrefoffset
);
8411 WARN("description for function %d not found\n", index
);
8415 VariantInit(pVarVal
);
8416 data
= TLB_get_custdata_by_guid(&desc
->custdata_list
, guid
);
8417 return data
? VariantCopy(pVarVal
, &data
->data
) : S_OK
;
8420 /* ITypeInfo2::GetParamCustData
8422 * Gets the custom data
8424 static HRESULT WINAPI
ITypeInfo2_fnGetParamCustData(
8431 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8432 const TLBFuncDesc
*pFDesc
;
8433 TLBCustData
*pCData
;
8437 TRACE("%p %u %u %s %p\n", This
, indexFunc
, indexParam
,
8438 debugstr_guid(guid
), pVarVal
);
8440 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8444 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8445 return TYPE_E_ELEMENTNOTFOUND
;
8447 pCData
= TLB_get_custdata_by_guid(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, guid
);
8449 return TYPE_E_ELEMENTNOTFOUND
;
8451 VariantInit(pVarVal
);
8452 VariantCopy(pVarVal
, &pCData
->data
);
8457 /* ITypeInfo2::GetVarCustData
8459 * Gets the custom data
8461 static HRESULT WINAPI
ITypeInfo2_fnGetVarCustData(
8467 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8468 TLBCustData
*pCData
;
8469 TLBVarDesc
*pVDesc
= &This
->vardescs
[index
];
8471 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), pVarVal
);
8473 if(index
>= This
->typeattr
.cVars
)
8474 return TYPE_E_ELEMENTNOTFOUND
;
8476 pCData
= TLB_get_custdata_by_guid(&pVDesc
->custdata_list
, guid
);
8478 return TYPE_E_ELEMENTNOTFOUND
;
8480 VariantInit(pVarVal
);
8481 VariantCopy(pVarVal
, &pCData
->data
);
8486 /* ITypeInfo2::GetImplCustData
8488 * Gets the custom data
8490 static HRESULT WINAPI
ITypeInfo2_fnGetImplTypeCustData(
8496 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8497 TLBCustData
*pCData
;
8498 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8500 TRACE("%p %u %s %p\n", This
, index
, debugstr_guid(guid
), pVarVal
);
8502 if(index
>= This
->typeattr
.cImplTypes
)
8503 return TYPE_E_ELEMENTNOTFOUND
;
8505 pCData
= TLB_get_custdata_by_guid(&pRDesc
->custdata_list
, guid
);
8507 return TYPE_E_ELEMENTNOTFOUND
;
8509 VariantInit(pVarVal
);
8510 VariantCopy(pVarVal
, &pCData
->data
);
8515 /* ITypeInfo2::GetDocumentation2
8517 * Retrieves the documentation string, the complete Help file name and path,
8518 * the localization context to use, and the context ID for the library Help
8519 * topic in the Help file.
8522 static HRESULT WINAPI
ITypeInfo2_fnGetDocumentation2(
8526 BSTR
*pbstrHelpString
,
8527 DWORD
*pdwHelpStringContext
,
8528 BSTR
*pbstrHelpStringDll
)
8530 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8531 const TLBFuncDesc
*pFDesc
;
8532 const TLBVarDesc
*pVDesc
;
8533 TRACE("(%p) memid %d lcid(0x%x) HelpString(%p) "
8534 "HelpStringContext(%p) HelpStringDll(%p)\n",
8535 This
, memid
, lcid
, pbstrHelpString
, pdwHelpStringContext
,
8536 pbstrHelpStringDll
);
8537 /* the help string should be obtained from the helpstringdll,
8538 * using the _DLLGetDocumentation function, based on the supplied
8539 * lcid. Nice to do sometime...
8541 if(memid
==MEMBERID_NIL
){ /* documentation for the typeinfo */
8543 *pbstrHelpString
=SysAllocString(TLB_get_bstr(This
->Name
));
8544 if(pdwHelpStringContext
)
8545 *pdwHelpStringContext
=This
->dwHelpStringContext
;
8546 if(pbstrHelpStringDll
)
8547 *pbstrHelpStringDll
=
8548 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8550 }else {/* for a member */
8551 pFDesc
= TLB_get_funcdesc_by_memberid(This
, memid
);
8554 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pFDesc
->HelpString
));
8555 if(pdwHelpStringContext
)
8556 *pdwHelpStringContext
=pFDesc
->HelpStringContext
;
8557 if(pbstrHelpStringDll
)
8558 *pbstrHelpStringDll
=
8559 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8562 pVDesc
= TLB_get_vardesc_by_memberid(This
, memid
);
8565 *pbstrHelpString
=SysAllocString(TLB_get_bstr(pVDesc
->HelpString
));
8566 if(pdwHelpStringContext
)
8567 *pdwHelpStringContext
=pVDesc
->HelpStringContext
;
8568 if(pbstrHelpStringDll
)
8569 *pbstrHelpStringDll
=
8570 SysAllocString(TLB_get_bstr(This
->pTypeLib
->HelpStringDll
));/* FIXME */
8574 return TYPE_E_ELEMENTNOTFOUND
;
8577 /* ITypeInfo2::GetAllCustData
8579 * Gets all custom data items for the Type info.
8582 static HRESULT WINAPI
ITypeInfo2_fnGetAllCustData(
8584 CUSTDATA
*pCustData
)
8586 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8588 TRACE("%p %p\n", This
, pCustData
);
8590 return TLB_copy_all_custdata(This
->pcustdata_list
, pCustData
);
8593 /* ITypeInfo2::GetAllFuncCustData
8595 * Gets all custom data items for the specified Function
8598 static HRESULT WINAPI
ITypeInfo2_fnGetAllFuncCustData(
8601 CUSTDATA
*pCustData
)
8603 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8604 const TLBFuncDesc
*pFDesc
;
8608 TRACE("%p %u %p\n", This
, index
, pCustData
);
8610 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, index
, &pFDesc
, &hrefoffset
);
8614 return TLB_copy_all_custdata(&pFDesc
->custdata_list
, pCustData
);
8617 /* ITypeInfo2::GetAllParamCustData
8619 * Gets all custom data items for the Functions
8622 static HRESULT WINAPI
ITypeInfo2_fnGetAllParamCustData( ITypeInfo2
* iface
,
8623 UINT indexFunc
, UINT indexParam
, CUSTDATA
*pCustData
)
8625 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8626 const TLBFuncDesc
*pFDesc
;
8630 TRACE("%p %u %u %p\n", This
, indexFunc
, indexParam
, pCustData
);
8632 hr
= ITypeInfoImpl_GetInternalFuncDesc((ITypeInfo
*)iface
, indexFunc
, &pFDesc
, &hrefoffset
);
8636 if(indexParam
>= pFDesc
->funcdesc
.cParams
)
8637 return TYPE_E_ELEMENTNOTFOUND
;
8639 return TLB_copy_all_custdata(&pFDesc
->pParamDesc
[indexParam
].custdata_list
, pCustData
);
8642 /* ITypeInfo2::GetAllVarCustData
8644 * Gets all custom data items for the specified Variable
8647 static HRESULT WINAPI
ITypeInfo2_fnGetAllVarCustData( ITypeInfo2
* iface
,
8648 UINT index
, CUSTDATA
*pCustData
)
8650 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8651 TLBVarDesc
* pVDesc
= &This
->vardescs
[index
];
8653 TRACE("%p %u %p\n", This
, index
, pCustData
);
8655 if(index
>= This
->typeattr
.cVars
)
8656 return TYPE_E_ELEMENTNOTFOUND
;
8658 return TLB_copy_all_custdata(&pVDesc
->custdata_list
, pCustData
);
8661 /* ITypeInfo2::GetAllImplCustData
8663 * Gets all custom data items for the specified implementation type
8666 static HRESULT WINAPI
ITypeInfo2_fnGetAllImplTypeCustData(
8669 CUSTDATA
*pCustData
)
8671 ITypeInfoImpl
*This
= impl_from_ITypeInfo2(iface
);
8672 TLBImplType
*pRDesc
= &This
->impltypes
[index
];
8674 TRACE("%p %u %p\n", This
, index
, pCustData
);
8676 if(index
>= This
->typeattr
.cImplTypes
)
8677 return TYPE_E_ELEMENTNOTFOUND
;
8679 return TLB_copy_all_custdata(&pRDesc
->custdata_list
, pCustData
);
8682 static const ITypeInfo2Vtbl tinfvt
=
8685 ITypeInfo_fnQueryInterface
,
8687 ITypeInfo_fnRelease
,
8689 ITypeInfo_fnGetTypeAttr
,
8690 ITypeInfo_fnGetTypeComp
,
8691 ITypeInfo_fnGetFuncDesc
,
8692 ITypeInfo_fnGetVarDesc
,
8693 ITypeInfo_fnGetNames
,
8694 ITypeInfo_fnGetRefTypeOfImplType
,
8695 ITypeInfo_fnGetImplTypeFlags
,
8696 ITypeInfo_fnGetIDsOfNames
,
8698 ITypeInfo_fnGetDocumentation
,
8699 ITypeInfo_fnGetDllEntry
,
8700 ITypeInfo_fnGetRefTypeInfo
,
8701 ITypeInfo_fnAddressOfMember
,
8702 ITypeInfo_fnCreateInstance
,
8703 ITypeInfo_fnGetMops
,
8704 ITypeInfo_fnGetContainingTypeLib
,
8705 ITypeInfo_fnReleaseTypeAttr
,
8706 ITypeInfo_fnReleaseFuncDesc
,
8707 ITypeInfo_fnReleaseVarDesc
,
8709 ITypeInfo2_fnGetTypeKind
,
8710 ITypeInfo2_fnGetTypeFlags
,
8711 ITypeInfo2_fnGetFuncIndexOfMemId
,
8712 ITypeInfo2_fnGetVarIndexOfMemId
,
8713 ITypeInfo2_fnGetCustData
,
8714 ITypeInfo2_fnGetFuncCustData
,
8715 ITypeInfo2_fnGetParamCustData
,
8716 ITypeInfo2_fnGetVarCustData
,
8717 ITypeInfo2_fnGetImplTypeCustData
,
8718 ITypeInfo2_fnGetDocumentation2
,
8719 ITypeInfo2_fnGetAllCustData
,
8720 ITypeInfo2_fnGetAllFuncCustData
,
8721 ITypeInfo2_fnGetAllParamCustData
,
8722 ITypeInfo2_fnGetAllVarCustData
,
8723 ITypeInfo2_fnGetAllImplTypeCustData
,
8726 /******************************************************************************
8727 * CreateDispTypeInfo [OLEAUT32.31]
8729 * Build type information for an object so it can be called through an
8730 * IDispatch interface.
8733 * Success: S_OK. pptinfo contains the created ITypeInfo object.
8734 * Failure: E_INVALIDARG, if one or more arguments is invalid.
8737 * This call allows an objects methods to be accessed through IDispatch, by
8738 * building an ITypeInfo object that IDispatch can use to call through.
8740 HRESULT WINAPI
CreateDispTypeInfo(
8741 INTERFACEDATA
*pidata
, /* [I] Description of the interface to build type info for */
8742 LCID lcid
, /* [I] Locale Id */
8743 ITypeInfo
**pptinfo
) /* [O] Destination for created ITypeInfo object */
8745 ITypeInfoImpl
*pTIClass
, *pTIIface
;
8746 ITypeLibImpl
*pTypeLibImpl
;
8747 unsigned int param
, func
;
8748 TLBFuncDesc
*pFuncDesc
;
8752 pTypeLibImpl
= TypeLibImpl_Constructor();
8753 if (!pTypeLibImpl
) return E_FAIL
;
8755 pTypeLibImpl
->TypeInfoCount
= 2;
8756 pTypeLibImpl
->typeinfos
= heap_alloc_zero(pTypeLibImpl
->TypeInfoCount
* sizeof(ITypeInfoImpl
*));
8758 pTIIface
= pTypeLibImpl
->typeinfos
[0] = ITypeInfoImpl_Constructor();
8759 pTIIface
->pTypeLib
= pTypeLibImpl
;
8760 pTIIface
->index
= 0;
8761 pTIIface
->Name
= NULL
;
8762 pTIIface
->dwHelpContext
= -1;
8763 pTIIface
->guid
= NULL
;
8764 pTIIface
->typeattr
.lcid
= lcid
;
8765 pTIIface
->typeattr
.typekind
= TKIND_INTERFACE
;
8766 pTIIface
->typeattr
.wMajorVerNum
= 0;
8767 pTIIface
->typeattr
.wMinorVerNum
= 0;
8768 pTIIface
->typeattr
.cbAlignment
= 2;
8769 pTIIface
->typeattr
.cbSizeInstance
= -1;
8770 pTIIface
->typeattr
.cbSizeVft
= -1;
8771 pTIIface
->typeattr
.cFuncs
= 0;
8772 pTIIface
->typeattr
.cImplTypes
= 0;
8773 pTIIface
->typeattr
.cVars
= 0;
8774 pTIIface
->typeattr
.wTypeFlags
= 0;
8775 pTIIface
->hreftype
= 0;
8777 pTIIface
->funcdescs
= TLBFuncDesc_Alloc(pidata
->cMembers
);
8778 pFuncDesc
= pTIIface
->funcdescs
;
8779 for(func
= 0; func
< pidata
->cMembers
; func
++) {
8780 METHODDATA
*md
= pidata
->pmethdata
+ func
;
8781 pFuncDesc
->Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->szName
);
8782 pFuncDesc
->funcdesc
.memid
= md
->dispid
;
8783 pFuncDesc
->funcdesc
.lprgscode
= NULL
;
8784 pFuncDesc
->funcdesc
.funckind
= FUNC_VIRTUAL
;
8785 pFuncDesc
->funcdesc
.invkind
= md
->wFlags
;
8786 pFuncDesc
->funcdesc
.callconv
= md
->cc
;
8787 pFuncDesc
->funcdesc
.cParams
= md
->cArgs
;
8788 pFuncDesc
->funcdesc
.cParamsOpt
= 0;
8789 pFuncDesc
->funcdesc
.oVft
= md
->iMeth
* sizeof(void *);
8790 pFuncDesc
->funcdesc
.cScodes
= 0;
8791 pFuncDesc
->funcdesc
.wFuncFlags
= 0;
8792 pFuncDesc
->funcdesc
.elemdescFunc
.tdesc
.vt
= md
->vtReturn
;
8793 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.wParamFlags
= PARAMFLAG_NONE
;
8794 pFuncDesc
->funcdesc
.elemdescFunc
.u
.paramdesc
.pparamdescex
= NULL
;
8795 pFuncDesc
->funcdesc
.lprgelemdescParam
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
,
8796 md
->cArgs
* sizeof(ELEMDESC
));
8797 pFuncDesc
->pParamDesc
= TLBParDesc_Constructor(md
->cArgs
);
8798 for(param
= 0; param
< md
->cArgs
; param
++) {
8799 pFuncDesc
->funcdesc
.lprgelemdescParam
[param
].tdesc
.vt
= md
->ppdata
[param
].vt
;
8800 pFuncDesc
->pParamDesc
[param
].Name
= TLB_append_str(&pTypeLibImpl
->name_list
, md
->ppdata
[param
].szName
);
8802 pFuncDesc
->helpcontext
= 0;
8803 pFuncDesc
->HelpStringContext
= 0;
8804 pFuncDesc
->HelpString
= NULL
;
8805 pFuncDesc
->Entry
= NULL
;
8806 list_init(&pFuncDesc
->custdata_list
);
8807 pTIIface
->typeattr
.cFuncs
++;
8811 dump_TypeInfo(pTIIface
);
8813 pTIClass
= pTypeLibImpl
->typeinfos
[1] = ITypeInfoImpl_Constructor();
8814 pTIClass
->pTypeLib
= pTypeLibImpl
;
8815 pTIClass
->index
= 1;
8816 pTIClass
->Name
= NULL
;
8817 pTIClass
->dwHelpContext
= -1;
8818 pTIClass
->guid
= NULL
;
8819 pTIClass
->typeattr
.lcid
= lcid
;
8820 pTIClass
->typeattr
.typekind
= TKIND_COCLASS
;
8821 pTIClass
->typeattr
.wMajorVerNum
= 0;
8822 pTIClass
->typeattr
.wMinorVerNum
= 0;
8823 pTIClass
->typeattr
.cbAlignment
= 2;
8824 pTIClass
->typeattr
.cbSizeInstance
= -1;
8825 pTIClass
->typeattr
.cbSizeVft
= -1;
8826 pTIClass
->typeattr
.cFuncs
= 0;
8827 pTIClass
->typeattr
.cImplTypes
= 1;
8828 pTIClass
->typeattr
.cVars
= 0;
8829 pTIClass
->typeattr
.wTypeFlags
= 0;
8830 pTIClass
->hreftype
= sizeof(MSFT_TypeInfoBase
);
8832 pTIClass
->impltypes
= TLBImplType_Alloc(1);
8834 ref
= heap_alloc_zero(sizeof(*ref
));
8835 ref
->pImpTLInfo
= TLB_REF_INTERNAL
;
8836 list_add_head(&pTypeLibImpl
->ref_list
, &ref
->entry
);
8838 dump_TypeInfo(pTIClass
);
8840 *pptinfo
= (ITypeInfo
*)&pTIClass
->ITypeInfo2_iface
;
8842 ITypeInfo_AddRef(*pptinfo
);
8843 ITypeLib2_Release(&pTypeLibImpl
->ITypeLib2_iface
);
8849 static HRESULT WINAPI
ITypeComp_fnQueryInterface(ITypeComp
* iface
, REFIID riid
, LPVOID
* ppv
)
8851 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8853 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, ppv
);
8856 static ULONG WINAPI
ITypeComp_fnAddRef(ITypeComp
* iface
)
8858 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8860 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
8863 static ULONG WINAPI
ITypeComp_fnRelease(ITypeComp
* iface
)
8865 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8867 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
8870 static HRESULT WINAPI
ITypeComp_fnBind(
8875 ITypeInfo
** ppTInfo
,
8876 DESCKIND
* pDescKind
,
8879 ITypeInfoImpl
*This
= info_impl_from_ITypeComp(iface
);
8880 const TLBFuncDesc
*pFDesc
;
8881 const TLBVarDesc
*pVDesc
;
8882 HRESULT hr
= DISP_E_MEMBERNOTFOUND
;
8885 TRACE("(%p)->(%s, %x, 0x%x, %p, %p, %p)\n", This
, debugstr_w(szName
), lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8887 *pDescKind
= DESCKIND_NONE
;
8888 pBindPtr
->lpfuncdesc
= NULL
;
8891 for(fdc
= 0; fdc
< This
->typeattr
.cFuncs
; ++fdc
){
8892 pFDesc
= &This
->funcdescs
[fdc
];
8893 if (!lstrcmpiW(TLB_get_bstr(pFDesc
->Name
), szName
)) {
8894 if (!wFlags
|| (pFDesc
->funcdesc
.invkind
& wFlags
))
8897 /* name found, but wrong flags */
8898 hr
= TYPE_E_TYPEMISMATCH
;
8902 if (fdc
< This
->typeattr
.cFuncs
)
8904 HRESULT hr
= TLB_AllocAndInitFuncDesc(
8906 &pBindPtr
->lpfuncdesc
,
8907 This
->typeattr
.typekind
== TKIND_DISPATCH
);
8910 *pDescKind
= DESCKIND_FUNCDESC
;
8911 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8912 ITypeInfo_AddRef(*ppTInfo
);
8915 pVDesc
= TLB_get_vardesc_by_name(This
, szName
);
8917 HRESULT hr
= TLB_AllocAndInitVarDesc(&pVDesc
->vardesc
, &pBindPtr
->lpvardesc
);
8920 *pDescKind
= DESCKIND_VARDESC
;
8921 *ppTInfo
= (ITypeInfo
*)&This
->ITypeInfo2_iface
;
8922 ITypeInfo_AddRef(*ppTInfo
);
8927 if (hr
== DISP_E_MEMBERNOTFOUND
&& This
->impltypes
) {
8928 /* recursive search */
8932 hr
=ITypeInfo2_GetRefTypeInfo(&This
->ITypeInfo2_iface
, This
->impltypes
[0].hRef
, &pTInfo
);
8935 hr
= ITypeInfo_GetTypeComp(pTInfo
,&pTComp
);
8936 ITypeInfo_Release(pTInfo
);
8940 hr
= ITypeComp_Bind(pTComp
, szName
, lHash
, wFlags
, ppTInfo
, pDescKind
, pBindPtr
);
8941 ITypeComp_Release(pTComp
);
8942 if (SUCCEEDED(hr
) && *pDescKind
== DESCKIND_FUNCDESC
&&
8943 This
->typeattr
.typekind
== TKIND_DISPATCH
)
8945 FUNCDESC
*tmp
= pBindPtr
->lpfuncdesc
;
8946 hr
= TLB_AllocAndInitFuncDesc(tmp
, &pBindPtr
->lpfuncdesc
, TRUE
);
8947 SysFreeString((BSTR
)tmp
);
8951 WARN("Could not search inherited interface!\n");
8953 if (hr
== DISP_E_MEMBERNOTFOUND
)
8955 TRACE("did not find member with name %s, flags 0x%x\n", debugstr_w(szName
), wFlags
);
8959 static HRESULT WINAPI
ITypeComp_fnBindType(
8963 ITypeInfo
** ppTInfo
,
8964 ITypeComp
** ppTComp
)
8966 TRACE("(%s, %x, %p, %p)\n", debugstr_w(szName
), lHash
, ppTInfo
, ppTComp
);
8968 /* strange behaviour (does nothing) but like the
8971 if (!ppTInfo
|| !ppTComp
)
8980 static const ITypeCompVtbl tcompvt
=
8983 ITypeComp_fnQueryInterface
,
8985 ITypeComp_fnRelease
,
8988 ITypeComp_fnBindType
8991 HRESULT WINAPI
CreateTypeLib2(SYSKIND syskind
, LPCOLESTR szFile
,
8992 ICreateTypeLib2
** ppctlib
)
8997 TRACE("(%d,%s,%p)\n", syskind
, debugstr_w(szFile
), ppctlib
);
8999 if (!szFile
) return E_INVALIDARG
;
9001 This
= TypeLibImpl_Constructor();
9003 return E_OUTOFMEMORY
;
9005 This
->lcid
= GetSystemDefaultLCID();
9006 This
->syskind
= syskind
;
9007 This
->ptr_size
= get_ptr_size(syskind
);
9009 This
->path
= heap_alloc((lstrlenW(szFile
) + 1) * sizeof(WCHAR
));
9011 ITypeLib2_Release(&This
->ITypeLib2_iface
);
9012 return E_OUTOFMEMORY
;
9014 lstrcpyW(This
->path
, szFile
);
9016 hres
= ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, &IID_ICreateTypeLib2
, (LPVOID
*)ppctlib
);
9017 ITypeLib2_Release(&This
->ITypeLib2_iface
);
9021 static HRESULT WINAPI
ICreateTypeLib2_fnQueryInterface(ICreateTypeLib2
*iface
,
9022 REFIID riid
, void **object
)
9024 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9026 return ITypeLib2_QueryInterface(&This
->ITypeLib2_iface
, riid
, object
);
9029 static ULONG WINAPI
ICreateTypeLib2_fnAddRef(ICreateTypeLib2
*iface
)
9031 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9033 return ITypeLib2_AddRef(&This
->ITypeLib2_iface
);
9036 static ULONG WINAPI
ICreateTypeLib2_fnRelease(ICreateTypeLib2
*iface
)
9038 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9040 return ITypeLib2_Release(&This
->ITypeLib2_iface
);
9043 static HRESULT WINAPI
ICreateTypeLib2_fnCreateTypeInfo(ICreateTypeLib2
*iface
,
9044 LPOLESTR name
, TYPEKIND kind
, ICreateTypeInfo
**ctinfo
)
9046 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9047 ITypeInfoImpl
*info
;
9050 TRACE("%p %s %d %p\n", This
, wine_dbgstr_w(name
), kind
, ctinfo
);
9052 if (!ctinfo
|| !name
)
9053 return E_INVALIDARG
;
9055 info
= TLB_get_typeinfo_by_name(This
, name
);
9057 return TYPE_E_NAMECONFLICT
;
9059 if (This
->typeinfos
)
9060 This
->typeinfos
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->typeinfos
,
9061 sizeof(ITypeInfoImpl
*) * (This
->TypeInfoCount
+ 1));
9063 This
->typeinfos
= heap_alloc_zero(sizeof(ITypeInfoImpl
*));
9065 info
= This
->typeinfos
[This
->TypeInfoCount
] = ITypeInfoImpl_Constructor();
9067 info
->pTypeLib
= This
;
9068 info
->Name
= TLB_append_str(&This
->name_list
, name
);
9069 info
->index
= This
->TypeInfoCount
;
9070 info
->typeattr
.typekind
= kind
;
9071 info
->typeattr
.cbAlignment
= 4;
9073 switch (info
->typeattr
.typekind
) {
9075 case TKIND_INTERFACE
:
9076 case TKIND_DISPATCH
:
9078 info
->typeattr
.cbSizeInstance
= This
->ptr_size
;
9082 info
->typeattr
.cbSizeInstance
= 0;
9085 info
->typeattr
.cbSizeInstance
= 2;
9088 info
->typeattr
.cbSizeInstance
= -0x75;
9091 FIXME("unrecognized typekind %d\n", info
->typeattr
.typekind
);
9092 info
->typeattr
.cbSizeInstance
= 0xdeadbeef;
9096 hres
= ITypeInfo2_QueryInterface(&info
->ITypeInfo2_iface
,
9097 &IID_ICreateTypeInfo
, (void **)ctinfo
);
9099 ITypeInfo2_Release(&info
->ITypeInfo2_iface
);
9103 info
->hreftype
= info
->index
* sizeof(MSFT_TypeInfoBase
);
9105 ++This
->TypeInfoCount
;
9110 static HRESULT WINAPI
ICreateTypeLib2_fnSetName(ICreateTypeLib2
*iface
,
9113 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9115 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
9118 return E_INVALIDARG
;
9120 This
->Name
= TLB_append_str(&This
->name_list
, name
);
9125 static HRESULT WINAPI
ICreateTypeLib2_fnSetVersion(ICreateTypeLib2
*iface
,
9126 WORD majorVerNum
, WORD minorVerNum
)
9128 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9130 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
9132 This
->ver_major
= majorVerNum
;
9133 This
->ver_minor
= minorVerNum
;
9138 static HRESULT WINAPI
ICreateTypeLib2_fnSetGuid(ICreateTypeLib2
*iface
,
9141 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9143 TRACE("%p %s\n", This
, debugstr_guid(guid
));
9145 This
->guid
= TLB_append_guid(&This
->guid_list
, guid
, -2);
9150 static HRESULT WINAPI
ICreateTypeLib2_fnSetDocString(ICreateTypeLib2
*iface
,
9153 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9155 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
9158 return E_INVALIDARG
;
9160 This
->DocString
= TLB_append_str(&This
->string_list
, doc
);
9165 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpFileName(ICreateTypeLib2
*iface
,
9166 LPOLESTR helpFileName
)
9168 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9170 TRACE("%p %s\n", This
, wine_dbgstr_w(helpFileName
));
9173 return E_INVALIDARG
;
9175 This
->HelpFile
= TLB_append_str(&This
->string_list
, helpFileName
);
9180 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpContext(ICreateTypeLib2
*iface
,
9183 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9185 TRACE("%p %d\n", This
, helpContext
);
9187 This
->dwHelpContext
= helpContext
;
9192 static HRESULT WINAPI
ICreateTypeLib2_fnSetLcid(ICreateTypeLib2
*iface
,
9195 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9197 TRACE("%p %x\n", This
, lcid
);
9199 This
->set_lcid
= lcid
;
9204 static HRESULT WINAPI
ICreateTypeLib2_fnSetLibFlags(ICreateTypeLib2
*iface
,
9207 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
9209 TRACE("%p %x\n", This
, libFlags
);
9211 This
->libflags
= libFlags
;
9216 typedef struct tagWMSFT_SegContents
{
9219 } WMSFT_SegContents
;
9221 typedef struct tagWMSFT_TLBFile
{
9223 WMSFT_SegContents typeinfo_seg
;
9224 WMSFT_SegContents impfile_seg
;
9225 WMSFT_SegContents impinfo_seg
;
9226 WMSFT_SegContents ref_seg
;
9227 WMSFT_SegContents guidhash_seg
;
9228 WMSFT_SegContents guid_seg
;
9229 WMSFT_SegContents namehash_seg
;
9230 WMSFT_SegContents name_seg
;
9231 WMSFT_SegContents string_seg
;
9232 WMSFT_SegContents typdesc_seg
;
9233 WMSFT_SegContents arraydesc_seg
;
9234 WMSFT_SegContents custdata_seg
;
9235 WMSFT_SegContents cdguids_seg
;
9237 WMSFT_SegContents aux_seg
;
9240 static HRESULT
WMSFT_compile_strings(ITypeLibImpl
*This
,
9241 WMSFT_TLBFile
*file
)
9247 file
->string_seg
.len
= 0;
9248 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9251 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
), NULL
, 0, NULL
, NULL
);
9253 return E_UNEXPECTED
;
9255 size
+= sizeof(INT16
);
9257 size
= (size
+ 4) & ~0x3;
9261 file
->string_seg
.len
+= size
;
9263 /* temporarily use str->offset to store the length of the aligned,
9264 * converted string */
9268 file
->string_seg
.data
= data
= heap_alloc(file
->string_seg
.len
);
9271 LIST_FOR_EACH_ENTRY(str
, &This
->string_list
, TLBString
, entry
) {
9274 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9275 data
+ sizeof(INT16
), file
->string_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
9277 heap_free(file
->string_seg
.data
);
9278 return E_UNEXPECTED
;
9281 *((INT16
*)data
) = size
;
9283 memset(data
+ sizeof(INT16
) + size
, 0x57, str
->offset
- size
- sizeof(INT16
));
9287 str
->offset
= last_offs
;
9294 static HRESULT
WMSFT_compile_names(ITypeLibImpl
*This
,
9295 WMSFT_TLBFile
*file
)
9300 MSFT_NameIntro
*last_intro
= NULL
;
9302 file
->header
.nametablecount
= 0;
9303 file
->header
.nametablechars
= 0;
9305 file
->name_seg
.len
= 0;
9306 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9309 size
= lstrlenW(str
->str
);
9310 file
->header
.nametablechars
+= size
;
9311 file
->header
.nametablecount
++;
9313 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, size
, NULL
, 0, NULL
, NULL
);
9315 return E_UNEXPECTED
;
9317 size
+= sizeof(MSFT_NameIntro
);
9319 size
= (size
+ 4) & ~0x3;
9323 file
->name_seg
.len
+= size
;
9325 /* temporarily use str->offset to store the length of the aligned,
9326 * converted string */
9330 /* Allocate bigger buffer so we can temporarily NULL terminate the name */
9331 file
->name_seg
.data
= data
= heap_alloc(file
->name_seg
.len
+1);
9334 LIST_FOR_EACH_ENTRY(str
, &This
->name_list
, TLBString
, entry
) {
9336 MSFT_NameIntro
*intro
= (MSFT_NameIntro
*)data
;
9338 size
= WideCharToMultiByte(CP_ACP
, 0, str
->str
, lstrlenW(str
->str
),
9339 data
+ sizeof(MSFT_NameIntro
),
9340 file
->name_seg
.len
- last_offs
- sizeof(MSFT_NameIntro
), NULL
, NULL
);
9342 heap_free(file
->name_seg
.data
);
9343 return E_UNEXPECTED
;
9345 data
[sizeof(MSFT_NameIntro
) + size
] = '\0';
9347 intro
->hreftype
= -1; /* TODO? */
9348 intro
->namelen
= size
& 0xFF;
9349 /* TODO: namelen & 0xFF00 == ??? maybe HREF type indicator? */
9350 hash
= LHashValOfNameSysA(This
->syskind
, This
->lcid
, data
+ sizeof(MSFT_NameIntro
));
9351 intro
->namelen
|= hash
<< 16;
9352 intro
->next_hash
= ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f];
9353 ((DWORD
*)file
->namehash_seg
.data
)[hash
& 0x7f] = last_offs
;
9355 memset(data
+ sizeof(MSFT_NameIntro
) + size
, 0x57,
9356 str
->offset
- size
- sizeof(MSFT_NameIntro
));
9358 /* update str->offset to actual value to use in other
9359 * compilation functions that require positions within
9360 * the string table */
9364 str
->offset
= last_offs
;
9369 last_intro
->hreftype
= 0; /* last one is 0? */
9374 static inline int hash_guid(GUID
*guid
)
9378 for (i
= 0; i
< 8; i
++)
9379 hash
^= ((const short *)guid
)[i
];
9384 static HRESULT
WMSFT_compile_guids(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
9387 MSFT_GuidEntry
*entry
;
9389 int hash_key
, *guidhashtab
;
9391 file
->guid_seg
.len
= sizeof(MSFT_GuidEntry
) * list_count(&This
->guid_list
);
9392 file
->guid_seg
.data
= heap_alloc(file
->guid_seg
.len
);
9394 entry
= file
->guid_seg
.data
;
9396 guidhashtab
= file
->guidhash_seg
.data
;
9397 LIST_FOR_EACH_ENTRY(guid
, &This
->guid_list
, TLBGuid
, entry
){
9398 memcpy(&entry
->guid
, &guid
->guid
, sizeof(GUID
));
9399 entry
->hreftype
= guid
->hreftype
;
9401 hash_key
= hash_guid(&guid
->guid
);
9402 entry
->next_hash
= guidhashtab
[hash_key
];
9403 guidhashtab
[hash_key
] = offs
;
9405 guid
->offset
= offs
;
9406 offs
+= sizeof(MSFT_GuidEntry
);
9413 static DWORD
WMSFT_encode_variant(VARIANT
*value
, WMSFT_TLBFile
*file
)
9416 VARTYPE arg_type
= V_VT(value
);
9419 DWORD ret
= file
->custdata_seg
.len
;
9421 if(arg_type
== VT_INT
)
9423 if(arg_type
== VT_UINT
)
9427 if(V_VT(value
) != arg_type
) {
9428 hres
= VariantChangeType(&v
, value
, 0, arg_type
);
9430 ERR("VariantChangeType failed: %08x\n", hres
);
9435 /* Check if default value can be stored in-place */
9440 if(V_UI4(&v
) > 0x3ffffff)
9453 return ((0x80 + 0x4 * V_VT(value
)) << 24) | (V_UI4(&v
) & mask
);
9456 /* have to allocate space in custdata_seg */
9465 /* Construct the data to be allocated */
9468 if(file
->custdata_seg
.data
){
9469 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ sizeof(int) * 2);
9470 data
= (int *)(((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
);
9471 file
->custdata_seg
.len
+= sizeof(int) * 2;
9473 file
->custdata_seg
.len
= sizeof(int) * 2;
9474 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9477 data
[0] = V_VT(value
) + (V_UI4(&v
) << 16);
9478 data
[1] = (V_UI4(&v
) >> 16) + 0x57570000;
9480 /* TODO: Check if the encoded data is already present in custdata_seg */
9486 int i
, len
= (6+SysStringLen(V_BSTR(&v
))+3) & ~0x3;
9489 if(file
->custdata_seg
.data
){
9490 file
->custdata_seg
.data
= heap_realloc(file
->custdata_seg
.data
, file
->custdata_seg
.len
+ len
);
9491 data
= ((char *)file
->custdata_seg
.data
) + file
->custdata_seg
.len
;
9492 file
->custdata_seg
.len
+= len
;
9494 file
->custdata_seg
.len
= len
;
9495 data
= file
->custdata_seg
.data
= heap_alloc(file
->custdata_seg
.len
);
9498 *((unsigned short *)data
) = V_VT(value
);
9499 *((unsigned int *)(data
+2)) = SysStringLen(V_BSTR(&v
));
9500 for(i
=0; i
<SysStringLen(V_BSTR(&v
)); i
++) {
9501 if(V_BSTR(&v
)[i
] <= 0x7f)
9502 data
[i
+6] = V_BSTR(&v
)[i
];
9506 WideCharToMultiByte(CP_ACP
, 0, V_BSTR(&v
), SysStringLen(V_BSTR(&v
)), &data
[6], len
-6, NULL
, NULL
);
9507 for(i
=6+SysStringLen(V_BSTR(&v
)); i
<len
; i
++)
9510 /* TODO: Check if the encoded data is already present in custdata_seg */
9515 FIXME("Argument type not yet handled\n");
9520 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
);
9522 static DWORD
WMSFT_append_arraydesc(ARRAYDESC
*desc
, WMSFT_TLBFile
*file
)
9524 DWORD offs
= file
->arraydesc_seg
.len
;
9528 /* TODO: we should check for duplicates, but that's harder because each
9529 * chunk is variable length (really we should store TYPEDESC and ARRAYDESC
9530 * at the library-level) */
9532 file
->arraydesc_seg
.len
+= (2 + desc
->cDims
* 2) * sizeof(DWORD
);
9533 if(!file
->arraydesc_seg
.data
)
9534 file
->arraydesc_seg
.data
= heap_alloc(file
->arraydesc_seg
.len
);
9536 file
->arraydesc_seg
.data
= heap_realloc(file
->arraydesc_seg
.data
, file
->arraydesc_seg
.len
);
9537 encoded
= (DWORD
*)((char *)file
->arraydesc_seg
.data
+ offs
);
9539 encoded
[0] = WMSFT_append_typedesc(&desc
->tdescElem
, file
, NULL
, NULL
);
9540 encoded
[1] = desc
->cDims
| ((desc
->cDims
* 2 * sizeof(DWORD
)) << 16);
9541 for(i
= 0; i
< desc
->cDims
; ++i
){
9542 encoded
[2 + i
* 2] = desc
->rgbounds
[i
].cElements
;
9543 encoded
[2 + i
* 2 + 1] = desc
->rgbounds
[i
].lLbound
;
9549 static DWORD
WMSFT_append_typedesc(TYPEDESC
*desc
, WMSFT_TLBFile
*file
, DWORD
*out_mix
, INT16
*out_size
)
9555 VARTYPE vt
, subtype
;
9566 vt
= desc
->vt
& VT_TYPEMASK
;
9568 if(vt
== VT_PTR
|| vt
== VT_SAFEARRAY
){
9570 encoded
[1] = WMSFT_append_typedesc(desc
->u
.lptdesc
, file
, &mix
, out_size
);
9571 encoded
[0] = desc
->vt
| ((mix
| VT_BYREF
) << 16);
9573 *out_size
+= 2 * sizeof(DWORD
);
9574 }else if(vt
== VT_CARRAY
){
9575 encoded
[0] = desc
->vt
| (0x7FFE << 16);
9576 encoded
[1] = WMSFT_append_arraydesc(desc
->u
.lpadesc
, file
);
9578 }else if(vt
== VT_USERDEFINED
){
9579 encoded
[0] = desc
->vt
| (0x7FFF << 16);
9580 encoded
[1] = desc
->u
.hreftype
;
9581 *out_mix
= 0x7FFF; /* FIXME: Should get TYPEKIND of the hreftype, e.g. TKIND_ENUM => VT_I4 */
9583 TRACE("Mixing in-place, VT: 0x%x\n", desc
->vt
);
9601 return 0x80000000 | (subtype
<< 16) | desc
->vt
;
9604 data
= file
->typdesc_seg
.data
;
9605 while(offs
< file
->typdesc_seg
.len
){
9606 if(!memcmp(&data
[offs
], encoded
, sizeof(encoded
)))
9608 offs
+= sizeof(encoded
);
9611 file
->typdesc_seg
.len
+= sizeof(encoded
);
9612 if(!file
->typdesc_seg
.data
)
9613 data
= file
->typdesc_seg
.data
= heap_alloc(file
->typdesc_seg
.len
);
9615 data
= file
->typdesc_seg
.data
= heap_realloc(file
->typdesc_seg
.data
, file
->typdesc_seg
.len
);
9617 memcpy(&data
[offs
], encoded
, sizeof(encoded
));
9622 static DWORD
WMSFT_compile_custdata(struct list
*custdata_list
, WMSFT_TLBFile
*file
)
9624 WMSFT_SegContents
*cdguids_seg
= &file
->cdguids_seg
;
9625 DWORD ret
= cdguids_seg
->len
, offs
;
9626 MSFT_CDGuid
*cdguid
;
9629 if(list_empty(custdata_list
))
9632 cdguids_seg
->len
+= sizeof(MSFT_CDGuid
) * list_count(custdata_list
);
9633 if(!cdguids_seg
->data
){
9634 cdguid
= cdguids_seg
->data
= heap_alloc(cdguids_seg
->len
);
9636 cdguids_seg
->data
= heap_realloc(cdguids_seg
->data
, cdguids_seg
->len
);
9637 cdguid
= (MSFT_CDGuid
*)((char*)cdguids_seg
->data
+ ret
);
9640 offs
= ret
+ sizeof(MSFT_CDGuid
);
9641 LIST_FOR_EACH_ENTRY(cd
, custdata_list
, TLBCustData
, entry
){
9642 cdguid
->GuidOffset
= cd
->guid
->offset
;
9643 cdguid
->DataOffset
= WMSFT_encode_variant(&cd
->data
, file
);
9644 cdguid
->next
= offs
;
9645 offs
+= sizeof(MSFT_CDGuid
);
9655 static DWORD
WMSFT_compile_typeinfo_aux(ITypeInfoImpl
*info
,
9656 WMSFT_TLBFile
*file
)
9658 WMSFT_SegContents
*aux_seg
= &file
->aux_seg
;
9659 DWORD ret
= aux_seg
->len
, i
, j
, recorded_size
= 0, extra_size
= 0;
9660 MSFT_VarRecord
*varrecord
;
9661 MSFT_FuncRecord
*funcrecord
;
9663 DWORD
*name
, *offsets
, offs
;
9665 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9666 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9668 recorded_size
+= 6 * sizeof(INT
); /* mandatory fields */
9670 /* optional fields */
9671 /* TODO: oArgCustData - FuncSetCustData not impl yet */
9672 if(!list_empty(&desc
->custdata_list
))
9673 recorded_size
+= 7 * sizeof(INT
);
9674 else if(desc
->HelpStringContext
!= 0)
9675 recorded_size
+= 6 * sizeof(INT
);
9677 else if(desc
->Entry
)
9678 recorded_size
+= 3 * sizeof(INT
);
9679 else if(desc
->HelpString
)
9680 recorded_size
+= 2 * sizeof(INT
);
9681 else if(desc
->helpcontext
)
9682 recorded_size
+= sizeof(INT
);
9684 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(MSFT_ParameterInfo
);
9686 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9687 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9688 recorded_size
+= desc
->funcdesc
.cParams
* sizeof(INT
);
9693 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9696 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9697 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9699 recorded_size
+= 5 * sizeof(INT
); /* mandatory fields */
9701 /* optional fields */
9702 if(desc
->HelpStringContext
!= 0)
9703 recorded_size
+= 5 * sizeof(INT
);
9704 else if(!list_empty(&desc
->custdata_list
))
9705 recorded_size
+= 4 * sizeof(INT
);
9707 else if(desc
->HelpString
)
9708 recorded_size
+= 2 * sizeof(INT
);
9709 else if(desc
->HelpContext
!= 0)
9710 recorded_size
+= sizeof(INT
);
9712 extra_size
+= 2 * sizeof(INT
); /* memberid, name offs */
9715 if(!recorded_size
&& !extra_size
)
9718 extra_size
+= sizeof(INT
); /* total aux size for this typeinfo */
9720 aux_seg
->len
+= recorded_size
+ extra_size
;
9722 aux_seg
->len
+= sizeof(INT
) * (info
->typeattr
.cVars
+ info
->typeattr
.cFuncs
); /* offsets at the end */
9725 aux_seg
->data
= heap_realloc(aux_seg
->data
, aux_seg
->len
);
9727 aux_seg
->data
= heap_alloc(aux_seg
->len
);
9729 *((DWORD
*)((char *)aux_seg
->data
+ ret
)) = recorded_size
;
9731 offsets
= (DWORD
*)((char *)aux_seg
->data
+ ret
+ recorded_size
+ extra_size
);
9734 funcrecord
= (MSFT_FuncRecord
*)(((char *)aux_seg
->data
) + ret
+ sizeof(INT
));
9735 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9736 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9737 DWORD size
= 6 * sizeof(INT
), paramdefault_size
= 0, *paramdefault
;
9739 funcrecord
->funcdescsize
= sizeof(desc
->funcdesc
) + desc
->funcdesc
.cParams
* sizeof(ELEMDESC
);
9740 funcrecord
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.elemdescFunc
.tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9741 funcrecord
->Flags
= desc
->funcdesc
.wFuncFlags
;
9742 funcrecord
->VtableOffset
= desc
->funcdesc
.oVft
;
9745 * XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
9750 * ^has_param_defaults
9751 * ^oEntry_is_intresource
9753 funcrecord
->FKCCIC
=
9754 desc
->funcdesc
.funckind
|
9755 (desc
->funcdesc
.invkind
<< 3) |
9756 (list_empty(&desc
->custdata_list
) ? 0 : 0x80) |
9757 (desc
->funcdesc
.callconv
<< 8);
9759 if(desc
->Entry
&& desc
->Entry
!= (TLBString
*)-1 && IS_INTRESOURCE(desc
->Entry
))
9760 funcrecord
->FKCCIC
|= 0x2000;
9762 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9763 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
){
9764 paramdefault_size
= sizeof(INT
) * desc
->funcdesc
.cParams
;
9765 funcrecord
->funcdescsize
+= sizeof(PARAMDESCEX
);
9768 if(paramdefault_size
> 0)
9769 funcrecord
->FKCCIC
|= 0x1000;
9771 funcrecord
->nrargs
= desc
->funcdesc
.cParams
;
9772 funcrecord
->nroargs
= desc
->funcdesc
.cParamsOpt
;
9774 /* optional fields */
9776 if(!list_empty(&desc
->custdata_list
)){
9777 size
+= 7 * sizeof(INT
);
9778 funcrecord
->HelpContext
= desc
->helpcontext
;
9779 if(desc
->HelpString
)
9780 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9782 funcrecord
->oHelpString
= -1;
9784 funcrecord
->oEntry
= -1;
9785 else if(IS_INTRESOURCE(desc
->Entry
))
9786 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9788 funcrecord
->oEntry
= desc
->Entry
->offset
;
9789 funcrecord
->res9
= -1;
9790 funcrecord
->resA
= -1;
9791 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9792 funcrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9793 }else if(desc
->HelpStringContext
!= 0){
9794 size
+= 6 * sizeof(INT
);
9795 funcrecord
->HelpContext
= desc
->helpcontext
;
9796 if(desc
->HelpString
)
9797 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9799 funcrecord
->oHelpString
= -1;
9801 funcrecord
->oEntry
= -1;
9802 else if(IS_INTRESOURCE(desc
->Entry
))
9803 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9805 funcrecord
->oEntry
= desc
->Entry
->offset
;
9806 funcrecord
->res9
= -1;
9807 funcrecord
->resA
= -1;
9808 funcrecord
->HelpStringContext
= desc
->HelpStringContext
;
9809 }else if(desc
->Entry
){
9810 size
+= 3 * sizeof(INT
);
9811 funcrecord
->HelpContext
= desc
->helpcontext
;
9812 if(desc
->HelpString
)
9813 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9815 funcrecord
->oHelpString
= -1;
9817 funcrecord
->oEntry
= -1;
9818 else if(IS_INTRESOURCE(desc
->Entry
))
9819 funcrecord
->oEntry
= LOWORD(desc
->Entry
);
9821 funcrecord
->oEntry
= desc
->Entry
->offset
;
9822 }else if(desc
->HelpString
){
9823 size
+= 2 * sizeof(INT
);
9824 funcrecord
->HelpContext
= desc
->helpcontext
;
9825 funcrecord
->oHelpString
= desc
->HelpString
->offset
;
9826 }else if(desc
->helpcontext
){
9827 size
+= sizeof(INT
);
9828 funcrecord
->HelpContext
= desc
->helpcontext
;
9831 paramdefault
= (DWORD
*)((char *)funcrecord
+ size
);
9832 size
+= paramdefault_size
;
9834 for(j
= 0; j
< desc
->funcdesc
.cParams
; ++j
){
9835 MSFT_ParameterInfo
*info
= (MSFT_ParameterInfo
*)(((char *)funcrecord
) + size
);
9837 info
->DataType
= WMSFT_append_typedesc(&desc
->funcdesc
.lprgelemdescParam
[j
].tdesc
, file
, NULL
, &funcrecord
->funcdescsize
);
9838 if(desc
->pParamDesc
[j
].Name
)
9839 info
->oName
= desc
->pParamDesc
[j
].Name
->offset
;
9842 info
->Flags
= desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
;
9844 if(paramdefault_size
){
9845 if(desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
)
9846 *paramdefault
= WMSFT_encode_variant(&desc
->funcdesc
.lprgelemdescParam
[j
].u
.paramdesc
.pparamdescex
->varDefaultValue
, file
);
9847 else if(paramdefault_size
)
9852 size
+= sizeof(MSFT_ParameterInfo
);
9855 funcrecord
->Info
= size
| (i
<< 16); /* is it just the index? */
9861 funcrecord
= (MSFT_FuncRecord
*)(((char*)funcrecord
) + size
);
9864 varrecord
= (MSFT_VarRecord
*)funcrecord
;
9865 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9866 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9867 DWORD size
= 5 * sizeof(INT
);
9869 varrecord
->vardescsize
= sizeof(desc
->vardesc
);
9870 varrecord
->DataType
= WMSFT_append_typedesc(&desc
->vardesc
.elemdescVar
.tdesc
, file
, NULL
, &varrecord
->vardescsize
);
9871 varrecord
->Flags
= desc
->vardesc
.wVarFlags
;
9872 varrecord
->VarKind
= desc
->vardesc
.varkind
;
9874 if(desc
->vardesc
.varkind
== VAR_CONST
){
9875 varrecord
->vardescsize
+= sizeof(VARIANT
);
9876 varrecord
->OffsValue
= WMSFT_encode_variant(desc
->vardesc
.u
.lpvarValue
, file
);
9878 varrecord
->OffsValue
= desc
->vardesc
.u
.oInst
;
9881 if(desc
->HelpStringContext
!= 0){
9882 size
+= 5 * sizeof(INT
);
9883 varrecord
->HelpContext
= desc
->HelpContext
;
9884 if(desc
->HelpString
)
9885 varrecord
->HelpString
= desc
->HelpString
->offset
;
9887 varrecord
->HelpString
= -1;
9888 varrecord
->res9
= -1;
9889 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9890 varrecord
->HelpStringContext
= desc
->HelpStringContext
;
9891 }else if(!list_empty(&desc
->custdata_list
)){
9892 size
+= 4 * sizeof(INT
);
9893 varrecord
->HelpContext
= desc
->HelpContext
;
9894 if(desc
->HelpString
)
9895 varrecord
->HelpString
= desc
->HelpString
->offset
;
9897 varrecord
->HelpString
= -1;
9898 varrecord
->res9
= -1;
9899 varrecord
->oCustData
= WMSFT_compile_custdata(&desc
->custdata_list
, file
);
9900 }else if(desc
->HelpString
){
9901 size
+= 2 * sizeof(INT
);
9902 varrecord
->HelpContext
= desc
->HelpContext
;
9903 if(desc
->HelpString
)
9904 varrecord
->HelpString
= desc
->HelpString
->offset
;
9906 varrecord
->HelpString
= -1;
9907 }else if(desc
->HelpContext
!= 0){
9908 size
+= sizeof(INT
);
9909 varrecord
->HelpContext
= desc
->HelpContext
;
9912 varrecord
->Info
= size
| (i
<< 16);
9918 varrecord
= (MSFT_VarRecord
*)(((char*)varrecord
) + size
);
9921 memid
= (MEMBERID
*)varrecord
;
9922 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9923 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9924 *memid
= desc
->funcdesc
.memid
;
9927 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9928 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9929 *memid
= desc
->vardesc
.memid
;
9933 name
= (UINT
*)memid
;
9934 for(i
= 0; i
< info
->typeattr
.cFuncs
; ++i
){
9935 TLBFuncDesc
*desc
= &info
->funcdescs
[i
];
9937 *name
= desc
->Name
->offset
;
9942 for(i
= 0; i
< info
->typeattr
.cVars
; ++i
){
9943 TLBVarDesc
*desc
= &info
->vardescs
[i
];
9945 *name
= desc
->Name
->offset
;
9954 typedef struct tagWMSFT_RefChunk
{
9961 static DWORD
WMSFT_compile_typeinfo_ref(ITypeInfoImpl
*info
, WMSFT_TLBFile
*file
)
9963 DWORD offs
= file
->ref_seg
.len
, i
;
9964 WMSFT_RefChunk
*chunk
;
9966 file
->ref_seg
.len
+= info
->typeattr
.cImplTypes
* sizeof(WMSFT_RefChunk
);
9967 if(!file
->ref_seg
.data
)
9968 file
->ref_seg
.data
= heap_alloc(file
->ref_seg
.len
);
9970 file
->ref_seg
.data
= heap_realloc(file
->ref_seg
.data
, file
->ref_seg
.len
);
9972 chunk
= (WMSFT_RefChunk
*)((char*)file
->ref_seg
.data
+ offs
);
9974 for(i
= 0; i
< info
->typeattr
.cImplTypes
; ++i
){
9975 chunk
->href
= info
->impltypes
[i
].hRef
;
9976 chunk
->res04
= info
->impltypes
[i
].implflags
;
9978 if(i
< info
->typeattr
.cImplTypes
- 1)
9979 chunk
->next
= offs
+ sizeof(WMSFT_RefChunk
) * (i
+ 1);
9988 static DWORD
WMSFT_compile_typeinfo(ITypeInfoImpl
*info
, INT16 index
, WMSFT_TLBFile
*file
, char *data
)
9992 size
= sizeof(MSFT_TypeInfoBase
);
9995 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)data
;
9996 if(info
->typeattr
.wTypeFlags
& TYPEFLAG_FDUAL
)
9997 base
->typekind
= TKIND_DISPATCH
;
9999 base
->typekind
= info
->typeattr
.typekind
;
10000 base
->typekind
|= index
<< 16; /* TODO: There are some other flags here */
10001 base
->typekind
|= (info
->typeattr
.cbAlignment
<< 11) | (info
->typeattr
.cbAlignment
<< 6);
10002 base
->memoffset
= WMSFT_compile_typeinfo_aux(info
, file
);
10007 base
->cElement
= (info
->typeattr
.cVars
<< 16) | info
->typeattr
.cFuncs
;
10013 base
->posguid
= info
->guid
->offset
;
10015 base
->posguid
= -1;
10016 base
->flags
= info
->typeattr
.wTypeFlags
;
10018 base
->NameOffset
= info
->Name
->offset
;
10020 ((unsigned char*)file
->name_seg
.data
)[info
->Name
->offset
+9] = 0x38;
10021 *(HREFTYPE
*)((unsigned char*)file
->name_seg
.data
+info
->Name
->offset
) = info
->hreftype
;
10023 base
->NameOffset
= -1;
10025 base
->version
= (info
->typeattr
.wMinorVerNum
<< 16) | info
->typeattr
.wMajorVerNum
;
10026 if(info
->DocString
)
10027 base
->docstringoffs
= info
->DocString
->offset
;
10029 base
->docstringoffs
= -1;
10030 base
->helpstringcontext
= info
->dwHelpStringContext
;
10031 base
->helpcontext
= info
->dwHelpContext
;
10032 base
->oCustData
= WMSFT_compile_custdata(info
->pcustdata_list
, file
);
10033 base
->cImplTypes
= info
->typeattr
.cImplTypes
;
10034 base
->cbSizeVft
= info
->typeattr
.cbSizeVft
;
10035 base
->size
= info
->typeattr
.cbSizeInstance
;
10036 if(info
->typeattr
.typekind
== TKIND_COCLASS
){
10037 base
->datatype1
= WMSFT_compile_typeinfo_ref(info
, file
);
10038 }else if(info
->typeattr
.typekind
== TKIND_ALIAS
){
10039 base
->datatype1
= WMSFT_append_typedesc(info
->tdescAlias
, file
, NULL
, NULL
);
10040 }else if(info
->typeattr
.typekind
== TKIND_MODULE
){
10042 base
->datatype1
= info
->DllName
->offset
;
10044 base
->datatype1
= -1;
10046 if(info
->typeattr
.cImplTypes
> 0)
10047 base
->datatype1
= info
->impltypes
[0].hRef
;
10049 base
->datatype1
= -1;
10051 base
->datatype2
= index
; /* FIXME: i think there's more here */
10059 static void WMSFT_compile_typeinfo_seg(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
, DWORD
*junk
)
10063 file
->typeinfo_seg
.len
= 0;
10064 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10065 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10066 *junk
= file
->typeinfo_seg
.len
;
10068 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, NULL
, NULL
);
10071 file
->typeinfo_seg
.data
= heap_alloc(file
->typeinfo_seg
.len
);
10072 memset(file
->typeinfo_seg
.data
, 0x96, file
->typeinfo_seg
.len
);
10074 file
->aux_seg
.len
= 0;
10075 file
->aux_seg
.data
= NULL
;
10077 file
->typeinfo_seg
.len
= 0;
10078 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10079 ITypeInfoImpl
*info
= This
->typeinfos
[i
];
10080 file
->typeinfo_seg
.len
+= WMSFT_compile_typeinfo(info
, i
, file
,
10081 ((char *)file
->typeinfo_seg
.data
) + file
->typeinfo_seg
.len
);
10085 typedef struct tagWMSFT_ImpFile
{
10091 static void WMSFT_compile_impfile(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10094 WMSFT_ImpFile
*impfile
;
10096 DWORD last_offs
= 0;
10098 file
->impfile_seg
.len
= 0;
10099 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10103 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10107 path
= implib
->name
;
10108 size
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
), NULL
, 0, NULL
, NULL
);
10110 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10113 size
+= sizeof(INT16
);
10115 size
= (size
+ 4) & ~0x3;
10119 file
->impfile_seg
.len
+= sizeof(WMSFT_ImpFile
) + size
;
10122 data
= file
->impfile_seg
.data
= heap_alloc(file
->impfile_seg
.len
);
10124 LIST_FOR_EACH_ENTRY(implib
, &This
->implib_list
, TLBImpLib
, entry
){
10125 int strlen
= 0, size
;
10127 impfile
= (WMSFT_ImpFile
*)data
;
10128 impfile
->guid_offs
= implib
->guid
->offset
;
10129 impfile
->lcid
= implib
->lcid
;
10130 impfile
->version
= (implib
->wVersionMinor
<< 16) | implib
->wVersionMajor
;
10132 data
+= sizeof(WMSFT_ImpFile
);
10135 WCHAR
*path
= wcsrchr(implib
->name
, '\\');
10139 path
= implib
->name
;
10140 strlen
= WideCharToMultiByte(CP_ACP
, 0, path
, lstrlenW(path
),
10141 data
+ sizeof(INT16
), file
->impfile_seg
.len
- last_offs
- sizeof(INT16
), NULL
, NULL
);
10143 ERR("failed to convert wide string: %s\n", debugstr_w(path
));
10146 *((INT16
*)data
) = (strlen
<< 2) | 1; /* FIXME: is that a flag, or what? */
10148 size
= strlen
+ sizeof(INT16
);
10150 size
= (size
+ 4) & ~0x3;
10153 memset(data
+ sizeof(INT16
) + strlen
, 0x57, size
- strlen
- sizeof(INT16
));
10156 implib
->offset
= last_offs
;
10157 last_offs
+= size
+ sizeof(WMSFT_ImpFile
);
10161 static void WMSFT_compile_impinfo(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10163 MSFT_ImpInfo
*info
;
10164 TLBRefType
*ref_type
;
10167 WMSFT_compile_impfile(This
, file
);
10169 file
->impinfo_seg
.len
= sizeof(MSFT_ImpInfo
) * list_count(&This
->ref_list
);
10170 info
= file
->impinfo_seg
.data
= heap_alloc(file
->impinfo_seg
.len
);
10172 LIST_FOR_EACH_ENTRY(ref_type
, &This
->ref_list
, TLBRefType
, entry
){
10173 info
->flags
= i
| ((ref_type
->tkind
& 0xFF) << 24);
10174 if(ref_type
->index
== TLB_REF_USE_GUID
){
10175 info
->flags
|= MSFT_IMPINFO_OFFSET_IS_GUID
;
10176 info
->oGuid
= ref_type
->guid
->offset
;
10178 info
->oGuid
= ref_type
->index
;
10179 info
->oImpFile
= ref_type
->pImpTLInfo
->offset
;
10185 static void WMSFT_compile_guidhash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10187 file
->guidhash_seg
.len
= 0x80;
10188 file
->guidhash_seg
.data
= heap_alloc(file
->guidhash_seg
.len
);
10189 memset(file
->guidhash_seg
.data
, 0xFF, file
->guidhash_seg
.len
);
10192 static void WMSFT_compile_namehash(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
)
10194 file
->namehash_seg
.len
= 0x200;
10195 file
->namehash_seg
.data
= heap_alloc(file
->namehash_seg
.len
);
10196 memset(file
->namehash_seg
.data
, 0xFF, file
->namehash_seg
.len
);
10199 static void tmp_fill_segdir_seg(MSFT_pSeg
*segdir
, WMSFT_SegContents
*contents
, DWORD
*running_offset
)
10201 if(contents
&& contents
->len
){
10202 segdir
->offset
= *running_offset
;
10203 segdir
->length
= contents
->len
;
10204 *running_offset
+= segdir
->length
;
10206 segdir
->offset
= -1;
10207 segdir
->length
= 0;
10210 /* TODO: do these ever change? */
10211 segdir
->res08
= -1;
10212 segdir
->res0c
= 0xf;
10215 static void WMSFT_write_segment(HANDLE outfile
, WMSFT_SegContents
*segment
)
10219 WriteFile(outfile
, segment
->data
, segment
->len
, &written
, NULL
);
10222 static HRESULT
WMSFT_fixup_typeinfos(ITypeLibImpl
*This
, WMSFT_TLBFile
*file
,
10226 MSFT_TypeInfoBase
*base
= (MSFT_TypeInfoBase
*)file
->typeinfo_seg
.data
;
10228 for(i
= 0; i
< This
->TypeInfoCount
; ++i
){
10229 base
->memoffset
+= file_len
;
10236 static void WMSFT_free_file(WMSFT_TLBFile
*file
)
10238 HeapFree(GetProcessHeap(), 0, file
->typeinfo_seg
.data
);
10239 HeapFree(GetProcessHeap(), 0, file
->guidhash_seg
.data
);
10240 HeapFree(GetProcessHeap(), 0, file
->guid_seg
.data
);
10241 HeapFree(GetProcessHeap(), 0, file
->ref_seg
.data
);
10242 HeapFree(GetProcessHeap(), 0, file
->impinfo_seg
.data
);
10243 HeapFree(GetProcessHeap(), 0, file
->impfile_seg
.data
);
10244 HeapFree(GetProcessHeap(), 0, file
->namehash_seg
.data
);
10245 HeapFree(GetProcessHeap(), 0, file
->name_seg
.data
);
10246 HeapFree(GetProcessHeap(), 0, file
->string_seg
.data
);
10247 HeapFree(GetProcessHeap(), 0, file
->typdesc_seg
.data
);
10248 HeapFree(GetProcessHeap(), 0, file
->arraydesc_seg
.data
);
10249 HeapFree(GetProcessHeap(), 0, file
->custdata_seg
.data
);
10250 HeapFree(GetProcessHeap(), 0, file
->cdguids_seg
.data
);
10251 HeapFree(GetProcessHeap(), 0, file
->aux_seg
.data
);
10254 static HRESULT WINAPI
ICreateTypeLib2_fnSaveAllChanges(ICreateTypeLib2
*iface
)
10256 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10257 WMSFT_TLBFile file
;
10258 DWORD written
, junk_size
, junk_offs
, running_offset
;
10265 TRACE("%p\n", This
);
10267 for(i
= 0; i
< This
->TypeInfoCount
; ++i
)
10268 if(This
->typeinfos
[i
]->needs_layout
)
10269 ICreateTypeInfo2_LayOut(&This
->typeinfos
[i
]->ICreateTypeInfo2_iface
);
10271 memset(&file
, 0, sizeof(file
));
10273 file
.header
.magic1
= 0x5446534D;
10274 file
.header
.magic2
= 0x00010002;
10275 file
.header
.lcid
= This
->set_lcid
? This
->set_lcid
: MAKELANGID(LANG_ENGLISH
, SUBLANG_ENGLISH_US
);
10276 file
.header
.lcid2
= This
->set_lcid
;
10277 file
.header
.varflags
= 0x40 | This
->syskind
;
10278 if (This
->HelpFile
)
10279 file
.header
.varflags
|= 0x10;
10280 if (This
->HelpStringDll
)
10281 file
.header
.varflags
|= HELPDLLFLAG
;
10282 file
.header
.version
= (This
->ver_minor
<< 16) | This
->ver_major
;
10283 file
.header
.flags
= This
->libflags
;
10284 file
.header
.helpstringcontext
= 0; /* TODO - SetHelpStringContext not implemented yet */
10285 file
.header
.helpcontext
= This
->dwHelpContext
;
10286 file
.header
.res44
= 0x20;
10287 file
.header
.res48
= 0x80;
10288 file
.header
.dispatchpos
= This
->dispatch_href
;
10290 WMSFT_compile_namehash(This
, &file
);
10291 /* do name and string compilation to get offsets for other compilations */
10292 hres
= WMSFT_compile_names(This
, &file
);
10294 WMSFT_free_file(&file
);
10298 hres
= WMSFT_compile_strings(This
, &file
);
10300 WMSFT_free_file(&file
);
10304 WMSFT_compile_guidhash(This
, &file
);
10305 hres
= WMSFT_compile_guids(This
, &file
);
10307 WMSFT_free_file(&file
);
10312 file
.header
.helpfile
= This
->HelpFile
->offset
;
10314 file
.header
.helpfile
= -1;
10316 if(This
->DocString
)
10317 file
.header
.helpstring
= This
->DocString
->offset
;
10319 file
.header
.helpstring
= -1;
10321 /* do some more segment compilation */
10322 file
.header
.nimpinfos
= list_count(&This
->ref_list
);
10323 file
.header
.nrtypeinfos
= This
->TypeInfoCount
;
10326 file
.header
.NameOffset
= This
->Name
->offset
;
10328 file
.header
.NameOffset
= -1;
10330 file
.header
.CustomDataOffset
= WMSFT_compile_custdata(&This
->custdata_list
, &file
);
10333 file
.header
.posguid
= This
->guid
->offset
;
10335 file
.header
.posguid
= -1;
10337 junk_size
= file
.header
.nrtypeinfos
* sizeof(DWORD
);
10338 if(file
.header
.varflags
& HELPDLLFLAG
)
10339 junk_size
+= sizeof(DWORD
);
10341 junk
= heap_alloc_zero(junk_size
);
10342 if(file
.header
.varflags
& HELPDLLFLAG
){
10343 *junk
= This
->HelpStringDll
->offset
;
10352 WMSFT_compile_typeinfo_seg(This
, &file
, junk
+ junk_offs
);
10353 WMSFT_compile_impinfo(This
, &file
);
10355 running_offset
= 0;
10357 TRACE("header at: 0x%x\n", running_offset
);
10358 running_offset
+= sizeof(file
.header
);
10360 TRACE("junk at: 0x%x\n", running_offset
);
10361 running_offset
+= junk_size
;
10363 TRACE("segdir at: 0x%x\n", running_offset
);
10364 running_offset
+= sizeof(file
.segdir
);
10366 TRACE("typeinfo at: 0x%x\n", running_offset
);
10367 tmp_fill_segdir_seg(&file
.segdir
.pTypeInfoTab
, &file
.typeinfo_seg
, &running_offset
);
10369 TRACE("guidhashtab at: 0x%x\n", running_offset
);
10370 tmp_fill_segdir_seg(&file
.segdir
.pGuidHashTab
, &file
.guidhash_seg
, &running_offset
);
10372 TRACE("guidtab at: 0x%x\n", running_offset
);
10373 tmp_fill_segdir_seg(&file
.segdir
.pGuidTab
, &file
.guid_seg
, &running_offset
);
10375 TRACE("reftab at: 0x%x\n", running_offset
);
10376 tmp_fill_segdir_seg(&file
.segdir
.pRefTab
, &file
.ref_seg
, &running_offset
);
10378 TRACE("impinfo at: 0x%x\n", running_offset
);
10379 tmp_fill_segdir_seg(&file
.segdir
.pImpInfo
, &file
.impinfo_seg
, &running_offset
);
10381 TRACE("impfiles at: 0x%x\n", running_offset
);
10382 tmp_fill_segdir_seg(&file
.segdir
.pImpFiles
, &file
.impfile_seg
, &running_offset
);
10384 TRACE("namehashtab at: 0x%x\n", running_offset
);
10385 tmp_fill_segdir_seg(&file
.segdir
.pNameHashTab
, &file
.namehash_seg
, &running_offset
);
10387 TRACE("nametab at: 0x%x\n", running_offset
);
10388 tmp_fill_segdir_seg(&file
.segdir
.pNametab
, &file
.name_seg
, &running_offset
);
10390 TRACE("stringtab at: 0x%x\n", running_offset
);
10391 tmp_fill_segdir_seg(&file
.segdir
.pStringtab
, &file
.string_seg
, &running_offset
);
10393 TRACE("typdesc at: 0x%x\n", running_offset
);
10394 tmp_fill_segdir_seg(&file
.segdir
.pTypdescTab
, &file
.typdesc_seg
, &running_offset
);
10396 TRACE("arraydescriptions at: 0x%x\n", running_offset
);
10397 tmp_fill_segdir_seg(&file
.segdir
.pArrayDescriptions
, &file
.arraydesc_seg
, &running_offset
);
10399 TRACE("custdata at: 0x%x\n", running_offset
);
10400 tmp_fill_segdir_seg(&file
.segdir
.pCustData
, &file
.custdata_seg
, &running_offset
);
10402 TRACE("cdguids at: 0x%x\n", running_offset
);
10403 tmp_fill_segdir_seg(&file
.segdir
.pCDGuids
, &file
.cdguids_seg
, &running_offset
);
10405 TRACE("res0e at: 0x%x\n", running_offset
);
10406 tmp_fill_segdir_seg(&file
.segdir
.res0e
, NULL
, &running_offset
);
10408 TRACE("res0f at: 0x%x\n", running_offset
);
10409 tmp_fill_segdir_seg(&file
.segdir
.res0f
, NULL
, &running_offset
);
10411 TRACE("aux_seg at: 0x%x\n", running_offset
);
10413 WMSFT_fixup_typeinfos(This
, &file
, running_offset
);
10415 outfile
= CreateFileW(This
->path
, GENERIC_WRITE
, 0, NULL
, CREATE_ALWAYS
,
10416 FILE_ATTRIBUTE_NORMAL
, 0);
10417 if (outfile
== INVALID_HANDLE_VALUE
){
10418 WMSFT_free_file(&file
);
10420 return TYPE_E_IOERROR
;
10423 br
= WriteFile(outfile
, &file
.header
, sizeof(file
.header
), &written
, NULL
);
10425 WMSFT_free_file(&file
);
10426 CloseHandle(outfile
);
10428 return TYPE_E_IOERROR
;
10431 br
= WriteFile(outfile
, junk
, junk_size
, &written
, NULL
);
10434 WMSFT_free_file(&file
);
10435 CloseHandle(outfile
);
10436 return TYPE_E_IOERROR
;
10439 br
= WriteFile(outfile
, &file
.segdir
, sizeof(file
.segdir
), &written
, NULL
);
10441 WMSFT_free_file(&file
);
10442 CloseHandle(outfile
);
10443 return TYPE_E_IOERROR
;
10446 WMSFT_write_segment(outfile
, &file
.typeinfo_seg
);
10447 WMSFT_write_segment(outfile
, &file
.guidhash_seg
);
10448 WMSFT_write_segment(outfile
, &file
.guid_seg
);
10449 WMSFT_write_segment(outfile
, &file
.ref_seg
);
10450 WMSFT_write_segment(outfile
, &file
.impinfo_seg
);
10451 WMSFT_write_segment(outfile
, &file
.impfile_seg
);
10452 WMSFT_write_segment(outfile
, &file
.namehash_seg
);
10453 WMSFT_write_segment(outfile
, &file
.name_seg
);
10454 WMSFT_write_segment(outfile
, &file
.string_seg
);
10455 WMSFT_write_segment(outfile
, &file
.typdesc_seg
);
10456 WMSFT_write_segment(outfile
, &file
.arraydesc_seg
);
10457 WMSFT_write_segment(outfile
, &file
.custdata_seg
);
10458 WMSFT_write_segment(outfile
, &file
.cdguids_seg
);
10459 WMSFT_write_segment(outfile
, &file
.aux_seg
);
10461 WMSFT_free_file(&file
);
10463 CloseHandle(outfile
);
10468 static HRESULT WINAPI
ICreateTypeLib2_fnDeleteTypeInfo(ICreateTypeLib2
*iface
,
10471 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10472 FIXME("%p %s - stub\n", This
, wine_dbgstr_w(name
));
10476 static HRESULT WINAPI
ICreateTypeLib2_fnSetCustData(ICreateTypeLib2
*iface
,
10477 REFGUID guid
, VARIANT
*varVal
)
10479 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10482 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
10484 if (!guid
|| !varVal
)
10485 return E_INVALIDARG
;
10487 tlbguid
= TLB_append_guid(&This
->guid_list
, guid
, -1);
10489 return TLB_set_custdata(&This
->custdata_list
, tlbguid
, varVal
);
10492 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringContext(ICreateTypeLib2
*iface
,
10493 ULONG helpStringContext
)
10495 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10496 FIXME("%p %u - stub\n", This
, helpStringContext
);
10500 static HRESULT WINAPI
ICreateTypeLib2_fnSetHelpStringDll(ICreateTypeLib2
*iface
,
10503 ITypeLibImpl
*This
= impl_from_ICreateTypeLib2(iface
);
10504 TRACE("%p %s\n", This
, wine_dbgstr_w(filename
));
10507 return E_INVALIDARG
;
10509 This
->HelpStringDll
= TLB_append_str(&This
->string_list
, filename
);
10514 static const ICreateTypeLib2Vtbl CreateTypeLib2Vtbl
= {
10515 ICreateTypeLib2_fnQueryInterface
,
10516 ICreateTypeLib2_fnAddRef
,
10517 ICreateTypeLib2_fnRelease
,
10518 ICreateTypeLib2_fnCreateTypeInfo
,
10519 ICreateTypeLib2_fnSetName
,
10520 ICreateTypeLib2_fnSetVersion
,
10521 ICreateTypeLib2_fnSetGuid
,
10522 ICreateTypeLib2_fnSetDocString
,
10523 ICreateTypeLib2_fnSetHelpFileName
,
10524 ICreateTypeLib2_fnSetHelpContext
,
10525 ICreateTypeLib2_fnSetLcid
,
10526 ICreateTypeLib2_fnSetLibFlags
,
10527 ICreateTypeLib2_fnSaveAllChanges
,
10528 ICreateTypeLib2_fnDeleteTypeInfo
,
10529 ICreateTypeLib2_fnSetCustData
,
10530 ICreateTypeLib2_fnSetHelpStringContext
,
10531 ICreateTypeLib2_fnSetHelpStringDll
10534 static HRESULT WINAPI
ICreateTypeInfo2_fnQueryInterface(ICreateTypeInfo2
*iface
,
10535 REFIID riid
, void **object
)
10537 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10539 return ITypeInfo2_QueryInterface(&This
->ITypeInfo2_iface
, riid
, object
);
10542 static ULONG WINAPI
ICreateTypeInfo2_fnAddRef(ICreateTypeInfo2
*iface
)
10544 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10546 return ITypeInfo2_AddRef(&This
->ITypeInfo2_iface
);
10549 static ULONG WINAPI
ICreateTypeInfo2_fnRelease(ICreateTypeInfo2
*iface
)
10551 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10553 return ITypeInfo2_Release(&This
->ITypeInfo2_iface
);
10556 static HRESULT WINAPI
ICreateTypeInfo2_fnSetGuid(ICreateTypeInfo2
*iface
,
10559 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10561 TRACE("%p %s\n", This
, debugstr_guid(guid
));
10563 This
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, This
->hreftype
);
10568 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeFlags(ICreateTypeInfo2
*iface
,
10571 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10575 TRACE("%p %x\n", This
, typeFlags
);
10577 if (typeFlags
& TYPEFLAG_FDUAL
) {
10578 static const WCHAR stdole2tlb
[] = { 's','t','d','o','l','e','2','.','t','l','b',0 };
10580 ITypeInfo
*dispatch
;
10584 hres
= LoadTypeLib(stdole2tlb
, &stdole
);
10588 hres
= ITypeLib_GetTypeInfoOfGuid(stdole
, &IID_IDispatch
, &dispatch
);
10589 ITypeLib_Release(stdole
);
10593 hres
= ICreateTypeInfo2_AddRefTypeInfo(iface
, dispatch
, &hreftype
);
10594 ITypeInfo_Release(dispatch
);
10599 old_flags
= This
->typeattr
.wTypeFlags
;
10600 This
->typeattr
.wTypeFlags
= typeFlags
;
10602 hres
= ICreateTypeInfo2_LayOut(iface
);
10603 if (FAILED(hres
)) {
10604 This
->typeattr
.wTypeFlags
= old_flags
;
10611 static HRESULT WINAPI
ICreateTypeInfo2_fnSetDocString(ICreateTypeInfo2
*iface
,
10614 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10616 TRACE("%p %s\n", This
, wine_dbgstr_w(doc
));
10619 return E_INVALIDARG
;
10621 This
->DocString
= TLB_append_str(&This
->pTypeLib
->string_list
, doc
);
10626 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpContext(ICreateTypeInfo2
*iface
,
10629 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10631 TRACE("%p %d\n", This
, helpContext
);
10633 This
->dwHelpContext
= helpContext
;
10638 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVersion(ICreateTypeInfo2
*iface
,
10639 WORD majorVerNum
, WORD minorVerNum
)
10641 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10643 TRACE("%p %d %d\n", This
, majorVerNum
, minorVerNum
);
10645 This
->typeattr
.wMajorVerNum
= majorVerNum
;
10646 This
->typeattr
.wMinorVerNum
= minorVerNum
;
10651 static HRESULT WINAPI
ICreateTypeInfo2_fnAddRefTypeInfo(ICreateTypeInfo2
*iface
,
10652 ITypeInfo
*typeInfo
, HREFTYPE
*refType
)
10654 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10656 ITypeLib
*container
;
10657 TLBRefType
*ref_type
;
10659 TYPEATTR
*typeattr
;
10663 TRACE("%p %p %p\n", This
, typeInfo
, refType
);
10665 if (!typeInfo
|| !refType
)
10666 return E_INVALIDARG
;
10668 hres
= ITypeInfo_GetContainingTypeLib(typeInfo
, &container
, &index
);
10672 if (container
== (ITypeLib
*)&This
->pTypeLib
->ITypeLib2_iface
) {
10673 ITypeInfoImpl
*target
= impl_from_ITypeInfo(typeInfo
);
10675 ITypeLib_Release(container
);
10677 *refType
= target
->hreftype
;
10682 hres
= ITypeLib_GetLibAttr(container
, &libattr
);
10683 if (FAILED(hres
)) {
10684 ITypeLib_Release(container
);
10688 LIST_FOR_EACH_ENTRY(implib
, &This
->pTypeLib
->implib_list
, TLBImpLib
, entry
){
10689 if(IsEqualGUID(&implib
->guid
->guid
, &libattr
->guid
) &&
10690 implib
->lcid
== libattr
->lcid
&&
10691 implib
->wVersionMajor
== libattr
->wMajorVerNum
&&
10692 implib
->wVersionMinor
== libattr
->wMinorVerNum
)
10696 if(&implib
->entry
== &This
->pTypeLib
->implib_list
){
10697 implib
= heap_alloc_zero(sizeof(TLBImpLib
));
10699 if((ITypeLib2Vtbl
*)container
->lpVtbl
== &tlbvt
){
10700 const ITypeLibImpl
*our_container
= impl_from_ITypeLib2((ITypeLib2
*)container
);
10701 implib
->name
= SysAllocString(our_container
->path
);
10703 hres
= QueryPathOfRegTypeLib(&libattr
->guid
, libattr
->wMajorVerNum
,
10704 libattr
->wMinorVerNum
, libattr
->lcid
, &implib
->name
);
10706 implib
->name
= NULL
;
10707 TRACE("QueryPathOfRegTypeLib failed, no name stored: %08x\n", hres
);
10711 implib
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &libattr
->guid
, 2);
10712 implib
->lcid
= libattr
->lcid
;
10713 implib
->wVersionMajor
= libattr
->wMajorVerNum
;
10714 implib
->wVersionMinor
= libattr
->wMinorVerNum
;
10716 list_add_tail(&This
->pTypeLib
->implib_list
, &implib
->entry
);
10719 ITypeLib_ReleaseTLibAttr(container
, libattr
);
10720 ITypeLib_Release(container
);
10722 hres
= ITypeInfo_GetTypeAttr(typeInfo
, &typeattr
);
10727 LIST_FOR_EACH_ENTRY(ref_type
, &This
->pTypeLib
->ref_list
, TLBRefType
, entry
){
10728 if(ref_type
->index
== TLB_REF_USE_GUID
&&
10729 IsEqualGUID(&ref_type
->guid
->guid
, &typeattr
->guid
) &&
10730 ref_type
->tkind
== typeattr
->typekind
)
10735 if(&ref_type
->entry
== &This
->pTypeLib
->ref_list
){
10736 ref_type
= heap_alloc_zero(sizeof(TLBRefType
));
10738 ref_type
->tkind
= typeattr
->typekind
;
10739 ref_type
->pImpTLInfo
= implib
;
10740 ref_type
->reference
= index
* sizeof(MSFT_ImpInfo
);
10742 ref_type
->index
= TLB_REF_USE_GUID
;
10744 ref_type
->guid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, &typeattr
->guid
, ref_type
->reference
+1);
10746 list_add_tail(&This
->pTypeLib
->ref_list
, &ref_type
->entry
);
10749 ITypeInfo_ReleaseTypeAttr(typeInfo
, typeattr
);
10751 *refType
= ref_type
->reference
| 0x1;
10753 if(IsEqualGUID(&ref_type
->guid
->guid
, &IID_IDispatch
))
10754 This
->pTypeLib
->dispatch_href
= *refType
;
10759 static HRESULT WINAPI
ICreateTypeInfo2_fnAddFuncDesc(ICreateTypeInfo2
*iface
,
10760 UINT index
, FUNCDESC
*funcDesc
)
10762 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10763 TLBFuncDesc tmp_func_desc
, *func_desc
;
10768 TRACE("%p %u %p\n", This
, index
, funcDesc
);
10770 if (!funcDesc
|| funcDesc
->oVft
& 3)
10771 return E_INVALIDARG
;
10773 switch (This
->typeattr
.typekind
) {
10775 if (funcDesc
->funckind
!= FUNC_STATIC
)
10776 return TYPE_E_BADMODULEKIND
;
10778 case TKIND_DISPATCH
:
10779 if (funcDesc
->funckind
!= FUNC_DISPATCH
)
10780 return TYPE_E_BADMODULEKIND
;
10783 if (funcDesc
->funckind
!= FUNC_PUREVIRTUAL
)
10784 return TYPE_E_BADMODULEKIND
;
10787 if (index
> This
->typeattr
.cFuncs
)
10788 return TYPE_E_ELEMENTNOTFOUND
;
10790 if (funcDesc
->invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
) &&
10791 !funcDesc
->cParams
)
10792 return TYPE_E_INCONSISTENTPROPFUNCS
;
10795 if(This
->pTypeLib
->syskind
== SYS_WIN64
&&
10796 funcDesc
->oVft
% 8 != 0)
10797 return E_INVALIDARG
;
10800 memset(&tmp_func_desc
, 0, sizeof(tmp_func_desc
));
10801 TLBFuncDesc_Constructor(&tmp_func_desc
);
10803 tmp_func_desc
.funcdesc
= *funcDesc
;
10805 if (tmp_func_desc
.funcdesc
.oVft
!= 0)
10806 tmp_func_desc
.funcdesc
.oVft
|= 1;
10808 if (funcDesc
->cScodes
&& funcDesc
->lprgscode
) {
10809 tmp_func_desc
.funcdesc
.lprgscode
= heap_alloc(sizeof(SCODE
) * funcDesc
->cScodes
);
10810 memcpy(tmp_func_desc
.funcdesc
.lprgscode
, funcDesc
->lprgscode
, sizeof(SCODE
) * funcDesc
->cScodes
);
10812 tmp_func_desc
.funcdesc
.lprgscode
= NULL
;
10813 tmp_func_desc
.funcdesc
.cScodes
= 0;
10816 buf_size
= TLB_SizeElemDesc(&funcDesc
->elemdescFunc
);
10817 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10818 buf_size
+= sizeof(ELEMDESC
);
10819 buf_size
+= TLB_SizeElemDesc(funcDesc
->lprgelemdescParam
+ i
);
10821 tmp_func_desc
.funcdesc
.lprgelemdescParam
= heap_alloc(buf_size
);
10822 buffer
= (char*)(tmp_func_desc
.funcdesc
.lprgelemdescParam
+ funcDesc
->cParams
);
10824 hres
= TLB_CopyElemDesc(&funcDesc
->elemdescFunc
, &tmp_func_desc
.funcdesc
.elemdescFunc
, &buffer
);
10825 if (FAILED(hres
)) {
10826 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10827 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10831 for (i
= 0; i
< funcDesc
->cParams
; ++i
) {
10832 hres
= TLB_CopyElemDesc(funcDesc
->lprgelemdescParam
+ i
,
10833 tmp_func_desc
.funcdesc
.lprgelemdescParam
+ i
, &buffer
);
10834 if (FAILED(hres
)) {
10835 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10836 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10839 if (tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.wParamFlags
& PARAMFLAG_FHASDEFAULT
&&
10840 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_VARIANT
&&
10841 tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].tdesc
.vt
!= VT_USERDEFINED
){
10842 hres
= TLB_SanitizeVariant(&tmp_func_desc
.funcdesc
.lprgelemdescParam
[i
].u
.paramdesc
.pparamdescex
->varDefaultValue
);
10843 if (FAILED(hres
)) {
10844 heap_free(tmp_func_desc
.funcdesc
.lprgelemdescParam
);
10845 heap_free(tmp_func_desc
.funcdesc
.lprgscode
);
10851 tmp_func_desc
.pParamDesc
= TLBParDesc_Constructor(funcDesc
->cParams
);
10853 if (This
->funcdescs
) {
10854 This
->funcdescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->funcdescs
,
10855 sizeof(TLBFuncDesc
) * (This
->typeattr
.cFuncs
+ 1));
10857 if (index
< This
->typeattr
.cFuncs
) {
10858 memmove(This
->funcdescs
+ index
+ 1, This
->funcdescs
+ index
,
10859 (This
->typeattr
.cFuncs
- index
) * sizeof(TLBFuncDesc
));
10860 func_desc
= This
->funcdescs
+ index
;
10862 func_desc
= This
->funcdescs
+ This
->typeattr
.cFuncs
;
10864 /* move custdata lists to the new memory location */
10865 for(i
= 0; i
< This
->typeattr
.cFuncs
+ 1; ++i
){
10867 TLB_relink_custdata(&This
->funcdescs
[i
].custdata_list
);
10870 func_desc
= This
->funcdescs
= heap_alloc(sizeof(TLBFuncDesc
));
10872 memcpy(func_desc
, &tmp_func_desc
, sizeof(tmp_func_desc
));
10873 list_init(&func_desc
->custdata_list
);
10875 ++This
->typeattr
.cFuncs
;
10877 This
->needs_layout
= TRUE
;
10882 static HRESULT WINAPI
ICreateTypeInfo2_fnAddImplType(ICreateTypeInfo2
*iface
,
10883 UINT index
, HREFTYPE refType
)
10885 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10886 TLBImplType
*impl_type
;
10889 TRACE("%p %u %d\n", This
, index
, refType
);
10891 switch(This
->typeattr
.typekind
){
10892 case TKIND_COCLASS
: {
10894 FIXME("Unhandled index: -1\n");
10898 if(index
!= This
->typeattr
.cImplTypes
)
10899 return TYPE_E_ELEMENTNOTFOUND
;
10903 case TKIND_INTERFACE
:
10904 case TKIND_DISPATCH
:
10905 if (index
!= 0 || This
->typeattr
.cImplTypes
)
10906 return TYPE_E_ELEMENTNOTFOUND
;
10909 FIXME("Unimplemented typekind: %d\n", This
->typeattr
.typekind
);
10913 if (This
->impltypes
){
10916 This
->impltypes
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->impltypes
,
10917 sizeof(TLBImplType
) * (This
->typeattr
.cImplTypes
+ 1));
10919 if (index
< This
->typeattr
.cImplTypes
) {
10920 memmove(This
->impltypes
+ index
+ 1, This
->impltypes
+ index
,
10921 (This
->typeattr
.cImplTypes
- index
) * sizeof(TLBImplType
));
10922 impl_type
= This
->impltypes
+ index
;
10924 impl_type
= This
->impltypes
+ This
->typeattr
.cImplTypes
;
10926 /* move custdata lists to the new memory location */
10927 for(i
= 0; i
< This
->typeattr
.cImplTypes
+ 1; ++i
){
10929 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
10932 impl_type
= This
->impltypes
= heap_alloc(sizeof(TLBImplType
));
10934 memset(impl_type
, 0, sizeof(TLBImplType
));
10935 TLBImplType_Constructor(impl_type
);
10936 impl_type
->hRef
= refType
;
10938 ++This
->typeattr
.cImplTypes
;
10940 if((refType
& (~0x3)) == (This
->pTypeLib
->dispatch_href
& (~0x3)))
10941 This
->typeattr
.wTypeFlags
|= TYPEFLAG_FDISPATCHABLE
;
10943 hres
= ICreateTypeInfo2_LayOut(iface
);
10950 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeFlags(ICreateTypeInfo2
*iface
,
10951 UINT index
, INT implTypeFlags
)
10953 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10954 TLBImplType
*impl_type
= &This
->impltypes
[index
];
10956 TRACE("%p %u %x\n", This
, index
, implTypeFlags
);
10958 if (This
->typeattr
.typekind
!= TKIND_COCLASS
)
10959 return TYPE_E_BADMODULEKIND
;
10961 if (index
>= This
->typeattr
.cImplTypes
)
10962 return TYPE_E_ELEMENTNOTFOUND
;
10964 impl_type
->implflags
= implTypeFlags
;
10969 static HRESULT WINAPI
ICreateTypeInfo2_fnSetAlignment(ICreateTypeInfo2
*iface
,
10972 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10974 TRACE("%p %d\n", This
, alignment
);
10976 This
->typeattr
.cbAlignment
= alignment
;
10981 static HRESULT WINAPI
ICreateTypeInfo2_fnSetSchema(ICreateTypeInfo2
*iface
,
10984 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
10986 TRACE("%p %s\n", This
, wine_dbgstr_w(schema
));
10989 return E_INVALIDARG
;
10991 This
->Schema
= TLB_append_str(&This
->pTypeLib
->string_list
, schema
);
10993 This
->typeattr
.lpstrSchema
= This
->Schema
->str
;
10998 static HRESULT WINAPI
ICreateTypeInfo2_fnAddVarDesc(ICreateTypeInfo2
*iface
,
10999 UINT index
, VARDESC
*varDesc
)
11001 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11002 TLBVarDesc
*var_desc
;
11004 TRACE("%p %u %p\n", This
, index
, varDesc
);
11006 if (This
->vardescs
){
11009 This
->vardescs
= HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, This
->vardescs
,
11010 sizeof(TLBVarDesc
) * (This
->typeattr
.cVars
+ 1));
11012 if (index
< This
->typeattr
.cVars
) {
11013 memmove(This
->vardescs
+ index
+ 1, This
->vardescs
+ index
,
11014 (This
->typeattr
.cVars
- index
) * sizeof(TLBVarDesc
));
11015 var_desc
= This
->vardescs
+ index
;
11017 var_desc
= This
->vardescs
+ This
->typeattr
.cVars
;
11019 /* move custdata lists to the new memory location */
11020 for(i
= 0; i
< This
->typeattr
.cVars
+ 1; ++i
){
11022 TLB_relink_custdata(&This
->vardescs
[i
].custdata_list
);
11025 var_desc
= This
->vardescs
= heap_alloc_zero(sizeof(TLBVarDesc
));
11027 TLBVarDesc_Constructor(var_desc
);
11028 TLB_AllocAndInitVarDesc(varDesc
, &var_desc
->vardesc_create
);
11029 var_desc
->vardesc
= *var_desc
->vardesc_create
;
11031 ++This
->typeattr
.cVars
;
11033 This
->needs_layout
= TRUE
;
11038 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncAndParamNames(ICreateTypeInfo2
*iface
,
11039 UINT index
, LPOLESTR
*names
, UINT numNames
)
11041 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11042 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11045 TRACE("%p %u %p %u\n", This
, index
, names
, numNames
);
11048 return E_INVALIDARG
;
11050 if (index
>= This
->typeattr
.cFuncs
|| numNames
== 0)
11051 return TYPE_E_ELEMENTNOTFOUND
;
11053 if (func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
)){
11054 if(numNames
> func_desc
->funcdesc
.cParams
)
11055 return TYPE_E_ELEMENTNOTFOUND
;
11057 if(numNames
> func_desc
->funcdesc
.cParams
+ 1)
11058 return TYPE_E_ELEMENTNOTFOUND
;
11060 for(i
= 0; i
< This
->typeattr
.cFuncs
; ++i
) {
11061 TLBFuncDesc
*iter
= &This
->funcdescs
[i
];
11062 if (iter
->Name
&& !wcscmp(TLB_get_bstr(iter
->Name
), *names
)) {
11063 if (iter
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11064 func_desc
->funcdesc
.invkind
& (INVOKE_PROPERTYPUT
| INVOKE_PROPERTYPUTREF
| INVOKE_PROPERTYGET
) &&
11065 func_desc
->funcdesc
.invkind
!= iter
->funcdesc
.invkind
)
11067 return TYPE_E_AMBIGUOUSNAME
;
11071 func_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *names
);
11073 for (i
= 1; i
< numNames
; ++i
) {
11074 TLBParDesc
*par_desc
= func_desc
->pParamDesc
+ i
- 1;
11075 par_desc
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, *(names
+ i
));
11081 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarName(ICreateTypeInfo2
*iface
,
11082 UINT index
, LPOLESTR name
)
11084 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11086 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(name
));
11089 return E_INVALIDARG
;
11091 if(index
>= This
->typeattr
.cVars
)
11092 return TYPE_E_ELEMENTNOTFOUND
;
11094 This
->vardescs
[index
].Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11098 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeDescAlias(ICreateTypeInfo2
*iface
,
11099 TYPEDESC
*tdescAlias
)
11101 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11104 TRACE("%p %p\n", This
, tdescAlias
);
11107 return E_INVALIDARG
;
11109 if(This
->typeattr
.typekind
!= TKIND_ALIAS
)
11110 return TYPE_E_BADMODULEKIND
;
11112 hr
= TLB_size_instance(This
, This
->pTypeLib
->syskind
, tdescAlias
, &This
->typeattr
.cbSizeInstance
, &This
->typeattr
.cbAlignment
);
11116 heap_free(This
->tdescAlias
);
11117 This
->tdescAlias
= heap_alloc(TLB_SizeTypeDesc(tdescAlias
, TRUE
));
11118 TLB_CopyTypeDesc(NULL
, tdescAlias
, This
->tdescAlias
);
11123 static HRESULT WINAPI
ICreateTypeInfo2_fnDefineFuncAsDllEntry(ICreateTypeInfo2
*iface
,
11124 UINT index
, LPOLESTR dllName
, LPOLESTR procName
)
11126 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11127 FIXME("%p %u %s %s - stub\n", This
, index
, wine_dbgstr_w(dllName
), wine_dbgstr_w(procName
));
11131 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncDocString(ICreateTypeInfo2
*iface
,
11132 UINT index
, LPOLESTR docString
)
11134 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11135 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11137 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11140 return E_INVALIDARG
;
11142 if(index
>= This
->typeattr
.cFuncs
)
11143 return TYPE_E_ELEMENTNOTFOUND
;
11145 func_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11150 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarDocString(ICreateTypeInfo2
*iface
,
11151 UINT index
, LPOLESTR docString
)
11153 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11154 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11156 TRACE("%p %u %s\n", This
, index
, wine_dbgstr_w(docString
));
11159 return E_INVALIDARG
;
11161 if(index
>= This
->typeattr
.cVars
)
11162 return TYPE_E_ELEMENTNOTFOUND
;
11164 var_desc
->HelpString
= TLB_append_str(&This
->pTypeLib
->string_list
, docString
);
11169 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpContext(ICreateTypeInfo2
*iface
,
11170 UINT index
, DWORD helpContext
)
11172 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11173 TLBFuncDesc
*func_desc
= &This
->funcdescs
[index
];
11175 TRACE("%p %u %d\n", This
, index
, helpContext
);
11177 if(index
>= This
->typeattr
.cFuncs
)
11178 return TYPE_E_ELEMENTNOTFOUND
;
11180 func_desc
->helpcontext
= helpContext
;
11185 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpContext(ICreateTypeInfo2
*iface
,
11186 UINT index
, DWORD helpContext
)
11188 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11189 TLBVarDesc
*var_desc
= &This
->vardescs
[index
];
11191 TRACE("%p %u %d\n", This
, index
, helpContext
);
11193 if(index
>= This
->typeattr
.cVars
)
11194 return TYPE_E_ELEMENTNOTFOUND
;
11196 var_desc
->HelpContext
= helpContext
;
11201 static HRESULT WINAPI
ICreateTypeInfo2_fnSetMops(ICreateTypeInfo2
*iface
,
11202 UINT index
, BSTR bstrMops
)
11204 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11205 FIXME("%p %u %s - stub\n", This
, index
, wine_dbgstr_w(bstrMops
));
11209 static HRESULT WINAPI
ICreateTypeInfo2_fnSetTypeIdldesc(ICreateTypeInfo2
*iface
,
11212 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11214 TRACE("%p %p\n", This
, idlDesc
);
11217 return E_INVALIDARG
;
11219 This
->typeattr
.idldescType
.dwReserved
= idlDesc
->dwReserved
;
11220 This
->typeattr
.idldescType
.wIDLFlags
= idlDesc
->wIDLFlags
;
11225 static HRESULT WINAPI
ICreateTypeInfo2_fnLayOut(ICreateTypeInfo2
*iface
)
11227 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11228 ITypeInfo2
*tinfo
= &This
->ITypeInfo2_iface
;
11229 TLBFuncDesc
*func_desc
;
11230 UINT user_vft
= 0, i
, depth
= 0;
11231 HRESULT hres
= S_OK
;
11233 TRACE("%p\n", This
);
11235 This
->needs_layout
= FALSE
;
11237 if (This
->typeattr
.typekind
== TKIND_INTERFACE
) {
11242 hres
= ITypeInfo2_GetRefTypeOfImplType(tinfo
, 0, &inh_href
);
11244 if (SUCCEEDED(hres
)) {
11245 hres
= ITypeInfo2_GetRefTypeInfo(tinfo
, inh_href
, &inh
);
11247 if (SUCCEEDED(hres
)) {
11248 hres
= ITypeInfo_GetTypeAttr(inh
, &attr
);
11249 if (FAILED(hres
)) {
11250 ITypeInfo_Release(inh
);
11253 This
->typeattr
.cbSizeVft
= attr
->cbSizeVft
;
11254 ITypeInfo_ReleaseTypeAttr(inh
, attr
);
11258 hres
= ITypeInfo_GetRefTypeOfImplType(inh
, 0, &inh_href
);
11259 if(SUCCEEDED(hres
)){
11261 hres
= ITypeInfo_GetRefTypeInfo(inh
, inh_href
, &next
);
11262 if(SUCCEEDED(hres
)){
11263 ITypeInfo_Release(inh
);
11267 }while(SUCCEEDED(hres
));
11270 ITypeInfo_Release(inh
);
11271 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11272 This
->typeattr
.cbSizeVft
= 0;
11276 } else if (hres
== TYPE_E_ELEMENTNOTFOUND
) {
11277 This
->typeattr
.cbSizeVft
= 0;
11281 } else if (This
->typeattr
.typekind
== TKIND_DISPATCH
)
11282 This
->typeattr
.cbSizeVft
= 7 * This
->pTypeLib
->ptr_size
;
11284 This
->typeattr
.cbSizeVft
= 0;
11286 func_desc
= This
->funcdescs
;
11288 while (i
< This
->typeattr
.cFuncs
) {
11289 if (!(func_desc
->funcdesc
.oVft
& 0x1))
11290 func_desc
->funcdesc
.oVft
= This
->typeattr
.cbSizeVft
;
11292 if ((func_desc
->funcdesc
.oVft
& 0xFFFC) > user_vft
)
11293 user_vft
= func_desc
->funcdesc
.oVft
& 0xFFFC;
11295 This
->typeattr
.cbSizeVft
+= This
->pTypeLib
->ptr_size
;
11297 if (func_desc
->funcdesc
.memid
== MEMBERID_NIL
) {
11300 BOOL reset
= FALSE
;
11302 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + i
;
11304 iter
= This
->funcdescs
;
11305 while (j
< This
->typeattr
.cFuncs
) {
11306 if (iter
!= func_desc
&& iter
->funcdesc
.memid
== func_desc
->funcdesc
.memid
) {
11308 func_desc
->funcdesc
.memid
= 0x60000000 + (depth
<< 16) + This
->typeattr
.cFuncs
;
11311 ++func_desc
->funcdesc
.memid
;
11312 iter
= This
->funcdescs
;
11325 if (user_vft
> This
->typeattr
.cbSizeVft
)
11326 This
->typeattr
.cbSizeVft
= user_vft
+ This
->pTypeLib
->ptr_size
;
11328 for(i
= 0; i
< This
->typeattr
.cVars
; ++i
){
11329 TLBVarDesc
*var_desc
= &This
->vardescs
[i
];
11330 if(var_desc
->vardesc
.memid
== MEMBERID_NIL
){
11332 BOOL reset
= FALSE
;
11335 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + i
;
11337 iter
= This
->vardescs
;
11338 while (j
< This
->typeattr
.cVars
) {
11339 if (iter
!= var_desc
&& iter
->vardesc
.memid
== var_desc
->vardesc
.memid
) {
11341 var_desc
->vardesc
.memid
= 0x40000000 + (depth
<< 16) + This
->typeattr
.cVars
;
11344 ++var_desc
->vardesc
.memid
;
11345 iter
= This
->vardescs
;
11358 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDesc(ICreateTypeInfo2
*iface
,
11361 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11362 FIXME("%p %u - stub\n", This
, index
);
11366 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteFuncDescByMemId(ICreateTypeInfo2
*iface
,
11367 MEMBERID memid
, INVOKEKIND invKind
)
11369 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11370 FIXME("%p %x %d - stub\n", This
, memid
, invKind
);
11374 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDesc(ICreateTypeInfo2
*iface
,
11377 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11378 FIXME("%p %u - stub\n", This
, index
);
11382 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteVarDescByMemId(ICreateTypeInfo2
*iface
,
11385 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11386 FIXME("%p %x - stub\n", This
, memid
);
11390 static HRESULT WINAPI
ICreateTypeInfo2_fnDeleteImplType(ICreateTypeInfo2
*iface
,
11393 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11396 TRACE("%p %u\n", This
, index
);
11398 if (index
>= This
->typeattr
.cImplTypes
)
11399 return TYPE_E_ELEMENTNOTFOUND
;
11401 TLB_FreeCustData(&This
->impltypes
[index
].custdata_list
);
11402 --This
->typeattr
.cImplTypes
;
11404 if (index
< This
->typeattr
.cImplTypes
)
11406 memmove(This
->impltypes
+ index
, This
->impltypes
+ index
+ 1, (This
->typeattr
.cImplTypes
- index
) *
11407 sizeof(*This
->impltypes
));
11408 for (i
= index
; i
< This
->typeattr
.cImplTypes
; ++i
)
11409 TLB_relink_custdata(&This
->impltypes
[i
].custdata_list
);
11415 static HRESULT WINAPI
ICreateTypeInfo2_fnSetCustData(ICreateTypeInfo2
*iface
,
11416 REFGUID guid
, VARIANT
*varVal
)
11420 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11422 TRACE("%p %s %p\n", This
, debugstr_guid(guid
), varVal
);
11424 if (!guid
|| !varVal
)
11425 return E_INVALIDARG
;
11427 tlbguid
= TLB_append_guid(&This
->pTypeLib
->guid_list
, guid
, -1);
11429 return TLB_set_custdata(This
->pcustdata_list
, tlbguid
, varVal
);
11432 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncCustData(ICreateTypeInfo2
*iface
,
11433 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11435 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11436 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11440 static HRESULT WINAPI
ICreateTypeInfo2_fnSetParamCustData(ICreateTypeInfo2
*iface
,
11441 UINT funcIndex
, UINT paramIndex
, REFGUID guid
, VARIANT
*varVal
)
11443 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11444 FIXME("%p %u %u %s %p - stub\n", This
, funcIndex
, paramIndex
, debugstr_guid(guid
), varVal
);
11448 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarCustData(ICreateTypeInfo2
*iface
,
11449 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11451 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11452 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11456 static HRESULT WINAPI
ICreateTypeInfo2_fnSetImplTypeCustData(ICreateTypeInfo2
*iface
,
11457 UINT index
, REFGUID guid
, VARIANT
*varVal
)
11459 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11460 FIXME("%p %u %s %p - stub\n", This
, index
, debugstr_guid(guid
), varVal
);
11464 static HRESULT WINAPI
ICreateTypeInfo2_fnSetHelpStringContext(ICreateTypeInfo2
*iface
,
11465 ULONG helpStringContext
)
11467 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11469 TRACE("%p %u\n", This
, helpStringContext
);
11471 This
->dwHelpStringContext
= helpStringContext
;
11476 static HRESULT WINAPI
ICreateTypeInfo2_fnSetFuncHelpStringContext(ICreateTypeInfo2
*iface
,
11477 UINT index
, ULONG helpStringContext
)
11479 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11480 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11484 static HRESULT WINAPI
ICreateTypeInfo2_fnSetVarHelpStringContext(ICreateTypeInfo2
*iface
,
11485 UINT index
, ULONG helpStringContext
)
11487 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11488 FIXME("%p %u %u - stub\n", This
, index
, helpStringContext
);
11492 static HRESULT WINAPI
ICreateTypeInfo2_fnInvalidate(ICreateTypeInfo2
*iface
)
11494 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11495 FIXME("%p - stub\n", This
);
11499 static HRESULT WINAPI
ICreateTypeInfo2_fnSetName(ICreateTypeInfo2
*iface
,
11502 ITypeInfoImpl
*This
= info_impl_from_ICreateTypeInfo2(iface
);
11504 TRACE("%p %s\n", This
, wine_dbgstr_w(name
));
11507 return E_INVALIDARG
;
11509 This
->Name
= TLB_append_str(&This
->pTypeLib
->name_list
, name
);
11514 static const ICreateTypeInfo2Vtbl CreateTypeInfo2Vtbl
= {
11515 ICreateTypeInfo2_fnQueryInterface
,
11516 ICreateTypeInfo2_fnAddRef
,
11517 ICreateTypeInfo2_fnRelease
,
11518 ICreateTypeInfo2_fnSetGuid
,
11519 ICreateTypeInfo2_fnSetTypeFlags
,
11520 ICreateTypeInfo2_fnSetDocString
,
11521 ICreateTypeInfo2_fnSetHelpContext
,
11522 ICreateTypeInfo2_fnSetVersion
,
11523 ICreateTypeInfo2_fnAddRefTypeInfo
,
11524 ICreateTypeInfo2_fnAddFuncDesc
,
11525 ICreateTypeInfo2_fnAddImplType
,
11526 ICreateTypeInfo2_fnSetImplTypeFlags
,
11527 ICreateTypeInfo2_fnSetAlignment
,
11528 ICreateTypeInfo2_fnSetSchema
,
11529 ICreateTypeInfo2_fnAddVarDesc
,
11530 ICreateTypeInfo2_fnSetFuncAndParamNames
,
11531 ICreateTypeInfo2_fnSetVarName
,
11532 ICreateTypeInfo2_fnSetTypeDescAlias
,
11533 ICreateTypeInfo2_fnDefineFuncAsDllEntry
,
11534 ICreateTypeInfo2_fnSetFuncDocString
,
11535 ICreateTypeInfo2_fnSetVarDocString
,
11536 ICreateTypeInfo2_fnSetFuncHelpContext
,
11537 ICreateTypeInfo2_fnSetVarHelpContext
,
11538 ICreateTypeInfo2_fnSetMops
,
11539 ICreateTypeInfo2_fnSetTypeIdldesc
,
11540 ICreateTypeInfo2_fnLayOut
,
11541 ICreateTypeInfo2_fnDeleteFuncDesc
,
11542 ICreateTypeInfo2_fnDeleteFuncDescByMemId
,
11543 ICreateTypeInfo2_fnDeleteVarDesc
,
11544 ICreateTypeInfo2_fnDeleteVarDescByMemId
,
11545 ICreateTypeInfo2_fnDeleteImplType
,
11546 ICreateTypeInfo2_fnSetCustData
,
11547 ICreateTypeInfo2_fnSetFuncCustData
,
11548 ICreateTypeInfo2_fnSetParamCustData
,
11549 ICreateTypeInfo2_fnSetVarCustData
,
11550 ICreateTypeInfo2_fnSetImplTypeCustData
,
11551 ICreateTypeInfo2_fnSetHelpStringContext
,
11552 ICreateTypeInfo2_fnSetFuncHelpStringContext
,
11553 ICreateTypeInfo2_fnSetVarHelpStringContext
,
11554 ICreateTypeInfo2_fnInvalidate
,
11555 ICreateTypeInfo2_fnSetName
11558 /******************************************************************************
11559 * ClearCustData (OLEAUT32.171)
11561 * Clear a custom data type's data.
11564 * lpCust [I] The custom data type instance
11569 void WINAPI
ClearCustData(CUSTDATA
*lpCust
)
11571 if (lpCust
&& lpCust
->cCustData
)
11573 if (lpCust
->prgCustData
)
11577 for (i
= 0; i
< lpCust
->cCustData
; i
++)
11578 VariantClear(&lpCust
->prgCustData
[i
].varValue
);
11580 CoTaskMemFree(lpCust
->prgCustData
);
11581 lpCust
->prgCustData
= NULL
;
11583 lpCust
->cCustData
= 0;